/*******************************************************************************
 * Copyright (c) 2003, 2016 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.tools.internal;
import java.io.*;
import java.util.*;

/* Produces the java classes mapping to XPCOM Mozilla objects */
public class MozillaGenerator {
	FileReader r = null;
	FileWriter w = null;
	int maxLines = 1000;
	int cntLines = 0;
	int n = 0;
	String[] b = null;
	String body = null;
	int nMethods = 0;
	String uuidName;
	String uuidValue;
	String className;
	String parentName;
	String[] constantNames;
	String[] constantValues;
	String[] methodNames;
	String[][] argTypes;
	String[][] argNames;
	String bodyOrder;
	Map<Integer, List<String>> vtbls;

	static boolean DEBUG = false;

	// Contains the characters found before a method name
	// Useful to extract the method name. e.g.
	//  NS_IMETHOD QueryInterface(const nsIID & uuid, void * *result) = 0;
	//  NS_IMETHOD_(nsrefcnt) AddRef(void) = 0;
	// method name follows: QueryInterface, AddRef etc.
	static String[] BEFORE_METHOD_NAME = {
		"  NS_IMETHOD ",
		"  NS_IMETHOD_(nsrefcnt) ",
		"  NS_IMETHOD_(void *) ",
		"  NS_IMETHOD_(void) ",
		"  NS_IMETHOD_(nsresult) ",
		"  NS_SCRIPTABLE NS_IMETHOD ",
		"  NS_SCRIPTABLE NS_IMETHOD_(nsrefcnt) ",
		"  NS_SCRIPTABLE NS_IMETHOD_(void *) ",
		"  NS_SCRIPTABLE NS_IMETHOD_(void) ",
		"  NS_SCRIPTABLE NS_IMETHOD_(nsresult) ",
	};
	static String NO_SUPER_CLASS = "SWT_NO_SUPER_CLASS";
	
	static String[][] TYPES_C2JAVA = { 
		{ "PRBool *", "int[]" },
		{ "nsIID &", "nsID" },
		{ "nsCID &", "nsID" },
		{ "nsCID * *", "int /*long*/" }, // nsID[] not supported by jnigen
		{ "* *", "int /*long*/[]" },
		{ "**", "int /*long*/[]" },
		{ "* &", "int /*long*/[]" },
		{ "PRUint32 *", "int[]" }, 
		{ "PRInt32 *", "int[]" },
		{ "PRInt64 *", "long[]" },
		{ "PRUnichar *", "char[]" },
		{ "char *", "byte[]" },
		{ "float *", "float[]" },
		{ "PRUint16 *", "short[]" },
		{ "nativeWindow *", "int /*long*/[]" },
		{ "nsWriteSegmentFun", "int /*long*/" },
		{ "nativeWindow", "int /*long*/" },

		{ "*", "int /*long*/" }, // c type containing one or more * (and any other character, and did not match previous patterns) is a simple pointer
		{ "&", "int /*long*/" }, 

		{ "PRUint32", "int" },
		{ "PRInt32", "int" }, 
		{ "PRInt64", "long" }, 
		{ "nsresult", "int" },
		{ "PRBool", "int" },
		{ "float", "float" },
		{ "PRUint16", "short" },
		{ "size_t", "int" },
		};

	static String GECKO = "/opt/mozilla/1.4/linux_gtk2/mozilla/dist/include/";
	static String TARGET_FOLDER = "/opt/workspace/org.eclipse.swt/Eclipse SWT Mozilla/common/org/eclipse/swt/internal/mozilla/";
	static String[] XPCOM_HEADERS = {
		"profile/nsIProfile.h",
		"widget/nsIAppShell.h",
		"widget/nsIBaseWindow.h",
		"xpcom/nsIComponentManager.h",
		"xpcom/nsIComponentRegistrar.h",
		"webbrwsr/nsIContextMenuListener.h", 
		"docshell/nsIDocShell.h",
		"dom/nsIDOMEvent.h",
		"dom/nsIDOMMouseEvent.h",
		"dom/nsIDOMUIEvent.h",
		"dom/nsIDOMWindow.h",
		"uriloader/nsIDownload.h", 
		"webbrwsr/nsIEmbeddingSiteWindow.h",
		"xpcom/nsIFactory.h", 
		"xpcom/nsIFile.h",
		"helperAppDlg/nsIHelperAppLauncherDialog.h",
		"exthandler/nsIExternalHelperAppService.h", // contains nsIHelperAppLauncher
		"xpcom/nsIInputStream.h", 
		"xpcom/nsIInterfaceRequestor.h",
		"necko/nsIIOService.h", 
		"xpcom/nsILocalFile.h", 
		"xpcom/nsIMemory.h",
		"progressDlg/nsIProgressDialog.h",
		"windowwatcher/nsIPromptService.h", 
		"xpcom/nsIServiceManager.h",
		"xpcom/nsISupports.h", 
		"webbrwsr/nsITooltipListener.h", 
		"necko/nsIURI.h",
		"uriloader/nsIURIContentListener.h", 
		"xpcom/nsIWeakReference.h",
		"webbrwsr/nsIWebBrowser.h", 
		"webbrwsr/nsIWebBrowserChrome.h",
		"webbrwsr/nsIWebBrowserChromeFocus.h",
		"webbrwsr/nsIWebBrowserFocus.h", 
		"docshell/nsIWebNavigation.h",
		"uriloader/nsIWebProgress.h", 
		"uriloader/nsIWebProgressListener.h",
		"embed_base/nsIWindowCreator.h", 
		"windowwatcher/nsIWindowWatcher.h" };

	public static void main(String[] args) {
		MozillaGenerator x = new MozillaGenerator();
		for (int i = 0; i < XPCOM_HEADERS.length; i++)
			x.parse(GECKO + XPCOM_HEADERS[i], TARGET_FOLDER);
		x.outputVtblCall();
		System.out.println("done");
	}

	public MozillaGenerator() {
		vtbls = new HashMap<>();
	}

	/** Write callbacks */
	public void write(String data) {
		if (DEBUG) {
			System.out.print(data);
			return;
		}
		try {
			w.write(data);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void writeLine() {
		if (DEBUG) {
			System.out.println();
			return;
		}
		write("\r\n");
	}

	public void writeLine(String data) {
		if (DEBUG) {
			System.out.println(data);
			return;
		}
		write(data + "\r\n");
	}

	public void writeCopyrights() {
		writeLine(COPYRIGHTS);
	}

	public void writePackageDeclaration() {
		writeLine(PACKAGE_DECLARATION);
	}

	public void writeClassDeclaration(String className, String parentName) {
		String line = "public class " + className;
		if (!parentName.equals(NO_SUPER_CLASS)) line += " extends " + parentName;
		line += " {";
		writeLine(line);
	}

	public void writeLastMethodId(String parentName, int nMethods) {
		String line = "\tstatic final int LAST_METHOD_ID = ";
		if (!parentName.equals(NO_SUPER_CLASS)) line += parentName + ".LAST_METHOD_ID + " + nMethods + ";";
		else line += "" + (nMethods - 1)+ ";"; // zero indexed
		writeLine(line);
	}

	public void writeIID(String uuidName, String uuidValue, String className) {
		writeLine("\tstatic final String " + uuidName + " = \"" + uuidValue + "\";");
		writeLine();
		writeLine("\tstatic {");
		writeLine("\t\tIIDStore.RegisterIID(" + className + ".class, MozillaVersion.VERSION_BASE, new nsID(" + uuidName + "));");
		writeLine("\t}");
	}

	public void writeAddressField() {
		writeLine("\tint /*long*/ address;");
	}
	public void writeConstructor(String className, String parentName) {
		writeLine("\tpublic " + className + "(int /*long*/ address) {");
		if (!parentName.equals(NO_SUPER_CLASS)) {
			writeLine("\t\tsuper(address);");
		} else {
			writeLine("\t\tthis.address = address;");
		}
		writeLine("\t}");
	}

	public void writeAddressGetter() {
		writeLine("\tpublic int /*long*/ getAddress() {");
		writeLine("\t\treturn this.address;");
		writeLine("\t}");
	}
	
	public void writeConstant(String name, String value) {
		writeLine("\tpublic static final int " + name + " = " + value + ";");
	}

	public void writeMethod(String name, String parentName, int methodIndex, String[] argTypes, String[] argNames) {
		write("\tpublic int " + name + "(");
		for (int i = 0; i < argTypes.length; i++) {
			write(argTypes[i] + " " + argNames[i]);
			if (i < argTypes.length - 1)
				write(", ");
		}
		write(") {");
		writeLine();
		String line = "\t\treturn XPCOM.VtblCall(";
		if (!parentName.equals(NO_SUPER_CLASS)) line += parentName + ".LAST_METHOD_ID + " + (methodIndex + 1) + ", getAddress()";
		else line += methodIndex + ", getAddress()"; // zero indexed
		write(line);
		if (argTypes.length > 0)
			write(", ");
		for (int i = 0; i < argTypes.length; i++) {
			write(argNames[i]);
			if (i < argTypes.length - 1)
				write(", ");
		}
		writeLine(");");
		writeLine("\t}");
	}

	public void writeClassEnd() {
		write("}");
	}

	public void logVtblCall(String[] argTypes) {
		String vtbl = "static final native int VtblCall(int fnNumber, int /*long*/ ppVtbl";
		if (argTypes.length > 0)
			vtbl += ", ";
		for (int i = 0; i < argTypes.length; i++) {
			vtbl += argTypes[i] + " arg" + i;
			if (i < argTypes.length - 1)
				vtbl += ", ";
		}
		vtbl += ");";
		Integer key = Integer.valueOf(argTypes.length);
		List<String> list = vtbls.get(key);
		if (list == null) {
			list = new ArrayList<>();
			vtbls.put(key, list);
		}
		boolean duplicate = false;
		Iterator<String> e = list.iterator();
		while (e.hasNext()) {
			String s = e.next();
			if (vtbl.equals(s)) {
				duplicate = true;
				break;
			}
		}
		if (!duplicate)
			list.add(vtbl);
	}

	public void outputVtblCall() {
		Iterator<Integer> e = vtbls.keySet().iterator();
		int n = 0;
		while (e.hasNext()) {
			e.next();
			n++;
		}
		Integer[] keys = new Integer[n];
		e = vtbls.keySet().iterator();
		n = 0;
		while (e.hasNext()) {
			keys[n] = e.next();
			n++;
		}
		Arrays.sort(keys);
		for (int i = 0; i < keys.length; i++) {
			List<String> list = vtbls.get(keys[i]);
			Object[] elts = list.toArray();
			Arrays.sort(elts);
			for (int j = 0; j < elts.length; j++) {
				System.out.println(elts[j]);
			}
		}

	}

	/** Parsing invoking write callbacks */

	/*
	 * Convert a C header file into a Java source file matching SWT Mozilla
	 binding.
	 */
	public void parse(String src, String destPath) {
		if (DEBUG) writeLine("*** PARSING <"+src+"> to folder "+destPath);
		b = new String[maxLines];
		cntLines = 0;
		try {
			r = new FileReader(src);
			try (BufferedReader br = new BufferedReader(r)) {
				while ((b[cntLines] = br.readLine()) != null) {
					cntLines++;
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
			return;
		}
		n = 0;
		boolean lookForClasses = true;
		while (lookForClasses) {	
			/* parsing */
			lookForClasses = parse();
	
			String destFile = destPath + className + ".java";
			try {
				w = new FileWriter(destFile);
				if (DEBUG) writeLine("** CREATED JAVA FILE <"+destFile+">");
			} catch (IOException e) {
				e.printStackTrace();
				return;
			}
	
			/* writing */
			writeCopyrights();
			writePackageDeclaration();
			writeLine();
			writeClassDeclaration(className, parentName);
			writeLine();
			writeLastMethodId(parentName, nMethods);
			writeLine();
			writeIID(uuidName, uuidValue, className);
			writeLine();
			if (parentName.equals(NO_SUPER_CLASS)) {
				writeAddressField();
				writeLine();
			}
			writeConstructor(className, parentName);
			writeLine();
			
			if (parentName.equals(NO_SUPER_CLASS)) {
				writeAddressGetter();
				writeLine();
			}
	
			int constantIndex = 0, methodIndex = 0;
			for (int i = 0; i < bodyOrder.length(); i++) {
				if (bodyOrder.charAt(i) == 'C') {
					writeConstant(constantNames[constantIndex],
							constantValues[constantIndex]);
					if (i < bodyOrder.length() - 1) writeLine();
					constantIndex++;
				} else if (bodyOrder.charAt(i) == 'M') {
					writeMethod(methodNames[methodIndex], parentName, methodIndex,
							argTypes[methodIndex], argNames[methodIndex]);
					if (i < bodyOrder.length() - 1) writeLine();
					methodIndex++;
				}
			}
	
			writeClassEnd();
	
			try {
				w.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public String getPackages() {
		return "package org.eclipse.swt.internal.mozilla;";
	}

	public boolean parse() {
		if (!jumpToUuidDeclaration()) return false;
		uuidName = getUuidName(b[n]);
		if (DEBUG)
			System.out.println("UUID name: <" + uuidName + ">");
		uuidValue = getUuidValue(b[n]);
		if (DEBUG)
			System.out.println("UUID value: <" + uuidValue + ">");
		jumpToInterfaceDeclaration();
		className = getClassName(b[n]);
		if (DEBUG)
			System.out.println("Interface name: <" + className + ">");
		parentName = getParentName(b[n]);
		if (DEBUG)
			System.out.println("parentName: <" + parentName + ">");
		parseBody();
		return true;
	}

	boolean jumpToUuidDeclaration() {
		// jump to line matching: "#define NS_IWEBBROWSERCHROME_IID_STR "ba434c60-9d52-11d3-afb0-00a024ffc08c""
		while (!(b[n].startsWith("#define ") && b[n].indexOf("_IID_STR \"") != -1)) {
			n++;
			if (n >= cntLines) return false;
		}
		return true;
	}

	//assume a declaration matching: "#define NS_IWEBBROWSERCHROME_IID_STR "ba434c60-9d52-11d3-afb0-00a024ffc08c""
	//returns NS_IWEBBROWSERCHROME_IID_STR
	String getUuidName(String declaration) {
		return declaration.substring(declaration.indexOf("#define ")
				+ "#define ".length(), declaration.indexOf(" \""));
	}

	//assume a declaration matching: "#define NS_IWEBBROWSERCHROME_IID_STR "ba434c60-9d52-11d3-afb0-00a024ffc08c""
	//returns ba434c60-9d52-11d3-afb0-00a024ffc08c
	String getUuidValue(String declaration) {
		return declaration.substring(declaration.indexOf("_IID_STR \"")
				+ "_IID_STR \"".length(), declaration.lastIndexOf('"'));
	}

	void jumpToInterfaceDeclaration() {
		// jump to line matching: "class NS_NO_VTABLE nsIWebBrowserChrome : public nsISupports {"
		while (!(b[n].startsWith("class NS_NO_VTABLE "))) {
			n++;
		}
	}

	// Assume a declaration matching: "class NS_NO_VTABLE nsIWebBrowserChrome : public nsISupports {"
	// or "class NS_NO_VTABLE NS_SCRIPTABLE nsIWebBrowserChrome : public nsISupports {" returns nsIWebBrowserChrome.
	// Special case for nsISupports that has no super class: class NS_NO_VTABLE nsISupports {
	String getClassName(String declaration) {
		int endIndex = declaration.indexOf(" :");
		// nsISupports special case (no super class)
		if (endIndex == -1) endIndex = declaration.indexOf(" {");
		String searchString = "class NS_NO_VTABLE NS_SCRIPTABLE";
		int startIndex = declaration.indexOf(searchString);
		if (startIndex == -1) {
			searchString = "class NS_NO_VTABLE ";
			startIndex = declaration.indexOf(searchString);
		}
		return declaration.substring(startIndex + searchString.length(), endIndex);
	}

	// assume a declaration matching: "class NS_NO_VTABLE nsIWebBrowserChrome : public nsISupports {"
	// returns nsISupports
	// special case for nsISupports that has no super class: class NS_NO_VTABLE nsISupports {
	String getParentName(String declaration) {
		if (declaration.indexOf(" :") == -1) return NO_SUPER_CLASS;
		return declaration.substring(declaration.indexOf(": public ")
				+ ": public ".length(), declaration.indexOf(" {"));
	}

	// parse methods and constants declarations starting at the current index
	// out:
	// .String body - contains the corresponding java content
	// .n - set to the end of the interface body declaration ( line with the enclosing "};" )
	// .nMethods    - set to the number of methods parsed
	void parseBody() {
		body = "";
		bodyOrder = "";
		int nConstants = 0;
		nMethods = 0;

		int tmp_n = n;
		while (true) {
			int type = jumpToNextConstantOrMethod();
			if (type == CONSTANT)
				nConstants++;
			if (type == METHOD)
				nMethods++;
			if (type == END_BODY)
				break;
			n++;
		}
		n = tmp_n;
		constantNames = new String[nConstants];
		constantValues = new String[nConstants];
		methodNames = new String[nMethods];
		argTypes = new String[nMethods][];
		argNames = new String[nMethods][];
		int constantIndex = 0, methodIndex = 0;
		while (true) {
			int type = jumpToNextConstantOrMethod();
			if (type == CONSTANT) {
				parseConstant(b[n], constantIndex);
				bodyOrder += "C";
				constantIndex++;
			}
			if (type == METHOD) {
				parseMethod(b[n], methodIndex);
				logVtblCall(argTypes[methodIndex]);
				bodyOrder += "M";
				methodIndex++;
			}
			if (type == END_BODY)
				return;
			n++;
		}
	}

	static int CONSTANT = 0;

	static int METHOD = 1;

	static int END_BODY = 2;

	boolean isEndOfInterfaceBody() {
		return b[n].startsWith("};");
	}

	int jumpToNextConstantOrMethod() {
		while (!isEndOfInterfaceBody()) {
			if (b[n].startsWith("  enum { ")) {
				return CONSTANT;
			}
			if (methodNameStartIndexOf(b[n]) != -1) {
				return METHOD;
			}
			n++;
		}
		return END_BODY;
	}

	void parseConstant(String constant, int constantIndex) {
		String constantName = constant.substring(constant.indexOf(" enum { ")
				+ " enum { ".length(), constant.indexOf(" ="));
		if (DEBUG)
			writeLine("constantName <" + constantName + ">");
		constantNames[constantIndex] = constantName;
		
		// most constants values have a trailing U
		// enum { APP_TYPE_UNKNOWN = 0U };
		int endIndex = constant.indexOf("U };");
		// a few others don't
		// enum { ENUMERATE_FORWARDS = 0 };		
		if (endIndex == -1) endIndex = constant.indexOf(" };");
		String constantValue = constant.substring(constant.indexOf(" = ")
				+ " = ".length(), endIndex);
		if (DEBUG)
			writeLine("constantValue <" + constantValue + ">");
		constantValues[constantIndex] = constantValue;
	}

	// NS_IMETHOD SetStatus(PRUint32 statusType, const PRUnichar *status) = 0;
	// identify:
	// method name: <SetStatus>
	// Nbr of arguments: 2
	// Type of argument 0: PRUint32
	// Name of argument 0: statusType
	// Type of argument 1: const PRUnichar *
	// Name of argument 1: status
	void parseMethod(String line, int methodIndex) {
		int start = methodNameStartIndexOf(line);
		int end = methodNameEndIndexOf(line);
		String methodName = line.substring(start, end);
		if (DEBUG)
			writeLine("method name: <" + methodName + ">");
		methodNames[methodIndex] = methodName;
		int argStart = end+"(".length();
		int argEnd = line.indexOf(")", argStart);
		parseArgs(line.substring(argStart, argEnd), methodIndex);
	}

	// Given a line, returns the start of the method name or -1
	// if the line does not contain a method declaration.
	int methodNameStartIndexOf(String line) {
		for (int i = 0; i < BEFORE_METHOD_NAME.length; i++) {
			int index = line.indexOf(BEFORE_METHOD_NAME[i]);
			if (index != -1) return index + BEFORE_METHOD_NAME[i].length();
		}
		return -1;
	}
	int methodNameEndIndexOf(String line) {
		int startIndex = methodNameStartIndexOf(line);
		return line.indexOf("(", startIndex);
	}
	void parseArgs(String args, int methodIndex) {
		int nArgs = -1;
		// methods with no args look like: () or (void)
		String[] noArgs = new String[] { "", "void" };
		for (int i = 0; i < noArgs.length; i++) {
			if (args.equals(noArgs[i])) {
				nArgs = 0;
				break;
			}
		}
		if (nArgs == -1)
			nArgs = count(args, ", ") + 1;
		String[] argTypes = new String[nArgs];
		this.argTypes[methodIndex] = argTypes;
		String[] argNames = new String[nArgs];
		this.argNames[methodIndex] = argNames;
		int typeStart = 0;

		// name is separated from its type by either of the following (sorted by decreasing size to find the most complete pattern */
		String[] typeNameSep = new String[] { " * *", " **", " * & ", " * ", " *",
				" & ", " " };
		for (int i = 0; i < nArgs; i++) {
			/* get the type */
			int nextTypeStart = i < nArgs - 1 ? args.indexOf(", ", typeStart)
					+ ", ".length() : args.length();
			int typeNameSepIndex = 0;
			int separatorIndex = 0;
			for (; typeNameSepIndex < typeNameSep.length; typeNameSepIndex++) {
				separatorIndex = args.indexOf(typeNameSep[typeNameSepIndex],
						typeStart);
				if (separatorIndex != -1 && separatorIndex < nextTypeStart)
					break;
			}
			String separator = typeNameSep[typeNameSepIndex];
			argTypes[i] = getC2JavaType(args.substring(typeStart,
					separatorIndex + separator.length()));
			if (DEBUG)
				writeLine("arg type" + i + ": <" + argTypes[i] + ">");
			/* get the name */
			int nameStart = separatorIndex + separator.length();
			int nameEnd = i < nArgs - 1 ? args.indexOf(", ", nameStart) : args
					.length();
			argNames[i] = args.substring(nameStart, nameEnd);
			if (DEBUG)
				writeLine("arg name" + i + ": <" + argNames[i] + ">");

			typeStart = nextTypeStart;
		}
	}

	String getC2JavaType(String cType) {
		for (int i = 0; i < TYPES_C2JAVA.length; i++) {
			if (cType.indexOf(TYPES_C2JAVA[i][0]) != -1)
				return TYPES_C2JAVA[i][1];
		}
		return "!ERROR UNKNOWN C TYPE <" + cType + ">!";
	}

	// how many times part can be found in s
	static int count(String s, String part) {
		int index = -1, cnt = 0;
		while ((index = s.indexOf(part, index + 1)) != -1)
			cnt++;
		return cnt;
	}

	static String COPYRIGHTS =
		"/* ***** BEGIN LICENSE BLOCK *****\r\n"
		+ " * Version: MPL 1.1\r\n"
		+ " *\r\n"
		+ " * The contents of this file are subject to the Mozilla Public License Version\r\n"
		+ " * 1.1 (the \"License\"); you may not use this file except in compliance with\r\n"
		+ " * the License. You may obtain a copy of the License at\r\n"
		+ " * http://www.mozilla.org/MPL/\r\n"
		+ " *\r\n"
		+ " * Software distributed under the License is distributed on an \"AS IS\" basis,\r\n"
		+ " * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\r\n"
		+ " * for the specific language governing rights and limitations under the\r\n"
		+ " * License.\r\n"
		+ " *\r\n"
		+ " * The Original Code is Mozilla Communicator client code, released March 31, 1998.\r\n"
		+ " *\r\n"
		+ " * The Initial Developer of the Original Code is\r\n"
		+ " * Netscape Communications Corporation.\r\n"
		+ " * Portions created by Netscape are Copyright (C) 1998-1999\r\n"
		+ " * Netscape Communications Corporation.  All Rights Reserved.\r\n"
		+ " *\r\n" 
		+ " * Contributor(s):\r\n" 
		+ " *\r\n" 
		+ " * IBM\r\n"
		+ " * -  Binding to permit interfacing between Mozilla and SWT\r\n"
		+ " * -  Copyright (C) 2014 IBM Corp.  All Rights Reserved.\r\n"
		+ " *\r\n" + " * ***** END LICENSE BLOCK ***** */";

	static String PACKAGE_DECLARATION = "package org.eclipse.swt.internal.mozilla;";

}
