New compiler level: v_785_R33x
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java
index 9ac9be7..093eeb9 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 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
@@ -11,57 +11,51 @@
 package org.eclipse.jdt.internal.compiler.batch;
 
 import java.io.File;
+import java.io.FilenameFilter;
 import java.io.IOException;
 import java.util.Hashtable;
 
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
+import org.eclipse.jdt.internal.compiler.util.Util;
 
 public class ClasspathDirectory extends ClasspathLocation {
 
-String path;
-Hashtable directoryCache;
-String[] missingPackageHolder = new String[1];
-String encoding;
-public int mode; // ability to only consider one kind of files (source vs. binaries), by default use both
+private char[] normalizedPath;
+private String path;
+private Hashtable directoryCache;
+private String[] missingPackageHolder = new String[1];
+private int mode; // ability to only consider one kind of files (source vs. binaries), by default use both
+private String encoding; // only useful if referenced in the source path
 
-public static final int SOURCE = 1;
-public static final int BINARY = 2;
-
-ClasspathDirectory(File directory, String encoding, int mode, AccessRuleSet accessRuleSet) {
-	super(accessRuleSet);
-	if (mode == 0){
-		this.mode = SOURCE | BINARY;
-	}
-	else {
-	    this.mode = mode;
-	}
+ClasspathDirectory(File directory, String encoding, int mode, 
+		AccessRuleSet accessRuleSet, String destinationPath) {
+	super(accessRuleSet, destinationPath);
+	this.mode = mode;
 	this.path = directory.getAbsolutePath();
 	if (!this.path.endsWith(File.separator))
 		this.path += File.separator;
 	this.directoryCache = new Hashtable(11);
 	this.encoding = encoding;
 }
-
-ClasspathDirectory(File directory, String encoding) {
-	this(directory, encoding, SOURCE | BINARY, null); // by default consider both sources and binaries
-}
 String[] directoryList(String qualifiedPackageName) {
 	String[] dirList = (String[]) this.directoryCache.get(qualifiedPackageName);
 	if (dirList == this.missingPackageHolder) return null; // package exists in another classpath directory or jar
 	if (dirList != null) return dirList;
 
 	File dir = new File(this.path + qualifiedPackageName);
-	notFound : if (dir != null && dir.isDirectory()) {
+	notFound : if (dir.isDirectory()) {
 		// must protect against a case insensitive File call
 		// walk the qualifiedPackageName backwards looking for an uppercase character before the '/'
 		int index = qualifiedPackageName.length();
 		int last = qualifiedPackageName.lastIndexOf(File.separatorChar);
-		while (--index > last && !Character.isUpperCase(qualifiedPackageName.charAt(index))){/*empty*/}
+		while (--index > last && !ScannerHelper.isUpperCase(qualifiedPackageName.charAt(index))){/*empty*/}
 		if (index > last) {
 			if (last == -1) {
-				if (!doesFileExist(qualifiedPackageName, ""))  //$NON-NLS-1$ 
+				if (!doesFileExist(qualifiedPackageName, Util.EMPTY_STRING))
 					break notFound;
 			} else {
 				String packageName = qualifiedPackageName.substring(last + 1);
@@ -71,7 +65,7 @@
 			}
 		}
 		if ((dirList = dir.list()) == null)
-			dirList = new String[0];
+			dirList = CharOperation.NO_STRINGS;
 		this.directoryCache.put(qualifiedPackageName, dirList);
 		return dirList;
 	}
@@ -88,29 +82,31 @@
 	return false;
 }
 public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName) {
+	return findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, false);
+}
+public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly) {
 	if (!isPackage(qualifiedPackageName)) return null; // most common case
 
 	String fileName = new String(typeName);
 	boolean binaryExists = ((this.mode & BINARY) != 0) && doesFileExist(fileName + SUFFIX_STRING_class, qualifiedPackageName);
 	boolean sourceExists = ((this.mode & SOURCE) != 0) && doesFileExist(fileName + SUFFIX_STRING_java, qualifiedPackageName);
-	if (sourceExists) {
+	if (sourceExists && !asBinaryOnly) {
 		String fullSourcePath = this.path + qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - 6)  + SUFFIX_STRING_java;
 		if (!binaryExists)
 			return new NameEnvironmentAnswer(new CompilationUnit(null,
-					fullSourcePath, this.encoding),
+					fullSourcePath, this.encoding, destinationPath),
 					fetchAccessRestriction(qualifiedBinaryFileName));
 		String fullBinaryPath = this.path + qualifiedBinaryFileName;
 		long binaryModified = new File(fullBinaryPath).lastModified();
 		long sourceModified = new File(fullSourcePath).lastModified();
 		if (sourceModified > binaryModified)
 			return new NameEnvironmentAnswer(new CompilationUnit(null,
-					fullSourcePath, this.encoding),
+					fullSourcePath, this.encoding, destinationPath),
 					fetchAccessRestriction(qualifiedBinaryFileName));
 	}
 	if (binaryExists) {
 		try {
-			ClassFileReader reader = ClassFileReader.read(this.path
-					+ qualifiedBinaryFileName);
+			ClassFileReader reader = ClassFileReader.read(this.path + qualifiedBinaryFileName);
 			if (reader != null)
 				return new NameEnvironmentAnswer(
 						reader,
@@ -121,6 +117,33 @@
 	}
 	return null;
 }
+public char[][][] findTypeNames(String qualifiedPackageName) {
+	if (!isPackage(qualifiedPackageName)) {
+		return null; // most common case
+	}
+	File dir = new File(this.path + qualifiedPackageName);
+	if (!dir.exists() || !dir.isDirectory()) {
+		return null;
+	}
+	String[] listFiles = dir.list(new FilenameFilter() {
+		public boolean accept(File directory, String name) {
+			String fileName = name.toLowerCase();
+			return fileName.endsWith(".class") || fileName.endsWith(".java"); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+	});
+	int length;
+	if (listFiles == null || (length = listFiles.length) == 0) {
+		return null;
+	}
+	char[][][] result = new char[length][][];
+	char[][] packageName = CharOperation.splitOn(File.separatorChar, qualifiedPackageName.toCharArray());
+	for (int i = 0; i < length; i++) {
+		String fileName = listFiles[i];
+		int indexOfLastDot = fileName.indexOf('.');
+		result[i] = CharOperation.arrayConcat(packageName, fileName.substring(0, indexOfLastDot).toCharArray());
+	}
+	return result;
+}
 public void initialize() throws IOException {
 	// nothing to do
 }
@@ -133,8 +156,14 @@
 public String toString() {
 	return "ClasspathDirectory " + this.path; //$NON-NLS-1$
 }
-public String normalizedPath() {
-	return this.path;
+public char[] normalizedPath() {
+	if (this.normalizedPath == null) {
+		this.normalizedPath = this.path.toCharArray();
+		if (File.separatorChar == '\\') {
+			CharOperation.replace(this.normalizedPath, '\\', '/');
+		}
+	}
+	return this.normalizedPath;
 }
 public String getPath() {
 	return this.path;
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java
index 5697cee..54e14d3 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 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
@@ -12,41 +12,82 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.Hashtable;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.util.Util;
 
 public class ClasspathJar extends ClasspathLocation {
 	
-private File file;
-private ZipFile zipFile;
-private boolean closeZipFileAtEnd;
-private Hashtable packageCache;
+protected File file;
+protected ZipFile zipFile;
+protected boolean closeZipFileAtEnd;
+protected Hashtable packageCache;
+protected char[] normalizedPath;
 
-public ClasspathJar(File file) throws IOException {
-	this(file, true, null);
-}
-public ClasspathJar(File file, boolean closeZipFileAtEnd, AccessRuleSet accessRuleSet) {
-	super(accessRuleSet);
+public ClasspathJar(File file, boolean closeZipFileAtEnd, 
+		AccessRuleSet accessRuleSet, String destinationPath) {
+	super(accessRuleSet, destinationPath);
 	this.file = file;
 	this.closeZipFileAtEnd = closeZipFileAtEnd;
 }
-
 public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName) {
+	return findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, false);
+}
+public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly) {
 	if (!isPackage(qualifiedPackageName)) 
 		return null; // most common case
 
 	try {
 		ClassFileReader reader = ClassFileReader.read(this.zipFile, qualifiedBinaryFileName);
-		if (reader != null) return new NameEnvironmentAnswer(reader, 
-				fetchAccessRestriction(qualifiedBinaryFileName));
-	} catch (Exception e) {
+		if (reader != null)
+			return new NameEnvironmentAnswer(reader, fetchAccessRestriction(qualifiedBinaryFileName));
+	} catch(ClassFormatException e) {
 		// treat as if class file is missing
+	} catch (IOException e) {
+		// treat as if class file is missing
+	}
+	return null;
+}
+public char[][][] findTypeNames(String qualifiedPackageName) {
+	if (!isPackage(qualifiedPackageName)) 
+		return null; // most common case
+
+	ArrayList answers = new ArrayList();
+	nextEntry : for (Enumeration e = this.zipFile.entries(); e.hasMoreElements(); ) {
+		String fileName = ((ZipEntry) e.nextElement()).getName();
+
+		// add the package name & all of its parent packages
+		int last = fileName.lastIndexOf('/');
+		while (last > 0) {
+			// extract the package name
+			String packageName = fileName.substring(0, last);
+			if (!qualifiedPackageName.equals(packageName))
+				continue nextEntry;
+			int indexOfDot = fileName.lastIndexOf('.');
+			if (indexOfDot != -1) {
+				String typeName = fileName.substring(last + 1, indexOfDot);
+				char[] packageArray = packageName.toCharArray();
+				answers.add(
+					CharOperation.arrayConcat(
+						CharOperation.splitOn('/', packageArray),
+						typeName.toCharArray()));
+			}
+		}
+	}
+	int size = answers.size();
+	if (size != 0) {
+		char[][][] result = new char[size][][];
+		answers.toArray(result);
+		return null;
 	}
 	return null;
 }
@@ -58,7 +99,7 @@
 		return this.packageCache.containsKey(qualifiedPackageName);
 
 	this.packageCache = new Hashtable(41);
-	this.packageCache.put("", ""); //$NON-NLS-1$ //$NON-NLS-2$
+	this.packageCache.put(Util.EMPTY_STRING, Util.EMPTY_STRING);
 
 	nextEntry : for (Enumeration e = this.zipFile.entries(); e.hasMoreElements(); ) {
 		String fileName = ((ZipEntry) e.nextElement()).getName();
@@ -90,9 +131,15 @@
 public String toString() {
 	return "Classpath for jar file " + this.file.getPath(); //$NON-NLS-1$
 }
-public String normalizedPath(){
-	String rawName = this.file.getPath();
-	return rawName.substring(0, rawName.lastIndexOf('.'));
+public char[] normalizedPath() {
+	if (this.normalizedPath == null) {
+		char[] rawName = this.file.getPath().toCharArray();
+		if (File.separatorChar == '\\') {
+			CharOperation.replace(rawName, '\\', '/');
+		}
+		this.normalizedPath = CharOperation.subarray(rawName, 0, CharOperation.lastIndexOf('.', rawName));
+	}
+	return this.normalizedPath;
 }
 public String getPath(){
 	return this.file.getPath();
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathLocation.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathLocation.java
index a0219b7..5846ed0 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathLocation.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathLocation.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 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
@@ -10,6 +10,9 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.batch;
 
+import java.io.File;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
@@ -17,10 +20,26 @@
 public abstract class ClasspathLocation implements FileSystem.Classpath,
 		SuffixConstants {
 
-	private AccessRuleSet accessRuleSet;
+	public static final int SOURCE = 1;
+	public static final int BINARY = 2;
+	
+	public AccessRuleSet accessRuleSet;
 
-	public ClasspathLocation(AccessRuleSet accessRuleSet) {
+	public String destinationPath;
+		// destination path for compilation units that are reached through this
+		// classpath location; the coding is consistent with the one of
+		// Main.destinationPath:
+		// == null: unspecified, use whatever value is set by the enclosing 
+		//          context, id est Main;
+		// == Main.NONE: absorbent element, do not output class files;
+		// else: use as the path of the directory into which class files must
+		//       be written.
+		// potentially carried by any entry that contains to be compiled files 
+		
+	protected ClasspathLocation(AccessRuleSet accessRuleSet, 
+			String destinationPath) {
 		this.accessRuleSet = accessRuleSet;
+		this.destinationPath = destinationPath;
 	}
 
 	/**
@@ -29,16 +48,21 @@
 	 * 
 	 * @param qualifiedBinaryFileName
 	 *            tested type specification, formed as:
-	 *            "org/eclipse/jdt/core/JavaCore.class"
+	 *            "org/eclipse/jdt/core/JavaCore.class"; on systems that
+	 *            use \ as File.separator, the 
+	 *            "org\eclipse\jdt\core\JavaCore.class" is accepted as well
 	 * @return the first access rule which is violated when accessing a given
 	 *         type, or null if none applies
 	 */
-	AccessRestriction fetchAccessRestriction(String qualifiedBinaryFileName) {
+	protected AccessRestriction fetchAccessRestriction(String qualifiedBinaryFileName) {
 		if (this.accessRuleSet == null)
 			return null;
-		return this.accessRuleSet
-					.getViolatedRestriction(
-						qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - SUFFIX_CLASS.length)
-						.toCharArray());
+		char [] qualifiedTypeName = qualifiedBinaryFileName.
+			substring(0, qualifiedBinaryFileName.length() - SUFFIX_CLASS.length)
+			.toCharArray(); 
+		if (File.separatorChar == '\\') {
+			CharOperation.replace(qualifiedTypeName, File.separatorChar, '/');
+		}
+		return this.accessRuleSet.getViolatedRestriction(qualifiedTypeName);
 	}
 }
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathSourceJar.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathSourceJar.java
new file mode 100755
index 0000000..2aa2c9a
--- /dev/null
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathSourceJar.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 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.jdt.internal.compiler.batch;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.zip.ZipEntry;
+
+import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
+import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.util.Util;
+
+public class ClasspathSourceJar extends ClasspathJar {
+	private String encoding;
+
+	public ClasspathSourceJar(File file, boolean closeZipFileAtEnd, 
+			AccessRuleSet accessRuleSet, String encoding, 
+			String destinationPath) {
+		super(file, closeZipFileAtEnd, accessRuleSet, destinationPath);
+		this.encoding = encoding;
+	}
+
+	public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly) {
+		if (!isPackage(qualifiedPackageName)) 
+			return null; // most common case
+
+		ZipEntry sourceEntry = this.zipFile.getEntry(qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - 6)  + SUFFIX_STRING_java);
+		if (sourceEntry != null) {
+			try {
+				return new NameEnvironmentAnswer(
+						new CompilationUnit(
+								Util.getInputStreamAsCharArray(this.zipFile.getInputStream(sourceEntry),
+										-1, this.encoding),
+						qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - 6)  + SUFFIX_STRING_java, 
+						this.encoding, this.destinationPath),
+						fetchAccessRestriction(qualifiedBinaryFileName));
+			} catch (IOException e) {
+				// treat as if source file is missing
+			}
+		}
+		return null;
+	}
+	public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName) {
+		return findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, false);
+	}
+}
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/CompilationUnit.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/CompilationUnit.java
index 09de7ba..092ac9c 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/CompilationUnit.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/CompilationUnit.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 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
@@ -15,6 +15,7 @@
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.jdt.internal.compiler.problem.AbortCompilationUnit;
 import org.eclipse.jdt.internal.compiler.util.Util;
 
 public class CompilationUnit implements ICompilationUnit {
@@ -22,31 +23,44 @@
 	public char[] fileName;
 	public char[] mainTypeName;
 	String encoding;
-	
+	public String destinationPath;
+		// a specific destination path for this compilation unit; coding is
+		// aligned with Main.destinationPath:
+		// == null: unspecified, use whatever value is set by the enclosing 
+		//          context, id est Main;
+		// == Main.NONE: absorbent element, do not output class files;
+		// else: use as the path of the directory into which class files must
+		//       be written.
+
 public CompilationUnit(char[] contents, String fileName, String encoding) {
+	this(contents, fileName, encoding, null);
+}
+public CompilationUnit(char[] contents, String fileName, String encoding,
+		String destinationPath) {
 	this.contents = contents;
-	if (File.separator.equals("/")) { //$NON-NLS-1$
-		if (fileName.indexOf("\\") != -1) { //$NON-NLS-1$
-			fileName = fileName.replace('\\', File.separatorChar);
-		}
-	} else {
-		// the file separator is \
-		if (fileName.indexOf('/') != -1) {
-			fileName = fileName.replace('/', File.separatorChar);
-		}
+	char[] fileNameCharArray = fileName.toCharArray();
+	switch(File.separatorChar) {
+		case '/' :
+			if (CharOperation.indexOf('\\', fileNameCharArray) != -1) {
+				CharOperation.replace(fileNameCharArray, '\\', '/');
+			}
+			break;
+		case '\\' :
+			if (CharOperation.indexOf('/', fileNameCharArray) != -1) {
+				CharOperation.replace(fileNameCharArray, '/', '\\');
+			}
 	}
-	this.fileName = fileName.toCharArray();
+	this.fileName = fileNameCharArray;
+	int start = CharOperation.lastIndexOf(File.separatorChar, fileNameCharArray) + 1; 
 
-	int start = fileName.lastIndexOf("/") + 1; //$NON-NLS-1$
-	if (start == 0 || start < fileName.lastIndexOf("\\")) //$NON-NLS-1$
-		start = fileName.lastIndexOf("\\") + 1; //$NON-NLS-1$
+	int end = CharOperation.lastIndexOf('.', fileNameCharArray);
+	if (end == -1) {
+		end = fileNameCharArray.length;
+	}
 
-	int end = fileName.lastIndexOf("."); //$NON-NLS-1$
-	if (end == -1)
-		end = fileName.length();
-
-	this.mainTypeName = fileName.substring(start, end).toCharArray();
+	this.mainTypeName = CharOperation.subarray(fileNameCharArray, start, end);
 	this.encoding = encoding;
+	this.destinationPath = destinationPath;
 }
 public char[] getContents() {
 	if (this.contents != null)
@@ -56,9 +70,9 @@
 	try {
 		return Util.getFileCharContent(new File(new String(this.fileName)), this.encoding);
 	} catch (IOException e) {
-		// assume no content then
+		this.contents = CharOperation.NO_CHAR; // assume no source if asked again
+		throw new AbortCompilationUnit(null, e, this.encoding);
 	}
-	return CharOperation.NO_CHAR;
 }
 /**
  * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName()
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileFinder.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileFinder.java
index 7293c7f..bed8d73 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileFinder.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileFinder.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 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
@@ -11,35 +11,28 @@
 package org.eclipse.jdt.internal.compiler.batch;
 
 import java.io.File;
+import java.util.ArrayList;
 
 public class FileFinder {
-	private static final int INITIAL_SIZE = 10;
-	public String[] resultFiles = new String[INITIAL_SIZE];
-	public int count = 0;
-public void find(File f, String pattern, boolean verbose) {
-	if (verbose) {
-		System.out.println(Main.bind("scanning.start",f.getAbsolutePath())); //$NON-NLS-1$
-	}
-	find0(f, pattern, verbose);
-	System.arraycopy(this.resultFiles, 0, (this.resultFiles = new String[this.count]), 0, this.count);
+	
+public static String[] find(File f, String pattern) {
+	ArrayList files = new ArrayList();
+	find0(f, pattern, files);
+	String[] result = new String[files.size()];
+	files.toArray(result);
+	return result;
 }
-public void find0(File f, String pattern, boolean verbose) {
+private static void find0(File f, String pattern, ArrayList collector) {
 	if (f.isDirectory()) {
 		String[] files = f.list();
 		if (files == null) return;
 		for (int i = 0, max = files.length; i < max; i++) {
 			File current = new File(f, files[i]);
 			if (current.isDirectory()) {
-				find0(current, pattern, verbose);
+				find0(current, pattern, collector);
 			} else {
 				if (current.getName().toUpperCase().endsWith(pattern)) {
-					int length;
-					if ((length = this.resultFiles.length) == this.count) {
-						System.arraycopy(this.resultFiles, 0, (this.resultFiles = new String[length * 2]), 0, length);
-					}
-					this.resultFiles[this.count++] = current.getAbsolutePath();
-					if (verbose && (this.count % 100) == 0)
-						System.out.print('.');
+					collector.add(current.getAbsolutePath());
 				}
 			}
 		}
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java
index 81cef77..68544f8 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 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
@@ -12,20 +12,24 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.compiler.util.Util;
 
 public class FileSystem implements INameEnvironment, SuffixConstants {
-	Classpath[] classpaths;
-	String[] knownFileNames;
-
-	interface Classpath {
+	public interface Classpath {
+		char[][][] findTypeNames(String qualifiedPackageName);
 		NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName);
-		boolean isPackage(String qualifiedPackageName); 
+		NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly);
+		boolean isPackage(String qualifiedPackageName);
 		/**
 		 * This method resets the environment. The resulting state is equivalent to
 		 * a new name environment without creating a new object.
@@ -37,10 +41,10 @@
 		 * (resp. '.zip') extension for jar (resp. zip) files.
 		 * @return a normalized path for file based classpath entries
 		 */
-		String normalizedPath();
+		char[] normalizedPath();
 		/**
 		 * Return the path for file based classpath entries. This is an absolute path
-		 * ending with a file separator for directories, an absolute path including from the '.jar'
+		 * ending with a file separator for directories, an absolute path including the '.jar'
 		 * (resp. '.zip') extension for jar (resp. zip) files.
 		 * @return the path for file based classpath entries
 		 */
@@ -50,22 +54,48 @@
 		 */
 		void initialize() throws IOException;
 	}
+
+	/**
+	 * This class is defined how to normalize the classpath entries.
+	 * It removes duplicate entries.
+	 */
+	public static class ClasspathNormalizer {
+		/**
+		 * Returns the normalized classpath entries (no duplicate).
+		 * <p>The given classpath entries are FileSystem.Classpath. We check the getPath() in order to find
+		 * duplicate entries.</p>
+		 *
+		 * @param classpaths the given classpath entries
+		 * @return the normalized classpath entries
+		 */
+		public static ArrayList normalize(ArrayList classpaths) {
+			ArrayList normalizedClasspath = new ArrayList();
+			HashSet cache = new HashSet();
+			for (Iterator iterator = classpaths.iterator(); iterator.hasNext(); ) {
+				FileSystem.Classpath classpath = (FileSystem.Classpath) iterator.next();
+				String path = classpath.getPath();
+				if (!cache.contains(path)) {
+					normalizedClasspath.add(classpath);
+					cache.add(path);
+				}
+			}
+			return normalizedClasspath;
+		}
+	}
+
+	Classpath[] classpaths;
+	Set knownFileNames;
+
 /*
 	classPathNames is a collection is Strings representing the full path of each class path
 	initialFileNames is a collection is Strings, the trailing '.java' will be removed if its not already.
 */
-
 public FileSystem(String[] classpathNames, String[] initialFileNames, String encoding) {
-	this(classpathNames, initialFileNames, encoding, null);
-}
-public FileSystem(String[] classpathNames, String[] initialFileNames, String encoding, int[] classpathDirectoryModes) {
 	final int classpathSize = classpathNames.length;
 	this.classpaths = new Classpath[classpathSize];
 	int counter = 0;
 	for (int i = 0; i < classpathSize; i++) {
-		Classpath classpath = getClasspath(classpathNames[i], encoding,
-					classpathDirectoryModes == null ? 0
-							: classpathDirectoryModes[i], null);
+		Classpath classpath = getClasspath(classpathNames[i], encoding, null);
 		try {
 			classpath.initialize();
 			this.classpaths[counter++] = classpath;
@@ -97,46 +127,70 @@
 	}
 	initializeKnownFileNames(initialFileNames);
 }
-static Classpath getClasspath(String classpathName, String encoding,
-		int classpathDirectoryMode, AccessRuleSet accessRuleSet) {
+public static Classpath getClasspath(String classpathName, String encoding, AccessRuleSet accessRuleSet) {
+	return getClasspath(classpathName, encoding, false, accessRuleSet, null);
+}
+public static Classpath getClasspath(String classpathName, String encoding,
+		boolean isSourceOnly, AccessRuleSet accessRuleSet,
+		String destinationPath) {
 	Classpath result = null;
 	File file = new File(convertPathSeparators(classpathName));
 	if (file.isDirectory()) {
 		if (file.exists()) {
 			result = new ClasspathDirectory(file, encoding,
-					classpathDirectoryMode, accessRuleSet);
+					isSourceOnly ? ClasspathLocation.SOURCE :
+						ClasspathLocation.SOURCE | ClasspathLocation.BINARY,
+					accessRuleSet,
+					destinationPath == null || destinationPath == Main.NONE ?
+						destinationPath : // keep == comparison valid
+						convertPathSeparators(destinationPath));
 		}
 	} else {
 		String lowercaseClasspathName = classpathName.toLowerCase();
 		if (lowercaseClasspathName.endsWith(SUFFIX_STRING_jar)
 				|| lowercaseClasspathName.endsWith(SUFFIX_STRING_zip)) {
-			result = new ClasspathJar(file, true, accessRuleSet);
-			// will throw an IOException if file does not exist
+			if (isSourceOnly) {
+				// source only mode
+				result = new ClasspathSourceJar(file, true, accessRuleSet,
+					encoding,
+					destinationPath == null || destinationPath == Main.NONE ?
+						destinationPath : // keep == comparison valid
+						convertPathSeparators(destinationPath));
+			} else if (destinationPath == null) {
+				// class file only mode
+				result = new ClasspathJar(file, true, accessRuleSet, null);
+			}
 		}
 	}
 	return result;
 }
 private void initializeKnownFileNames(String[] initialFileNames) {
-	this.knownFileNames = new String[initialFileNames.length];
+	if (initialFileNames == null) {
+		this.knownFileNames = new HashSet(0);
+		return;
+	}
+	this.knownFileNames = new HashSet(initialFileNames.length * 2);
 	for (int i = initialFileNames.length; --i >= 0;) {
-		String fileName = initialFileNames[i];
-		String matchingPathName = null;
-		if (fileName.lastIndexOf(".") != -1) //$NON-NLS-1$
-			fileName = fileName.substring(0, fileName.lastIndexOf('.')); // remove trailing ".java"
-
-		fileName = convertPathSeparators(fileName);
+		char[] fileName = initialFileNames[i].toCharArray();
+		char[] matchingPathName = null;
+		final int lastIndexOf = CharOperation.lastIndexOf('.', fileName);
+		if (lastIndexOf != -1) {
+			fileName = CharOperation.subarray(fileName, 0, lastIndexOf);
+		}
+		CharOperation.replace(fileName, '\\', '/');
 		for (int j = 0; j < classpaths.length; j++){
-			String matchCandidate = this.classpaths[j].normalizedPath();
-			if (this.classpaths[j] instanceof  ClasspathDirectory && 
-					fileName.startsWith(matchCandidate) && 
-					(matchingPathName == null || 
-							matchCandidate.length() < matchingPathName.length()))
+			char[] matchCandidate = this.classpaths[j].normalizedPath();
+			if (this.classpaths[j] instanceof  ClasspathDirectory &&
+					CharOperation.prefixEquals(matchCandidate, fileName) &&
+					(matchingPathName == null ||
+							matchCandidate.length < matchingPathName.length))
 				matchingPathName = matchCandidate;
 		}
-		if (matchingPathName == null)
-			this.knownFileNames[i] = fileName; // leave as is...
-		else
-			this.knownFileNames[i] = fileName.substring(matchingPathName.length());
+		if (matchingPathName == null) {
+			this.knownFileNames.add(new String(fileName)); // leave as is...
+		} else {
+			this.knownFileNames.add(new String(CharOperation.subarray(fileName, matchingPathName.length, fileName.length)));
+		}
 		matchingPathName = null;
 	}
 }
@@ -149,51 +203,116 @@
 		? path.replace('\\', '/')
 		 : path.replace('/', '\\');
 }
-private NameEnvironmentAnswer findClass(String qualifiedTypeName, char[] typeName){
-	for (int i = 0, length = this.knownFileNames.length; i < length; i++)
-		if (qualifiedTypeName.equals(this.knownFileNames[i]))
-			return null; // looking for a file which we know was provided at the beginning of the compilation
+private NameEnvironmentAnswer findClass(String qualifiedTypeName, char[] typeName, boolean asBinaryOnly){
+	if (this.knownFileNames.contains(qualifiedTypeName)) return null; // looking for a file which we know was provided at the beginning of the compilation
 
 	String qualifiedBinaryFileName = qualifiedTypeName + SUFFIX_STRING_class;
 	String qualifiedPackageName =
 		qualifiedTypeName.length() == typeName.length
-			? "" //$NON-NLS-1$
+			? Util.EMPTY_STRING
 			: qualifiedBinaryFileName.substring(0, qualifiedTypeName.length() - typeName.length - 1);
 	String qp2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar);
+	NameEnvironmentAnswer suggestedAnswer = null;
 	if (qualifiedPackageName == qp2) {
 		for (int i = 0, length = this.classpaths.length; i < length; i++) {
-			NameEnvironmentAnswer answer = this.classpaths[i].findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName);
-			if (answer != null) return answer;
+			NameEnvironmentAnswer answer = this.classpaths[i].findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, asBinaryOnly);
+			if (answer != null) {
+				if (!answer.ignoreIfBetter()) {
+					if (answer.isBetter(suggestedAnswer))
+						return answer;
+				} else if (answer.isBetter(suggestedAnswer))
+					// remember suggestion and keep looking
+					suggestedAnswer = answer;
+			}
 		}
 	} else {
 		String qb2 = qualifiedBinaryFileName.replace('/', File.separatorChar);
 		for (int i = 0, length = this.classpaths.length; i < length; i++) {
 			Classpath p = this.classpaths[i];
 			NameEnvironmentAnswer answer = (p instanceof ClasspathJar)
-				? p.findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName)
-				: p.findClass(typeName, qp2, qb2);
-			if (answer != null) return answer;
+				? p.findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, asBinaryOnly)
+				: p.findClass(typeName, qp2, qb2, asBinaryOnly);
+			if (answer != null) {
+				if (!answer.ignoreIfBetter()) {
+					if (answer.isBetter(suggestedAnswer))
+						return answer;
+				} else if (answer.isBetter(suggestedAnswer))
+					// remember suggestion and keep looking
+					suggestedAnswer = answer;
+			}
 		}
 	}
+	if (suggestedAnswer != null)
+		// no better answer was found
+		return suggestedAnswer;
 	return null;
 }
 public NameEnvironmentAnswer findType(char[][] compoundName) {
 	if (compoundName != null)
 		return findClass(
 			new String(CharOperation.concatWith(compoundName, '/')),
-			compoundName[compoundName.length - 1]);
+			compoundName[compoundName.length - 1],
+			false);
+	return null;
+}
+public char[][][] findTypeNames(char[][] packageName) {
+	char[][][] result = null;
+	if (packageName != null) {
+		String qualifiedPackageName = new String(CharOperation.concatWith(packageName, '/'));
+		String qualifiedPackageName2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar);
+		if (qualifiedPackageName == qualifiedPackageName2) {
+			for (int i = 0, length = this.classpaths.length; i < length; i++) {
+				char[][][] answers = this.classpaths[i].findTypeNames(qualifiedPackageName);
+				if (answers != null) {
+					// concat with previous answers
+					if (result == null) {
+						result = answers;
+					} else {
+						int resultLength = result.length;
+						int answersLength = answers.length;
+						System.arraycopy(result, 0, (result = new char[answersLength + resultLength][][]), 0, resultLength);
+						System.arraycopy(answers, 0, result, resultLength, answersLength);
+					}
+				}
+			}
+		} else {
+			for (int i = 0, length = this.classpaths.length; i < length; i++) {
+				Classpath p = this.classpaths[i];
+				char[][][] answers = (p instanceof ClasspathJar)
+					? p.findTypeNames(qualifiedPackageName)
+					: p.findTypeNames(qualifiedPackageName2);
+				if (answers != null) {
+					// concat with previous answers
+					if (result == null) {
+						result = answers;
+					} else {
+						int resultLength = result.length;
+						int answersLength = answers.length;
+						System.arraycopy(result, 0, (result = new char[answersLength + resultLength][][]), 0, resultLength);
+						System.arraycopy(answers, 0, result, resultLength, answersLength);
+					}
+				}
+			}
+		}
+	}
+	return result;
+}
+public NameEnvironmentAnswer findType(char[][] compoundName, boolean asBinaryOnly) {
+	if (compoundName != null)
+		return findClass(
+			new String(CharOperation.concatWith(compoundName, '/')),
+			compoundName[compoundName.length - 1],
+			asBinaryOnly);
 	return null;
 }
 public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) {
 	if (typeName != null)
 		return findClass(
 			new String(CharOperation.concatWith(packageName, typeName, '/')),
-			typeName);
+			typeName,
+			false);
 	return null;
 }
-public ClasspathJar getClasspathJar(File file) throws IOException {
-	return new ClasspathJar(file, true, null);
-}
 public boolean isPackage(char[][] compoundName, char[] packageName) {
 	String qualifiedPackageName = new String(CharOperation.concatWith(compoundName, packageName, '/'));
 	String qp2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar);
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
index 87588d8..fd18dbc 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 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
@@ -7,6 +7,8 @@
  *
  * Contributors:
  *     IBM Corporation - initial API and implementation
+ *     Tom Tromey - Contribution for bug 125961
+ *     Tom Tromey - Contribution for bug 159641
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.batch;
 
@@ -20,15 +22,15 @@
 import java.io.LineNumberReader;
 import java.io.PrintWriter;
 import java.io.StringReader;
+import java.io.StringWriter;
 import java.io.UnsupportedEncodingException;
 import java.lang.reflect.Field;
+import java.text.DateFormat;
 import java.text.MessageFormat;
-import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
+import java.util.Comparator;
 import java.util.Date;
-import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Locale;
@@ -38,49 +40,73 @@
 import java.util.Set;
 import java.util.StringTokenizer;
 
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.compiler.InvalidInputException;
 import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.AbstractAnnotationProcessorManager;
 import org.eclipse.jdt.internal.compiler.ClassFile;
 import org.eclipse.jdt.internal.compiler.CompilationResult;
 import org.eclipse.jdt.internal.compiler.Compiler;
 import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
 import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
 import org.eclipse.jdt.internal.compiler.IProblemFactory;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.env.AccessRule;
 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
-import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
-import org.eclipse.jdt.internal.compiler.problem.DefaultProblem;
+import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
+import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
+import org.eclipse.jdt.internal.compiler.util.GenericXMLWriter;
+import org.eclipse.jdt.internal.compiler.util.HashtableOfInt;
 import org.eclipse.jdt.internal.compiler.util.Messages;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
 import org.eclipse.jdt.internal.compiler.util.Util;
 
 public class Main implements ProblemSeverities, SuffixConstants {
+	/**
+	 * Resource bundle factory to share bundles for the same locale
+	 */
+	public static class ResourceBundleFactory {
+		private static HashMap Cache = new HashMap();
+		public static synchronized ResourceBundle getBundle(Locale locale) {
+			ResourceBundle bundle = (ResourceBundle) Cache.get(locale);
+			if (bundle == null) {
+				bundle = ResourceBundle.getBundle(Main.bundleName, locale);
+				Cache.put(locale, bundle);
+			}
+			return bundle;
+		}
+	}
 
 	public static class Logger {
 		private static final String CLASS = "class"; //$NON-NLS-1$
 		private static final String CLASS_FILE = "classfile"; //$NON-NLS-1$
 		private static final String CLASSPATH = "classpath"; //$NON-NLS-1$
-		private static final String CLASSPATH_ID = "id"; //$NON-NLS-1$
 		private static final String CLASSPATH_FILE = "FILE"; //$NON-NLS-1$
 		private static final String CLASSPATH_FOLDER = "FOLDER"; //$NON-NLS-1$
+		private static final String CLASSPATH_ID = "id"; //$NON-NLS-1$
 		private static final String CLASSPATH_JAR = "JAR"; //$NON-NLS-1$
 		private static final String CLASSPATHS = "classpaths"; //$NON-NLS-1$
 		private static final String COMMAND_LINE_ARGUMENT = "argument"; //$NON-NLS-1$
 		private static final String COMMAND_LINE_ARGUMENTS = "command_line"; //$NON-NLS-1$
 		private static final String COMPILER = "compiler"; //$NON-NLS-1$
 		private static final String COMPILER_COPYRIGHT = "copyright"; //$NON-NLS-1$
-		private static final String COMPILER_VERSION = "version"; //$NON-NLS-1$
 		private static final String COMPILER_NAME = "name"; //$NON-NLS-1$
-		private static final String EXCEPTION = "exception"; //$NON-NLS-1$
+		private static final String COMPILER_VERSION = "version"; //$NON-NLS-1$
+		public static final int EMACS = 2;
 		private static final String ERROR = "ERROR"; //$NON-NLS-1$
 		private static final String ERROR_TAG = "error"; //$NON-NLS-1$
+		private static final String EXCEPTION = "exception"; //$NON-NLS-1$
+		private static final String EXTRA_PROBLEM_TAG = "extra_problem"; //$NON-NLS-1$
+		private static final String EXTRA_PROBLEMS = "extra_problems"; //$NON-NLS-1$
+		private static final HashtableOfInt FIELD_TABLE = new HashtableOfInt();
 		private static final String KEY = "key"; //$NON-NLS-1$
 		private static final String MESSAGE = "message"; //$NON-NLS-1$
 		private static final String NUMBER_OF_CLASSFILES = "number_of_classfiles"; //$NON-NLS-1$
@@ -91,16 +117,21 @@
 		private static final String NUMBER_OF_WARNINGS = "warnings"; //$NON-NLS-1$
 		private static final String OPTION = "option"; //$NON-NLS-1$
 		private static final String OPTIONS = "options"; //$NON-NLS-1$
+		private static final String OUTPUT = "output"; //$NON-NLS-1$
+		private static final String PACKAGE = "package"; //$NON-NLS-1$
 		private static final String PATH = "path"; //$NON-NLS-1$
 		private static final String PROBLEM_ARGUMENT = "argument"; //$NON-NLS-1$
 		private static final String PROBLEM_ARGUMENT_VALUE = "value"; //$NON-NLS-1$
 		private static final String PROBLEM_ARGUMENTS = "arguments"; //$NON-NLS-1$
-		private static final String PROBLEM_ID = "id"; //$NON-NLS-1$
+		private static final String PROBLEM_CATEGORY_ID = "categoryID"; //$NON-NLS-1$
+		private static final String ID = "id"; //$NON-NLS-1$
+		private static final String PROBLEM_ID = "problemID"; //$NON-NLS-1$
 		private static final String PROBLEM_LINE = "line"; //$NON-NLS-1$
+		private static final String PROBLEM_OPTION_KEY = "optionKey"; //$NON-NLS-1$
 		private static final String PROBLEM_MESSAGE = "message"; //$NON-NLS-1$
 		private static final String PROBLEM_SEVERITY = "severity"; //$NON-NLS-1$
-		private static final String PROBLEM_SOURCE_START = "charStart"; //$NON-NLS-1$
 		private static final String PROBLEM_SOURCE_END = "charEnd"; //$NON-NLS-1$
+		private static final String PROBLEM_SOURCE_START = "charStart"; //$NON-NLS-1$
 		private static final String PROBLEM_SUMMARY = "problem_summary"; //$NON-NLS-1$
 		private static final String PROBLEM_TAG = "problem"; //$NON-NLS-1$
 		private static final String PROBLEMS = "problems"; //$NON-NLS-1$
@@ -115,17 +146,20 @@
 		private static final String TIME = "time"; //$NON-NLS-1$
 		private static final String VALUE = "value"; //$NON-NLS-1$
 		private static final String WARNING = "WARNING"; //$NON-NLS-1$
-		private static final String XML_HEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; //$NON-NLS-1$
-		private static final String XML_DTD_DECLARATION = "<!DOCTYPE compiler SYSTEM \"compiler.dtd\">"; //$NON-NLS-1$
 
-		private static final HashMap FIELD_TABLE = new HashMap();
+		public static final int XML = 1;
+
+		private static final String XML_DTD_DECLARATION = "<!DOCTYPE compiler PUBLIC \"-//Eclipse.org//DTD Eclipse JDT 3.2.003 Compiler//EN\" \"http://www.eclipse.org/jdt/core/compiler_32_003.dtd\">"; //$NON-NLS-1$
 		static {
 			try {
 				Class c = IProblem.class;
 				Field[] fields = c.getFields();
 				for (int i = 0, max = fields.length; i < max; i++) {
 					Field field = fields[i];
-					FIELD_TABLE.put(field.get(null), field.getName());
+					if (field.getType().equals(Integer.TYPE)) {
+						Integer value = (Integer) field.get(null);
+						Logger.FIELD_TABLE.put(value.intValue() & IProblem.IgnoreCategoriesMask, field.getName());
+					}
 				}
 			} catch (SecurityException e) {
 				e.printStackTrace();
@@ -135,51 +169,17 @@
 				e.printStackTrace();
 			}
 		}
-		private static void appendEscapedChar(StringBuffer buffer, char c) {
-			String replacement= getReplacement(c);
-			if (replacement != null) {
-				buffer.append('&');
-				buffer.append(replacement);
-				buffer.append(';');
-			} else {
-				buffer.append(c);
-			}
-		}
-		private static String getEscaped(String s) {
-			StringBuffer result= new StringBuffer(s.length() + 10);
-			for (int i= 0; i < s.length(); ++i)
-				appendEscapedChar(result, s.charAt(i));
-			return result.toString();
-		}
-		private static String getReplacement(char c) {
-			// Encode special XML characters into the equivalent character references.
-			// These five are defined by default for all XML documents.
-			switch (c) {
-				case '<' :
-					return "lt"; //$NON-NLS-1$
-				case '>' :
-					return "gt"; //$NON-NLS-1$
-				case '"' :
-					return "quot"; //$NON-NLS-1$
-				case '\'' :
-					return "apos"; //$NON-NLS-1$
-				case '&' :
-					return "amp"; //$NON-NLS-1$
-			}
-			return null;
-		}
 		private PrintWriter err;
-		boolean isXml;
 		private PrintWriter log;
+		private Main main;
 		private PrintWriter out;
-		private int tab;
 		private HashMap parameters;
-
-		public Logger(PrintWriter out, PrintWriter err) {
+		int tagBits;
+		public Logger(Main main, PrintWriter out, PrintWriter err) {
 			this.out = out;
 			this.err = err;
-			this.isXml = false;
 			this.parameters = new HashMap();
+			this.main = main;
 		}
 
 		public String buildFileName(
@@ -187,7 +187,7 @@
 			String relativeFileName) {
 			char fileSeparatorChar = File.separatorChar;
 			String fileSeparator = File.separator;
-			
+
 			outputPath = outputPath.replace('/', fileSeparatorChar);
 			// To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
 			StringBuffer outDir = new StringBuffer(outputPath);
@@ -204,11 +204,11 @@
 			// token contains the last one
 			return outDir.append(token).toString();
 		}
-		
+
 		public void close() {
 			if (this.log != null) {
-				if (this.isXml) {
-					this.endTag(COMPILER);
+				if ((this.tagBits & Logger.XML) != 0) {
+					this.endTag(Logger.COMPILER);
 					this.flush();
 				}
 				this.log.close();
@@ -216,60 +216,75 @@
 		}
 
 		/**
-		 * 
+		 *
 		 */
 		public void compiling() {
-			this.printlnOut(Main.bind("progress.compiling")); //$NON-NLS-1$
+			this.printlnOut(this.main.bind("progress.compiling")); //$NON-NLS-1$
 		}
-		
+
 		/**
 		 * Used to stop logging problems.
 		 * Only use in xml mode.
 		 */
 		private void endLoggingProblems() {
-			this.endTag(PROBLEMS);
+			this.endTag(Logger.PROBLEMS);
+		}
+		private void endLoggingExtraProblems() {
+			this.endTag(Logger.EXTRA_PROBLEMS);
 		}
 		public void endLoggingSource() {
-			if (this.isXml) {
-				this.endTag(SOURCE);
+			if ((this.tagBits & Logger.XML) != 0) {
+				this.endTag(Logger.SOURCE);
 			}
 		}
+
 		public void endLoggingSources() {
-			if (this.isXml) {
-				this.endTag(SOURCES);
+			if ((this.tagBits & Logger.XML) != 0) {
+				this.endTag(Logger.SOURCES);
 			}
 		}
+
 		public void endLoggingTasks() {
-			if (this.isXml) {
-				this.endTag(TASKS);
+			if ((this.tagBits & Logger.XML) != 0) {
+				this.endTag(Logger.TASKS);
 			}
 		}
-		public void endTag(String name) {
-			tab--;
-			this.printTag('/' + name, null, true, false);
-			this.tab--;
+		private void endTag(String name) {
+			((GenericXMLWriter) this.log).endTag(name, true, true);
 		}
-		
-		private void extractContext(IProblem problem, char[] unitSource) {
+		private void extractContext(CategorizedProblem problem, char[] unitSource) {
 			//sanity .....
 			int startPosition = problem.getSourceStart();
 			int endPosition = problem.getSourceEnd();
+			if (unitSource == null) {
+				if (problem.getOriginatingFileName() != null) {
+					try {
+						unitSource = Util.getFileCharContent(new File(new String(problem.getOriginatingFileName())), null);
+					} catch(IOException e) {
+						// ignore
+					}
+				}
+			}
+			int length = unitSource== null ? 0 : unitSource.length;
 			if ((startPosition > endPosition)
-				|| ((startPosition < 0) && (endPosition < 0))) {
-				this.parameters.put(VALUE, Messages.problem_noSourceInformation); 
-				this.parameters.put(SOURCE_START, "-1"); //$NON-NLS-1$
-				this.parameters.put(SOURCE_END, "-1"); //$NON-NLS-1$
+					|| ((startPosition < 0) && (endPosition < 0))
+					|| (length <= 0)
+					|| (endPosition > length)) {
+				this.parameters.put(Logger.VALUE, Messages.problem_noSourceInformation);
+				this.parameters.put(Logger.SOURCE_START, "-1"); //$NON-NLS-1$
+				this.parameters.put(Logger.SOURCE_END, "-1"); //$NON-NLS-1$
+				this.printTag(Logger.SOURCE_CONTEXT, this.parameters, true, true);
 				return;
 			}
 
 			char c;
 			//the next code tries to underline the token.....
 			//it assumes (for a good display) that token source does not
-			//contain any \r \n. This is false on statements ! 
+			//contain any \r \n. This is false on statements !
 			//(the code still works but the display is not optimal !)
 
 			// expand to line limits
-			int length = unitSource.length, begin, end;
+			int begin, end;
 			for (begin = startPosition >= length ? length - 1 : startPosition; begin > 0; begin--) {
 				if ((c = unitSource[begin - 1]) == '\n' || c == '\r') break;
 			}
@@ -280,18 +295,15 @@
 			// trim left and right spaces/tabs
 			while ((c = unitSource[begin]) == ' ' || c == '\t') begin++;
 			while ((c = unitSource[end]) == ' ' || c == '\t') end--;
-			
+
 			// copy source
 			StringBuffer buffer = new StringBuffer();
 			buffer.append(unitSource, begin, end - begin + 1);
-			
-			this.parameters.put(VALUE, String.valueOf(buffer)); //$NON-NLS-1$
-			this.parameters.put(SOURCE_START, Integer.toString(startPosition - begin)); //$NON-NLS-1$
-			this.parameters.put(SOURCE_END, Integer.toString(endPosition - begin)); //$NON-NLS-1$
-		}
 
-		private String getFieldName(int id) {
-			return (String) FIELD_TABLE.get(new Integer(id));
+			this.parameters.put(Logger.VALUE, String.valueOf(buffer));
+			this.parameters.put(Logger.SOURCE_START, Integer.toString(startPosition - begin));
+			this.parameters.put(Logger.SOURCE_END, Integer.toString(endPosition - begin));
+			this.printTag(Logger.SOURCE_CONTEXT, this.parameters, true, true);
 		}
 
 		public void flush() {
@@ -301,6 +313,16 @@
 				this.log.flush();
 			}
 		}
+		private String getFieldName(int id) {
+			return (String) Logger.FIELD_TABLE.get(id & IProblem.IgnoreCategoriesMask);
+		}
+
+		// find out an option name controlling a given problemID
+		private String getProblemOptionKey(int problemID) {
+			long irritant = ProblemReporter.getIrritant(problemID);
+			return CompilerOptions.optionKeyFromIrritant(irritant);
+		}
+
 		public void logAverage(long[] times, long lineCount) {
 			Arrays.sort(times);
 			final int length = times.length;
@@ -309,48 +331,16 @@
 				sum += times[i];
 			}
 			long time = sum / (length - 2);
-			this.printlnOut(Main.bind(
+			this.printlnOut(this.main.bind(
 				"compile.averageTime", //$NON-NLS-1$
 				new String[] {
 					String.valueOf(lineCount),
 					String.valueOf(time),
 					String.valueOf(((int) (lineCount * 10000.0 / time)) / 10.0) }));
 		}
-		public void logClasspath(FileSystem.Classpath[] classpaths) {
-			if (classpaths == null) return;
-			if (this.isXml) {
-				final int length = classpaths.length;
-				if (length != 0) {
-					// generate xml output
-					this.printTag(CLASSPATHS, null, true, false);
-					for (int i = 0; i < length; i++) {
-						this.parameters.clear();
-						String classpath = classpaths[i].getPath();
-						parameters.put(PATH, classpath);
-						File f = new File(classpath);
-						String id = null;
-						if (f.isFile()) {
-							if (Util.isArchiveFileName(classpath)) {
-								id = CLASSPATH_JAR;
-							} else {
-								id = CLASSPATH_FILE;
-							}
-						} else if (f.isDirectory()) {
-							id = CLASSPATH_FOLDER;
-						}
-						if (id != null) {
-							this.parameters.put(CLASSPATH_ID, id);
-							this.printTag(CLASSPATH, parameters, true, true);
-						}
-					}
-					this.endTag(CLASSPATHS);
-				}
-			}
-			
-		}
 
 		public void logClassFile(boolean generatePackagesStructure, String outputPath, String relativeFileName) {
-			if (this.isXml) {
+			if ((this.tagBits & Logger.XML) != 0) {
 				String fileName = null;
 				if (generatePackagesStructure) {
 					fileName = buildFileName(outputPath, relativeFileName);
@@ -378,28 +368,56 @@
 				}
 				File f = new File(fileName);
 				try {
-					this.parameters.clear();
-					this.parameters.put(PATH, f.getCanonicalPath());
-					this.printTag(CLASS_FILE, this.parameters, true, true);
+					this.parameters.put(Logger.PATH, f.getCanonicalPath());
+					this.printTag(Logger.CLASS_FILE, this.parameters, true, true);
 				} catch (IOException e) {
-					this.logNoClassFileCreated(fileName);
+					this.logNoClassFileCreated(outputPath, relativeFileName, e);
 				}
-			}	
+			}
 		}
-		
+		public void logClasspath(FileSystem.Classpath[] classpaths) {
+			if (classpaths == null) return;
+			if ((this.tagBits & Logger.XML) != 0) {
+				final int length = classpaths.length;
+				if (length != 0) {
+					// generate xml output
+					this.printTag(Logger.CLASSPATHS, null, true, false);
+					for (int i = 0; i < length; i++) {
+						String classpath = classpaths[i].getPath();
+						this.parameters.put(Logger.PATH, classpath);
+						File f = new File(classpath);
+						String id = null;
+						if (f.isFile()) {
+							if (Util.isArchiveFileName(classpath)) {
+								id = Logger.CLASSPATH_JAR;
+							} else {
+								id = Logger.CLASSPATH_FILE;
+							}
+						} else if (f.isDirectory()) {
+							id = Logger.CLASSPATH_FOLDER;
+						}
+						if (id != null) {
+							this.parameters.put(Logger.CLASSPATH_ID, id);
+							this.printTag(Logger.CLASSPATH, this.parameters, true, true);
+						}
+					}
+					this.endTag(Logger.CLASSPATHS);
+				}
+			}
+
+		}
 		public void logCommandLineArguments(String[] commandLineArguments) {
 			if (commandLineArguments == null) return;
-			if (this.isXml) {
+			if ((this.tagBits & Logger.XML) != 0) {
 				final int length = commandLineArguments.length;
 				if (length != 0) {
 					// generate xml output
-					this.printTag(COMMAND_LINE_ARGUMENTS, null, true, false);
-					parameters.clear();
+					this.printTag(Logger.COMMAND_LINE_ARGUMENTS, null, true, false);
 					for (int i = 0; i < length; i++) {
-						parameters.put(VALUE, commandLineArguments[i]);
-						this.printTag(COMMAND_LINE_ARGUMENT, parameters, true, true);
+						this.parameters.put(Logger.VALUE, commandLineArguments[i]);
+						this.printTag(Logger.COMMAND_LINE_ARGUMENT, this.parameters, true, true);
 					}
-					this.endTag(COMMAND_LINE_ARGUMENTS);
+					this.endTag(Logger.COMMAND_LINE_ARGUMENTS);
 				}
 			}
 		}
@@ -408,14 +426,41 @@
 		 * @param e the given exception to log
 		 */
 		public void logException(Exception e) {
-			final String message = e.getMessage();
-			if (isXml) {
-				parameters.clear();
-				parameters.put(MESSAGE, message);
-				parameters.put(CLASS, e.getClass());
-				this.printTag(EXCEPTION, parameters, true, true);
+			StringWriter writer = new StringWriter();
+			PrintWriter printWriter = new PrintWriter(writer);
+			e.printStackTrace(printWriter);
+			printWriter.flush();
+			printWriter.close();
+			final String stackTrace = writer.getBuffer().toString();
+			if ((this.tagBits & Logger.XML) != 0) {
+				LineNumberReader reader = new LineNumberReader(new StringReader(stackTrace));
+				String line;
+				int i = 0;
+				StringBuffer buffer = new StringBuffer();
+				String message = e.getMessage();
+				if (message != null) {
+					buffer.append(message).append(Util.LINE_SEPARATOR);
+				}
+				try {
+					while ((line = reader.readLine()) != null && i < 4) {
+						buffer.append(line).append(Util.LINE_SEPARATOR);
+						i++;
+					}
+					reader.close();
+				} catch (IOException e1) {
+					// ignore
+				}
+				message = buffer.toString();
+				this.parameters.put(Logger.MESSAGE, message);
+				this.parameters.put(Logger.CLASS, e.getClass());
+				this.printTag(Logger.EXCEPTION, this.parameters, true, true);
 			}
-			this.printlnErr(message);
+			String message = e.getMessage();
+			if (message == null) {
+				this.printlnErr(stackTrace);
+			} else {
+				this.printlnErr(message);
+			}
 		}
 
 		/**
@@ -423,49 +468,89 @@
 		 *            the given wrong classpath entry
 		 */
 		public void logIncorrectClasspath(String wrongClasspath) {
-			if (isXml) {
-				this.parameters.clear();
-				this.parameters.put(MESSAGE, Main.bind("configure.incorrectClasspath", wrongClasspath)); //$NON-NLS-1$
-				this.printTag(ERROR_TAG, this.parameters, true, true);
+			if ((this.tagBits & Logger.XML) != 0) {
+				this.parameters.put(Logger.MESSAGE, this.main.bind("configure.incorrectClasspath", wrongClasspath)); //$NON-NLS-1$
+				this.printTag(Logger.ERROR_TAG, this.parameters, true, true);
 			}
-			this.printlnErr(Main.bind(
+			this.printlnErr(this.main.bind(
 				"configure.incorrectClasspath", wrongClasspath)); //$NON-NLS-1$
 		}
 
 		/**
-		 * 
+		 * @param wrongPath
+		 *            the given wrong path entry
 		 */
-		public void logNoClassFileCreated(String fileName) {
-			if (isXml) {
-				this.parameters.clear();
-				this.parameters.put(MESSAGE, Main.bind("output.noClassFileCreated", fileName)); //$NON-NLS-1$
-				this.printTag(ERROR_TAG, this.parameters, true, true);
+		public void logIncorrectEndorsedDirsEntry(String wrongPath) {
+			if ((this.tagBits & Logger.XML) != 0) {
+				this.parameters.put(Logger.MESSAGE, this.main.bind("configure.incorrectEndorsedDirsEntry", wrongPath)); //$NON-NLS-1$
+				this.printTag(Logger.ERROR_TAG, this.parameters, true, true);
 			}
-			this.printlnErr(Main.bind("output.noClassFileCreated", fileName)); //$NON-NLS-1$
+			this.printlnErr(this.main.bind(
+				"configure.incorrectEndorsedDirsEntry", wrongPath)); //$NON-NLS-1$
+		}
+
+		/**
+		 * @param wrongPath
+		 *            the given wrong path entry
+		 */
+		public void logIncorrectExtDirsEntry(String wrongPath) {
+			if ((this.tagBits & Logger.XML) != 0) {
+				this.parameters.put(Logger.MESSAGE, this.main.bind("configure.incorrectExtDirsEntry", wrongPath)); //$NON-NLS-1$
+				this.printTag(Logger.ERROR_TAG, this.parameters, true, true);
+			}
+			this.printlnErr(this.main.bind(
+				"configure.incorrectExtDirsEntry", wrongPath)); //$NON-NLS-1$
+		}
+
+		public void logIncorrectVMVersionForAnnotationProcessing() {
+			if ((this.tagBits & Logger.XML) != 0) {
+				this.parameters.put(Logger.MESSAGE, this.main.bind("configure.incorrectVMVersionforAPT")); //$NON-NLS-1$
+				this.printTag(Logger.ERROR_TAG, this.parameters, true, true);
+			}
+			this.printlnErr(this.main.bind("configure.incorrectVMVersionforAPT")); //$NON-NLS-1$
+		}
+
+		/**
+		 *
+		 */
+		public void logNoClassFileCreated(String outputDir, String relativeFileName, IOException e) {
+			if ((this.tagBits & Logger.XML) != 0) {
+				this.parameters.put(Logger.MESSAGE, this.main.bind("output.noClassFileCreated", //$NON-NLS-1$
+					new String[] {
+						outputDir,
+						relativeFileName,
+						e.getMessage()
+					}));
+				this.printTag(Logger.ERROR_TAG, this.parameters, true, true);
+			}
+			this.printlnErr(this.main.bind("output.noClassFileCreated", //$NON-NLS-1$
+				new String[] {
+					outputDir,
+					relativeFileName,
+					e.getMessage()
+				}));
 		}
 
 		public void logNoClasspath() {
-			if (isXml) {
-				this.parameters.clear();
-				this.parameters.put(MESSAGE, Main.bind("configure.noClasspath")); //$NON-NLS-1$//$NON-NLS-2$
-				this.printTag(ERROR_TAG, this.parameters, true, true);
+			if ((this.tagBits & Logger.XML) != 0) {
+				this.parameters.put(Logger.MESSAGE, this.main.bind("configure.noClasspath")); //$NON-NLS-1$
+				this.printTag(Logger.ERROR_TAG, this.parameters, true, true);
 			}
-			this.printlnErr(Main.bind("configure.noClasspath")); //$NON-NLS-1$
+			this.printlnErr(this.main.bind("configure.noClasspath")); //$NON-NLS-1$
 		}
 
 		/**
 		 * @param exportedClassFilesCounter
 		 */
 		public void logNumberOfClassFilesGenerated(int exportedClassFilesCounter) {
-			if (isXml) {
-				this.parameters.clear();
-				this.parameters.put(VALUE, new Integer(exportedClassFilesCounter)); //$NON-NLS-1$
-				this.printTag(NUMBER_OF_CLASSFILES, this.parameters, true, true);
+			if ((this.tagBits & Logger.XML) != 0) {
+				this.parameters.put(Logger.VALUE, new Integer(exportedClassFilesCounter));
+				this.printTag(Logger.NUMBER_OF_CLASSFILES, this.parameters, true, true);
 			}
 			if (exportedClassFilesCounter == 1) {
-				this.printlnOut(Main.bind("compile.oneClassFileGenerated")); //$NON-NLS-1$
+				this.printlnOut(this.main.bind("compile.oneClassFileGenerated")); //$NON-NLS-1$
 			} else {
-				this.printlnOut(Main.bind("compile.severalClassFilesGenerated", //$NON-NLS-1$
+				this.printlnOut(this.main.bind("compile.severalClassFilesGenerated", //$NON-NLS-1$
 					String.valueOf(exportedClassFilesCounter)));
 			}
 		}
@@ -474,142 +559,98 @@
 		 * @param options the given compiler options
 		 */
 		public void logOptions(Map options) {
-			if (this.isXml) {
-				this.printTag(OPTIONS, null, true, false);
-				final Set keySet = options.keySet();
-				Object[] keys = keySet.toArray();
-				Arrays.sort(keys);
-				for (int i = 0, max = keys.length; i < max; i++) {
-					this.parameters.clear();
-					Object key = keys[i];
-					this.parameters.put(KEY, key);
-					this.parameters.put(VALUE, options.get(key));
-					this.printTag(OPTION, this.parameters, true, true);
+			if ((this.tagBits & Logger.XML) != 0) {
+				this.printTag(Logger.OPTIONS, null, true, false);
+				final Set entriesSet = options.entrySet();
+				Object[] entries = entriesSet.toArray();
+				Arrays.sort(entries, new Comparator() {
+					public int compare(Object o1, Object o2) {
+						Map.Entry entry1 = (Map.Entry) o1;
+						Map.Entry entry2 = (Map.Entry) o2;
+						return ((String) entry1.getKey()).compareTo((String) entry2.getKey());
+					}
+				});
+				for (int i = 0, max = entries.length; i < max; i++) {
+					Map.Entry entry = (Map.Entry) entries[i];
+					String key = (String) entry.getKey();
+					this.parameters.put(Logger.KEY, key);
+					this.parameters.put(Logger.VALUE, entry.getValue());
+					this.printTag(Logger.OPTION, this.parameters, true, true);
 				}
-				this.endTag(OPTIONS);
+				this.endTag(Logger.OPTIONS);
 			}
 		}
 
-		private void logProblem(IProblem problem, int localErrorCount,
+		private void logProblem(CategorizedProblem problem, int localErrorCount,
 			int globalErrorCount, char[] unitSource) {
-			if (localErrorCount == 0) {
+			if ((this.tagBits & Logger.EMACS) != 0) {
+				String result = (new String(problem.getOriginatingFileName())
+						+ ":" //$NON-NLS-1$
+						+ problem.getSourceLineNumber()
+						+ ": " //$NON-NLS-1$
+						+ (problem.isError() ? this.main.bind("output.emacs.error") : this.main.bind("output.emacs.warning")) //$NON-NLS-1$ //$NON-NLS-2$
+						+ ": " //$NON-NLS-1$
+						+ problem.getMessage());
+				this.printlnErr(result);
+				final String errorReportSource = errorReportSource(problem, unitSource, this.tagBits);
+				if (errorReportSource.length() != 0) this.printlnErr(errorReportSource);
+			} else {
+				if (localErrorCount == 0) {
+					this.printlnErr("----------"); //$NON-NLS-1$
+				}
+				this.printErr(problem.isError() ?
+						this.main.bind(
+								"requestor.error", //$NON-NLS-1$
+								Integer.toString(globalErrorCount),
+								new String(problem.getOriginatingFileName()))
+								: this.main.bind(
+										"requestor.warning", //$NON-NLS-1$
+										Integer.toString(globalErrorCount),
+										new String(problem.getOriginatingFileName())));
+				try {
+					final String errorReportSource = errorReportSource(problem, unitSource, 0);
+					this.printlnErr(errorReportSource);
+					this.printlnErr(problem.getMessage());
+				} catch (Exception e) {
+					this.printlnErr(this.main.bind(
+						"requestor.notRetrieveErrorMessage", problem.toString())); //$NON-NLS-1$
+				}
 				this.printlnErr("----------"); //$NON-NLS-1$
 			}
-			this.printlnErr(problem.isError() ?
-				Main.bind(
-					"requestor.error", //$NON-NLS-1$
-					Integer.toString(globalErrorCount),
-					new String(problem.getOriginatingFileName()))
-				: Main.bind(
-					"requestor.warning", //$NON-NLS-1$
-					Integer.toString(globalErrorCount),
-					new String(problem.getOriginatingFileName())));
-			try {
-				this.printlnErr(((DefaultProblem) problem).errorReportSource(unitSource));
-				this.printlnErr(problem.getMessage());
-			} catch (Exception e) {
-				this.printlnErr(Main.bind(
-					"requestor.notRetrieveErrorMessage", problem.toString())); //$NON-NLS-1$
-			}
-			this.printlnErr("----------"); //$NON-NLS-1$
-		}
-		
-		/**
-		 * @param globalProblemsCount
-		 * @param globalErrorsCount
-		 * @param globalWarningsCount
-		 */
-		public void logProblemsSummary(int globalProblemsCount,
-			int globalErrorsCount, int globalWarningsCount, int globalTasksCount) {
-			if (this.isXml) {
-				// generate xml
-				parameters.clear();
-				parameters.put(NUMBER_OF_PROBLEMS, new Integer(globalProblemsCount));
-				parameters.put(NUMBER_OF_ERRORS, new Integer(globalErrorsCount));
-				parameters.put(NUMBER_OF_WARNINGS, new Integer(globalWarningsCount));
-				parameters.put(NUMBER_OF_TASKS, new Integer(globalTasksCount));
-				this.printTag(PROBLEM_SUMMARY, parameters, true, true);
-			}
-			if (globalProblemsCount == 1) {
-				String message = null;
-				if (globalErrorsCount == 1) {
-					message = Main.bind("compile.oneError"); //$NON-NLS-1$
-				} else {
-					message = Main.bind("compile.oneWarning"); //$NON-NLS-1$
-				}
-				this.printErr(Main.bind("compile.oneProblem", message)); //$NON-NLS-1$
-			} else {
-				String errorMessage = null;
-				String warningMessage = null;
-				if (globalErrorsCount > 0) {
-					if (globalErrorsCount == 1) {
-						errorMessage = Main.bind("compile.oneError"); //$NON-NLS-1$
-					} else {
-						errorMessage = Main.bind("compile.severalErrors", String.valueOf(globalErrorsCount)); //$NON-NLS-1$
-					}
-				}
-				int warningsNumber = globalWarningsCount + globalTasksCount;
-				if (warningsNumber > 0) {
-					if (warningsNumber == 1) {
-						warningMessage = Main.bind("compile.oneWarning"); //$NON-NLS-1$
-					} else {
-						warningMessage = Main.bind("compile.severalWarnings", String.valueOf(warningsNumber)); //$NON-NLS-1$
-					}
-				}
-				if (errorMessage == null || warningMessage == null) {
-					if (errorMessage == null) {
-						this.printErr(Main.bind(
-							"compile.severalProblemsErrorsOrWarnings", //$NON-NLS-1$
-							String.valueOf(globalProblemsCount),
-							warningMessage));
-					} else {
-						this.printErr(Main.bind(
-							"compile.severalProblemsErrorsOrWarnings", //$NON-NLS-1$
-							String.valueOf(globalProblemsCount),
-							errorMessage));
-					}
-				} else {
-					this.printErr(Main.bind(
-						"compile.severalProblemsErrorsAndWarnings", //$NON-NLS-1$
-						new String[] {
-							String.valueOf(globalProblemsCount),
-							errorMessage,
-							warningMessage
-						}));
-				}
-			}
 		}
 
-		public int logProblems(IProblem[] problems, char[] unitSource, Main currentMain) {
+		public int logProblems(CategorizedProblem[] problems, char[] unitSource, Main currentMain) {
 			final int count = problems.length;
 			int localErrorCount = 0;
+			int localProblemCount = 0;
 			if (count != 0) {
-				if (this.isXml) {
-					int errors = 0;
-					int warnings = 0;
-					int tasks = 0;
-					for (int i = 0; i < count; i++) {
-						IProblem problem = problems[i];
-						if (problem != null) {
-							currentMain.globalProblemsCount++;
-							this.logProblem(problem, localErrorCount, currentMain.globalProblemsCount, unitSource);
-							if (problem.isError()) {
-								errors++;
-								currentMain.globalErrorsCount++;
-								localErrorCount++;
-							} else if (problem.getID() == IProblem.Task) {
-								currentMain.globalTasksCount++;
-								tasks++;
-							} else {
-								currentMain.globalWarningsCount++;
-								warnings++;
-							}
+				int errors = 0;
+				int warnings = 0;
+				int tasks = 0;
+				for (int i = 0; i < count; i++) {
+					CategorizedProblem problem = problems[i];
+					if (problem != null) {
+						currentMain.globalProblemsCount++;
+						this.logProblem(problem, localProblemCount, currentMain.globalProblemsCount, unitSource);
+						localProblemCount++;
+						if (problem.isError()) {
+							localErrorCount++;
+							errors++;
+							currentMain.globalErrorsCount++;
+						} else if (problem.getID() == IProblem.Task) {
+							currentMain.globalTasksCount++;
+							tasks++;
+						} else {
+							currentMain.globalWarningsCount++;
+							warnings++;
 						}
 					}
+				}
+				if ((this.tagBits & Logger.XML) != 0) {
 					if ((errors + warnings) != 0) {
 						this.startLoggingProblems(errors, warnings);
 						for (int i = 0; i < count; i++) {
-							IProblem problem = problems[i];
+							CategorizedProblem problem = problems[i];
 							if (problem!= null) {
 								if (problem.getID() != IProblem.Task) {
 									this.logXmlProblem(problem, unitSource);
@@ -621,7 +662,7 @@
 					if (tasks != 0) {
 						this.startLoggingTasks(tasks);
 						for (int i = 0; i < count; i++) {
-							IProblem problem = problems[i];
+							CategorizedProblem problem = problems[i];
 							if (problem!= null) {
 								if (problem.getID() == IProblem.Task) {
 									this.logXmlTask(problem, unitSource);
@@ -630,26 +671,81 @@
 						}
 						this.endLoggingTasks();
 					}
-				} else {
-					for (int i = 0; i < count; i++) {
-						if (problems[i] != null) {
-							currentMain.globalProblemsCount++;
-							this.logProblem(problems[i], localErrorCount, currentMain.globalProblemsCount, unitSource);
-							if (problems[i].isError()) {
-								currentMain.globalErrorsCount++;
-								localErrorCount++;
-							} else {
-								currentMain.globalWarningsCount++;
-							}
-						}
-					}
 				}
 			}
 			return localErrorCount;
 		}
-		
+
 		/**
-		 * 
+		 * @param globalProblemsCount
+		 * @param globalErrorsCount
+		 * @param globalWarningsCount
+		 */
+		public void logProblemsSummary(int globalProblemsCount,
+			int globalErrorsCount, int globalWarningsCount, int globalTasksCount) {
+			if ((this.tagBits & Logger.XML) != 0) {
+				// generate xml
+				this.parameters.put(Logger.NUMBER_OF_PROBLEMS, new Integer(globalProblemsCount));
+				this.parameters.put(Logger.NUMBER_OF_ERRORS, new Integer(globalErrorsCount));
+				this.parameters.put(Logger.NUMBER_OF_WARNINGS, new Integer(globalWarningsCount));
+				this.parameters.put(Logger.NUMBER_OF_TASKS, new Integer(globalTasksCount));
+				this.printTag(Logger.PROBLEM_SUMMARY, this.parameters, true, true);
+			}
+			if (globalProblemsCount == 1) {
+				String message = null;
+				if (globalErrorsCount == 1) {
+					message = this.main.bind("compile.oneError"); //$NON-NLS-1$
+				} else {
+					message = this.main.bind("compile.oneWarning"); //$NON-NLS-1$
+				}
+				this.printErr(this.main.bind("compile.oneProblem", message)); //$NON-NLS-1$
+			} else {
+				String errorMessage = null;
+				String warningMessage = null;
+				if (globalErrorsCount > 0) {
+					if (globalErrorsCount == 1) {
+						errorMessage = this.main.bind("compile.oneError"); //$NON-NLS-1$
+					} else {
+						errorMessage = this.main.bind("compile.severalErrors", String.valueOf(globalErrorsCount)); //$NON-NLS-1$
+					}
+				}
+				int warningsNumber = globalWarningsCount + globalTasksCount;
+				if (warningsNumber > 0) {
+					if (warningsNumber == 1) {
+						warningMessage = this.main.bind("compile.oneWarning"); //$NON-NLS-1$
+					} else {
+						warningMessage = this.main.bind("compile.severalWarnings", String.valueOf(warningsNumber)); //$NON-NLS-1$
+					}
+				}
+				if (errorMessage == null || warningMessage == null) {
+					if (errorMessage == null) {
+						this.printErr(this.main.bind(
+							"compile.severalProblemsErrorsOrWarnings", //$NON-NLS-1$
+							String.valueOf(globalProblemsCount),
+							warningMessage));
+					} else {
+						this.printErr(this.main.bind(
+							"compile.severalProblemsErrorsOrWarnings", //$NON-NLS-1$
+							String.valueOf(globalProblemsCount),
+							errorMessage));
+					}
+				} else {
+					this.printErr(this.main.bind(
+						"compile.severalProblemsErrorsAndWarnings", //$NON-NLS-1$
+						new String[] {
+							String.valueOf(globalProblemsCount),
+							errorMessage,
+							warningMessage
+						}));
+				}
+			}
+			if ((this.tagBits & Logger.EMACS) != 0) {
+				this.printlnErr();
+			}
+		}
+
+		/**
+		 *
 		 */
 		public void logProgress() {
 			this.printOut('.');
@@ -662,88 +758,79 @@
 		 *            the given number of repetitions
 		 */
 		public void logRepetition(int i, int repetitions) {
-			this.printlnOut(Main.bind("compile.repetition", //$NON-NLS-1$
+			this.printlnOut(this.main.bind("compile.repetition", //$NON-NLS-1$
 				String.valueOf(i + 1), String.valueOf(repetitions)));
 		}
 
-		public void printStats(Main main) {
-			final boolean isTimed = main.timing;
-			if (isXml) {
-				this.printTag(STATS, null, true, false);
-			}
-			if (isTimed) {
-				long time = System.currentTimeMillis() - main.startTime;
-				this.logTiming(time, main.lineCount);
-				if (main.times != null) {
-					main.times[main.timesCounter++] = time;
-				}
-			}
-			if (main.globalProblemsCount > 0) {
-				this.logProblemsSummary(main.globalProblemsCount, main.globalErrorsCount, main.globalWarningsCount, main.globalTasksCount);
-			}
-			if (main.exportedClassFilesCounter != 0
-					&& (main.showProgress || isTimed || main.verbose)) {
-				this.logNumberOfClassFilesGenerated(main.exportedClassFilesCounter);
-			}
-			if (isXml) {
-				this.endTag(STATS);
-			}
-		}
 		/**
 		 * @param time
 		 * @param lineCount
 		 */
 		public void logTiming(long time, long lineCount) {
-			if (isXml) {
-				this.parameters.clear();
-				this.parameters.put(VALUE, new Long(time));
-				this.printTag(TIME, this.parameters, true, true);
-				this.parameters.clear();
-				this.parameters.put(VALUE, new Long(lineCount));
-				this.printTag(NUMBER_OF_LINES, this.parameters, true, true);
+			if ((this.tagBits & Logger.XML) != 0) {
+				this.parameters.put(Logger.VALUE, new Long(time));
+				this.printTag(Logger.TIME, this.parameters, true, true);
+				this.parameters.put(Logger.VALUE, new Long(lineCount));
+				this.printTag(Logger.NUMBER_OF_LINES, this.parameters, true, true);
 			}
 			if (lineCount != 0) {
-				this.printlnOut(Main.bind(
+				this.printlnOut(this.main.bind(
 					"compile.instantTime", //$NON-NLS-1$
 					new String[] {
 						String.valueOf(lineCount),
 						String.valueOf(time),
 						String.valueOf(((int) (lineCount * 10000.0 / time)) / 10.0) }));
 			} else {
-				this.printlnOut(Main.bind("compile.totalTime", String.valueOf(time))); //$NON-NLS-1$
+				this.printlnOut(this.main.bind("compile.totalTime", String.valueOf(time))); //$NON-NLS-1$
 			}
 		}
 
 		/**
+		 * Print the usage of the compiler
 		 * @param usage
 		 */
 		public void logUsage(String usage) {
-			this.printlnOut(usage); //$NON-NLS-1$//$NON-NLS-2$
+			this.printlnOut(usage);
 		}
 
 		/**
-		 * 
+		 * Print the version of the compiler in the log and/or the out field
 		 */
-		public void logVersion() {
-			this.printlnOut(Main.bind("misc.version", //$NON-NLS-1$
-				new String[] {
-					Main.bind("compiler.name"), //$NON-NLS-1$
-					Main.bind("compiler.version"), //$NON-NLS-1$
-					Main.bind("compiler.copyright") //$NON-NLS-1$
+		public void logVersion(final boolean printToOut) {
+			if (this.log != null && (this.tagBits & Logger.XML) == 0) {
+				final String version = this.main.bind("misc.version", //$NON-NLS-1$
+					new String[] {
+						this.main.bind("compiler.name"), //$NON-NLS-1$
+						this.main.bind("compiler.version"), //$NON-NLS-1$
+						this.main.bind("compiler.copyright") //$NON-NLS-1$
+					}
+				);
+				this.log.println("# " + version); //$NON-NLS-1$
+				if (printToOut) {
+					this.out.println(version);
+					this.out.flush();
 				}
-			));
+			} else if (printToOut) {
+				final String version = this.main.bind("misc.version", //$NON-NLS-1$
+					new String[] {
+						this.main.bind("compiler.name"), //$NON-NLS-1$
+						this.main.bind("compiler.version"), //$NON-NLS-1$
+						this.main.bind("compiler.copyright") //$NON-NLS-1$
+					}
+				);
+				this.out.println(version);
+				this.out.flush();
+			}
 		}
-
 		/**
-		 * 
+		 * Print the usage of wrong JDK
 		 */
 		public void logWrongJDK() {
-			if (isXml) {
-				parameters.clear();
-				parameters.put(MESSAGE, Main.bind("configure.requiresJDK1.2orAbove")); //$NON-NLS-1$//$NON-NLS-2$
-				this.printTag(ERROR, parameters, true, true);				
+			if ((this.tagBits & Logger.XML) != 0) {
+				this.parameters.put(Logger.MESSAGE, this.main.bind("configure.requiresJDK1.2orAbove")); //$NON-NLS-1$
+				this.printTag(Logger.ERROR, this.parameters, true, true);
 			}
-			this.printlnErr(Main.bind("configure.requiresJDK1.2orAbove")); //$NON-NLS-1$
+			this.printlnErr(this.main.bind("configure.requiresJDK1.2orAbove")); //$NON-NLS-1$
 		}
 
 		/**
@@ -752,84 +839,90 @@
 		 * @param unitSource
 		 *            the given unit source
 		 */
-		private void logXmlProblem(IProblem problem, char[] unitSource) {
+		private void logXmlProblem(CategorizedProblem problem, char[] unitSource) {
 			final int sourceStart = problem.getSourceStart();
 			final int sourceEnd = problem.getSourceEnd();
-			this.parameters.clear();
-			this.parameters.put(PROBLEM_ID, getFieldName(problem.getID()));
-			this.parameters.put(PROBLEM_SEVERITY, problem.isError() ? ERROR : WARNING);
-			this.parameters.put(PROBLEM_LINE, new Integer(problem.getSourceLineNumber()));
-			this.parameters.put(PROBLEM_SOURCE_START, new Integer(sourceStart));
-			this.parameters.put(PROBLEM_SOURCE_END, new Integer(sourceEnd));
-			this.printTag(PROBLEM_TAG, parameters, true, false);
-			this.parameters.clear();
-			this.parameters.put(VALUE, problem.getMessage());
-			this.printTag(PROBLEM_MESSAGE, parameters, true, true);
-			this.parameters.clear();
+			final int id = problem.getID();
+			this.parameters.put(Logger.ID, getFieldName(id)); // ID as field name
+			this.parameters.put(Logger.PROBLEM_ID, new Integer(id)); // ID as numeric value
+			boolean isError = problem.isError();
+			int severity = isError ? ProblemSeverities.Error : ProblemSeverities.Warning;
+			this.parameters.put(Logger.PROBLEM_SEVERITY, isError ? Logger.ERROR : Logger.WARNING);
+			this.parameters.put(Logger.PROBLEM_LINE, new Integer(problem.getSourceLineNumber()));
+			this.parameters.put(Logger.PROBLEM_SOURCE_START, new Integer(sourceStart));
+			this.parameters.put(Logger.PROBLEM_SOURCE_END, new Integer(sourceEnd));
+			String problemOptionKey = getProblemOptionKey(id);
+			if (problemOptionKey != null) {
+				this.parameters.put(Logger.PROBLEM_OPTION_KEY, problemOptionKey);
+			}
+			int categoryID = ProblemReporter.getProblemCategory(severity, id);
+			this.parameters.put(Logger.PROBLEM_CATEGORY_ID, new Integer(categoryID));
+			this.printTag(Logger.PROBLEM_TAG, this.parameters, true, false);
+			this.parameters.put(Logger.VALUE, problem.getMessage());
+			this.printTag(Logger.PROBLEM_MESSAGE, this.parameters, true, true);
 			extractContext(problem, unitSource);
-			this.printTag(SOURCE_CONTEXT, this.parameters, true, true);
 			String[] arguments = problem.getArguments();
 			final int length = arguments.length;
 			if (length != 0) {
-				this.printTag(PROBLEM_ARGUMENTS, null, true, false);
-				this.parameters.clear();
+				this.printTag(Logger.PROBLEM_ARGUMENTS, null, true, false);
 				for (int i = 0; i < length; i++) {
-					this.parameters.put(PROBLEM_ARGUMENT_VALUE, arguments[i]);
-					this.printTag(PROBLEM_ARGUMENT, this.parameters, true, true);
+					this.parameters.put(Logger.PROBLEM_ARGUMENT_VALUE, arguments[i]);
+					this.printTag(Logger.PROBLEM_ARGUMENT, this.parameters, true, true);
 				}
-				this.endTag(PROBLEM_ARGUMENTS);
+				this.endTag(Logger.PROBLEM_ARGUMENTS);
 			}
-			this.endTag(PROBLEM_TAG);
+			this.endTag(Logger.PROBLEM_TAG);
 		}
+
 		/**
 		 * @param problem
 		 *            the given problem to log
 		 * @param unitSource
 		 *            the given unit source
 		 */
-		private void logXmlTask(IProblem problem, char[] unitSource) {
-			this.parameters.clear();
-			this.parameters.put(PROBLEM_LINE, new Integer(problem.getSourceLineNumber()));
-			this.parameters.put(PROBLEM_SOURCE_START, new Integer(problem.getSourceStart()));
-			this.parameters.put(PROBLEM_SOURCE_END, new Integer(problem.getSourceEnd()));
-			this.printTag(TASK, this.parameters, true, false);
-			this.parameters.clear();
-			this.parameters.put(VALUE, problem.getMessage());
-			this.printTag(PROBLEM_MESSAGE, this.parameters, true, true);
-			this.parameters.clear();
+		private void logXmlTask(CategorizedProblem problem, char[] unitSource) {
+			this.parameters.put(Logger.PROBLEM_LINE, new Integer(problem.getSourceLineNumber()));
+			this.parameters.put(Logger.PROBLEM_SOURCE_START, new Integer(problem.getSourceStart()));
+			this.parameters.put(Logger.PROBLEM_SOURCE_END, new Integer(problem.getSourceEnd()));
+			String problemOptionKey = getProblemOptionKey(problem.getID());
+			if (problemOptionKey != null) {
+				this.parameters.put(Logger.PROBLEM_OPTION_KEY, problemOptionKey);
+			}
+			this.printTag(Logger.TASK, this.parameters, true, false);
+			this.parameters.put(Logger.VALUE, problem.getMessage());
+			this.printTag(Logger.PROBLEM_MESSAGE, this.parameters, true, true);
 			extractContext(problem, unitSource);
-			this.printTag(SOURCE_CONTEXT, this.parameters, true, true);
-			this.endTag(TASK);
+			this.endTag(Logger.TASK);
 		}
+
 		private void printErr(String s) {
 			this.err.print(s);
-			if (!this.isXml) {
-				if (this.log != null) {
-					this.log.print(s);
-				}
+			if ((this.tagBits & Logger.XML) == 0 && this.log != null) {
+				this.log.print(s);
 			}
 		}
 
+		private void printlnErr() {
+			this.err.println();
+			if ((this.tagBits & Logger.XML) == 0 && this.log != null) {
+				this.log.println();
+			}
+		}
 		private void printlnErr(String s) {
 			this.err.println(s);
-			if (!this.isXml) {
-				if (this.log != null) {
-					this.log.println(s);
-				}
+			if ((this.tagBits & Logger.XML) == 0 && this.log != null) {
+				this.log.println(s);
 			}
 		}
-
 		private void printlnOut(String s) {
 			this.out.println(s);
-			if (!this.isXml) {
-				if (this.log != null) {
-					this.log.println(s);
-				}
+			if ((this.tagBits & Logger.XML) == 0 && this.log != null) {
+				this.log.println(s);
 			}
 		}
 
 		/**
-		 * 
+		 *
 		 */
 		public void printNewLine() {
 			this.out.println();
@@ -838,61 +931,70 @@
 		private void printOut(char c) {
 			this.out.print(c);
 		}
-		public void printTag(String name, HashMap params, boolean insertNewLine, boolean closeTag) {
-			for (int i= this.tab; i > 0; i--) this.log.print('\t');
-			StringBuffer buffer= new StringBuffer();
-			buffer.append("<"); //$NON-NLS-1$
-			buffer.append(name);
-			if (params != null) {
-				for (Enumeration enumeration = Collections.enumeration(params.keySet()); enumeration.hasMoreElements();) {
-					buffer.append(" "); //$NON-NLS-1$
-					String key= (String) enumeration.nextElement();
-					buffer.append(key);
-					buffer.append("=\""); //$NON-NLS-1$
-					buffer.append(getEscaped(String.valueOf(params.get(key))));
-					buffer.append("\""); //$NON-NLS-1$
+
+		public void printStats() {
+			final boolean isTimed = this.main.timing;
+			if ((this.tagBits & Logger.XML) != 0) {
+				this.printTag(Logger.STATS, null, true, false);
+			}
+			if (isTimed) {
+				long time = System.currentTimeMillis() - this.main.startTime;
+				this.logTiming(time, this.main.lineCount);
+				if (this.main.times != null) {
+					this.main.times[this.main.timesCounter++] = time;
 				}
 			}
-			if (closeTag) {
-				buffer.append("/>"); //$NON-NLS-1$
-			} else {
-				buffer.append(">"); //$NON-NLS-1$
-				this.tab++;
+			if (this.main.globalProblemsCount > 0) {
+				this.logProblemsSummary(this.main.globalProblemsCount, this.main.globalErrorsCount, this.main.globalWarningsCount, main.globalTasksCount);
 			}
-			if (insertNewLine) {
-				this.log.println(String.valueOf(buffer));
-			} else {
-				this.log.print(String.valueOf(buffer));
+			if (this.main.exportedClassFilesCounter != 0
+					&& (this.main.showProgress || isTimed || this.main.verbose)) {
+				this.logNumberOfClassFilesGenerated(this.main.exportedClassFilesCounter);
 			}
+			if ((this.tagBits & Logger.XML) != 0) {
+				this.endTag(Logger.STATS);
+			}
+		}
+
+		private void printTag(String name, HashMap params, boolean insertNewLine, boolean closeTag) {
+			((GenericXMLWriter) this.log).printTag(name, parameters, true, insertNewLine, closeTag);
+			this.parameters.clear();
+		}
+
+		public void setEmacs() {
+			this.tagBits |= Logger.EMACS;
 		}
 
 		public void setLog(String logFileName) throws InvalidInputException {
 			final Date date = new Date();
-			final SimpleDateFormat dateFormat = new SimpleDateFormat("d MMM yyyy HH:mm:ss", Locale.getDefault());//$NON-NLS-1$
+			final DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.LONG, Locale.getDefault());
 			try {
-				this.log = new PrintWriter(new FileOutputStream(logFileName, false));
 				int index = logFileName.lastIndexOf('.');
 				if (index != -1) {
 					if (logFileName.substring(index).toLowerCase().equals(".xml")) { //$NON-NLS-1$
-						this.isXml = true;
-						this.log.println(XML_HEADER);
+						this.log = new GenericXMLWriter(new FileOutputStream(logFileName, false), Util.LINE_SEPARATOR, true);
+						this.tagBits |= Logger.XML;
 						// insert time stamp as comment
-						this.log.println("<!-- " + dateFormat.format(date) + " -->");//$NON-NLS-1$//$NON-NLS-2$
-						this.log.println(XML_DTD_DECLARATION);
-						this.tab = 0;
-						parameters.clear();
-						parameters.put(COMPILER_NAME, Main.bind("compiler.name")); //$NON-NLS-1$//$NON-NLS-2$
-						parameters.put(COMPILER_VERSION, Main.bind("compiler.version")); //$NON-NLS-1$//$NON-NLS-2$
-						parameters.put(COMPILER_COPYRIGHT, Main.bind("compiler.copyright")); //$NON-NLS-1$//$NON-NLS-2$
-						this.printTag(COMPILER, parameters, true, false);
+						try {
+							this.log.println("<!-- " + new String(dateFormat.format(date).getBytes(), "UTF-8") + " -->");//$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
+						} catch (UnsupportedEncodingException e) {
+							e.printStackTrace();
+						}
+						this.log.println(Logger.XML_DTD_DECLARATION);
+						this.parameters.put(Logger.COMPILER_NAME, this.main.bind("compiler.name")); //$NON-NLS-1$
+						this.parameters.put(Logger.COMPILER_VERSION, this.main.bind("compiler.version")); //$NON-NLS-1$
+						this.parameters.put(Logger.COMPILER_COPYRIGHT, this.main.bind("compiler.copyright")); //$NON-NLS-1$
+						this.printTag(Logger.COMPILER, this.parameters, true, false);
 					} else {
-						this.log.println("# " + dateFormat.format(date));//$NON-NLS-1$//$NON-NLS-2$
+						this.log = new PrintWriter(new FileOutputStream(logFileName, false));
+						this.log.println("# " + dateFormat.format(date));//$NON-NLS-1$
 					}
 				} else {
-					this.log.println("# " + dateFormat.format(date));//$NON-NLS-1$//$NON-NLS-2$
+					this.log = new PrintWriter(new FileOutputStream(logFileName, false));
+					this.log.println("# " + dateFormat.format(date));//$NON-NLS-1$
 				}
 			} catch (FileNotFoundException e) {
-				throw new InvalidInputException(Main.bind("configure.cannotOpenLog")); //$NON-NLS-1$
+				throw new InvalidInputException(this.main.bind("configure.cannotOpenLog", logFileName)); //$NON-NLS-1$
 			}
 		}
 
@@ -901,136 +1003,228 @@
 		 * Only use in xml mode.
 		 */
 		private void startLoggingProblems(int errors, int warnings) {
-			parameters.clear();
-			parameters.put(NUMBER_OF_PROBLEMS, new Integer(errors + warnings));
-			parameters.put(NUMBER_OF_ERRORS, new Integer(errors));
-			parameters.put(NUMBER_OF_WARNINGS, new Integer(warnings));
-			this.printTag(PROBLEMS, this.parameters, true, false);
+			this.parameters.put(Logger.NUMBER_OF_PROBLEMS, new Integer(errors + warnings));
+			this.parameters.put(Logger.NUMBER_OF_ERRORS, new Integer(errors));
+			this.parameters.put(Logger.NUMBER_OF_WARNINGS, new Integer(warnings));
+			this.printTag(Logger.PROBLEMS, this.parameters, true, false);
 		}
+		
+		private void startLoggingExtraProblems(int count) {
+			this.parameters.put(Logger.NUMBER_OF_PROBLEMS, new Integer(count));
+			this.printTag(Logger.EXTRA_PROBLEMS, this.parameters, true, false);
+		}
+
 		public void startLoggingSource(CompilationResult compilationResult) {
-			if (this.isXml) {
+			if ((this.tagBits & Logger.XML) != 0) {
 				ICompilationUnit compilationUnit = compilationResult.compilationUnit;
-				char[] fileName = compilationUnit.getFileName();
-				File f = new File(new String(fileName));
-				if (fileName != null) {
-					this.parameters.clear();
-					if (compilationUnit != null) {
-						this.parameters.put(PATH, f.getAbsolutePath());
+				if (compilationUnit != null) {
+    				char[] fileName = compilationUnit.getFileName();
+    				File f = new File(new String(fileName));
+    				if (fileName != null) {
+    					this.parameters.put(Logger.PATH, f.getAbsolutePath());
+    				}
+    				char[][] packageName = compilationResult.packageName;
+    				if (packageName != null) {
+    					this.parameters.put(
+    							Logger.PACKAGE,
+    							new String(CharOperation.concatWith(packageName, File.separatorChar)));
+    				}
+    				CompilationUnit unit = (CompilationUnit) compilationUnit;
+    				String destinationPath = unit.destinationPath;
+					if (destinationPath == null) {
+						destinationPath = this.main.destinationPath;
+					}
+					if (destinationPath != null && destinationPath != NONE) {
+						if (File.separatorChar == '/') {
+							this.parameters.put(Logger.OUTPUT, destinationPath);
+						} else {
+							this.parameters.put(Logger.OUTPUT, destinationPath.replace('/', File.separatorChar));
+						}
 					}
 				}
-				this.printTag(SOURCE, this.parameters, true, false);
+				this.printTag(Logger.SOURCE, this.parameters, true, false);
 			}
 		}
 		public void startLoggingSources() {
-			if (this.isXml) {
-				this.printTag(SOURCES, null, true, false);
+			if ((this.tagBits & Logger.XML) != 0) {
+				this.printTag(Logger.SOURCES, null, true, false);
 			}
 		}
 		public void startLoggingTasks(int tasks) {
-			if (this.isXml) {
-				parameters.clear();
-				parameters.put(NUMBER_OF_TASKS, new Integer(tasks));
-				this.printTag(TASKS, this.parameters, true, false);
+			if ((this.tagBits & Logger.XML) != 0) {
+				this.parameters.put(Logger.NUMBER_OF_TASKS, new Integer(tasks));
+				this.printTag(Logger.TASKS, this.parameters, true, false);
 			}
 		}
-	}
-	static {
-		relocalize();
-	}
 
-	/* Bundle containing messages */
-	public static ResourceBundle bundle;
-	public final static String bundleName =
-		"org.eclipse.jdt.internal.compiler.batch.messages"; 	//$NON-NLS-1$
-
-	FileSystem.Classpath[] checkedClasspaths;
-	public String destinationPath;
-	public String[] encodings;
-	public Logger logger;
-	public int exportedClassFilesCounter;
-	public String[] filenames;
-	public boolean generatePackagesStructure;
-	public int globalErrorsCount;
-	public int globalTasksCount;
-	public int globalProblemsCount;
-	public int globalWarningsCount;
-	public long lineCount;
-	public String log;
-
-	public boolean noWarn = false;
-
-	public Map options; 
-	public CompilerOptions compilerOptions; // read-only
-
-	public boolean proceed = true;
-	public boolean proceedOnError = false;
-	public boolean produceRefInfo = false;
-	public int repetitions;
-	public int maxProblems;
-	public boolean showProgress = false;
-	public boolean systemExitWhenFinished = true;
-	public long startTime;
-	public boolean timing = false;
-	public long[] times;
-	public int timesCounter;
-	public boolean verbose = false;
-
-	public Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhenFinished) {
-		this(outWriter, errWriter, systemExitWhenFinished, null);
-	}
-	
-	public Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhenFinished, Map customDefaultOptions) {
-		this.logger = new Logger(outWriter, errWriter);
-		this.systemExitWhenFinished = systemExitWhenFinished;
-		this.options = new CompilerOptions().getMap();
-		if (customDefaultOptions != null) {
-			for (Iterator iter = customDefaultOptions.keySet().iterator(); iter.hasNext();) {
-				Object key = iter.next();
-				this.options.put(key, customDefaultOptions.get(key));
+		public void loggingExtraProblems(Main currentMain) {
+			ArrayList problems = currentMain.extraProblems;
+			final int count = problems.size();
+			int localErrorCount = 0;
+			int localProblemCount = 0;
+			if (count != 0) {
+				int errors = 0;
+				int warnings = 0;
+				for (int i = 0; i < count; i++) {
+					CategorizedProblem problem = (CategorizedProblem) problems.get(i);
+					if (problem != null) {
+						currentMain.globalProblemsCount++;
+						this.logExtraProblem(problem, localProblemCount, currentMain.globalProblemsCount);
+						localProblemCount++;
+						if (problem.isError()) {
+							localErrorCount++;
+							errors++;
+							currentMain.globalErrorsCount++;
+						} else if (problem.isWarning()) {
+							currentMain.globalWarningsCount++;
+							warnings++;
+						}
+					}
+				}
+				if ((this.tagBits & Logger.XML) != 0) {
+					if ((errors + warnings) != 0) {
+						this.startLoggingExtraProblems(count);
+						for (int i = 0; i < count; i++) {
+							CategorizedProblem problem = (CategorizedProblem) problems.get(i);
+							if (problem!= null) {
+								if (problem.getID() != IProblem.Task) {
+									this.logXmlExtraProblem(problem, localProblemCount, currentMain.globalProblemsCount);
+								}
+							}
+						}
+						this.endLoggingExtraProblems();
+					}
+				}
 			}
 		}
-	}
-	
-	/*
-	 * Lookup the message with the given ID in this catalog 
-	 */
-	public static String bind(String id) {
-		return bind(id, (String[]) null);
-	}
 
-	/*
-	 * Lookup the message with the given ID in this catalog and bind its
-	 * substitution locations with the given string.
-	 */
-	public static String bind(String id, String binding) {
-		return bind(id, new String[] { binding });
-	}
-
-	/*
-	 * Lookup the message with the given ID in this catalog and bind its
-	 * substitution locations with the given strings.
-	 */
-	public static String bind(String id, String binding1, String binding2) {
-		return bind(id, new String[] { binding1, binding2 });
-	}
-
-	/*
-	 * Lookup the message with the given ID in this catalog and bind its
-	 * substitution locations with the given string values.
-	 */
-	public static String bind(String id, String[] arguments) {
-		if (id == null)
-			return "No message available"; //$NON-NLS-1$
-		String message = null;
-		try {
-			message = bundle.getString(id);
-		} catch (MissingResourceException e) {
-			// If we got an exception looking for the message, fail gracefully by just returning
-			// the id we were looking for.  In most cases this is semi-informative so is not too bad.
-			return "Missing message: " + id + " in: " + bundleName; //$NON-NLS-2$ //$NON-NLS-1$
+		private void logXmlExtraProblem(CategorizedProblem problem, int globalErrorCount, int localErrorCount) {
+			final int sourceStart = problem.getSourceStart();
+			final int sourceEnd = problem.getSourceEnd();
+			boolean isError = problem.isError();
+			this.parameters.put(Logger.PROBLEM_SEVERITY, isError ? Logger.ERROR : Logger.WARNING);
+			this.parameters.put(Logger.PROBLEM_LINE, new Integer(problem.getSourceLineNumber()));
+			this.parameters.put(Logger.PROBLEM_SOURCE_START, new Integer(sourceStart));
+			this.parameters.put(Logger.PROBLEM_SOURCE_END, new Integer(sourceEnd));
+			this.printTag(Logger.EXTRA_PROBLEM_TAG, this.parameters, true, false);
+			this.parameters.put(Logger.VALUE, problem.getMessage());
+			this.printTag(Logger.PROBLEM_MESSAGE, this.parameters, true, true);
+			extractContext(problem, null);
+			this.endTag(Logger.EXTRA_PROBLEM_TAG);
 		}
-		return MessageFormat.format(message, arguments);
+
+		private void logExtraProblem(CategorizedProblem problem, int localErrorCount, int globalErrorCount) {
+			char[] originatingFileName = problem.getOriginatingFileName();
+			String fileName =
+				originatingFileName == null
+				? this.main.bind("requestor.noFileNameSpecified")//$NON-NLS-1$
+				: new String(originatingFileName);
+			if ((this.tagBits & Logger.EMACS) != 0) {
+				String result = fileName
+						+ ":" //$NON-NLS-1$
+						+ problem.getSourceLineNumber()
+						+ ": " //$NON-NLS-1$
+						+ (problem.isError() ? this.main.bind("output.emacs.error") : this.main.bind("output.emacs.warning")) //$NON-NLS-1$ //$NON-NLS-2$
+						+ ": " //$NON-NLS-1$
+						+ problem.getMessage();
+				this.printlnErr(result);
+				final String errorReportSource = errorReportSource(problem, null, this.tagBits);
+				this.printlnErr(errorReportSource);
+			} else {
+				if (localErrorCount == 0) {
+					this.printlnErr("----------"); //$NON-NLS-1$
+				}
+				this.printErr(problem.isError() ?
+						this.main.bind(
+								"requestor.error", //$NON-NLS-1$
+								Integer.toString(globalErrorCount),
+								new String(fileName))
+								: this.main.bind(
+										"requestor.warning", //$NON-NLS-1$
+										Integer.toString(globalErrorCount),
+										new String(fileName)));
+				final String errorReportSource = errorReportSource(problem, null, 0);
+				this.printlnErr(errorReportSource);
+				this.printlnErr(problem.getMessage());
+				this.printlnErr("----------"); //$NON-NLS-1$
+			}
+		}
+
+		private String errorReportSource(CategorizedProblem problem, char[] unitSource, int bits) {
+			//extra from the source the innacurate     token
+			//and "highlight" it using some underneath ^^^^^
+			//put some context around too.
+
+			//this code assumes that the font used in the console is fixed size
+
+			//sanity .....
+			int startPosition = problem.getSourceStart();
+			int endPosition = problem.getSourceEnd();
+			if (unitSource == null) {
+				if (problem.getOriginatingFileName() != null) {
+					try {
+						unitSource = Util.getFileCharContent(new File(new String(problem.getOriginatingFileName())), null);
+					} catch (IOException e) {
+						// ignore;
+					}
+				}
+			}
+			int length = unitSource == null ? 0 : unitSource.length;
+			if ((startPosition > endPosition)
+				|| ((startPosition < 0) && (endPosition < 0))
+				|| length == 0)
+				return Messages.problem_noSourceInformation; 
+
+			StringBuffer errorBuffer = new StringBuffer();
+			if ((bits & Main.Logger.EMACS) == 0) {
+				errorBuffer.append(' ').append(Messages.bind(Messages.problem_atLine, String.valueOf(problem.getSourceLineNumber()))); 
+				errorBuffer.append(Util.LINE_SEPARATOR);
+			}
+			errorBuffer.append('\t');
+			
+			char c;
+			final char SPACE = '\u0020';
+			final char MARK = '^';
+			final char TAB = '\t';
+			//the next code tries to underline the token.....
+			//it assumes (for a good display) that token source does not
+			//contain any \r \n. This is false on statements ! 
+			//(the code still works but the display is not optimal !)
+
+			// expand to line limits
+			int begin;
+			int end;
+			for (begin = startPosition >= length ? length - 1 : startPosition; begin > 0; begin--) {
+				if ((c = unitSource[begin - 1]) == '\n' || c == '\r') break;
+			}
+			for (end = endPosition >= length ? length - 1 : endPosition ; end+1 < length; end++) {
+				if ((c = unitSource[end + 1]) == '\r' || c == '\n') break;
+			}
+			
+			// trim left and right spaces/tabs
+			while ((c = unitSource[begin]) == ' ' || c == '\t') begin++;
+			//while ((c = unitSource[end]) == ' ' || c == '\t') end--; TODO (philippe) should also trim right, but all tests are to be updated
+			
+			// copy source
+			errorBuffer.append(unitSource, begin, end-begin+1);
+			errorBuffer.append(Util.LINE_SEPARATOR).append("\t"); //$NON-NLS-1$
+
+			// compute underline
+			for (int i = begin; i <startPosition; i++) {
+				errorBuffer.append((unitSource[i] == TAB) ? TAB : SPACE);
+			}
+			for (int i = startPosition; i <= (endPosition >= length ? length - 1 : endPosition); i++) {
+				errorBuffer.append(MARK);
+			}
+			return errorBuffer.toString();
+		}
 	}
+	public final static String bundleName = "org.eclipse.jdt.internal.compiler.batch.messages"; //$NON-NLS-1$
+
+	// two uses: recognize 'none' in options; code the singleton none
+	// for the '-d none' option (wherever it may be found)
+	public static final int DEFAULT_SIZE_CLASSPATH = 4;
+	public static final String NONE = "none"; //$NON-NLS-1$
 
 	/*
 	 * Internal IDE API
@@ -1039,41 +1233,42 @@
 
 		return compile(commandLine, new PrintWriter(System.out), new PrintWriter(System.err));
 	}
-
-	/*
+		/*
 	 * Internal IDE API for test harness purpose
 	 */
 	public static boolean compile(String commandLine, PrintWriter outWriter, PrintWriter errWriter) {
 
 		return new Main(outWriter, errWriter, false).compile(tokenize(commandLine));
 	}
-	
-	/*
-	 * External API
-	 */
-
+	public static File[][] getLibrariesFiles(File[] files) {
+		FilenameFilter filter = new FilenameFilter() {
+			public boolean accept(File dir, String name) {
+				String lowerCaseName = name.toLowerCase();
+				if (lowerCaseName.endsWith(SuffixConstants.SUFFIX_STRING_jar) || lowerCaseName.endsWith(SuffixConstants.SUFFIX_STRING_zip)) {
+					return true;
+				}
+				return false;
+			}
+		};
+		final int filesLength = files.length;
+		File[][] result = new File[filesLength][];
+		for (int i = 0; i < filesLength; i++) {
+			File currentFile = files[i];
+			if (currentFile.exists() && currentFile.isDirectory()) {
+				result[i] = currentFile.listFiles(filter);
+			}
+		}
+		return result;
+	}
 	public static void main(String[] argv) {
 		new Main(new PrintWriter(System.out), new PrintWriter(System.err), true).compile(argv);
 	}
-
-	/**
-	 * Creates a NLS catalog for the given locale.
-	 */
-	public static void relocalize() {
-		try {
-			bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault());
-		} catch(MissingResourceException e) {
-			System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
-			throw e;
-		}
-	}
-
 	public static String[] tokenize(String commandLine) {
 
 		int count = 0;
 		String[] arguments = new String[10];
 		StringTokenizer tokenizer = new StringTokenizer(commandLine, " \"", true); //$NON-NLS-1$
-		String token = ""; //$NON-NLS-1$
+		String token = Util.EMPTY_STRING;
 		boolean insideQuotes = false;
 		boolean startNewToken = true;
 
@@ -1093,10 +1288,10 @@
 					startNewToken = true;
 				}
 			} else if (token.equals("\"")) { //$NON-NLS-1$
-				if (!insideQuotes && startNewToken) { //$NON-NLS-1$
+				if (!insideQuotes && startNewToken) {
 					if (count == arguments.length)
 						System.arraycopy(arguments, 0, (arguments = new String[count * 2]), 0, count);
-					arguments[count++] = ""; //$NON-NLS-1$
+					arguments[count++] = Util.EMPTY_STRING;
 				}
 				insideQuotes = !insideQuotes;
 				startNewToken = false;
@@ -1121,1291 +1316,93 @@
 		System.arraycopy(arguments, 0, arguments = new String[count], 0, count);
 		return arguments;
 	}
+	public Compiler batchCompiler;
+	/* Bundle containing messages */
+	public ResourceBundle bundle;
+	protected FileSystem.Classpath[] checkedClasspaths;
+	public Locale compilerLocale;
+	public CompilerOptions compilerOptions; // read-only
+	public String destinationPath;
+	public String[] destinationPaths;
+	// destination path for compilation units that get no more specific
+	// one (through directory arguments or various classpath options);
+	// coding is:
+	// == null: unspecified, write class files close to their respective
+	//          source files;
+	// == Main.NONE: absorbent element, do not output class files;
+	// else: use as the path of the directory into which class files must
+	//       be written.
+	private boolean didSpecifySource;
+	private boolean didSpecifyTarget;
 
-	/*
-	 *  Low-level API performing the actual compilation
-	 */
-	public boolean compile(String[] argv) {
+	public String[] encodings;
 
-		// decode command line arguments
-		try {
-			configure(argv);
-			if (this.proceed) {
-//				if (this.verbose) {
-//					System.out.println(new CompilerOptions(this.options));
-//				}
-				if (this.showProgress) this.logger.compiling(); //$NON-NLS-1$
-				for (int i = 0; i < this.repetitions; i++) {
-					this.globalProblemsCount = 0;
-					this.globalErrorsCount = 0;
-					this.globalWarningsCount = 0;
-					this.globalTasksCount = 0;
-					this.lineCount = 0;
-					this.exportedClassFilesCounter = 0;
+	public int exportedClassFilesCounter;
+	public String[] filenames;
 
-					if (this.repetitions > 1) {
-						this.logger.flush();
-						this.logger.logRepetition(i, this.repetitions);
-					} 
-					// request compilation
-					performCompilation();
-				}
-				if (this.times != null) {
-					this.logger.logAverage(this.times, this.lineCount);
-				}
-				if (this.showProgress) this.logger.printNewLine();
-			}
-			if (this.systemExitWhenFinished) {
-				this.logger.flush();
-    			this.logger.close();
-				System.exit(this.globalErrorsCount > 0 ? -1 : 0);
-			}
-		} catch (InvalidInputException e) {
-			this.logger.logException(e);
-			if (this.systemExitWhenFinished) {
-    			this.logger.flush();
-    			this.logger.close();
-				System.exit(-1);
-			}
-			return false;
-		} catch (RuntimeException e) { // internal compiler failure
-			if (this.systemExitWhenFinished) {
-				this.logger.flush();
-				this.logger.close();
-				System.exit(-1);
-			}
-			return false;
-		} finally {
-			this.logger.flush();
-			this.logger.close();
-		}
-		if (this.globalErrorsCount == 0)
-			return true;
-		return false;
+	public String[] classNames;
+
+	// overrides of destinationPath on a directory argument basis
+	public int globalErrorsCount;
+	public int globalProblemsCount;
+	public int globalTasksCount;
+	public int globalWarningsCount;
+	private File javaHomeCache;
+	private boolean javaHomeChecked = false;
+	public long lineCount;
+	public String log;
+	public Logger logger;
+	public int maxProblems;
+	public boolean noWarn = false;
+	public Map options;
+	protected PrintWriter out;
+	public boolean proceed = true;
+	public boolean proceedOnError = false;
+	public boolean produceRefInfo = false;
+	public int repetitions;
+
+	public boolean showProgress = false;
+	public long startTime;
+
+public boolean systemExitWhenFinished = true;
+
+public long[] times;
+
+public int timesCounter;
+
+public boolean timing = false;
+
+public boolean verbose = false;
+
+private String[] expandedCommandLine;
+
+private PrintWriter err;
+
+ArrayList extraProblems;
+
+public Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhenFinished) {
+	this(outWriter, errWriter, systemExitWhenFinished, null);
+}
+
+public Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhenFinished, Map customDefaultOptions) {
+	this.initialize(outWriter, errWriter, systemExitWhenFinished, customDefaultOptions);
+	this.relocalize();
+}
+public void addExtraProblems(CategorizedProblem problem) {
+	if (this.extraProblems == null) {
+		this.extraProblems = new ArrayList();
 	}
+	this.extraProblems.add(problem);
+}
+protected void addNewEntry(ArrayList paths, String currentClasspathName,
+		ArrayList currentRuleSpecs, String customEncoding,
+		String destPath, boolean isSourceOnly,
+		boolean rejectDestinationPathOnJars) throws InvalidInputException {
 
-	/*
-	Decode the command line arguments 
-	 */
-	public void configure(String[] argv) throws InvalidInputException {
-		
-		if ((argv == null) || (argv.length == 0)) {
-			printUsage();
-			return;
-		}
-		final int InsideClasspath = 1;
-		final int InsideDestinationPath = 2;
-		final int TargetSetting = 4;
-		final int InsideLog = 8;
-		final int InsideRepetition = 16;
-		final int InsideSource = 32;
-		final int InsideDefaultEncoding = 64;
-		final int InsideBootClasspath = 128;
-		final int InsideMaxProblems = 256;
-		final int InsideExtdirs = 512;
-		final int InsideSourcepath = 1024;
-
-		final int Default = 0;
-		int DEFAULT_SIZE_CLASSPATH = 4;
-		ArrayList bootclasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH),
-			extdirsClasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH),
-			extdirsNames = new ArrayList(DEFAULT_SIZE_CLASSPATH),
-			sourcepathClasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH),
-			classpaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
-		String currentClasspathName = null;
-		ArrayList currentRuleSpecs = new ArrayList(DEFAULT_SIZE_CLASSPATH);
-		int index = -1, filesCount = 0, argCount = argv.length;
-		int mode = Default;
-		this.repetitions = 0;
-		boolean printUsageRequired = false;
-		boolean printVersionRequired = false;
-		
-		boolean didSpecifySource = false;
-		boolean didSpecifyCompliance = false;
-		boolean didSpecifyDefaultEncoding = false;
-		boolean didSpecifyTarget = false;
-		boolean didSpecifyDeprecation = false;
-		boolean didSpecifyWarnings = false;
-		boolean useEnableJavadoc = false;
-
-		String customEncoding = null;
-		String currentArg = ""; //$NON-NLS-1$
-
-		// expand the command line if necessary
-		boolean needExpansion = false;
-		loop: for (int i = 0; i < argCount; i++) {
-				if (argv[i].startsWith("@")) { //$NON-NLS-1$
-					needExpansion = true;
-					break loop;
-				}
-		}
-
-		String[] newCommandLineArgs = null;
-		if (needExpansion) {
-			newCommandLineArgs = new String[argCount];
-			index = 0;
-			for (int i = 0; i < argCount; i++) {
-				String[] newArgs = null;
-				String arg = argv[i].trim();
-				if (arg.startsWith("@")) { //$NON-NLS-1$
-					try {
-						LineNumberReader reader = new LineNumberReader(new StringReader(new String(Util.getFileCharContent(new File(arg.substring(1)), null))));
-						StringBuffer buffer = new StringBuffer();
-						String line;
-						while((line = reader.readLine()) != null) {
-							buffer.append(line).append(" "); //$NON-NLS-1$
-						}
-						newArgs = tokenize(buffer.toString());
-					} catch(IOException e) {
-						throw new InvalidInputException(
-							Main.bind("configure.invalidexpansionargumentname", arg)); //$NON-NLS-1$
-					}
-				}
-				if (newArgs != null) {
-					int newCommandLineArgsLength = newCommandLineArgs.length;
-					int newArgsLength = newArgs.length;
-					System.arraycopy(newCommandLineArgs, 0, (newCommandLineArgs = new String[newCommandLineArgsLength + newArgsLength - 1]), 0, index);
-					System.arraycopy(newArgs, 0, newCommandLineArgs, index, newArgsLength);
-					index += newArgsLength;
-				} else {
-					newCommandLineArgs[index++] = arg;
-				}
-			}
-			index = -1;
-		} else {
-			newCommandLineArgs = argv;
-			for (int i = 0; i < argCount; i++) {
-				newCommandLineArgs[i] = newCommandLineArgs[i].trim();
-			}
-		}
-		argCount = newCommandLineArgs.length;
-		while (++index < argCount) {
-
-			if (customEncoding != null) {
-				throw new InvalidInputException(
-					Main.bind("configure.unexpectedCustomEncoding", currentArg, customEncoding)); //$NON-NLS-1$
-			}
-
-			currentArg = newCommandLineArgs[index];
-
-			customEncoding = null;
-			if (currentArg.endsWith("]") && !(mode == InsideBootClasspath || mode == InsideClasspath || //$NON-NLS-1$ 
-					mode == InsideSourcepath) ) {
-				// look for encoding specification
-				int encodingStart = currentArg.indexOf('[') + 1;
-				int encodingEnd = currentArg.length() - 1;
-				if (encodingStart >= 1) {
-					if (encodingStart < encodingEnd) {
-						customEncoding = currentArg.substring(encodingStart, encodingEnd);
-						try { // ensure encoding is supported
-							new InputStreamReader(new ByteArrayInputStream(new byte[0]), customEncoding);
-						} catch (UnsupportedEncodingException e) {
-							throw new InvalidInputException(
-								Main.bind("configure.unsupportedEncoding", customEncoding)); //$NON-NLS-1$
-						}
-					}
-					currentArg = currentArg.substring(0, encodingStart - 1);
-				}
-			}
-
-			if (currentArg.endsWith(SUFFIX_STRING_java)) {
-				if (this.filenames == null) {
-					this.filenames = new String[argCount - index];
-					this.encodings = new String[argCount - index];
-				} else if (filesCount == this.filenames.length) {
-					int length = this.filenames.length;
-					System.arraycopy(
-						this.filenames,
-						0,
-						(this.filenames = new String[length + argCount - index]),
-						0,
-						length);
-					System.arraycopy(
-						this.encodings,
-						0,
-						(this.encodings = new String[length + argCount - index]),
-						0,
-						length);
-				}
-				this.filenames[filesCount] = currentArg;
-				this.encodings[filesCount++] = customEncoding;
-				customEncoding = null;
-				mode = Default;
-				continue;
-			}
-			if (currentArg.equals("-log")) { //$NON-NLS-1$
-				if (this.log != null)
-					throw new InvalidInputException(
-						Main.bind("configure.duplicateLog", currentArg)); //$NON-NLS-1$
-				mode = InsideLog;
-				continue;
-			}
-			if (currentArg.equals("-repeat")) { //$NON-NLS-1$
-				if (this.repetitions > 0)
-					throw new InvalidInputException(
-						Main.bind("configure.duplicateRepeat", currentArg)); //$NON-NLS-1$
-				mode = InsideRepetition;
-				continue;
-			}
-			if (currentArg.equals("-maxProblems")) { //$NON-NLS-1$
-				if (this.maxProblems > 0)
-					throw new InvalidInputException(
-						Main.bind("configure.duplicateMaxProblems", currentArg)); //$NON-NLS-1$
-				mode = InsideMaxProblems;
-				continue;
-			}
-			if (currentArg.equals("-source")) { //$NON-NLS-1$
-				mode = InsideSource;
-				continue;
-			}
-			if (currentArg.equals("-encoding")) { //$NON-NLS-1$
-				mode = InsideDefaultEncoding;
-				continue;
-			}
-			if (currentArg.equals("-1.3")) { //$NON-NLS-1$
-				if (didSpecifyCompliance) {
-					throw new InvalidInputException(
-						Main.bind("configure.duplicateCompliance", currentArg));//$NON-NLS-1$
-				}
-				didSpecifyCompliance = true;
-				this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_3);
-				mode = Default;
-				continue;
-			}
-			if (currentArg.equals("-1.4")) { //$NON-NLS-1$
-				if (didSpecifyCompliance) {
-					throw new InvalidInputException(
-						Main.bind("configure.duplicateCompliance", currentArg)); //$NON-NLS-1$
-				}
-				didSpecifyCompliance = true;
-				this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
-				mode = Default;
-				continue;
-			}
-			if (currentArg.equals("-1.5") || currentArg.equals("-5") || currentArg.equals("-5.0")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-				if (didSpecifyCompliance) {
-					throw new InvalidInputException(
-						Main.bind("configure.duplicateCompliance", currentArg)); //$NON-NLS-1$
-				}
-				didSpecifyCompliance = true;
-				this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_5);
-				mode = Default;
-				continue;
-			}			
-			if (currentArg.equals("-d")) { //$NON-NLS-1$
-				if (this.destinationPath != null)
-					throw new InvalidInputException(
-						Main.bind("configure.duplicateOutputPath", currentArg)); //$NON-NLS-1$
-				mode = InsideDestinationPath;
-				this.generatePackagesStructure = true;
-				continue;
-			}
-			if (currentArg.equals("-classpath") //$NON-NLS-1$
-				|| currentArg.equals("-cp")) { //$NON-NLS-1$ //$NON-NLS-2$
-				mode = InsideClasspath;
-				continue;
-			}
-			if (currentArg.equals("-bootclasspath")) {//$NON-NLS-1$
-				if (bootclasspaths.size() > 0)
-					throw new InvalidInputException(
-						Main.bind("configure.duplicateBootClasspath", currentArg)); //$NON-NLS-1$
-				mode = InsideBootClasspath;
-				continue;
-			}
-			if (currentArg.equals("-sourcepath")) {//$NON-NLS-1$
-				if (sourcepathClasspaths.size() > 0)
-					throw new InvalidInputException(
-						Main.bind("configure.duplicateSourcepath", currentArg)); //$NON-NLS-1$
-				mode = InsideSourcepath;
-				continue;
-			}
-			if (currentArg.equals("-extdirs")) {//$NON-NLS-1$
-				if (extdirsNames.size() > 0)
-					throw new InvalidInputException(
-						Main.bind("configure.duplicateExtdirs", currentArg)); //$NON-NLS-1$
-				mode = InsideExtdirs;
-				continue;
-			}
-			if (currentArg.equals("-progress")) { //$NON-NLS-1$
-				mode = Default;
-				this.showProgress = true;
-				continue;
-			}
-			if (currentArg.equals("-proceedOnError")) { //$NON-NLS-1$
-				mode = Default;
-				this.proceedOnError = true;
-				continue;
-			}
-			if (currentArg.equals("-time")) { //$NON-NLS-1$
-				mode = Default;
-				this.timing = true;
-				continue;
-			}
-			if (currentArg.equals("-version") //$NON-NLS-1$
-					|| currentArg.equals("-v")) { //$NON-NLS-1$
-				printVersion();
-				this.proceed = false;
-				return;
-			}
-			if (currentArg.equals("-showversion")) { //$NON-NLS-1$
-				printVersionRequired = true;
-				continue;
-			}			
-			if ("-deprecation".equals(currentArg)) { //$NON-NLS-1$
-				didSpecifyDeprecation = true;
-				this.options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
-				continue;
-			}
-			if (currentArg.equals("-help") || currentArg.equals("-?")) { //$NON-NLS-1$ //$NON-NLS-2$
-				printUsageRequired = true;
-				continue;
-			}
-			if (currentArg.equals("-noExit")) { //$NON-NLS-1$
-				mode = Default;
-				this.systemExitWhenFinished = false;
-				continue;
-			}
-			if (currentArg.equals("-verbose")) { //$NON-NLS-1$
-				mode = Default;
-				this.verbose = true;
-				continue;
-			}
-			if (currentArg.equals("-referenceInfo")) { //$NON-NLS-1$
-				mode = Default;
-				this.produceRefInfo = true;
-				continue;
-			}
-			if (currentArg.equals("-inlineJSR")) { //$NON-NLS-1$
-			    mode = Default;
-				this.options.put(
-						CompilerOptions.OPTION_InlineJsr,
-						CompilerOptions.ENABLED);
-			    continue;
-			}
-			if (currentArg.startsWith("-g")) { //$NON-NLS-1$
-				mode = Default;
-				String debugOption = currentArg;
-				int length = currentArg.length();
-				if (length == 2) {
-					this.options.put(
-						CompilerOptions.OPTION_LocalVariableAttribute,
-						CompilerOptions.GENERATE);
-					this.options.put(
-						CompilerOptions.OPTION_LineNumberAttribute,
-						CompilerOptions.GENERATE);
-					this.options.put(
-						CompilerOptions.OPTION_SourceFileAttribute,
-						CompilerOptions.GENERATE);
-					continue;
-				}
-				if (length > 3) {
-					this.options.put(
-						CompilerOptions.OPTION_LocalVariableAttribute,
-						CompilerOptions.DO_NOT_GENERATE);
-					this.options.put(
-						CompilerOptions.OPTION_LineNumberAttribute,
-						CompilerOptions.DO_NOT_GENERATE);
-					this.options.put(
-						CompilerOptions.OPTION_SourceFileAttribute,
-						CompilerOptions.DO_NOT_GENERATE);
-					if (length == 7 && debugOption.equals("-g:none")) //$NON-NLS-1$
-						continue;
-					StringTokenizer tokenizer =
-						new StringTokenizer(debugOption.substring(3, debugOption.length()), ","); //$NON-NLS-1$
-					while (tokenizer.hasMoreTokens()) {
-						String token = tokenizer.nextToken();
-						if (token.equals("vars")) { //$NON-NLS-1$
-							this.options.put(
-								CompilerOptions.OPTION_LocalVariableAttribute,
-								CompilerOptions.GENERATE);
-						} else if (token.equals("lines")) { //$NON-NLS-1$
-							this.options.put(
-								CompilerOptions.OPTION_LineNumberAttribute,
-								CompilerOptions.GENERATE);
-						} else if (token.equals("source")) { //$NON-NLS-1$
-							this.options.put(
-								CompilerOptions.OPTION_SourceFileAttribute,
-								CompilerOptions.GENERATE);
-						} else {
-							throw new InvalidInputException(
-								Main.bind("configure.invalidDebugOption", debugOption)); //$NON-NLS-1$
-						}
-					}
-					continue;
-				}
-				throw new InvalidInputException(
-					Main.bind("configure.invalidDebugOption", debugOption)); //$NON-NLS-1$
-			}
-			if (currentArg.startsWith("-nowarn")) { //$NON-NLS-1$
-				disableWarnings();
-				mode = Default;
-				continue;
-			}
-			if (currentArg.startsWith("-warn")) { //$NON-NLS-1$
-				mode = Default;
-				String warningOption = currentArg;
-				int length = currentArg.length();
-				if (length == 10 && warningOption.equals("-warn:none")) { //$NON-NLS-1$
-					disableWarnings();
-					continue;
-				}
-				if (length <= 6) {
-					throw new InvalidInputException(
-						Main.bind("configure.invalidWarningConfiguration", warningOption)); //$NON-NLS-1$
-				}
-				int warnTokenStart;
-				boolean isEnabling;
-				switch (warningOption.charAt(6)) {
-					case '+' : 
-						warnTokenStart = 7;
-						isEnabling = true;
-						break;
-					case '-' :
-						warnTokenStart = 7;
-						isEnabling = false; // mentionned warnings are disabled
-						break;
-					default:
-						warnTokenStart = 6;
-						// clear default warning level
-						// but allow multiple warning option on the command line
-						if (!didSpecifyWarnings) disableWarnings();
-						isEnabling = true;
-				}
-			
-				StringTokenizer tokenizer =
-					new StringTokenizer(warningOption.substring(warnTokenStart, warningOption.length()), ","); //$NON-NLS-1$
-				int tokenCounter = 0;
-
-				if (didSpecifyDeprecation) {  // deprecation could have also been set through -deprecation option
-					this.options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
-				}
-				
-				while (tokenizer.hasMoreTokens()) {
-					String token = tokenizer.nextToken();
-					tokenCounter++;
-					if (token.equals("constructorName")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportMethodWithConstructorName,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("pkgDefaultMethod") || token.equals("packageDefaultMethod")/*backward compatible*/ ) { //$NON-NLS-1$ //$NON-NLS-2$
-						this.options.put(
-							CompilerOptions.OPTION_ReportOverridingPackageDefaultMethod,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("maskedCatchBlock") || token.equals("maskedCatchBlocks")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
-						this.options.put(
-							CompilerOptions.OPTION_ReportHiddenCatchBlock,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("deprecation")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportDeprecation, 
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-						this.options.put(
-							CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode, 
-							CompilerOptions.DISABLED);
-					} else if (token.equals("allDeprecation")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportDeprecation, 
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-						this.options.put(
-							CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode, 
-							isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
-						this.options.put(
-							CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod, 
-							isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
-					} else if (token.equals("unusedLocal") || token.equals("unusedLocals")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
-						this.options.put(
-							CompilerOptions.OPTION_ReportUnusedLocal, 
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("unusedArgument") || token.equals("unusedArguments")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
-						this.options.put(
-							CompilerOptions.OPTION_ReportUnusedParameter,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("unusedImport") || token.equals("unusedImports")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
-						this.options.put(
-							CompilerOptions.OPTION_ReportUnusedImport,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("unusedPrivate")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportUnusedPrivateMember,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("localHiding")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportLocalVariableHiding,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("fieldHiding")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportFieldHiding,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("specialParamHiding")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportSpecialParameterHidingField,
-							isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
-					} else if (token.equals("conditionAssign")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportPossibleAccidentalBooleanAssignment,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-   					} else if (token.equals("syntheticAccess") //$NON-NLS-1$
-   							|| token.equals("synthetic-access")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportSyntheticAccessEmulation,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("nls")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportNonExternalizedStringLiteral,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("staticReceiver")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportNonStaticAccessToStatic,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("indirectStatic")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportIndirectStaticAccess,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("noEffectAssign")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportNoEffectAssignment,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("intfNonInherited") || token.equals("interfaceNonInherited")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
-						this.options.put(
-							CompilerOptions.OPTION_ReportIncompatibleNonInheritedInterfaceMethod,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("charConcat") || token.equals("noImplicitStringConversion")/*backward compatible*/) {//$NON-NLS-1$ //$NON-NLS-2$
-						this.options.put(
-							CompilerOptions.OPTION_ReportNoImplicitStringConversion,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("semicolon")) {//$NON-NLS-1$ 
-						this.options.put(
-							CompilerOptions.OPTION_ReportEmptyStatement,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("serial")) {//$NON-NLS-1$ 
-						this.options.put(
-							CompilerOptions.OPTION_ReportMissingSerialVersion,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("emptyBlock")) {//$NON-NLS-1$ 
-						this.options.put(
-							CompilerOptions.OPTION_ReportUndocumentedEmptyBlock,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("uselessTypeCheck")) {//$NON-NLS-1$ 
-						this.options.put(
-							CompilerOptions.OPTION_ReportUnnecessaryTypeCheck,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("unchecked") || token.equals("unsafe")) {//$NON-NLS-1$ //$NON-NLS-2$ 
-						this.options.put(
-							CompilerOptions.OPTION_ReportUncheckedTypeOperation,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("finalBound")) {//$NON-NLS-1$ 
-						this.options.put(
-							CompilerOptions.OPTION_ReportFinalParameterBound,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("suppress")) {//$NON-NLS-1$ 
-						this.options.put(
-							CompilerOptions.OPTION_SuppressWarnings,
-							isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
-					} else if (token.equals("warningToken")) {//$NON-NLS-1$ 
-						this.options.put(
-							CompilerOptions.OPTION_ReportUnhandledWarningToken,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("unnecessaryElse")) {//$NON-NLS-1$ 
-						this.options.put(
-							CompilerOptions.OPTION_ReportUnnecessaryElse,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("javadoc")) {//$NON-NLS-1$ 
-						if (!useEnableJavadoc) {
-							this.options.put(
-								CompilerOptions.OPTION_DocCommentSupport,
-								isEnabling ? CompilerOptions.ENABLED: CompilerOptions.DISABLED);
-						}
-						// if disabling then it's not necessary to set other javadoc options
-						if (isEnabling) {
-							this.options.put(
-								CompilerOptions.OPTION_ReportInvalidJavadoc,
-								CompilerOptions.WARNING);
-							this.options.put(
-								CompilerOptions.OPTION_ReportInvalidJavadocTags,
-								CompilerOptions.ENABLED);
-							this.options.put(
-								CompilerOptions.OPTION_ReportInvalidJavadocTagsDeprecatedRef,
-								CompilerOptions.DISABLED);
-							this.options.put(
-								CompilerOptions.OPTION_ReportInvalidJavadocTagsNotVisibleRef,
-								CompilerOptions.DISABLED);
-							this.options.put(
-								CompilerOptions.OPTION_ReportInvalidJavadocTagsVisibility,
-								CompilerOptions.PRIVATE);
-							this.options.put(
-								CompilerOptions.OPTION_ReportMissingJavadocTags,
-								CompilerOptions.WARNING);
-							this.options.put(
-								CompilerOptions.OPTION_ReportMissingJavadocTagsVisibility,
-								CompilerOptions.PRIVATE);
-						}
-					} else if (token.equals("allJavadoc")) { //$NON-NLS-1$
-						if (!useEnableJavadoc) {
-							this.options.put(
-								CompilerOptions.OPTION_DocCommentSupport,
-								isEnabling ? CompilerOptions.ENABLED: CompilerOptions.DISABLED);
-						}
-						// if disabling then it's not necessary to set other javadoc options
-						if (isEnabling) {
-							this.options.put(
-							CompilerOptions.OPTION_ReportInvalidJavadoc,
-							CompilerOptions.WARNING);
-							this.options.put(
-								CompilerOptions.OPTION_ReportInvalidJavadocTags,
-								CompilerOptions.ENABLED);
-							this.options.put(
-								CompilerOptions.OPTION_ReportInvalidJavadocTagsVisibility,
-								CompilerOptions.PRIVATE);
-							this.options.put(
-								CompilerOptions.OPTION_ReportMissingJavadocTags,
-								CompilerOptions.WARNING);
-							this.options.put(
-								CompilerOptions.OPTION_ReportMissingJavadocTagsVisibility,
-								CompilerOptions.PRIVATE);
-							this.options.put(
-								CompilerOptions.OPTION_ReportMissingJavadocComments,
-								CompilerOptions.WARNING);
-						}
-					} else if (token.startsWith("tasks")) { //$NON-NLS-1$
-						String taskTags = ""; //$NON-NLS-1$
-						int start = token.indexOf('(');
-						int end = token.indexOf(')');
-						if (start >= 0 && end >= 0 && start < end){
-							taskTags = token.substring(start+1, end).trim();
-							taskTags = taskTags.replace('|',',');
-						}
-						if (taskTags.length() == 0){
-							throw new InvalidInputException(Main.bind("configure.invalidTaskTag", token)); //$NON-NLS-1$
-						}
-						this.options.put(
-							CompilerOptions.OPTION_TaskTags,
-							isEnabling ? taskTags : "");  //$NON-NLS-1$
-					} else if (token.equals("assertIdentifier")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportAssertIdentifier,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("enumIdentifier")) { //$NON-NLS-1$
-						this.options.put(
-								CompilerOptions.OPTION_ReportEnumIdentifier,
-								isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("finally")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportFinallyBlockNotCompletingNormally,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("unusedThrown")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportUnusedDeclaredThrownException,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("unqualifiedField") //$NON-NLS-1$
-							|| token.equals("unqualified-field-access")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportUnqualifiedFieldAccess,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("typeHiding")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportTypeParameterHiding,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("varargsCast")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportVarargsArgumentNeedCast,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);						
-					} else if (token.equals("null")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportNullReference,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);						
-					} else if (token.equals("boxing")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportAutoboxing,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);						
-					} else if (token.equals("over-ann")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportMissingOverrideAnnotation,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);						
-					} else if (token.equals("dep-ann")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportMissingDeprecatedAnnotation,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);						
-					} else if (token.equals("intfAnnotation")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportAnnotationSuperInterface,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);						
-					} else if (token.equals("enumSwitch") //$NON-NLS-1$
-							|| token.equals("incomplete-switch")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportIncompleteEnumSwitch,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);						
-					} else if (token.equals("hiding")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportHiddenCatchBlock,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-						this.options.put(
-							CompilerOptions.OPTION_ReportLocalVariableHiding,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-						this.options.put(
-							CompilerOptions.OPTION_ReportFieldHiding,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-						this.options.put(
-							CompilerOptions.OPTION_ReportTypeParameterHiding,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("static-access")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportNonStaticAccessToStatic,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-						this.options.put(
-							CompilerOptions.OPTION_ReportIndirectStaticAccess,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else if (token.equals("unused")) { //$NON-NLS-1$
-						this.options.put(
-							CompilerOptions.OPTION_ReportUnusedLocal, 
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-						this.options.put(
-							CompilerOptions.OPTION_ReportUnusedParameter,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-						this.options.put(
-							CompilerOptions.OPTION_ReportUnusedImport,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-						this.options.put(
-							CompilerOptions.OPTION_ReportUnusedPrivateMember,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-						this.options.put(
-							CompilerOptions.OPTION_ReportUnusedDeclaredThrownException,
-							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
-					} else {
-						throw new InvalidInputException(Main.bind("configure.invalidWarning", token)); //$NON-NLS-1$
-					}
-				}
-				if (tokenCounter == 0)
-					throw new InvalidInputException(
-						Main.bind("configure.invalidWarningOption", currentArg)); //$NON-NLS-1$
-				didSpecifyWarnings = true;
-				continue;
-			}
-			if (currentArg.equals("-target")) { //$NON-NLS-1$
-				mode = TargetSetting;
-				continue;
-			}
-			if (currentArg.equals("-preserveAllLocals")) { //$NON-NLS-1$
-				this.options.put(
-					CompilerOptions.OPTION_PreserveUnusedLocal,
-					CompilerOptions.PRESERVE);
-				continue;
-			}
-			if (currentArg.equals("-enableJavadoc")) {//$NON-NLS-1$
-				this.options.put(
-					CompilerOptions.OPTION_DocCommentSupport,
-					CompilerOptions.ENABLED);
-				useEnableJavadoc = true;
-				continue;
-			}
-			// tolerated javac options - quietly filtered out
-			if (currentArg.startsWith("-X")) { //$NON-NLS-1$
-				mode = Default;
-				continue;
-			}
-			if (currentArg.startsWith("-J")) { //$NON-NLS-1$
-				mode = Default;
-				continue;
-			}
-			if (currentArg.equals("-O")) { //$NON-NLS-1$
-				mode = Default;
-				continue;
-			}
-			
-			if (currentArg.equals("-sourcepath")) {//$NON-NLS-1$
-				if (sourcepathClasspaths.size() > 0)
-					throw new InvalidInputException(
-						Main.bind("configure.duplicateSourcepath", currentArg)); //$NON-NLS-1$
-				mode = InsideSourcepath;
-				continue;
-			}
-			if (currentArg.equals("-extdirs")) {//$NON-NLS-1$
-				if (extdirsNames.size() > 0)
-					throw new InvalidInputException(
-						Main.bind("configure.duplicateExtdirs", currentArg)); //$NON-NLS-1$
-				mode = InsideExtdirs;
-				continue;
-			}
-
-			if (mode == TargetSetting) {
-				if (didSpecifyTarget) {
-					throw new InvalidInputException(
-						Main.bind("configure.duplicateTarget", currentArg));//$NON-NLS-1$
-				}				
-				didSpecifyTarget = true;
-				if (currentArg.equals("1.1")) { //$NON-NLS-1$
-					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_1);
-				} else if (currentArg.equals("1.2")) { //$NON-NLS-1$
-					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2);
-				} else if (currentArg.equals("1.3")) { //$NON-NLS-1$
-					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_3);
-				} else if (currentArg.equals("1.4")) { //$NON-NLS-1$
-					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
-					if (didSpecifyCompliance && CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Compliance)) < ClassFileConstants.JDK1_4) {
-						throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForTarget", (String)this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_4)); //$NON-NLS-1$
-					}
-					this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
-				} else if (currentArg.equals("1.5") || currentArg.equals("5") || currentArg.equals("5.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
-					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
-					if (didSpecifyCompliance && CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Compliance)) < ClassFileConstants.JDK1_5) {
-						throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForTarget", (String)this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_5)); //$NON-NLS-1$
-					}
-					this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_5);
-				} else {
-					throw new InvalidInputException(Main.bind("configure.targetJDK", currentArg)); //$NON-NLS-1$
-				}
-				mode = Default;
-				continue;
-			}
-			if (mode == InsideLog) {
-				this.log = currentArg;
-				mode = Default;
-				continue;
-			}
-			if (mode == InsideRepetition) {
-				try {
-					this.repetitions = Integer.parseInt(currentArg);
-					if (this.repetitions <= 0) {
-						throw new InvalidInputException(Main.bind("configure.repetition", currentArg)); //$NON-NLS-1$
-					}
-				} catch (NumberFormatException e) {
-					throw new InvalidInputException(Main.bind("configure.repetition", currentArg)); //$NON-NLS-1$
-				}
-				mode = Default;
-				continue;
-			}
-			if (mode == InsideMaxProblems) {
-				try {
-					this.maxProblems = Integer.parseInt(currentArg);
-					if (this.maxProblems <= 0) {
-						throw new InvalidInputException(Main.bind("configure.maxProblems", currentArg)); //$NON-NLS-1$
-					}
-					this.options.put(CompilerOptions.OPTION_MaxProblemPerUnit, currentArg);
-				} catch (NumberFormatException e) {
-					throw new InvalidInputException(Main.bind("configure.maxProblems", currentArg)); //$NON-NLS-1$
-				}
-				mode = Default;
-				continue;
-			}
-			if (mode == InsideSource) {
-				if (didSpecifySource) {
-					throw new InvalidInputException(
-						Main.bind("configure.duplicateSource", currentArg));//$NON-NLS-1$
-				}				
-				didSpecifySource = true;
-				if (currentArg.equals("1.3")) { //$NON-NLS-1$
-					this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
-				} else if (currentArg.equals("1.4")) { //$NON-NLS-1$
-					this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_4);
-				} else if (currentArg.equals("1.5") || currentArg.equals("5") || currentArg.equals("5.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
-					this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_5);
-				} else {
-					throw new InvalidInputException(Main.bind("configure.source", currentArg)); //$NON-NLS-1$
-				}
-				mode = Default;
-				continue;
-			}
-			if (mode == InsideDefaultEncoding) {
-				if (didSpecifyDefaultEncoding) {
-					throw new InvalidInputException(
-						Main.bind("configure.duplicateDefaultEncoding", currentArg)); //$NON-NLS-1$
-				}
-				try { // ensure encoding is supported
-					new InputStreamReader(new ByteArrayInputStream(new byte[0]), currentArg);
-				} catch (UnsupportedEncodingException e) {
-					throw new InvalidInputException(
-						Main.bind("configure.unsupportedEncoding", currentArg)); //$NON-NLS-1$
-				}
-				this.options.put(CompilerOptions.OPTION_Encoding, currentArg);
-				didSpecifyDefaultEncoding = true;
-				mode = Default;
-				continue;
-			}
-			if (mode == InsideDestinationPath) {
-				this.destinationPath = currentArg;
-				mode = Default;
-				continue;
-			}
-			if (mode == InsideClasspath || mode == InsideBootClasspath || mode == InsideSourcepath) {
-				StringTokenizer tokenizer = new StringTokenizer(currentArg,
-						File.pathSeparator + "[]", true); //$NON-NLS-1$
-				// state machine
-				final int start = 0; 
-				final int readyToClose = 1;
-				// 'path' 'path1[rule];path2'
-				final int readyToCloseEndingWithRules = 2;
-				// 'path[rule]' 'path1;path2[rule]'
-				final int readyToCloseOrOtherEntry = 3;
-				// 'path[rule];' 'path;' 'path1;path2;'
-				final int rulesNeedAnotherRule = 4;
-				// 'path[rule1;'
-				final int rulesStart = 5;
-				// 'path[' 'path1;path2['
-				final int rulesReadyToClose = 6;
-				// 'path[rule' 'path[rule1;rule2'
-				final int error = 99;
-				int state = start;
-				String token = null;
-				while (tokenizer.hasMoreTokens()) {
-					token = tokenizer.nextToken();
-					if (token.equals(File.pathSeparator)) {
-						switch (state) {
-						case readyToClose:
-						case readyToCloseEndingWithRules:
-						case readyToCloseOrOtherEntry:
-							state = readyToCloseOrOtherEntry;
-							addNewEntry(InsideClasspath, InsideSourcepath, bootclasspaths, classpaths, sourcepathClasspaths, currentClasspathName, currentRuleSpecs, mode, customEncoding);
-							break;
-						case rulesReadyToClose:
-							state = rulesNeedAnotherRule;
-							break;
-						default:
-							state = error;
-						}
-					} else if (token.equals("[")) { //$NON-NLS-1$
-						switch (state) {
-						case readyToClose:
-							state = rulesStart;
-							break;
-						default:
-							state = error;
-						}
-					} else if (token.equals("]")) { //$NON-NLS-1$
-						switch (state) {
-						case rulesReadyToClose:
-							state = readyToCloseEndingWithRules;
-							break;
-						default:
-							state = error;
-						}
-
-					} else {
-						// regular word
-						switch (state) {
-						case start:
-						case readyToCloseOrOtherEntry:
-							state = readyToClose;
-							currentClasspathName = token;
-							break;
-						case rulesNeedAnotherRule:
-						case rulesStart:
-							state = rulesReadyToClose;
-							currentRuleSpecs.add(token);
-							break;
-						default:
-							state = error;
-						}
-					}
-				}
-				switch(state) {
-					case readyToClose :
-					case readyToCloseEndingWithRules :
-					case readyToCloseOrOtherEntry :
-						addNewEntry(InsideClasspath, InsideSourcepath, bootclasspaths, classpaths, sourcepathClasspaths, currentClasspathName, currentRuleSpecs, mode, customEncoding);
-						break;
-					default :
-						// we go on anyway
-						this.logger.logIncorrectClasspath(currentArg);
-				}
-				mode = Default;
-				continue;
-			}
-			if (mode == InsideExtdirs) {
-				StringTokenizer tokenizer = new StringTokenizer(currentArg,	File.pathSeparator, false);
-				while (tokenizer.hasMoreTokens())
-					extdirsNames.add(tokenizer.nextToken());
-				if (extdirsNames.size() == 0) // empty entry
-					extdirsNames.add(""); //$NON-NLS-1$
-				mode = Default;
-				continue;
-			}
-
-			//default is input directory
-			currentArg = currentArg.replace('/', File.separatorChar);
-			if (currentArg.endsWith(File.separator))
-				currentArg =
-					currentArg.substring(0, currentArg.length() - File.separator.length());
-			File dir = new File(currentArg);
-			if (!dir.isDirectory())
-				throw new InvalidInputException(
-					Main.bind("configure.directoryNotExist", currentArg)); //$NON-NLS-1$
-			FileFinder finder = new FileFinder();
-			try {
-				finder.find(dir, SUFFIX_STRING_JAVA, this.verbose); //$NON-NLS-1$
-			} catch (Exception e) {
-				throw new InvalidInputException(Main.bind("configure.IOError", currentArg)); //$NON-NLS-1$
-			}
-			if (this.filenames != null) {
-				// some source files were specified explicitly
-				String results[] = finder.resultFiles;
-				int length = results.length;
-				System.arraycopy(
-					this.filenames,
-					0,
-					(this.filenames = new String[length + filesCount]),
-					0,
-					filesCount);
-				System.arraycopy(
-					this.encodings,
-					0,
-					(this.encodings = new String[length + filesCount]),
-					0,
-					filesCount);
-				System.arraycopy(results, 0, this.filenames, filesCount, length);
-				for (int i = 0; i < length; i++) {
-					this.encodings[filesCount + i] = customEncoding;
-				}
-				filesCount += length;
-				customEncoding = null;
-			} else {
-				this.filenames = finder.resultFiles;
-				filesCount = this.filenames.length;
-				this.encodings = new String[filesCount];
-				for (int i = 0; i < filesCount; i++) {
-					this.encodings[i] = customEncoding;
-				}
-				customEncoding = null;
-			}
-			mode = Default;
-			continue;
-		}
-		
-
-		if (this.log != null) {
-			this.logger.setLog(this.log);
-		} else {
-			this.showProgress = false;
-		}
-		
-		if (printUsageRequired || filesCount == 0) {
-			printUsage();
-			this.proceed = false;
-			return;
-		}
-		if (printVersionRequired) {
-			printVersion();
-		}
-
-		if (filesCount != 0)
-			System.arraycopy(
-				this.filenames,
-				0,
-				(this.filenames = new String[filesCount]),
-				0,
-				filesCount);
-		if (classpaths.size() == 0) {
-			// no user classpath specified.
-			String classProp = System.getProperty("java.class.path"); //$NON-NLS-1$
-			if ((classProp == null) || (classProp.length() == 0)) {
-				this.logger.logNoClasspath(); //$NON-NLS-1$
-			}
-			else {
-				StringTokenizer tokenizer = new StringTokenizer(classProp, File.pathSeparator);
-				String token;
-				while (tokenizer.hasMoreTokens()) {
-					token = tokenizer.nextToken();
-					FileSystem.Classpath currentClasspath = FileSystem
-							.getClasspath(token, customEncoding, 0, null);
-					if (currentClasspath != null) {
-						classpaths.add(currentClasspath);
-					} else {
-						this.logger.logIncorrectClasspath(token);
-						// should not happen - we go on anyway
-					}
-				}
-			}
-		}
-		
-	 	 if (bootclasspaths.size() == 0) {
-			/* no bootclasspath specified
-			 * we can try to retrieve the default librairies of the VM used to run
-			 * the batch compiler
-			 */
-			 String javaversion = System.getProperty("java.version");//$NON-NLS-1$
-			 if (javaversion != null && javaversion.equalsIgnoreCase("1.1.8")) { //$NON-NLS-1$
-				this.logger.logWrongJDK(); //$NON-NLS-1$
-				this.proceed = false;
-				return;
-			 }
-
-		 	/*
-		 	 * Handle >= JDK 1.2.2 settings: retrieve rt.jar
-		 	 */
-		 	 if (getJavaHome() != null) {
-				File[] directoriesToCheck = new File[] { 
-						new File(getJavaHome(), "lib") //$NON-NLS-1$
-						};
-				File[][] systemLibrariesJars = getLibrariesFiles(directoriesToCheck);
-				if (systemLibrariesJars != null) {
-					for (int i = 0, max = systemLibrariesJars.length; i < max; i++) {
-						File[] current = systemLibrariesJars[i];
-						if (current != null) {
-							for (int j = 0, max2 = current.length; j < max2; j++) {
-								FileSystem.Classpath classpath = 
-									FileSystem.getClasspath(
-											current[j].getAbsolutePath(),
-											null, 0, null); 
-								if (classpath != null) {
-									bootclasspaths.add(classpath);
-								}
-							}
-						}
-					}
-				}
-	 		}
-	 	 }
-		
-		/*
-		 * Feed extdirsNames according to:
-		 * - -extdirs first if present;
-		 * - else java.ext.dirs if defined;
-		 * - else default extensions directory for the platform.
-		 */
-		if (extdirsNames.size() == 0) {
-			String extdirsStr = System.getProperty("java.ext.dirs"); //$NON-NLS-1$
-			if (extdirsStr == null) {
-				extdirsNames.add(getJavaHome().getAbsolutePath() + "/lib/ext"); //$NON-NLS-1$
-			}
-			else {
-				StringTokenizer tokenizer = new StringTokenizer(extdirsStr, File.pathSeparator);
-				while (tokenizer.hasMoreTokens()) 
-					extdirsNames.add(tokenizer.nextToken());
-			}
-		}
-		
-		/*
-		 * Feed extdirsClasspath with the entries found into the directories listed by
-		 * extdirsNames.
-		 */
-		if (extdirsNames.size() != 0) {
-			File[] directoriesToCheck = new File[extdirsNames.size()];
-			for (int i = 0; i < directoriesToCheck.length; i++) 
-				directoriesToCheck[i] = new File((String) extdirsNames.get(i));
-			File[][] extdirsJars = getLibrariesFiles(directoriesToCheck);
-			if (extdirsJars != null) {
-				for (int i = 0, max = extdirsJars.length; i < max; i++) {
-					File[] current = extdirsJars[i];
-					if (current != null) {
-						for (int j = 0, max2 = current.length; j < max2; j++) {
-							FileSystem.Classpath classpath = 
-								FileSystem.getClasspath(
-										current[j].getAbsolutePath(),
-										null, 0, null); 
-							if (classpath != null) {
-								extdirsClasspaths.add(classpath);
-							}
-						}
-					}
-				}
-			}
-		}
-
-		/* 
-		 * Concatenate classpath entries
-		 * We put the bootclasspath at the beginning of the classpath
-		 * entries, followed by the extension libraries, followed by
-		 * the sourcepath followed by the classpath.  All classpath
-		 * entries are searched for both sources and binaries except
-		 * the sourcepath entries which are searched for sources only.
-		 */
-		bootclasspaths.addAll(extdirsClasspaths);
-		bootclasspaths.addAll(sourcepathClasspaths);
-		bootclasspaths.addAll(classpaths);
-		classpaths = bootclasspaths;
-		this.checkedClasspaths = new FileSystem.Classpath[classpaths.size()];
-		classpaths.toArray(this.checkedClasspaths);
-		if (this.destinationPath == null) {
-			this.generatePackagesStructure = false;
-		} else if ("none".equals(this.destinationPath)) { //$NON-NLS-1$
-			this.destinationPath = null;
-		}
-		
-		if (didSpecifyCompliance) {
-			Object version = this.options.get(CompilerOptions.OPTION_Compliance);
-			if (CompilerOptions.VERSION_1_3.equals(version)) {
-				if (!didSpecifySource) this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
-				if (!didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_1);
-			} else if (CompilerOptions.VERSION_1_4.equals(version)) {
-				if (!didSpecifySource) this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
-				if (!didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2);
-			} else if (CompilerOptions.VERSION_1_5.equals(version)) {
-				if (!didSpecifySource) this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_5);
-				if (!didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
-			}
-		}
-		if (didSpecifySource) {
-			Object version = this.options.get(CompilerOptions.OPTION_Source);
-			 if (CompilerOptions.VERSION_1_4.equals(version)) {
-				if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
-				if (!didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
-			} else if (CompilerOptions.VERSION_1_5.equals(version)) {
-				if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_5);
-				if (!didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
-			}
-		}
-
-		// check and set compliance/source/target compatibilities
-		if (didSpecifyTarget) {
-			// target must be 1.5 if source is 1.5
-			if (CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Source)) >= ClassFileConstants.JDK1_5
-					&& CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_TargetPlatform)) < ClassFileConstants.JDK1_5){ 
-				throw new InvalidInputException(Main.bind("configure.incompatibleTargetForSource", (String)this.options.get(CompilerOptions.OPTION_TargetPlatform), CompilerOptions.VERSION_1_5)); //$NON-NLS-1$
-			}
-	   		 // target must be 1.4 if source is 1.4
-	   		if (CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Source)) >= ClassFileConstants.JDK1_4
-					&& CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_TargetPlatform)) < ClassFileConstants.JDK1_4){ 
-				throw new InvalidInputException(Main.bind("configure.incompatibleTargetForSource", (String)this.options.get(CompilerOptions.OPTION_TargetPlatform), CompilerOptions.VERSION_1_4)); //$NON-NLS-1$
-	   		}
-			// target cannot be greater than compliance level
-			if (CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Compliance)) < CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_TargetPlatform))){ 
-				throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForTarget", (String)this.options.get(CompilerOptions.OPTION_Compliance), (String)this.options.get(CompilerOptions.OPTION_TargetPlatform))); //$NON-NLS-1$
-			}
-		}
-
-		// compliance must be 1.5 if source is 1.5
-		if (this.options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_5)
-				&& CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Compliance)) < ClassFileConstants.JDK1_5) {
-			throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForSource", (String)this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_5)); //$NON-NLS-1$
-		} else 
-			// compliance must be 1.4 if source is 1.4
-			if (this.options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_4)
-					&& CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Compliance)) < ClassFileConstants.JDK1_4) { 
-				throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForSource", (String)this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_4)); //$NON-NLS-1$
-		}
-		// set default target according to compliance & sourcelevel.
-		if (!didSpecifyTarget) {
-			if (this.options.get(CompilerOptions.OPTION_Compliance).equals(CompilerOptions.VERSION_1_3)) {
-				this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_1);
-			} else if (this.options.get(CompilerOptions.OPTION_Compliance).equals(CompilerOptions.VERSION_1_4)) {
-				if (this.options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_3)) {
-					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2);
-				} else if (this.options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_4)) {
-					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
-				}
-			} else if (this.options.get(CompilerOptions.OPTION_Compliance).equals(CompilerOptions.VERSION_1_5)) {
-				if (this.options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_3)) {
-					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2);
-				} else if (this.options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_4)) {
-					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
-				} else if (this.options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_5)) {
-					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
-				}
-			}
-		}
-		this.logger.logCommandLineArguments(newCommandLineArgs);
-		this.logger.logOptions(this.options);
-		this.logger.logClasspath(this.checkedClasspaths);
-		if (this.repetitions == 0) {
-			this.repetitions = 1;
-		}
-		if (this.repetitions >= 3 && this.timing) {
-			this.times = new long[this.repetitions];
-			this.timesCounter = 0;
-		}
-	}
-
-	private void addNewEntry(final int InsideClasspath, final int InsideSourcepath, ArrayList bootclasspaths, ArrayList classpaths,ArrayList sourcepathClasspaths, String currentClasspathName, ArrayList currentRuleSpecs, int mode, String customEncoding) {
-		AccessRule[] accessRules = new AccessRule[currentRuleSpecs
-				.size()];
+	int rulesSpecsSize = currentRuleSpecs.size();
+	AccessRuleSet accessRuleSet = null;
+	if (rulesSpecsSize != 0) {
+		AccessRule[] accessRules = new AccessRule[currentRuleSpecs.size()];
 		boolean rulesOK = true;
 		Iterator i = currentRuleSpecs.iterator();
 		int j = 0;
@@ -2415,304 +1412,2592 @@
 			String pattern = ruleSpec.substring(1);
 			if (pattern.length() > 0) {
 				switch (key) {
-				case '+':
-					accessRules[j++] = new AccessRule(pattern
-							.toCharArray(), -1);
-					break;
-				case '~':
-					accessRules[j++] = new AccessRule(pattern
-							.toCharArray(),
-							IProblem.DiscouragedReference);
-					break;
-				case '-':
-					accessRules[j++] = new AccessRule(pattern
-							.toCharArray(),
-							IProblem.ForbiddenReference);
-					break;
-				default:
-					rulesOK = false;
+					case '+':
+						accessRules[j++] = new AccessRule(pattern
+								.toCharArray(), 0);
+						break;
+					case '~':
+						accessRules[j++] = new AccessRule(pattern
+								.toCharArray(),
+								IProblem.DiscouragedReference);
+						break;
+					case '-':
+						accessRules[j++] = new AccessRule(pattern
+								.toCharArray(),
+								IProblem.ForbiddenReference);
+						break;
+					case '?':
+						accessRules[j++] = new AccessRule(pattern
+								.toCharArray(),
+								IProblem.ForbiddenReference, true/*keep looking for accessible type*/);
+						break;
+					default:
+						rulesOK = false;
 				}
 			} else {
 				rulesOK = false;
 			}
 		}
 		if (rulesOK) {
-			AccessRuleSet accessRuleSet = new AccessRuleSet(
-					accessRules, "{0}"); //$NON-NLS-1$
-			FileSystem.Classpath currentClasspath = FileSystem
-					.getClasspath(currentClasspathName,
-							customEncoding, 0, accessRuleSet);
-			if (currentClasspath != null) {
-				if (mode == InsideClasspath) {
-					classpaths.add(currentClasspath);
-				} else if (mode == InsideSourcepath) {
-					if (currentClasspath instanceof ClasspathDirectory) {
-						((ClasspathDirectory) currentClasspath).mode = 
-							ClasspathDirectory.SOURCE; 
-						// TODO may consider adding this attribute to other classpath natures
-					}
-					sourcepathClasspaths.add(currentClasspath);
-				} else { // inside bootclasspath
+			String templates[] = new String[AccessRuleSet.MESSAGE_TEMPLATES_LENGTH];
+			templates[0] = this.bind(
+					"template.restrictedAccess.type", //$NON-NLS-1$
+					new String[] {"{0}", currentClasspathName}); //$NON-NLS-1$
+			templates[1] = this.bind(
+					"template.restrictedAccess.constructor", //$NON-NLS-1$
+					new String[] {"{0}", currentClasspathName}); //$NON-NLS-1$
+			templates[2] = this.bind(
+					"template.restrictedAccess.method", //$NON-NLS-1$
+					new String[] {"{0}", "{1}", currentClasspathName}); //$NON-NLS-1$ //$NON-NLS-2$
+			templates[3] = this.bind(
+					"template.restrictedAccess.field", //$NON-NLS-1$
+					new String[] {"{0}", "{1}", currentClasspathName}); //$NON-NLS-1$ //$NON-NLS-2$
+			accessRuleSet = new AccessRuleSet(accessRules, templates);
+		} else {
+			if (currentClasspathName.length() != 0) {
+				// we go on anyway
+				this.logger.logIncorrectClasspath(currentClasspathName);
+			}
+			return;
+		}
+	}
+	if (NONE.equals(destPath)) {
+		destPath = NONE; // keep == comparison valid
+	}
+	if (rejectDestinationPathOnJars && destPath != null &&
+			(currentClasspathName.endsWith(".jar") || //$NON-NLS-1$
+				currentClasspathName.endsWith(".zip"))) { //$NON-NLS-1$
+		throw new InvalidInputException(
+			this.bind("configure.unexpectedDestinationPathEntryFile", //$NON-NLS-1$
+						currentClasspathName));
+	}
+	FileSystem.Classpath currentClasspath = FileSystem.getClasspath(
+			currentClasspathName,
+			customEncoding,
+			isSourceOnly,
+			accessRuleSet,
+			destPath);
+	if (currentClasspath != null) {
+		paths.add(currentClasspath);
+	} else if (currentClasspathName.length() != 0) {
+		// we go on anyway
+		this.logger.logIncorrectClasspath(currentClasspathName);
+	}
+}
+/*
+ * Lookup the message with the given ID in this catalog
+ */
+public String bind(String id) {
+	return bind(id, (String[]) null);
+}
+/*
+ * Lookup the message with the given ID in this catalog and bind its
+ * substitution locations with the given string.
+ */
+public String bind(String id, String binding) {
+	return bind(id, new String[] { binding });
+}
+
+/*
+ * Lookup the message with the given ID in this catalog and bind its
+ * substitution locations with the given strings.
+ */
+public String bind(String id, String binding1, String binding2) {
+	return bind(id, new String[] { binding1, binding2 });
+}
+
+/*
+ * Lookup the message with the given ID in this catalog and bind its
+ * substitution locations with the given string values.
+ */
+public String bind(String id, String[] arguments) {
+	if (id == null)
+		return "No message available"; //$NON-NLS-1$
+	String message = null;
+	try {
+		message = this.bundle.getString(id);
+	} catch (MissingResourceException e) {
+		// If we got an exception looking for the message, fail gracefully by just returning
+		// the id we were looking for.  In most cases this is semi-informative so is not too bad.
+		return "Missing message: " + id + " in: " + Main.bundleName; //$NON-NLS-2$ //$NON-NLS-1$
+	}
+	return MessageFormat.format(message, arguments);
+}
+/**
+ * Return true if and only if the running VM supports the given minimal version.
+ * 
+ * <p>This only checks the major version, since the minor version is always 0 (at least for the useful cases).</p>
+ * <p>The given minimalSupportedVersion is one of the constants:</p>
+ * <ul>
+ * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_1</code></li>
+ * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_2</code></li>
+ * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_3</code></li>
+ * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_4</code></li>
+ * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_5</code></li>
+ * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_6</code></li>
+ * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_7</code></li>
+ * </ul>
+ * @param minimalSupportedVersion the given minimal version
+ * @return true if and only if the running VM supports the given minimal version, false otherwise
+ */
+private boolean checkVMVersion(long minimalSupportedVersion) {
+	// the format of this property is supposed to be xx.x where x are digits.
+	String classFileVersion = System.getProperty("java.class.version"); //$NON-NLS-1$
+	if (classFileVersion == null) {
+		// by default we don't support a class file version we cannot recognize
+		return false;
+	}
+	int index = classFileVersion.indexOf('.');
+	if (index == -1) {
+		// by default we don't support a class file version we cannot recognize
+		return false;
+	}
+	int majorVersion;
+	try {
+		majorVersion = Integer.parseInt(classFileVersion.substring(0, index));
+	} catch (NumberFormatException e) {
+		// by default we don't support a class file version we cannot recognize
+		return false;
+	}
+	switch(majorVersion) {
+		case 45 : // 1.0 and 1.1
+			return ClassFileConstants.JDK1_1 >= minimalSupportedVersion;
+		case 46 : // 1.2
+			return ClassFileConstants.JDK1_2 >= minimalSupportedVersion;
+		case 47 : // 1.3
+			return ClassFileConstants.JDK1_3 >= minimalSupportedVersion;
+		case 48 : // 1.4
+			return ClassFileConstants.JDK1_4 >= minimalSupportedVersion;
+		case 49 : // 1.5
+			return ClassFileConstants.JDK1_5 >= minimalSupportedVersion;
+		case 50 : // 1.6
+			return ClassFileConstants.JDK1_6 >= minimalSupportedVersion;
+		case 51 : // 1.7
+			return ClassFileConstants.JDK1_7 >= minimalSupportedVersion;
+	}
+	// unknown version
+	return false;
+}
+/*
+ *  Low-level API performing the actual compilation
+ */
+public boolean compile(String[] argv) {
+
+	// decode command line arguments
+	try {
+		configure(argv);
+		if (this.proceed) {
+//				if (this.verbose) {
+//					System.out.println(new CompilerOptions(this.options));
+//				}
+			if (this.showProgress) this.logger.compiling();
+			for (int i = 0; i < this.repetitions; i++) {
+				this.globalProblemsCount = 0;
+				this.globalErrorsCount = 0;
+				this.globalWarningsCount = 0;
+				this.globalTasksCount = 0;
+				this.lineCount = 0;
+				this.exportedClassFilesCounter = 0;
+
+				if (this.repetitions > 1) {
+					this.logger.flush();
+					this.logger.logRepetition(i, this.repetitions);
+				}
+				// request compilation
+				performCompilation();
+			}
+			if (this.times != null) {
+				this.logger.logAverage(this.times, this.lineCount);
+			}
+			if (this.showProgress) this.logger.printNewLine();
+		}
+		if (this.systemExitWhenFinished) {
+			this.logger.flush();
+			this.logger.close();
+			System.exit(this.globalErrorsCount > 0 ? -1 : 0);
+		}
+	} catch (InvalidInputException e) {
+		this.logger.logException(e);
+		if (this.systemExitWhenFinished) {
+			this.logger.flush();
+			this.logger.close();
+			System.exit(-1);
+		}
+		return false;
+	} catch (RuntimeException e) { // internal compiler failure
+		this.logger.logException(e);
+		if (this.systemExitWhenFinished) {
+			this.logger.flush();
+			this.logger.close();
+			System.exit(-1);
+		}
+		return false;
+	} finally {
+		this.logger.flush();
+		this.logger.close();
+	}
+	if (this.globalErrorsCount == 0)
+		return true;
+	return false;
+}
+
+/*
+ * External API
+ * Handle a single warning token.
+*/
+protected void handleWarningToken(String token, boolean isEnabling, boolean useEnableJavadoc) throws InvalidInputException {
+	if (token.equals("constructorName")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportMethodWithConstructorName,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("pkgDefaultMethod") || token.equals("packageDefaultMethod")/*backward compatible*/ ) { //$NON-NLS-1$ //$NON-NLS-2$
+		this.options.put(
+			CompilerOptions.OPTION_ReportOverridingPackageDefaultMethod,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("maskedCatchBlock") || token.equals("maskedCatchBlocks")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
+		this.options.put(
+			CompilerOptions.OPTION_ReportHiddenCatchBlock,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("deprecation")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportDeprecation,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+		this.options.put(
+			CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode,
+			CompilerOptions.DISABLED);
+		this.options.put(
+			CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod,
+			CompilerOptions.DISABLED);
+	} else if (token.equals("allDeprecation")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportDeprecation,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+		this.options.put(
+			CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode,
+			isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
+		this.options.put(
+			CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod,
+			isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
+	} else if (token.equals("unusedLocal") || token.equals("unusedLocals")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
+		this.options.put(
+			CompilerOptions.OPTION_ReportUnusedLocal,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("unusedArgument") || token.equals("unusedArguments")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
+		this.options.put(
+			CompilerOptions.OPTION_ReportUnusedParameter,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("unusedImport") || token.equals("unusedImports")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
+		this.options.put(
+			CompilerOptions.OPTION_ReportUnusedImport,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("unusedPrivate")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportUnusedPrivateMember,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("unusedLabel")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportUnusedLabel,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("localHiding")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportLocalVariableHiding,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("fieldHiding")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportFieldHiding,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("specialParamHiding")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportSpecialParameterHidingField,
+			isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
+	} else if (token.equals("conditionAssign")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportPossibleAccidentalBooleanAssignment,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+		} else if (token.equals("syntheticAccess") //$NON-NLS-1$
+				|| token.equals("synthetic-access")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportSyntheticAccessEmulation,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("nls")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportNonExternalizedStringLiteral,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("staticReceiver")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportNonStaticAccessToStatic,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("indirectStatic")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportIndirectStaticAccess,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("noEffectAssign")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportNoEffectAssignment,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("intfNonInherited") || token.equals("interfaceNonInherited")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
+		this.options.put(
+			CompilerOptions.OPTION_ReportIncompatibleNonInheritedInterfaceMethod,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("charConcat") || token.equals("noImplicitStringConversion")/*backward compatible*/) {//$NON-NLS-1$ //$NON-NLS-2$
+		this.options.put(
+			CompilerOptions.OPTION_ReportNoImplicitStringConversion,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("semicolon")) {//$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportEmptyStatement,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("serial")) {//$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportMissingSerialVersion,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("emptyBlock")) {//$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportUndocumentedEmptyBlock,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("uselessTypeCheck")) {//$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportUnnecessaryTypeCheck,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("unchecked") || token.equals("unsafe")) {//$NON-NLS-1$ //$NON-NLS-2$
+		this.options.put(
+			CompilerOptions.OPTION_ReportUncheckedTypeOperation,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("raw")) {//$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportRawTypeReference,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("finalBound")) {//$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportFinalParameterBound,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("suppress")) {//$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_SuppressWarnings,
+			isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
+	} else if (token.equals("warningToken")) {//$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportUnhandledWarningToken,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("unnecessaryElse")) {//$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportUnnecessaryElse,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("javadoc")) {//$NON-NLS-1$
+		if (!useEnableJavadoc) {
+			this.options.put(
+				CompilerOptions.OPTION_DocCommentSupport,
+				isEnabling ? CompilerOptions.ENABLED: CompilerOptions.DISABLED);
+		}
+		// if disabling then it's not necessary to set other javadoc options
+		if (isEnabling) {
+			this.options.put(
+				CompilerOptions.OPTION_ReportInvalidJavadoc,
+				CompilerOptions.WARNING);
+			this.options.put(
+				CompilerOptions.OPTION_ReportInvalidJavadocTags,
+				CompilerOptions.ENABLED);
+			this.options.put(
+				CompilerOptions.OPTION_ReportInvalidJavadocTagsDeprecatedRef,
+				CompilerOptions.DISABLED);
+			this.options.put(
+				CompilerOptions.OPTION_ReportInvalidJavadocTagsNotVisibleRef,
+				CompilerOptions.DISABLED);
+			this.options.put(
+				CompilerOptions.OPTION_ReportInvalidJavadocTagsVisibility,
+				CompilerOptions.PRIVATE);
+			this.options.put(
+				CompilerOptions.OPTION_ReportMissingJavadocTags,
+				CompilerOptions.WARNING);
+			this.options.put(
+				CompilerOptions.OPTION_ReportMissingJavadocTagsVisibility,
+				CompilerOptions.PRIVATE);
+		}
+	} else if (token.equals("allJavadoc")) { //$NON-NLS-1$
+		if (!useEnableJavadoc) {
+			this.options.put(
+				CompilerOptions.OPTION_DocCommentSupport,
+				isEnabling ? CompilerOptions.ENABLED: CompilerOptions.DISABLED);
+		}
+		// if disabling then it's not necessary to set other javadoc options
+		if (isEnabling) {
+			this.options.put(
+			CompilerOptions.OPTION_ReportInvalidJavadoc,
+			CompilerOptions.WARNING);
+			this.options.put(
+				CompilerOptions.OPTION_ReportInvalidJavadocTags,
+				CompilerOptions.ENABLED);
+			this.options.put(
+				CompilerOptions.OPTION_ReportInvalidJavadocTagsVisibility,
+				CompilerOptions.PRIVATE);
+			this.options.put(
+				CompilerOptions.OPTION_ReportMissingJavadocTags,
+				CompilerOptions.WARNING);
+			this.options.put(
+				CompilerOptions.OPTION_ReportMissingJavadocTagsVisibility,
+				CompilerOptions.PRIVATE);
+			this.options.put(
+				CompilerOptions.OPTION_ReportMissingJavadocComments,
+				CompilerOptions.WARNING);
+		}
+	} else if (token.startsWith("tasks")) { //$NON-NLS-1$
+		String taskTags = Util.EMPTY_STRING;
+		int start = token.indexOf('(');
+		int end = token.indexOf(')');
+		if (start >= 0 && end >= 0 && start < end){
+			taskTags = token.substring(start+1, end).trim();
+			taskTags = taskTags.replace('|',',');
+		}
+		if (taskTags.length() == 0){
+			throw new InvalidInputException(this.bind("configure.invalidTaskTag", token)); //$NON-NLS-1$
+		}
+		this.options.put(
+			CompilerOptions.OPTION_TaskTags,
+			isEnabling ? taskTags : Util.EMPTY_STRING);
+	} else if (token.equals("assertIdentifier")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportAssertIdentifier,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("enumIdentifier")) { //$NON-NLS-1$
+		this.options.put(
+				CompilerOptions.OPTION_ReportEnumIdentifier,
+				isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("finally")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportFinallyBlockNotCompletingNormally,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("unusedThrown")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportUnusedDeclaredThrownException,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("unqualifiedField") //$NON-NLS-1$
+			|| token.equals("unqualified-field-access")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportUnqualifiedFieldAccess,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("typeHiding")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportTypeParameterHiding,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("varargsCast")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportVarargsArgumentNeedCast,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("null")) { //$NON-NLS-1$
+		if (isEnabling) {
+			this.options.put(CompilerOptions.OPTION_ReportNullReference,
+					CompilerOptions.WARNING);
+			this.options.put(CompilerOptions.OPTION_ReportPotentialNullReference,
+					CompilerOptions.WARNING);
+			this.options.put(CompilerOptions.OPTION_ReportRedundantNullCheck,
+					CompilerOptions.WARNING);
+		} else {
+			this.options.put(CompilerOptions.OPTION_ReportNullReference,
+					CompilerOptions.IGNORE);
+			this.options.put(CompilerOptions.OPTION_ReportPotentialNullReference,
+					CompilerOptions.IGNORE);
+			this.options.put(CompilerOptions.OPTION_ReportRedundantNullCheck,
+					CompilerOptions.IGNORE);
+		}
+	} else if (token.equals("nullDereference")) { //$NON-NLS-1$
+		if (isEnabling) {
+			this.options.put(CompilerOptions.OPTION_ReportNullReference,
+					CompilerOptions.WARNING);
+		} else {
+			this.options.put(CompilerOptions.OPTION_ReportNullReference,
+					CompilerOptions.IGNORE);
+			this.options.put(CompilerOptions.OPTION_ReportPotentialNullReference,
+					CompilerOptions.IGNORE);
+			this.options.put(CompilerOptions.OPTION_ReportRedundantNullCheck,
+					CompilerOptions.IGNORE);
+		}
+	} else if (token.equals("boxing")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportAutoboxing,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("over-ann")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportMissingOverrideAnnotation,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("dep-ann")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportMissingDeprecatedAnnotation,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("intfAnnotation")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportAnnotationSuperInterface,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("enumSwitch") //$NON-NLS-1$
+			|| token.equals("incomplete-switch")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportIncompleteEnumSwitch,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("hiding")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportHiddenCatchBlock,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+		this.options.put(
+			CompilerOptions.OPTION_ReportLocalVariableHiding,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+		this.options.put(
+			CompilerOptions.OPTION_ReportFieldHiding,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+		this.options.put(
+			CompilerOptions.OPTION_ReportTypeParameterHiding,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("static-access")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportNonStaticAccessToStatic,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+		this.options.put(
+			CompilerOptions.OPTION_ReportIndirectStaticAccess,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("unused")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportUnusedLocal,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+		this.options.put(
+			CompilerOptions.OPTION_ReportUnusedParameter,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+		this.options.put(
+			CompilerOptions.OPTION_ReportUnusedImport,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+		this.options.put(
+			CompilerOptions.OPTION_ReportUnusedPrivateMember,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+		this.options.put(
+			CompilerOptions.OPTION_ReportUnusedDeclaredThrownException,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+		this.options.put(
+				CompilerOptions.OPTION_ReportUnusedLabel,
+				isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("paramAssign")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportParameterAssignment,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("discouraged")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportDiscouragedReference,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("forbidden")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportForbiddenReference,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("fallthrough")) { //$NON-NLS-1$
+		this.options.put(
+			CompilerOptions.OPTION_ReportFallthroughCase,
+			isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else if (token.equals("super")) { //$NON-NLS-1$
+		this.options.put(
+				CompilerOptions.OPTION_ReportOverridingMethodWithoutSuperInvocation,
+				isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+	} else {
+		throw new InvalidInputException(this.bind("configure.invalidWarning", token)); //$NON-NLS-1$
+	}
+}
+/*
+ * External API
+ */
+protected ArrayList handleBootclasspath(ArrayList bootclasspaths, String customEncoding) throws InvalidInputException {
+ 	final int bootclasspathsSize = bootclasspaths == null ? 0 : bootclasspaths.size();
+	if (bootclasspathsSize != 0) {
+		String[] paths = new String[bootclasspathsSize];
+		bootclasspaths.toArray(paths);
+		bootclasspaths.clear();
+		for (int i = 0; i < bootclasspathsSize; i++) {
+			processPathEntries(DEFAULT_SIZE_CLASSPATH, bootclasspaths,
+				paths[i], customEncoding, false, true);
+		}
+	} else {
+	 	bootclasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
+		/* no bootclasspath specified
+		 * we can try to retrieve the default librairies of the VM used to run
+		 * the batch compiler
+		 */
+		 String javaversion = System.getProperty("java.version");//$NON-NLS-1$
+		 if (javaversion != null && javaversion.equalsIgnoreCase("1.1.8")) { //$NON-NLS-1$
+			this.logger.logWrongJDK();
+			this.proceed = false;
+			return null;
+		 }
+
+	 	/*
+	 	 * Handle >= JDK 1.2.2 settings: retrieve the bootclasspath
+	 	 */
+		// check bootclasspath properties for Sun, JRockit and Harmony VMs
+		String bootclasspathProperty = System.getProperty("sun.boot.class.path"); //$NON-NLS-1$
+		if ((bootclasspathProperty == null) || (bootclasspathProperty.length() == 0)) {
+			// IBM J9 VMs
+			bootclasspathProperty = System.getProperty("vm.boot.class.path"); //$NON-NLS-1$
+			if ((bootclasspathProperty == null) || (bootclasspathProperty.length() == 0)) {
+				// Harmony using IBM VME
+				bootclasspathProperty = System.getProperty("org.apache.harmony.boot.class.path"); //$NON-NLS-1$
+			}
+		}
+		if ((bootclasspathProperty != null) && (bootclasspathProperty.length() != 0)) {
+			StringTokenizer tokenizer = new StringTokenizer(bootclasspathProperty, File.pathSeparator);
+			String token;
+			while (tokenizer.hasMoreTokens()) {
+				token = tokenizer.nextToken();
+				FileSystem.Classpath currentClasspath = FileSystem
+						.getClasspath(token, customEncoding, null);
+				if (currentClasspath != null) {
 					bootclasspaths.add(currentClasspath);
 				}
-			} else {
-				this.logger.logIncorrectClasspath(currentClasspathName);
-				// we go on anyway
 			}
 		} else {
-			this.logger.logIncorrectClasspath(currentClasspathName);
-			// we go on anyway
-		}
-	}
-
-	private File javaHomeCache;
-	private boolean javaHomeChecked;
-	private File getJavaHome() {
-		if (!javaHomeChecked) {
-			javaHomeChecked = true;
-			String javaHome = System.getProperty("java.home");//$NON-NLS-1$
+			// try to get all jars inside the lib folder of the java home
+			final File javaHome = getJavaHome();
 			if (javaHome != null) {
-				javaHomeCache = new File(javaHome);
-				if (!javaHomeCache.exists())
-					javaHomeCache = null;
+				File[] directoriesToCheck = null;
+				if (System.getProperty("os.name").startsWith("Mac")) {//$NON-NLS-1$//$NON-NLS-2$
+					directoriesToCheck = new File[] {
+						new File(javaHome, "../Classes"), //$NON-NLS-1$
+					};
+				} else {
+					// fall back to try to retrieve them out of the lib directory
+					directoriesToCheck = new File[] {
+						new File(javaHome, "lib") //$NON-NLS-1$
+					};
+				}
+				File[][] systemLibrariesJars = getLibrariesFiles(directoriesToCheck);
+				if (systemLibrariesJars != null) {
+					for (int i = 0, max = systemLibrariesJars.length; i < max; i++) {
+						File[] current = systemLibrariesJars[i];
+						if (current != null) {
+							for (int j = 0, max2 = current.length; j < max2; j++) {
+								FileSystem.Classpath classpath =
+									FileSystem.getClasspath(current[j].getAbsolutePath(),
+										null, false, null, null);
+								if (classpath != null) {
+									bootclasspaths.add(classpath);
+								}
+							}
+						}
+					}
+				}
 			}
 		}
-		return javaHomeCache;
 	}
-	
-	private void disableWarnings() {
-		Object[] entries = this.options.entrySet().toArray();
-		for (int i = 0, max = entries.length; i < max; i++) {
-			Map.Entry entry = (Map.Entry) entries[i];
-			if (!(entry.getKey() instanceof String))
+	return bootclasspaths;
+}
+/*
+ * External API
+ */
+protected ArrayList handleClasspath(ArrayList classpaths, String customEncoding) throws InvalidInputException {
+	final int classpathsSize = classpaths == null ? 0 : classpaths.size();
+	if (classpathsSize != 0) {
+		String[] paths = new String[classpathsSize];
+		classpaths.toArray(paths);
+		classpaths.clear();
+		for (int i = 0; i < classpathsSize; i++) {
+			processPathEntries(DEFAULT_SIZE_CLASSPATH, classpaths, paths[i],
+					customEncoding, false, true);
+		}
+	} else {
+		// no user classpath specified.
+		classpaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
+		String classProp = System.getProperty("java.class.path"); //$NON-NLS-1$
+		if ((classProp == null) || (classProp.length() == 0)) {
+			this.logger.logNoClasspath();
+			classpaths.add(FileSystem.getClasspath(System.getProperty("user.dir"), customEncoding, null));//$NON-NLS-1$
+		} else {
+			StringTokenizer tokenizer = new StringTokenizer(classProp, File.pathSeparator);
+			String token;
+			while (tokenizer.hasMoreTokens()) {
+				token = tokenizer.nextToken();
+				FileSystem.Classpath currentClasspath = FileSystem
+						.getClasspath(token, customEncoding, null);
+				if (currentClasspath != null) {
+					classpaths.add(currentClasspath);
+				} else if (token.length() != 0) {
+					this.logger.logIncorrectClasspath(token);
+				}
+			}
+		}
+	}
+	return classpaths;
+}
+/*
+ * External API
+ * Handle extdirs processing
+ */
+protected ArrayList handleExtdirs(ArrayList extdirsClasspaths) {
+ 	final File javaHome = getJavaHome();
+
+	/*
+	 * Feed extDirClasspath according to:
+	 * - -extdirs first if present;
+	 * - else java.ext.dirs if defined;
+	 * - else default extensions directory for the platform.
+	 */
+	if (extdirsClasspaths == null) {
+		extdirsClasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
+		String extdirsStr = System.getProperty("java.ext.dirs"); //$NON-NLS-1$
+		if (extdirsStr == null) {
+			extdirsClasspaths.add(javaHome.getAbsolutePath() + "/lib/ext"); //$NON-NLS-1$
+		} else {
+			StringTokenizer tokenizer = new StringTokenizer(extdirsStr, File.pathSeparator);
+			while (tokenizer.hasMoreTokens())
+				extdirsClasspaths.add(tokenizer.nextToken());
+		}
+	}
+
+	/*
+	 * Feed extdirsClasspath with the entries found into the directories listed by
+	 * extdirsNames.
+	 */
+	if (extdirsClasspaths.size() != 0) {
+		File[] directoriesToCheck = new File[extdirsClasspaths.size()];
+		for (int i = 0; i < directoriesToCheck.length; i++)
+			directoriesToCheck[i] = new File((String) extdirsClasspaths.get(i));
+		extdirsClasspaths.clear();
+		File[][] extdirsJars = getLibrariesFiles(directoriesToCheck);
+		if (extdirsJars != null) {
+			for (int i = 0, max = extdirsJars.length; i < max; i++) {
+				File[] current = extdirsJars[i];
+				if (current != null) {
+					for (int j = 0, max2 = current.length; j < max2; j++) {
+						FileSystem.Classpath classpath =
+							FileSystem.getClasspath(
+									current[j].getAbsolutePath(),
+									null, null);
+						if (classpath != null) {
+							extdirsClasspaths.add(classpath);
+						}
+					}
+				} else if (directoriesToCheck[i].isFile()) {
+					this.logger.logIncorrectExtDirsEntry(directoriesToCheck[i].getAbsolutePath());
+				}
+			}
+		}
+	}
+
+	return extdirsClasspaths;
+}
+/*
+ * External API
+ */
+protected ArrayList handleEndorseddirs(ArrayList endorsedDirClasspaths) {
+ 	final File javaHome = getJavaHome();
+	/*
+	 * Feed endorsedDirClasspath according to:
+	 * - -endorseddirs first if present;
+	 * - else java.endorsed.dirs if defined;
+	 * - else default extensions directory for the platform. (/lib/endorsed)
+	 */
+	if (endorsedDirClasspaths == null) {
+		endorsedDirClasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
+		String endorsedDirsStr = System.getProperty("java.endorsed.dirs"); //$NON-NLS-1$
+		if (endorsedDirsStr == null) {
+			if (javaHome != null) {
+				endorsedDirClasspaths.add(javaHome.getAbsolutePath() + "/lib/endorsed"); //$NON-NLS-1$
+			}
+		} else {
+			StringTokenizer tokenizer = new StringTokenizer(endorsedDirsStr, File.pathSeparator);
+			while (tokenizer.hasMoreTokens()) {
+				endorsedDirClasspaths.add(tokenizer.nextToken());
+			}
+		}
+	}
+
+	/*
+	 * Feed extdirsClasspath with the entries found into the directories listed by
+	 * extdirsNames.
+	 */
+	if (endorsedDirClasspaths.size() != 0) {
+		File[] directoriesToCheck = new File[endorsedDirClasspaths.size()];
+		for (int i = 0; i < directoriesToCheck.length; i++)
+			directoriesToCheck[i] = new File((String) endorsedDirClasspaths.get(i));
+		endorsedDirClasspaths.clear();
+		File[][] endorsedDirsJars = getLibrariesFiles(directoriesToCheck);
+		if (endorsedDirsJars != null) {
+			for (int i = 0, max = endorsedDirsJars.length; i < max; i++) {
+				File[] current = endorsedDirsJars[i];
+				if (current != null) {
+					for (int j = 0, max2 = current.length; j < max2; j++) {
+						FileSystem.Classpath classpath =
+							FileSystem.getClasspath(
+									current[j].getAbsolutePath(),
+									null, null);
+						if (classpath != null) {
+							endorsedDirClasspaths.add(classpath);
+						}
+					}
+				} else if (directoriesToCheck[i].isFile()) {
+					this.logger.logIncorrectEndorsedDirsEntry(directoriesToCheck[i].getAbsolutePath());
+				}
+			}
+		}
+	}
+	return endorsedDirClasspaths;
+}
+
+/*
+Decode the command line arguments
+ */
+public void configure(String[] argv) throws InvalidInputException {
+
+	if ((argv == null) || (argv.length == 0)) {
+		printUsage();
+		return;
+	}
+
+	final int INSIDE_CLASSPATH_start = 1;
+	final int INSIDE_DESTINATION_PATH = 3;
+	final int INSIDE_TARGET = 4;
+	final int INSIDE_LOG = 5;
+	final int INSIDE_REPETITION = 6;
+	final int INSIDE_SOURCE = 7;
+	final int INSIDE_DEFAULT_ENCODING = 8;
+	final int INSIDE_BOOTCLASSPATH_start = 9;
+	final int INSIDE_MAX_PROBLEMS = 11;
+	final int INSIDE_EXT_DIRS = 12;
+	final int INSIDE_SOURCE_PATH_start = 13;
+	final int INSIDE_ENDORSED_DIRS = 15;
+	final int INSIDE_SOURCE_DIRECTORY_DESTINATION_PATH = 16;
+	final int INSIDE_PROCESSOR_PATH_start = 17;
+	final int INSIDE_PROCESSOR_start = 18;
+	final int INSIDE_S_start = 19;
+	final int INSIDE_CLASS_NAMES = 20;
+
+	final int DEFAULT = 0;
+	ArrayList bootclasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
+	String sourcepathClasspathArg = null;
+	ArrayList sourcepathClasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
+	ArrayList classpaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
+	ArrayList extdirsClasspaths = null;
+	ArrayList endorsedDirClasspaths = null;
+
+	int index = -1;
+	int filesCount = 0;
+	int classCount = 0;
+	int argCount = argv.length;
+	int mode = DEFAULT;
+	this.repetitions = 0;
+	boolean printUsageRequired = false;
+	String usageSection = null;
+	boolean printVersionRequired = false;
+
+	boolean didSpecifyDefaultEncoding = false;
+	boolean didSpecifyDeprecation = false;
+	boolean didSpecifyWarnings = false;
+	boolean useEnableJavadoc = false;
+	boolean didSpecifyCompliance = false;
+	boolean didSpecifyDisabledAnnotationProcessing = false;
+
+	String customEncoding = null;
+	String customDestinationPath = null;
+	String currentSourceDirectory = null;
+	String currentArg = Util.EMPTY_STRING;
+
+	// expand the command line if necessary
+	boolean needExpansion = false;
+	loop: for (int i = 0; i < argCount; i++) {
+			if (argv[i].startsWith("@")) { //$NON-NLS-1$
+				needExpansion = true;
+				break loop;
+			}
+	}
+
+	String[] newCommandLineArgs = null;
+	if (needExpansion) {
+		newCommandLineArgs = new String[argCount];
+		index = 0;
+		for (int i = 0; i < argCount; i++) {
+			String[] newArgs = null;
+			String arg = argv[i].trim();
+			if (arg.startsWith("@")) { //$NON-NLS-1$
+				try {
+					LineNumberReader reader = new LineNumberReader(new StringReader(new String(Util.getFileCharContent(new File(arg.substring(1)), null))));
+					StringBuffer buffer = new StringBuffer();
+					String line;
+					while((line = reader.readLine()) != null) {
+						line = line.trim();
+						if (!line.startsWith("#")) { //$NON-NLS-1$
+							buffer.append(line).append(" "); //$NON-NLS-1$
+						}
+					}
+					newArgs = tokenize(buffer.toString());
+				} catch(IOException e) {
+					throw new InvalidInputException(
+						this.bind("configure.invalidexpansionargumentname", arg)); //$NON-NLS-1$
+				}
+			}
+			if (newArgs != null) {
+				int newCommandLineArgsLength = newCommandLineArgs.length;
+				int newArgsLength = newArgs.length;
+				System.arraycopy(newCommandLineArgs, 0, (newCommandLineArgs = new String[newCommandLineArgsLength + newArgsLength - 1]), 0, index);
+				System.arraycopy(newArgs, 0, newCommandLineArgs, index, newArgsLength);
+				index += newArgsLength;
+			} else {
+				newCommandLineArgs[index++] = arg;
+			}
+		}
+		index = -1;
+	} else {
+		newCommandLineArgs = argv;
+		for (int i = 0; i < argCount; i++) {
+			newCommandLineArgs[i] = newCommandLineArgs[i].trim();
+		}
+	}
+	argCount = newCommandLineArgs.length;
+	this.expandedCommandLine = newCommandLineArgs;
+	while (++index < argCount) {
+
+		if (customEncoding != null) {
+			throw new InvalidInputException(
+				this.bind("configure.unexpectedCustomEncoding", currentArg, customEncoding)); //$NON-NLS-1$
+		}
+
+		currentArg = newCommandLineArgs[index];
+
+		switch(mode) {
+			case DEFAULT :
+				if (currentArg.startsWith("[")) { //$NON-NLS-1$
+					throw new InvalidInputException(
+						this.bind("configure.unexpectedBracket", //$NON-NLS-1$
+									currentArg));
+				}
+
+				if (currentArg.endsWith("]")) { //$NON-NLS-1$
+					// look for encoding specification
+					int encodingStart = currentArg.indexOf('[') + 1;
+					if (encodingStart <= 1) {
+						throw new InvalidInputException(
+								this.bind("configure.unexpectedBracket", currentArg)); //$NON-NLS-1$
+					}
+					int encodingEnd = currentArg.length() - 1;
+					if (encodingStart >= 1) {
+						if (encodingStart < encodingEnd) {
+							customEncoding = currentArg.substring(encodingStart, encodingEnd);
+							try { // ensure encoding is supported
+								new InputStreamReader(new ByteArrayInputStream(new byte[0]), customEncoding);
+							} catch (UnsupportedEncodingException e) {
+								throw new InvalidInputException(
+									this.bind("configure.unsupportedEncoding", customEncoding)); //$NON-NLS-1$
+							}
+						}
+						currentArg = currentArg.substring(0, encodingStart - 1);
+					}
+				}
+
+				if (currentArg.endsWith(SuffixConstants.SUFFIX_STRING_java)) {
+					if (this.filenames == null) {
+						this.filenames = new String[argCount - index];
+						this.encodings = new String[argCount - index];
+						this.destinationPaths = new String[argCount - index];
+					} else if (filesCount == this.filenames.length) {
+						int length = this.filenames.length;
+						System.arraycopy(
+							this.filenames,
+							0,
+							(this.filenames = new String[length + argCount - index]),
+							0,
+							length);
+						System.arraycopy(
+							this.encodings,
+							0,
+							(this.encodings = new String[length + argCount - index]),
+							0,
+							length);
+						System.arraycopy(
+							this.destinationPaths,
+							0,
+							(this.destinationPaths = new String[length + argCount - index]),
+							0,
+							length);
+					}
+					this.filenames[filesCount] = currentArg;
+					this.encodings[filesCount++] = customEncoding;
+					// destination path cannot be specified upon an individual file
+					customEncoding = null;
+					mode = DEFAULT;
+					continue;
+				}
+				if (currentArg.equals("-log")) { //$NON-NLS-1$
+					if (this.log != null)
+						throw new InvalidInputException(
+							this.bind("configure.duplicateLog", currentArg)); //$NON-NLS-1$
+					mode = INSIDE_LOG;
+					continue;
+				}
+				if (currentArg.equals("-repeat")) { //$NON-NLS-1$
+					if (this.repetitions > 0)
+						throw new InvalidInputException(
+							this.bind("configure.duplicateRepeat", currentArg)); //$NON-NLS-1$
+					mode = INSIDE_REPETITION;
+					continue;
+				}
+				if (currentArg.equals("-maxProblems")) { //$NON-NLS-1$
+					if (this.maxProblems > 0)
+						throw new InvalidInputException(
+							this.bind("configure.duplicateMaxProblems", currentArg)); //$NON-NLS-1$
+					mode = INSIDE_MAX_PROBLEMS;
+					continue;
+				}
+				if (currentArg.equals("-source")) { //$NON-NLS-1$
+					mode = INSIDE_SOURCE;
+					continue;
+				}
+				if (currentArg.equals("-encoding")) { //$NON-NLS-1$
+					mode = INSIDE_DEFAULT_ENCODING;
+					continue;
+				}
+				if (currentArg.equals("-1.3")) { //$NON-NLS-1$
+					if (didSpecifyCompliance) {
+						throw new InvalidInputException(
+							this.bind("configure.duplicateCompliance", currentArg));//$NON-NLS-1$
+					}
+					didSpecifyCompliance = true;
+					this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_3);
+					mode = DEFAULT;
+					continue;
+				}
+				if (currentArg.equals("-1.4")) { //$NON-NLS-1$
+					if (didSpecifyCompliance) {
+						throw new InvalidInputException(
+							this.bind("configure.duplicateCompliance", currentArg)); //$NON-NLS-1$
+					}
+					didSpecifyCompliance = true;
+					this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
+					mode = DEFAULT;
+					continue;
+				}
+				if (currentArg.equals("-1.5") || currentArg.equals("-5") || currentArg.equals("-5.0")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+					if (didSpecifyCompliance) {
+						throw new InvalidInputException(
+							this.bind("configure.duplicateCompliance", currentArg)); //$NON-NLS-1$
+					}
+					didSpecifyCompliance = true;
+					this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_5);
+					mode = DEFAULT;
+					continue;
+				}
+				if (currentArg.equals("-1.6") || currentArg.equals("-6") || currentArg.equals("-6.0")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+					if (didSpecifyCompliance) {
+						throw new InvalidInputException(
+							this.bind("configure.duplicateCompliance", currentArg)); //$NON-NLS-1$
+					}
+					didSpecifyCompliance = true;
+					this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_6);
+					mode = DEFAULT;
+					continue;
+				}
+				if (currentArg.equals("-1.7") || currentArg.equals("-7") || currentArg.equals("-7.0")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+					if (didSpecifyCompliance) {
+						throw new InvalidInputException(
+							this.bind("configure.duplicateCompliance", currentArg)); //$NON-NLS-1$
+					}
+					didSpecifyCompliance = true;
+					this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_7);
+					mode = DEFAULT;
+					continue;
+				}
+				if (currentArg.equals("-d")) { //$NON-NLS-1$
+					if (this.destinationPath != null) {
+						StringBuffer errorMessage = new StringBuffer();
+						errorMessage.append(currentArg);
+						if ((index + 1) < argCount) {
+							errorMessage.append(' ');
+							errorMessage.append(newCommandLineArgs[index + 1]);
+						}
+						throw new InvalidInputException(
+							this.bind("configure.duplicateOutputPath", errorMessage.toString())); //$NON-NLS-1$
+					}
+					mode = INSIDE_DESTINATION_PATH;
+					continue;
+				}
+				if (currentArg.equals("-classpath") //$NON-NLS-1$
+					|| currentArg.equals("-cp")) { //$NON-NLS-1$
+					mode = INSIDE_CLASSPATH_start;
+					continue;
+				}
+				if (currentArg.equals("-bootclasspath")) {//$NON-NLS-1$
+					if (bootclasspaths.size() > 0) {
+						StringBuffer errorMessage = new StringBuffer();
+						errorMessage.append(currentArg);
+						if ((index + 1) < argCount) {
+							errorMessage.append(' ');
+							errorMessage.append(newCommandLineArgs[index + 1]);
+						}
+						throw new InvalidInputException(
+							this.bind("configure.duplicateBootClasspath", errorMessage.toString())); //$NON-NLS-1$
+					}
+					mode = INSIDE_BOOTCLASSPATH_start;
+					continue;
+				}
+				if (currentArg.equals("-sourcepath")) {//$NON-NLS-1$
+					if (sourcepathClasspathArg != null) {
+						StringBuffer errorMessage = new StringBuffer();
+						errorMessage.append(currentArg);
+						if ((index + 1) < argCount) {
+							errorMessage.append(' ');
+							errorMessage.append(newCommandLineArgs[index + 1]);
+						}
+						throw new InvalidInputException(
+							this.bind("configure.duplicateSourcepath", errorMessage.toString())); //$NON-NLS-1$
+					}
+					mode = INSIDE_SOURCE_PATH_start;
+					continue;
+				}
+				if (currentArg.equals("-extdirs")) {//$NON-NLS-1$
+					if (extdirsClasspaths != null) {
+						StringBuffer errorMessage = new StringBuffer();
+						errorMessage.append(currentArg);
+						if ((index + 1) < argCount) {
+							errorMessage.append(' ');
+							errorMessage.append(newCommandLineArgs[index + 1]);
+						}
+						throw new InvalidInputException(
+							this.bind("configure.duplicateExtDirs", errorMessage.toString())); //$NON-NLS-1$
+					}
+					mode = INSIDE_EXT_DIRS;
+					continue;
+				}
+				if (currentArg.equals("-endorseddirs")) { //$NON-NLS-1$
+					if (endorsedDirClasspaths != null) {
+						StringBuffer errorMessage = new StringBuffer();
+						errorMessage.append(currentArg);
+						if ((index + 1) < argCount) {
+							errorMessage.append(' ');
+							errorMessage.append(newCommandLineArgs[index + 1]);
+						}
+						throw new InvalidInputException(
+							this.bind("configure.duplicateEndorsedDirs", errorMessage.toString())); //$NON-NLS-1$
+					}
+					mode = INSIDE_ENDORSED_DIRS;
+					continue;
+				}
+				if (currentArg.equals("-progress")) { //$NON-NLS-1$
+					mode = DEFAULT;
+					this.showProgress = true;
+					continue;
+				}
+				if (currentArg.equals("-proceedOnError")) { //$NON-NLS-1$
+					mode = DEFAULT;
+					this.proceedOnError = true;
+					continue;
+				}
+				if (currentArg.equals("-time")) { //$NON-NLS-1$
+					mode = DEFAULT;
+					this.timing = true;
+					continue;
+				}
+				if (currentArg.equals("-version") //$NON-NLS-1$
+						|| currentArg.equals("-v")) { //$NON-NLS-1$
+					this.logger.logVersion(true);
+					this.proceed = false;
+					return;
+				}
+				if (currentArg.equals("-showversion")) { //$NON-NLS-1$
+					printVersionRequired = true;
+					mode = DEFAULT;
+					continue;
+				}
+				if ("-deprecation".equals(currentArg)) { //$NON-NLS-1$
+					didSpecifyDeprecation = true;
+					this.options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
+					mode = DEFAULT;
+					continue;
+				}
+				if (currentArg.equals("-help") || currentArg.equals("-?")) { //$NON-NLS-1$ //$NON-NLS-2$
+					printUsageRequired = true;
+					mode = DEFAULT;
+					continue;
+				}
+				if (currentArg.equals("-help:warn") || //$NON-NLS-1$
+						currentArg.equals("-?:warn")) { //$NON-NLS-1$
+					printUsageRequired = true;
+					usageSection = "misc.usage.warn"; //$NON-NLS-1$
+					continue;
+				}
+				if (currentArg.equals("-noExit")) { //$NON-NLS-1$
+					this.systemExitWhenFinished = false;
+					mode = DEFAULT;
+					continue;
+				}
+				if (currentArg.equals("-verbose")) { //$NON-NLS-1$
+					this.verbose = true;
+					mode = DEFAULT;
+					continue;
+				}
+				if (currentArg.equals("-referenceInfo")) { //$NON-NLS-1$
+					this.produceRefInfo = true;
+					mode = DEFAULT;
+					continue;
+				}
+				if (currentArg.equals("-inlineJSR")) { //$NON-NLS-1$
+				    mode = DEFAULT;
+					this.options.put(
+							CompilerOptions.OPTION_InlineJsr,
+							CompilerOptions.ENABLED);
+				    continue;
+				}
+				if (currentArg.startsWith("-g")) { //$NON-NLS-1$
+					mode = DEFAULT;
+					String debugOption = currentArg;
+					int length = currentArg.length();
+					if (length == 2) {
+						this.options.put(
+							CompilerOptions.OPTION_LocalVariableAttribute,
+							CompilerOptions.GENERATE);
+						this.options.put(
+							CompilerOptions.OPTION_LineNumberAttribute,
+							CompilerOptions.GENERATE);
+						this.options.put(
+							CompilerOptions.OPTION_SourceFileAttribute,
+							CompilerOptions.GENERATE);
+						continue;
+					}
+					if (length > 3) {
+						this.options.put(
+							CompilerOptions.OPTION_LocalVariableAttribute,
+							CompilerOptions.DO_NOT_GENERATE);
+						this.options.put(
+							CompilerOptions.OPTION_LineNumberAttribute,
+							CompilerOptions.DO_NOT_GENERATE);
+						this.options.put(
+							CompilerOptions.OPTION_SourceFileAttribute,
+							CompilerOptions.DO_NOT_GENERATE);
+						if (length == 7 && debugOption.equals("-g:" + NONE)) //$NON-NLS-1$
+							continue;
+						StringTokenizer tokenizer =
+							new StringTokenizer(debugOption.substring(3, debugOption.length()), ","); //$NON-NLS-1$
+						while (tokenizer.hasMoreTokens()) {
+							String token = tokenizer.nextToken();
+							if (token.equals("vars")) { //$NON-NLS-1$
+								this.options.put(
+									CompilerOptions.OPTION_LocalVariableAttribute,
+									CompilerOptions.GENERATE);
+							} else if (token.equals("lines")) { //$NON-NLS-1$
+								this.options.put(
+									CompilerOptions.OPTION_LineNumberAttribute,
+									CompilerOptions.GENERATE);
+							} else if (token.equals("source")) { //$NON-NLS-1$
+								this.options.put(
+									CompilerOptions.OPTION_SourceFileAttribute,
+									CompilerOptions.GENERATE);
+							} else {
+								throw new InvalidInputException(
+									this.bind("configure.invalidDebugOption", debugOption)); //$NON-NLS-1$
+							}
+						}
+						continue;
+					}
+					throw new InvalidInputException(
+						this.bind("configure.invalidDebugOption", debugOption)); //$NON-NLS-1$
+				}
+				if (currentArg.startsWith("-nowarn")) { //$NON-NLS-1$
+					disableWarnings();
+					mode = DEFAULT;
+					continue;
+				}
+				if (currentArg.startsWith("-warn")) { //$NON-NLS-1$
+					mode = DEFAULT;
+					String warningOption = currentArg;
+					int length = currentArg.length();
+					if (length == 10 && warningOption.equals("-warn:" + NONE)) { //$NON-NLS-1$
+						disableWarnings();
+						continue;
+					}
+					if (length <= 6) {
+						throw new InvalidInputException(
+							this.bind("configure.invalidWarningConfiguration", warningOption)); //$NON-NLS-1$
+					}
+					int warnTokenStart;
+					boolean isEnabling;
+					switch (warningOption.charAt(6)) {
+						case '+' :
+							warnTokenStart = 7;
+							isEnabling = true;
+							break;
+						case '-' :
+							warnTokenStart = 7;
+							isEnabling = false; // mentionned warnings are disabled
+							break;
+						default:
+							warnTokenStart = 6;
+							// clear default warning level
+							// but allow multiple warning option on the command line
+							if (!didSpecifyWarnings) disableWarnings();
+							isEnabling = true;
+					}
+
+					StringTokenizer tokenizer =
+						new StringTokenizer(warningOption.substring(warnTokenStart, warningOption.length()), ","); //$NON-NLS-1$
+					int tokenCounter = 0;
+
+					if (didSpecifyDeprecation) {  // deprecation could have also been set through -deprecation option
+						this.options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
+					}
+
+					while (tokenizer.hasMoreTokens()) {
+						String token = tokenizer.nextToken();
+						tokenCounter++;
+						handleWarningToken(token, isEnabling, useEnableJavadoc);
+					}
+					if (tokenCounter == 0)
+						throw new InvalidInputException(
+							this.bind("configure.invalidWarningOption", currentArg)); //$NON-NLS-1$
+					didSpecifyWarnings = true;
+					continue;
+				}
+				if (currentArg.equals("-target")) { //$NON-NLS-1$
+					mode = INSIDE_TARGET;
+					continue;
+				}
+				if (currentArg.equals("-preserveAllLocals")) { //$NON-NLS-1$
+					this.options.put(
+						CompilerOptions.OPTION_PreserveUnusedLocal,
+						CompilerOptions.PRESERVE);
+				    mode = DEFAULT;
+					continue;
+				}
+				if (currentArg.equals("-enableJavadoc")) {//$NON-NLS-1$
+				    mode = DEFAULT;
+					this.options.put(
+						CompilerOptions.OPTION_DocCommentSupport,
+						CompilerOptions.ENABLED);
+					useEnableJavadoc = true;
+					continue;
+				}
+				if (currentArg.equals("-Xemacs")) { //$NON-NLS-1$
+					mode = DEFAULT;
+					this.logger.setEmacs();
+					continue;
+				}
+				// annotation processing
+				if (currentArg.startsWith("-A")) { //$NON-NLS-1$
+					mode = DEFAULT;
+					continue;
+				}
+				if (currentArg.equals("-processorpath")) { //$NON-NLS-1$
+					mode = INSIDE_PROCESSOR_PATH_start;
+					continue;
+				}
+				if (currentArg.equals("-processor")) { //$NON-NLS-1$
+					mode = INSIDE_PROCESSOR_start;
+					continue;
+				}
+				if (currentArg.equals("-proc:only")) { //$NON-NLS-1$
+					this.options.put(
+						CompilerOptions.OPTION_GenerateClassFiles,
+						CompilerOptions.DISABLED);
+					mode = DEFAULT;
+					continue;
+				}
+				if (currentArg.equals("-proc:none")) { //$NON-NLS-1$
+					didSpecifyDisabledAnnotationProcessing = true;
+					this.options.put(
+						CompilerOptions.OPTION_Process_Annotations,
+						CompilerOptions.DISABLED);
+					mode = DEFAULT;
+					continue;
+				}
+				if (currentArg.equals("-s")) { //$NON-NLS-1$
+					mode = INSIDE_S_start;
+					continue;
+				}
+				if (currentArg.equals("-XprintProcessorInfo") //$NON-NLS-1$
+						|| currentArg.equals("-XprintRounds")) { //$NON-NLS-1$
+					mode = DEFAULT;
+					continue;
+				}
+				// tolerated javac options - quietly filtered out
+				if (currentArg.startsWith("-X")) { //$NON-NLS-1$
+					mode = DEFAULT;
+					continue;
+				}
+				if (currentArg.startsWith("-J")) { //$NON-NLS-1$
+					mode = DEFAULT;
+					continue;
+				}
+				if (currentArg.equals("-O")) { //$NON-NLS-1$
+					mode = DEFAULT;
+					continue;
+				}
+				if (currentArg.equals("-classNames")) { //$NON-NLS-1$
+					mode = INSIDE_CLASS_NAMES;
+					continue;
+				}
+				break;
+			case INSIDE_TARGET :
+				if (this.didSpecifyTarget) {
+					throw new InvalidInputException(
+						this.bind("configure.duplicateTarget", currentArg));//$NON-NLS-1$
+				}
+				this.didSpecifyTarget = true;
+				if (currentArg.equals("1.1")) { //$NON-NLS-1$
+					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_1);
+				} else if (currentArg.equals("1.2")) { //$NON-NLS-1$
+					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2);
+				} else if (currentArg.equals("1.3")) { //$NON-NLS-1$
+					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_3);
+				} else if (currentArg.equals("1.4")) { //$NON-NLS-1$
+					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
+				} else if (currentArg.equals("1.5") || currentArg.equals("5") || currentArg.equals("5.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
+				} else if (currentArg.equals("1.6") || currentArg.equals("6") || currentArg.equals("6.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
+				} else if (currentArg.equals("1.7") || currentArg.equals("7") || currentArg.equals("7.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_7);
+				} else if (currentArg.equals("jsr14")) { //$NON-NLS-1$
+					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_JSR14);
+				} else {
+					throw new InvalidInputException(this.bind("configure.targetJDK", currentArg)); //$NON-NLS-1$
+				}
+				mode = DEFAULT;
 				continue;
-			if (!(entry.getValue() instanceof String))
+			case INSIDE_LOG :
+				this.log = currentArg;
+				mode = DEFAULT;
 				continue;
-			if (((String) entry.getValue()).equals(CompilerOptions.WARNING)) {
-				this.options.put(entry.getKey(), CompilerOptions.IGNORE);
-			}
-		}
-		this.options.put(CompilerOptions.OPTION_TaskTags, ""); //$NON-NLS-1$
-	}
-
-	public String extractDestinationPathFromSourceFile(CompilationResult result) {
-		ICompilationUnit compilationUnit = result.compilationUnit;
-		if (compilationUnit != null) {
-			char[] fileName = compilationUnit.getFileName();
-			int lastIndex = CharOperation.lastIndexOf(java.io.File.separatorChar, fileName);
-			if (lastIndex == -1) {
-				return System.getProperty("user.dir"); //$NON-NLS-1$
-			}
-			return new String(fileName, 0, lastIndex);
-		}
-		return System.getProperty("user.dir"); //$NON-NLS-1$
-	}
-	/*
-	 * Answer the component to which will be handed back compilation results from the compiler
-	 */
-	public ICompilerRequestor getBatchRequestor() {
-		return new ICompilerRequestor() {
-			int lineDelta = 0;
-			public void acceptResult(CompilationResult compilationResult) {
-				if (compilationResult.lineSeparatorPositions != null) {
-					int unitLineCount = compilationResult.lineSeparatorPositions.length;
-					Main.this.lineCount += unitLineCount;
-					this.lineDelta += unitLineCount;
-					if (Main.this.showProgress && this.lineDelta > 2000) {
-						// in -log mode, dump a dot every 2000 lines compiled
-						Main.this.logger.logProgress();
-						this.lineDelta = 0;
+			case INSIDE_REPETITION :
+				try {
+					this.repetitions = Integer.parseInt(currentArg);
+					if (this.repetitions <= 0) {
+						throw new InvalidInputException(this.bind("configure.repetition", currentArg)); //$NON-NLS-1$
 					}
+				} catch (NumberFormatException e) {
+					throw new InvalidInputException(this.bind("configure.repetition", currentArg)); //$NON-NLS-1$
 				}
-				Main.this.logger.startLoggingSource(compilationResult);
-				if (compilationResult.hasProblems() || compilationResult.hasTasks()) {
-					int localErrorCount = Main.this.logger.logProblems(compilationResult.getAllProblems(), compilationResult.compilationUnit.getContents(), Main.this);
-					// exit?
-					if (Main.this.systemExitWhenFinished && !Main.this.proceedOnError && (localErrorCount > 0)) {
-						Main.this.logger.endLoggingSource();
-						Main.this.logger.endLoggingSources();
-						Main.this.logger.printStats(Main.this);
-						Main.this.logger.flush();
-						Main.this.logger.close();
-						System.exit(-1);
+				mode = DEFAULT;
+				continue;
+			case INSIDE_MAX_PROBLEMS :
+				try {
+					this.maxProblems = Integer.parseInt(currentArg);
+					if (this.maxProblems <= 0) {
+						throw new InvalidInputException(this.bind("configure.maxProblems", currentArg)); //$NON-NLS-1$
 					}
+					this.options.put(CompilerOptions.OPTION_MaxProblemPerUnit, currentArg);
+				} catch (NumberFormatException e) {
+					throw new InvalidInputException(this.bind("configure.maxProblems", currentArg)); //$NON-NLS-1$
 				}
-				outputClassFiles(compilationResult);
-				Main.this.logger.endLoggingSource();
-			}
-		};
-	}
-	/*
-	 *  Build the set of compilation source units
-	 */
-	public CompilationUnit[] getCompilationUnits()
-		throws InvalidInputException {
-		int fileCount = this.filenames.length;
-		CompilationUnit[] units = new CompilationUnit[fileCount];
-		HashtableOfObject knownFileNames = new HashtableOfObject(fileCount);
-
-		String defaultEncoding = (String) this.options.get(CompilerOptions.OPTION_Encoding);
-		if ("".equals(defaultEncoding)) //$NON-NLS-1$
-			defaultEncoding = null; //$NON-NLS-1$
-
-		for (int i = 0; i < fileCount; i++) {
-			char[] charName = this.filenames[i].toCharArray();
-			if (knownFileNames.get(charName) != null)
-				throw new InvalidInputException(Main.bind("unit.more", this.filenames[i])); //$NON-NLS-1$
-			knownFileNames.put(charName, charName);
-			File file = new File(this.filenames[i]);
-			if (!file.exists())
-				throw new InvalidInputException(Main.bind("unit.missing", this.filenames[i])); //$NON-NLS-1$
-			String encoding = this.encodings[i];
-			if (encoding == null)
-				encoding = defaultEncoding;
-			units[i] = new CompilationUnit(null, this.filenames[i], encoding);
+				mode = DEFAULT;
+				continue;
+			case INSIDE_SOURCE :
+				if (this.didSpecifySource) {
+					throw new InvalidInputException(
+						this.bind("configure.duplicateSource", currentArg));//$NON-NLS-1$
+				}
+				this.didSpecifySource = true;
+				if (currentArg.equals("1.3")) { //$NON-NLS-1$
+					this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
+				} else if (currentArg.equals("1.4")) { //$NON-NLS-1$
+					this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_4);
+				} else if (currentArg.equals("1.5") || currentArg.equals("5") || currentArg.equals("5.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+					this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_5);
+				} else if (currentArg.equals("1.6") || currentArg.equals("6") || currentArg.equals("6.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+					this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_6);
+				} else if (currentArg.equals("1.7") || currentArg.equals("7") || currentArg.equals("7.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+					this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_7);
+				} else {
+					throw new InvalidInputException(this.bind("configure.source", currentArg)); //$NON-NLS-1$
+				}
+				mode = DEFAULT;
+				continue;
+			case INSIDE_DEFAULT_ENCODING :
+				if (didSpecifyDefaultEncoding) {
+					throw new InvalidInputException(
+						this.bind("configure.duplicateDefaultEncoding", currentArg)); //$NON-NLS-1$
+				}
+				try { // ensure encoding is supported
+					new InputStreamReader(new ByteArrayInputStream(new byte[0]), currentArg);
+				} catch (UnsupportedEncodingException e) {
+					throw new InvalidInputException(
+						this.bind("configure.unsupportedEncoding", currentArg)); //$NON-NLS-1$
+				}
+				this.options.put(CompilerOptions.OPTION_Encoding, currentArg);
+				didSpecifyDefaultEncoding = true;
+				mode = DEFAULT;
+				continue;
+			case INSIDE_DESTINATION_PATH :
+				this.setDestinationPath(currentArg.equals(NONE) ? NONE : currentArg);
+				mode = DEFAULT;
+				continue;
+			case INSIDE_CLASSPATH_start:
+				mode = DEFAULT;
+				index += processPaths(newCommandLineArgs, index, currentArg, classpaths);
+				continue;
+			case INSIDE_BOOTCLASSPATH_start:
+				mode = DEFAULT;
+				index += processPaths(newCommandLineArgs, index, currentArg, bootclasspaths);
+				continue;
+			case INSIDE_SOURCE_PATH_start:
+				mode = DEFAULT;
+				String[] sourcePaths = new String[1];
+				index += processPaths(newCommandLineArgs, index, currentArg, sourcePaths);
+				sourcepathClasspathArg = sourcePaths[0];
+				continue;
+			case INSIDE_EXT_DIRS:
+				if (currentArg.indexOf("[-d") != -1) { //$NON-NLS-1$
+					throw new InvalidInputException(
+						this.bind("configure.unexpectedDestinationPathEntry", //$NON-NLS-1$
+							"-extdir")); //$NON-NLS-1$
+				}
+				StringTokenizer tokenizer = new StringTokenizer(currentArg,	File.pathSeparator, false);
+				extdirsClasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
+				while (tokenizer.hasMoreTokens())
+					extdirsClasspaths.add(tokenizer.nextToken());
+				mode = DEFAULT;
+				continue;
+			case INSIDE_ENDORSED_DIRS:
+				if (currentArg.indexOf("[-d") != -1) { //$NON-NLS-1$
+					throw new InvalidInputException(
+						this.bind("configure.unexpectedDestinationPathEntry", //$NON-NLS-1$
+							"-endorseddirs")); //$NON-NLS-1$
+				}				tokenizer = new StringTokenizer(currentArg,	File.pathSeparator, false);
+				endorsedDirClasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
+				while (tokenizer.hasMoreTokens())
+					endorsedDirClasspaths.add(tokenizer.nextToken());
+				mode = DEFAULT;
+				continue;
+			case INSIDE_SOURCE_DIRECTORY_DESTINATION_PATH:
+				if (currentArg.endsWith("]")) { //$NON-NLS-1$
+					customDestinationPath = currentArg.substring(0,
+						currentArg.length() - 1);
+				} else {
+					throw new InvalidInputException(
+						this.bind("configure.incorrectDestinationPathEntry", //$NON-NLS-1$
+							"[-d " + currentArg)); //$NON-NLS-1$
+				}
+				break;
+			case INSIDE_PROCESSOR_PATH_start :
+				// nothing to do here. This is consumed again by the AnnotationProcessorManager
+				mode = DEFAULT;
+				continue;
+			case INSIDE_PROCESSOR_start :
+				// nothing to do here. This is consumed again by the AnnotationProcessorManager
+				mode = DEFAULT;
+				continue;
+			case INSIDE_S_start :
+				// nothing to do here. This is consumed again by the AnnotationProcessorManager
+				mode = DEFAULT;
+				continue;
+			case INSIDE_CLASS_NAMES :
+				tokenizer = new StringTokenizer(currentArg, ","); //$NON-NLS-1$
+				if (this.classNames == null) {
+					this.classNames = new String[DEFAULT_SIZE_CLASSPATH];
+				}
+				while (tokenizer.hasMoreTokens()) {
+					if (this.classNames.length == classCount) {
+						// resize
+						System.arraycopy(
+							this.classNames,
+							0,
+							(this.classNames = new String[classCount * 2]),
+							0,
+							classCount);
+					}
+					this.classNames[classCount++] = tokenizer.nextToken();
+				}
+				mode = DEFAULT;
+				continue;
 		}
-		return units;
+
+		// default is input directory, if no custom destination path exists
+		if (customDestinationPath == null) {
+			if (File.separatorChar != '/') {
+				currentArg = currentArg.replace('/', File.separatorChar);
+			}
+			if (currentArg.endsWith("[-d")) { //$NON-NLS-1$
+				currentSourceDirectory = currentArg.substring(0,
+					currentArg.length() - 3);
+				mode = INSIDE_SOURCE_DIRECTORY_DESTINATION_PATH;
+				continue;
+			} else {
+				currentSourceDirectory = currentArg;
+			}
+		}
+		File dir = new File(currentSourceDirectory);
+		if (!dir.isDirectory()) {
+			throw new InvalidInputException(
+				this.bind("configure.unrecognizedOption", currentSourceDirectory)); //$NON-NLS-1$
+		}
+		String[] result = FileFinder.find(dir, SuffixConstants.SUFFIX_STRING_JAVA);
+		if (NONE.equals(customDestinationPath)) {
+			customDestinationPath = NONE; // ensure == comparison
+		}
+		if (this.filenames != null) {
+			// some source files were specified explicitly
+			int length = result.length;
+			System.arraycopy(
+				this.filenames,
+				0,
+				(this.filenames = new String[length + filesCount]),
+				0,
+				filesCount);
+			System.arraycopy(
+				this.encodings,
+				0,
+				(this.encodings = new String[length + filesCount]),
+				0,
+				filesCount);
+			System.arraycopy(
+				this.destinationPaths,
+				0,
+				(this.destinationPaths = new String[length + filesCount]),
+				0,
+				filesCount);
+			System.arraycopy(result, 0, this.filenames, filesCount, length);
+			for (int i = 0; i < length; i++) {
+				this.encodings[filesCount + i] = customEncoding;
+				this.destinationPaths[filesCount + i] = customDestinationPath;
+			}
+			filesCount += length;
+			customEncoding = null;
+			customDestinationPath = null;
+			currentSourceDirectory = null;
+		} else {
+			this.filenames = result;
+			filesCount = this.filenames.length;
+			this.encodings = new String[filesCount];
+			this.destinationPaths = new String[filesCount];
+			for (int i = 0; i < filesCount; i++) {
+				this.encodings[i] = customEncoding;
+				this.destinationPaths[i] = customDestinationPath;
+			}
+			customEncoding = null;
+			customDestinationPath = null;
+			currentSourceDirectory = null;
+		}
+		mode = DEFAULT;
+		continue;
+	}
+
+	if (printUsageRequired || (filesCount == 0 && classCount == 0)) {
+		if (usageSection ==  null) {
+			printUsage(); // default
+		} else {
+			printUsage(usageSection);
+		}
+		this.proceed = false;
+		return;
+	}
+
+	if (this.log != null) {
+		this.logger.setLog(this.log);
+	} else {
+		this.showProgress = false;
+	}
+	this.logger.logVersion(printVersionRequired);
+
+	validateOptions(didSpecifyCompliance);
+	
+	// Enable annotation processing by default in batch mode when compliance is at least 1.6
+	// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=185768
+	if (!didSpecifyDisabledAnnotationProcessing
+			&& CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Compliance)) >= ClassFileConstants.JDK1_6) {
+		this.options.put(CompilerOptions.OPTION_Process_Annotations, CompilerOptions.ENABLED);
+	}
+
+	this.logger.logCommandLineArguments(newCommandLineArgs);
+	this.logger.logOptions(this.options);
+	if (this.repetitions == 0) {
+		this.repetitions = 1;
+	}
+	if (this.repetitions >= 3 && this.timing) {
+		this.times = new long[this.repetitions];
+		this.timesCounter = 0;
+	}
+
+	if (filesCount != 0) {
+		System.arraycopy(
+			this.filenames,
+			0,
+			(this.filenames = new String[filesCount]),
+			0,
+			filesCount);
+	}
+
+	if (classCount != 0) {
+		System.arraycopy(
+			this.classNames,
+			0,
+			(this.classNames = new String[classCount]),
+			0,
+			classCount);
 	}
 	
-	private File[][] getLibrariesFiles(File[] files) {
-		FilenameFilter filter = new FilenameFilter() {
-			public boolean accept(File dir, String name) {
-				String lowerCaseName = name.toLowerCase();
-				if (lowerCaseName.endsWith(SUFFIX_STRING_jar) || lowerCaseName.endsWith(SUFFIX_STRING_zip)) {
-					return true;
-				}
-				return false;
-			}
-		};
-		final int filesLength = files.length;
-		File[][] result = new File[filesLength][];
-		for (int i = 0; i < filesLength; i++) {
-			File currentFile = files[i];
-			if (currentFile.exists() && currentFile.isDirectory()) {
-				result[i] = currentFile.listFiles(filter);
+	setPaths(bootclasspaths,
+			sourcepathClasspathArg,
+			sourcepathClasspaths,
+			classpaths,
+			extdirsClasspaths,
+			endorsedDirClasspaths,
+			customEncoding);
+}
+
+protected void disableWarnings() {
+	Object[] entries = this.options.entrySet().toArray();
+	for (int i = 0, max = entries.length; i < max; i++) {
+		Map.Entry entry = (Map.Entry) entries[i];
+		if (!(entry.getKey() instanceof String))
+			continue;
+		if (!(entry.getValue() instanceof String))
+			continue;
+		if (((String) entry.getValue()).equals(CompilerOptions.WARNING)) {
+			this.options.put(entry.getKey(), CompilerOptions.IGNORE);
+		}
+	}
+	this.options.put(CompilerOptions.OPTION_TaskTags, Util.EMPTY_STRING);
+}
+
+public String extractDestinationPathFromSourceFile(CompilationResult result) {
+	ICompilationUnit compilationUnit = result.compilationUnit;
+	if (compilationUnit != null) {
+		char[] fileName = compilationUnit.getFileName();
+		int lastIndex = CharOperation.lastIndexOf(java.io.File.separatorChar, fileName);
+		if (lastIndex != -1) {
+			final String outputPathName = new String(fileName, 0, lastIndex);
+			final File output = new File(outputPathName);
+			if (output.exists() && output.isDirectory()) {
+				return outputPathName;
 			}
 		}
-		return result;
 	}
-	
-	/*
-	 *  Low-level API performing the actual compilation
-	 */
-	public IErrorHandlingPolicy getHandlingPolicy() {
+	return System.getProperty("user.dir"); //$NON-NLS-1$
+}
 
-		// passes the initial set of files to the batch oracle (to avoid finding more than once the same units when case insensitive match)	
-		return new IErrorHandlingPolicy() {
-			public boolean proceedOnErrors() {
-				return Main.this.proceedOnError; // stop if there are some errors 
+/*
+ * Answer the component to which will be handed back compilation results from the compiler
+ */
+public ICompilerRequestor getBatchRequestor() {
+	return new ICompilerRequestor() {
+		int lineDelta = 0;
+		public void acceptResult(CompilationResult compilationResult) {
+			if (compilationResult.lineSeparatorPositions != null) {
+				int unitLineCount = compilationResult.lineSeparatorPositions.length;
+				Main.this.lineCount += unitLineCount;
+				this.lineDelta += unitLineCount;
+				if (Main.this.showProgress && this.lineDelta > 2000) {
+					// in -log mode, dump a dot every 2000 lines compiled
+					Main.this.logger.logProgress();
+					this.lineDelta = 0;
+				}
 			}
-			public boolean stopOnFirstError() {
-				return false;
-			}
-		};
-	}
-	public FileSystem getLibraryAccess() {
-
-		String defaultEncoding = (String) this.options.get(CompilerOptions.OPTION_Encoding);
-		if ("".equals(defaultEncoding)) //$NON-NLS-1$
-			defaultEncoding = null;	
-		return new FileSystem(this.checkedClasspaths, this.filenames);
-	}
-	/*
-	 *  Low-level API performing the actual compilation
-	 */
-	public IProblemFactory getProblemFactory() {
-		return new DefaultProblemFactory(Locale.getDefault());
-	}
-	// Dump classfiles onto disk for all compilation units that where successfull.
-
-	public void outputClassFiles(CompilationResult unitResult) {
-		if (!((unitResult == null) || (unitResult.hasErrors() && !this.proceedOnError))) {
-			ClassFile[] classFiles = unitResult.getClassFiles();
-			if (!this.generatePackagesStructure) {
-				this.destinationPath = extractDestinationPathFromSourceFile(unitResult);
-			}
-			if (this.destinationPath != null) {
-				for (int i = 0, fileCount = classFiles.length; i < fileCount; i++) {
-					// retrieve the key and the corresponding classfile
-					ClassFile classFile = classFiles[i];
-					char[] filename = classFile.fileName();
-					int length = filename.length;
-					char[] relativeName = new char[length + 6];
-					System.arraycopy(filename, 0, relativeName, 0, length);
-					System.arraycopy(SUFFIX_class, 0, relativeName, length, 6);
-					CharOperation.replace(relativeName, '/', File.separatorChar);
-					String relativeStringName = new String(relativeName);
-					try {
-						if (this.compilerOptions.verbose)
-							System.out.println(
-								Messages.bind(
-									Messages.compilation_write,
-									new String[] {
-										String.valueOf(this.exportedClassFilesCounter+1),
-										relativeStringName
-									}));
-						ClassFile.writeToDisk(
-							this.generatePackagesStructure,
-							this.destinationPath,
-							relativeStringName,
-							classFile.getBytes());
-						this.logger.logClassFile(
-							this.generatePackagesStructure,
-							this.destinationPath,
-							relativeStringName);
-					} catch (IOException e) {
-						String fileName = this.destinationPath + relativeStringName;
-						e.printStackTrace();
-						this.logger.logNoClassFileCreated(fileName); //$NON-NLS-1$
+			Main.this.logger.startLoggingSource(compilationResult);
+			if (compilationResult.hasProblems() || compilationResult.hasTasks()) {
+				int localErrorCount = Main.this.logger.logProblems(compilationResult.getAllProblems(), compilationResult.compilationUnit.getContents(), Main.this);
+				// exit?
+				if (Main.this.systemExitWhenFinished && !Main.this.proceedOnError && (localErrorCount > 0)) {
+					// ensure dumping problems for enqueued units as well, since may contain primary errors (123476)
+					CompilationUnitDeclaration[] queuedUnits = Main.this.batchCompiler.unitsToProcess;
+					for (int i = 0, length = Main.this.batchCompiler.totalUnits; i < length; i++) {
+						CompilationUnitDeclaration queuedUnit = queuedUnits[i];
+						if (queuedUnit == null) continue;
+						CompilationResult result = queuedUnit.compilationResult;
+						if (result.hasProblems() && !result.hasBeenAccepted) {
+							Main.this.logger.logProblems(result.getAllProblems(), result.compilationUnit.getContents(), Main.this);
+						}
 					}
+					Main.this.logger.endLoggingSource();
+					Main.this.logger.endLoggingSources();
+					Main.this.logger.printStats();
+					Main.this.logger.flush();
+					Main.this.logger.close();
+					System.exit(-1);
+				}
+			}
+			outputClassFiles(compilationResult);
+			Main.this.logger.endLoggingSource();
+		}
+	};
+}
+
+/*
+ *  Build the set of compilation source units
+ */
+public CompilationUnit[] getCompilationUnits()
+	throws InvalidInputException {
+	int fileCount = this.filenames.length;
+	CompilationUnit[] units = new CompilationUnit[fileCount];
+	HashtableOfObject knownFileNames = new HashtableOfObject(fileCount);
+
+	String defaultEncoding = (String) this.options.get(CompilerOptions.OPTION_Encoding);
+	if (Util.EMPTY_STRING.equals(defaultEncoding))
+		defaultEncoding = null;
+
+	for (int i = 0; i < fileCount; i++) {
+		char[] charName = this.filenames[i].toCharArray();
+		if (knownFileNames.get(charName) != null)
+			throw new InvalidInputException(this.bind("unit.more", this.filenames[i])); //$NON-NLS-1$
+		knownFileNames.put(charName, charName);
+		File file = new File(this.filenames[i]);
+		if (!file.exists())
+			throw new InvalidInputException(this.bind("unit.missing", this.filenames[i])); //$NON-NLS-1$
+		String encoding = this.encodings[i];
+		if (encoding == null)
+			encoding = defaultEncoding;
+		units[i] = new CompilationUnit(null, this.filenames[i], encoding,
+				this.destinationPaths[i]);
+	}
+	return units;
+}
+
+/*
+ *  Low-level API performing the actual compilation
+ */
+public IErrorHandlingPolicy getHandlingPolicy() {
+
+	// passes the initial set of files to the batch oracle (to avoid finding more than once the same units when case insensitive match)
+	return new IErrorHandlingPolicy() {
+		public boolean proceedOnErrors() {
+			return Main.this.proceedOnError; // stop if there are some errors
+		}
+		public boolean stopOnFirstError() {
+			return false;
+		}
+	};
+}
+/*
+ * External API
+ */
+public File getJavaHome() {
+	if (!javaHomeChecked) {
+		javaHomeChecked = true;
+		String javaHome = System.getProperty("java.home");//$NON-NLS-1$
+		if (javaHome != null) {
+			this.javaHomeCache = new File(javaHome);
+			if (!this.javaHomeCache.exists())
+				this.javaHomeCache = null;
+		}
+	}
+	return this.javaHomeCache;
+}
+
+public FileSystem getLibraryAccess() {
+	return new FileSystem(this.checkedClasspaths, this.filenames);
+}
+
+/*
+ *  Low-level API performing the actual compilation
+ */
+public IProblemFactory getProblemFactory() {
+	return new DefaultProblemFactory(this.compilerLocale);
+}
+/*
+ * External API
+ */
+protected void initialize(PrintWriter outWriter,
+		PrintWriter errWriter,
+		boolean systemExit) {
+	this.initialize(outWriter, errWriter, systemExit, null);
+}
+protected void initialize(PrintWriter outWriter,
+		PrintWriter errWriter,
+		boolean systemExit,
+		Map customDefaultOptions) {
+	this.logger = new Logger(this, outWriter, errWriter);
+	this.proceed = true;
+	this.out = outWriter;
+	this.err = errWriter;
+	this.systemExitWhenFinished = systemExit;
+	this.options = new CompilerOptions().getMap();
+	if (customDefaultOptions != null) {
+		this.didSpecifySource = customDefaultOptions.get(CompilerOptions.OPTION_Source) != null;
+		this.didSpecifyTarget = customDefaultOptions.get(CompilerOptions.OPTION_TargetPlatform) != null;
+		for (Iterator iter = customDefaultOptions.entrySet().iterator(); iter.hasNext();) {
+			Map.Entry entry = (Map.Entry) iter.next();
+			this.options.put(entry.getKey(), entry.getValue());
+		}
+	} else {
+		this.didSpecifySource = false;
+		this.didSpecifyTarget = false;
+	}
+	this.classNames = null;
+}
+// Dump classfiles onto disk for all compilation units that where successful
+// and do not carry a -d none spec, either directly or inherited from Main.
+public void outputClassFiles(CompilationResult unitResult) {
+	if (!((unitResult == null) || (unitResult.hasErrors() && !this.proceedOnError))) {
+		ClassFile[] classFiles = unitResult.getClassFiles();
+		String currentDestinationPath = null;
+		boolean generateClasspathStructure = false;
+		CompilationUnit compilationUnit =
+			(CompilationUnit) unitResult.compilationUnit;
+		if (compilationUnit.destinationPath == null) {
+			if (this.destinationPath == null) {
+				currentDestinationPath =
+					extractDestinationPathFromSourceFile(unitResult);
+			} else if (this.destinationPath != NONE) {
+				currentDestinationPath = this.destinationPath;
+				generateClasspathStructure = true;
+			} // else leave currentDestinationPath null
+		} else if (compilationUnit.destinationPath != NONE) {
+			currentDestinationPath = compilationUnit.destinationPath;
+			generateClasspathStructure = true;
+		} // else leave currentDestinationPath null
+		if (currentDestinationPath != null) {
+			for (int i = 0, fileCount = classFiles.length; i < fileCount; i++) {
+				// retrieve the key and the corresponding classfile
+				ClassFile classFile = classFiles[i];
+				char[] filename = classFile.fileName();
+				int length = filename.length;
+				char[] relativeName = new char[length + 6];
+				System.arraycopy(filename, 0, relativeName, 0, length);
+				System.arraycopy(SuffixConstants.SUFFIX_class, 0, relativeName, length, 6);
+				CharOperation.replace(relativeName, '/', File.separatorChar);
+				String relativeStringName = new String(relativeName);
+				try {
+					if (this.compilerOptions.verbose)
+						this.out.println(
+							Messages.bind(
+								Messages.compilation_write,
+								new String[] {
+									String.valueOf(this.exportedClassFilesCounter+1),
+									relativeStringName
+								}));
+					ClassFile.writeToDisk(
+						generateClasspathStructure,
+						currentDestinationPath,
+						relativeStringName,
+						classFile);
+					LookupEnvironment env = this.batchCompiler.lookupEnvironment;
+					if (classFile.isShared) env.classFilePool.release(classFile);
+					this.logger.logClassFile(
+						generateClasspathStructure,
+						currentDestinationPath,
+						relativeStringName);
 					this.exportedClassFilesCounter++;
+				} catch (IOException e) {
+					this.logger.logNoClassFileCreated(currentDestinationPath, relativeStringName, e);
 				}
 			}
 		}
 	}
-	/*
-	 *  Low-level API performing the actual compilation
-	 */
-	public void performCompilation() throws InvalidInputException {
+}
 
-		this.startTime = System.currentTimeMillis();
+/*
+ *  Low-level API performing the actual compilation
+ */
+public void performCompilation() throws InvalidInputException {
 
-		INameEnvironment environment = getLibraryAccess();
-		Compiler batchCompiler =
-			new Compiler(
-				environment,
-				getHandlingPolicy(),
-				this.options,
-				getBatchRequestor(),
-				getProblemFactory());
-		this.compilerOptions = batchCompiler.options;
+	this.startTime = System.currentTimeMillis();
 
-		// set the non-externally configurable options.
-		this.compilerOptions.verbose = this.verbose;
-		this.compilerOptions.produceReferenceInfo = this.produceRefInfo;
-		try {
-			this.logger.startLoggingSources();
-			batchCompiler.compile(getCompilationUnits());
-		} finally {
-			this.logger.endLoggingSources();
+	FileSystem environment = getLibraryAccess();
+	this.compilerOptions = new CompilerOptions(this.options);
+	this.compilerOptions.performMethodsFullRecovery = false;
+	this.compilerOptions.performStatementsRecovery = false;
+	this.batchCompiler =
+		new Compiler(
+			environment,
+			getHandlingPolicy(),
+			this.compilerOptions,
+			getBatchRequestor(),
+			getProblemFactory(),
+			this.out);
+
+	if (this.compilerOptions.complianceLevel >= ClassFileConstants.JDK1_6
+			&& this.compilerOptions.processAnnotations) {
+		if (checkVMVersion(ClassFileConstants.JDK1_6)) {
+			initializeAnnotationProcessorManager();
+			if (this.classNames != null) {
+				this.batchCompiler.setBinaryTypes(processClassNames(this.batchCompiler.lookupEnvironment));
+			}
+		} else {
+			// report a warning
+			this.logger.logIncorrectVMVersionForAnnotationProcessing();
 		}
-
-		this.logger.printStats(this);
-		
-		// cleanup
-		environment.cleanup();
 	}
-	
-	public void printUsage() {
-		this.logger.logUsage(Main.bind("misc.usage", //$NON-NLS-1$
+
+	// set the non-externally configurable options.
+	this.compilerOptions.verbose = this.verbose;
+	this.compilerOptions.produceReferenceInfo = this.produceRefInfo;
+	try {
+		this.logger.startLoggingSources();
+		this.batchCompiler.compile(getCompilationUnits());
+	} finally {
+		this.logger.endLoggingSources();
+	}
+
+	if (this.extraProblems != null) {
+		this.logger.loggingExtraProblems(this);
+		this.extraProblems = null;
+	}
+	this.logger.printStats();
+
+	// cleanup
+	environment.cleanup();
+}
+private ReferenceBinding[] processClassNames(LookupEnvironment environment) throws InvalidInputException {
+	// check for .class file presence in case of apt processing
+	int length = this.classNames.length;
+	ReferenceBinding[] referenceBindings = new ReferenceBinding[length];
+	for (int i = 0; i < length; i++) {
+		String currentName = this.classNames[i];
+		char[][] compoundName = null;
+		if (currentName.indexOf('.') != -1) {
+			// consider names with '.' as fully qualified names
+			char[] typeName = currentName.toCharArray();
+			compoundName = CharOperation.splitOn('.', typeName);
+		} else {
+			compoundName = new char[][] { currentName.toCharArray() };
+		}
+		ReferenceBinding type = environment.getType(compoundName);
+		if (type != null && type.isValidBinding()) {
+			if (type.isBinaryBinding()) {
+				referenceBindings[i] = type;
+			}
+		} else {
+			throw new InvalidInputException(
+					this.bind("configure.invalidClassName", currentName));//$NON-NLS-1$
+		}
+	}
+	return referenceBindings;
+}
+protected void initializeAnnotationProcessorManager() {
+	try {
+		Class c = Class.forName("org.eclipse.jdt.internal.compiler.apt.dispatch.BatchAnnotationProcessorManager"); //$NON-NLS-1$
+		AbstractAnnotationProcessorManager annotationManager = (AbstractAnnotationProcessorManager) c.newInstance();
+		annotationManager.configure(this, this.expandedCommandLine);
+		annotationManager.setErr(this.err);
+		annotationManager.setOut(this.out);
+		this.batchCompiler.annotationProcessorManager = annotationManager;
+	} catch (ClassNotFoundException e) {
+		// ignore
+	} catch (InstantiationException e) {
+		// should not happen
+		throw new org.eclipse.jdt.internal.compiler.problem.AbortCompilation();
+	} catch (IllegalAccessException e) {
+		// should not happen
+		throw new org.eclipse.jdt.internal.compiler.problem.AbortCompilation();
+	} catch(UnsupportedClassVersionError e) {
+		// report a warning
+		this.logger.logIncorrectVMVersionForAnnotationProcessing();
+	}
+}
+public void printUsage() {
+	printUsage("misc.usage"); //$NON-NLS-1$
+}
+private void printUsage(String sectionID) {
+	this.logger.logUsage(
+		this.bind(
+			sectionID,
 			new String[] {
 				System.getProperty("path.separator"), //$NON-NLS-1$
-				Main.bind("compiler.name"), //$NON-NLS-1$
-				Main.bind("compiler.version"), //$NON-NLS-1$
-				Main.bind("compiler.copyright") //$NON-NLS-1$
+				this.bind("compiler.name"), //$NON-NLS-1$
+				this.bind("compiler.version"), //$NON-NLS-1$
+				this.bind("compiler.copyright") //$NON-NLS-1$
+			}));
+	this.logger.flush();
+}
+/*
+ * External API
+ */
+public void processPathEntries(final int defaultSize, final ArrayList paths,
+			final String currentPath, String customEncoding, boolean isSourceOnly,
+			boolean rejectDestinationPathOnJars)
+		throws InvalidInputException {
+	String currentClasspathName = null;
+	String currentDestinationPath = null;
+	ArrayList currentRuleSpecs = new ArrayList(defaultSize);
+	StringTokenizer tokenizer = new StringTokenizer(currentPath,
+			File.pathSeparator + "[]", true); //$NON-NLS-1$
+	ArrayList tokens = new ArrayList();
+	while (tokenizer.hasMoreTokens()) {
+		tokens.add(tokenizer.nextToken());
+	}
+	// state machine
+	final int start = 0;
+	final int readyToClose = 1;
+	// 'path' 'path1[rule];path2'
+	final int readyToCloseEndingWithRules = 2;
+	// 'path[rule]' 'path1;path2[rule]'
+	final int readyToCloseOrOtherEntry = 3;
+	// 'path[rule];' 'path;' 'path1;path2;'
+	final int rulesNeedAnotherRule = 4;
+	// 'path[rule1;'
+	final int rulesStart = 5;
+	// 'path[' 'path1;path2['
+	final int rulesReadyToClose = 6;
+	// 'path[rule' 'path[rule1;rule2'
+	final int destinationPathReadyToClose = 7;
+	// 'path[-d bin'
+	final int readyToCloseEndingWithDestinationPath = 8;
+	// 'path[-d bin]' 'path[rule][-d bin]'
+	final int destinationPathStart = 9;
+	// 'path[rule]['
+	final int bracketOpened = 10;
+	// '.*[.*'
+	final int bracketClosed = 11;
+	// '.*([.*])+'
+
+	final int error = 99;
+	int state = start;
+	String token = null;
+	int cursor = 0, tokensNb = tokens.size(), bracket = -1;
+	while (cursor < tokensNb && state != error) {
+		token = (String) tokens.get(cursor++);
+		if (token.equals(File.pathSeparator)) {
+			switch (state) {
+			case start:
+			case readyToCloseOrOtherEntry:
+			case bracketOpened:
+				break;
+			case readyToClose:
+			case readyToCloseEndingWithRules:
+			case readyToCloseEndingWithDestinationPath:
+				state = readyToCloseOrOtherEntry;
+				addNewEntry(paths, currentClasspathName, currentRuleSpecs,
+						customEncoding, currentDestinationPath, isSourceOnly,
+						rejectDestinationPathOnJars);
+				currentRuleSpecs.clear();
+				break;
+			case rulesReadyToClose:
+				state = rulesNeedAnotherRule;
+				break;
+			case destinationPathReadyToClose:
+				throw new InvalidInputException(
+					this.bind("configure.incorrectDestinationPathEntry", //$NON-NLS-1$
+						currentPath));
+			case bracketClosed:
+				cursor = bracket + 1;
+				state = rulesStart;
+				break;
+			default:
+				state = error;
 			}
-		));
-		this.logger.flush();
+		} else if (token.equals("[")) { //$NON-NLS-1$
+			switch (state) {
+			case start:
+				currentClasspathName = ""; //$NON-NLS-1$
+			case readyToClose:
+				bracket = cursor - 1;
+			case bracketClosed:
+				state = bracketOpened;
+				break;
+			case readyToCloseEndingWithRules:
+				state = destinationPathStart;
+				break;
+			case readyToCloseEndingWithDestinationPath:
+				state = rulesStart;
+				break;
+			case bracketOpened:
+			default:
+				state = error;
+			}
+		} else if (token.equals("]")) { //$NON-NLS-1$
+			switch (state) {
+			case rulesReadyToClose:
+				state = readyToCloseEndingWithRules;
+				break;
+			case destinationPathReadyToClose:
+				state = readyToCloseEndingWithDestinationPath;
+				break;
+			case bracketOpened:
+				state = bracketClosed;
+				break;
+			case bracketClosed:
+			default:
+				state = error;
+			}
+		} else {
+			// regular word
+			switch (state) {
+			case start:
+			case readyToCloseOrOtherEntry:
+				state = readyToClose;
+				currentClasspathName = token;
+				break;
+			case rulesStart:
+				if (token.startsWith("-d ")) { //$NON-NLS-1$
+					if (currentDestinationPath != null) {
+						throw new InvalidInputException(
+								this.bind("configure.duplicateDestinationPathEntry", //$NON-NLS-1$
+										currentPath));
+					}
+					currentDestinationPath = token.substring(3).trim();
+					state = destinationPathReadyToClose;
+					break;
+				} // else we proceed with a rule
+			case rulesNeedAnotherRule:
+				if (currentDestinationPath != null) {
+					throw new InvalidInputException(
+							this.bind("configure.accessRuleAfterDestinationPath", //$NON-NLS-1$
+								currentPath));
+				}
+				state = rulesReadyToClose;
+				currentRuleSpecs.add(token);
+				break;
+			case destinationPathStart:
+				if (!token.startsWith("-d ")) { //$NON-NLS-1$
+					state = error;
+				} else {
+					currentDestinationPath = token.substring(3).trim();
+					state = destinationPathReadyToClose;
+				}
+				break;
+			case bracketClosed:
+				for (int i = bracket; i < cursor ; i++) {
+					currentClasspathName += (String) tokens.get(i);
+				}
+				state = readyToClose;
+				break;
+			case bracketOpened:
+				break;
+			default:
+				state = error;
+			}
+		}
+		if (state == bracketClosed && cursor == tokensNb) {
+			cursor = bracket + 1;
+			state = rulesStart;
+		}
 	}
-	public void printVersion() {
-		this.logger.logVersion();  //$NON-NLS-1$
-		this.logger.flush();
+	switch(state) {
+		case readyToCloseOrOtherEntry:
+			break;
+		case readyToClose:
+		case readyToCloseEndingWithRules:
+		case readyToCloseEndingWithDestinationPath:
+			addNewEntry(paths, currentClasspathName, currentRuleSpecs,
+				customEncoding, currentDestinationPath, isSourceOnly,
+				rejectDestinationPathOnJars);
+			break;
+		case bracketOpened:
+		case bracketClosed:
+		default :
+			// we go on anyway
+			if (currentPath.length() != 0) {
+				this.logger.logIncorrectClasspath(currentPath);
+			}
 	}
 }
+
+private int processPaths(String[] args, int index, String currentArg, ArrayList paths) throws InvalidInputException {
+	int localIndex = index;
+	int count = 0;
+	for (int i = 0, max = currentArg.length(); i < max; i++) {
+		switch(currentArg.charAt(i)) {
+			case '[' :
+				count++;
+				break;
+			case ']' :
+				count--;
+				break;
+		}
+	}
+	if (count == 0) {
+		paths.add(currentArg);
+	} else if (count > 1) {
+		throw new InvalidInputException(
+				this.bind("configure.unexpectedBracket", //$NON-NLS-1$
+							currentArg));
+	} else {
+		StringBuffer currentPath = new StringBuffer(currentArg);
+		while (true) {
+    		if (localIndex >= args.length) {
+    			throw new InvalidInputException(
+    					this.bind("configure.unexpectedBracket", //$NON-NLS-1$
+    								currentArg));
+    		}
+    		localIndex++;
+    		String nextArg = args[localIndex];
+    		for (int i = 0, max = nextArg.length(); i < max; i++) {
+    			switch(nextArg.charAt(i)) {
+    				case '[' :
+    					if (count > 1) {
+    						throw new InvalidInputException(
+    								this.bind("configure.unexpectedBracket", //$NON-NLS-1$
+    											nextArg));
+    					}
+    					count++;
+    					break;
+    				case ']' :
+    					count--;
+    					break;
+    			}
+    		}
+    		if (count == 0) {
+    			currentPath.append(' ');
+    			currentPath.append(nextArg);
+    			paths.add(currentPath.toString());
+    			return localIndex - index;
+    		} else if (count < 0) {
+				throw new InvalidInputException(
+						this.bind("configure.unexpectedBracket", //$NON-NLS-1$
+									nextArg));
+			} else {
+				currentPath.append(' ');
+				currentPath.append(nextArg);
+			}
+		}
+
+	}
+	return localIndex - index;
+}
+private int processPaths(String[] args, int index, String currentArg, String[] paths) throws InvalidInputException {
+	int localIndex = index;
+	int count = 0;
+	for (int i = 0, max = currentArg.length(); i < max; i++) {
+		switch(currentArg.charAt(i)) {
+			case '[' :
+				count++;
+				break;
+			case ']' :
+				count--;
+				break;
+		}
+	}
+	if (count == 0) {
+		paths[0] = currentArg;
+	} else {
+		StringBuffer currentPath = new StringBuffer(currentArg);
+		while (true) {
+    		localIndex++;
+    		if (localIndex >= args.length) {
+    			throw new InvalidInputException(
+    					this.bind("configure.unexpectedBracket", //$NON-NLS-1$
+    								currentArg));
+    		}
+    		String nextArg = args[localIndex];
+    		for (int i = 0, max = nextArg.length(); i < max; i++) {
+    			switch(nextArg.charAt(i)) {
+    				case '[' :
+    					if (count > 1) {
+    						throw new InvalidInputException(
+    								this.bind("configure.unexpectedBracket", //$NON-NLS-1$
+    											currentArg));
+    					}
+    					count++;
+    					break;
+    				case ']' :
+    					count--;
+    					break;
+    			}
+    		}
+    		if (count == 0) {
+    			currentPath.append(' ');
+    			currentPath.append(nextArg);
+    			paths[0] = currentPath.toString();
+    			return localIndex - index;
+    		} else if (count < 0) {
+				throw new InvalidInputException(
+						this.bind("configure.unexpectedBracket", //$NON-NLS-1$
+									currentArg));
+			} else {
+				currentPath.append(' ');
+				currentPath.append(nextArg);
+			}
+		}
+
+	}
+	return localIndex - index;
+}
+/**
+ * Creates a NLS catalog for the given locale.
+ */
+public void relocalize() {
+	relocalize(Locale.getDefault());
+}
+
+private void relocalize(Locale locale) {
+	this.compilerLocale = locale;
+	try {
+		this.bundle = ResourceBundleFactory.getBundle(locale);
+	} catch(MissingResourceException e) {
+		System.out.println("Missing resource : " + Main.bundleName.replace('.', '/') + ".properties for locale " + locale); //$NON-NLS-1$//$NON-NLS-2$
+		throw e;
+	}
+}
+/*
+ * External API
+ */
+public void setLocale(Locale locale) {
+	relocalize(locale);
+}
+/*
+ * External API
+ */
+public void setDestinationPath(String dest) {
+	this.destinationPath = dest;
+}
+/*
+ * External API
+ */
+protected void setPaths(ArrayList bootclasspaths,
+		String sourcepathClasspathArg,
+		ArrayList sourcepathClasspaths,
+		ArrayList classpaths,
+		ArrayList extdirsClasspaths,
+		ArrayList endorsedDirClasspaths,
+		String customEncoding) throws InvalidInputException {
+
+	// process bootclasspath, classpath and sourcepaths
+ 	bootclasspaths = handleBootclasspath(bootclasspaths, customEncoding);
+
+	classpaths = handleClasspath(classpaths, customEncoding);
+
+	if (sourcepathClasspathArg != null) {
+		processPathEntries(DEFAULT_SIZE_CLASSPATH, sourcepathClasspaths,
+			sourcepathClasspathArg, customEncoding, true, false);
+	}
+
+	/*
+	 * Feed endorsedDirClasspath according to:
+	 * - -extdirs first if present;
+	 * - else java.ext.dirs if defined;
+	 * - else default extensions directory for the platform.
+	 */
+	extdirsClasspaths = handleExtdirs(extdirsClasspaths);
+
+	endorsedDirClasspaths = handleEndorseddirs(endorsedDirClasspaths);
+
+	/*
+	 * Concatenate classpath entries
+	 * We put the bootclasspath at the beginning of the classpath
+	 * entries, followed by the extension libraries, followed by
+	 * the sourcepath followed by the classpath.  All classpath
+	 * entries are searched for both sources and binaries except
+	 * the sourcepath entries which are searched for sources only.
+	 */
+	bootclasspaths.addAll(endorsedDirClasspaths);
+	bootclasspaths.addAll(extdirsClasspaths);
+	bootclasspaths.addAll(sourcepathClasspaths);
+	bootclasspaths.addAll(classpaths);
+	classpaths = bootclasspaths;
+	classpaths = FileSystem.ClasspathNormalizer.normalize(classpaths);
+	this.checkedClasspaths = new FileSystem.Classpath[classpaths.size()];
+	classpaths.toArray(this.checkedClasspaths);
+	this.logger.logClasspath(this.checkedClasspaths);
+}
+protected void validateOptions(boolean didSpecifyCompliance) throws InvalidInputException {
+	if (didSpecifyCompliance) {
+		Object version = this.options.get(CompilerOptions.OPTION_Compliance);
+		if (CompilerOptions.VERSION_1_3.equals(version)) {
+			if (!this.didSpecifySource) this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
+			if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_1);
+		} else if (CompilerOptions.VERSION_1_4.equals(version)) {
+			if (this.didSpecifySource) {
+				Object source = this.options.get(CompilerOptions.OPTION_Source);
+				if (CompilerOptions.VERSION_1_3.equals(source)) {
+					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2);
+				} else if (CompilerOptions.VERSION_1_4.equals(source)) {
+					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
+				}
+			} else {
+				this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
+				if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2);
+			}
+		} else if (CompilerOptions.VERSION_1_5.equals(version)) {
+			if (this.didSpecifySource) {
+				Object source = this.options.get(CompilerOptions.OPTION_Source);
+				if (CompilerOptions.VERSION_1_3.equals(source)
+						|| CompilerOptions.VERSION_1_4.equals(source)) {
+					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
+				} else if (CompilerOptions.VERSION_1_5.equals(source)) {
+					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
+				}
+			} else {
+				this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_5);
+				if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
+			}
+		} else if (CompilerOptions.VERSION_1_6.equals(version)) {
+			if (this.didSpecifySource) {
+				Object source = this.options.get(CompilerOptions.OPTION_Source);
+				if (CompilerOptions.VERSION_1_3.equals(source)
+						|| CompilerOptions.VERSION_1_4.equals(source)) {
+					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
+				} else if (CompilerOptions.VERSION_1_5.equals(source)
+						|| CompilerOptions.VERSION_1_6.equals(source)) {
+					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
+				}
+			} else {
+				this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_6);
+				if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
+			}
+		} else if (CompilerOptions.VERSION_1_7.equals(version)) {
+			if (this.didSpecifySource) {
+				Object source = this.options.get(CompilerOptions.OPTION_Source);
+				if (CompilerOptions.VERSION_1_3.equals(source)
+						|| CompilerOptions.VERSION_1_4.equals(source)) {
+					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
+				} else if (CompilerOptions.VERSION_1_5.equals(source)
+						|| CompilerOptions.VERSION_1_6.equals(source)) {
+					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
+				} else if (CompilerOptions.VERSION_1_7.equals(source)) {
+					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_7);
+				}
+			} else {
+				this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_7);
+				if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_7);
+			}
+		}
+	} else if (this.didSpecifySource) {
+		Object version = this.options.get(CompilerOptions.OPTION_Source);
+		// default is source 1.3 target 1.2 and compliance 1.4
+		if (CompilerOptions.VERSION_1_4.equals(version)) {
+			if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
+			if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
+		} else if (CompilerOptions.VERSION_1_5.equals(version)) {
+			if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_5);
+			if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
+		} else if (CompilerOptions.VERSION_1_6.equals(version)) {
+			if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_6);
+			if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
+		} else if (CompilerOptions.VERSION_1_7.equals(version)) {
+			if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_7);
+			if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_7);
+		}
+	}
+
+	final Object sourceVersion = this.options.get(CompilerOptions.OPTION_Source);
+	final Object compliance = this.options.get(CompilerOptions.OPTION_Compliance);
+	if (sourceVersion.equals(CompilerOptions.VERSION_1_7)
+			&& CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK1_7) {
+		// compliance must be 1.7 if source is 1.7
+		throw new InvalidInputException(this.bind("configure.incompatibleComplianceForSource", (String)this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_7)); //$NON-NLS-1$
+	} else if (sourceVersion.equals(CompilerOptions.VERSION_1_6)
+			&& CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK1_6) {
+		// compliance must be 1.6 if source is 1.6
+		throw new InvalidInputException(this.bind("configure.incompatibleComplianceForSource", (String)this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_6)); //$NON-NLS-1$
+	} else if (sourceVersion.equals(CompilerOptions.VERSION_1_5)
+			&& CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK1_5) {
+		// compliance must be 1.5 if source is 1.5
+		throw new InvalidInputException(this.bind("configure.incompatibleComplianceForSource", (String)this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_5)); //$NON-NLS-1$
+	} else if (sourceVersion.equals(CompilerOptions.VERSION_1_4)
+			&& CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK1_4) {
+		// compliance must be 1.4 if source is 1.4
+		throw new InvalidInputException(this.bind("configure.incompatibleComplianceForSource", (String)this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_4)); //$NON-NLS-1$
+	}
+
+	// check and set compliance/source/target compatibilities
+	if (this.didSpecifyTarget) {
+		final Object targetVersion = this.options.get(CompilerOptions.OPTION_TargetPlatform);
+		// tolerate jsr14 target
+		if (CompilerOptions.VERSION_JSR14.equals(targetVersion)) {
+			// expecting source >= 1.5
+			if (CompilerOptions.versionToJdkLevel(sourceVersion) < ClassFileConstants.JDK1_5) {
+				throw new InvalidInputException(this.bind("configure.incompatibleTargetForGenericSource", (String) targetVersion, (String) sourceVersion)); //$NON-NLS-1$
+			}
+		} else {
+			// target must be 1.7 if source is 1.7
+			if (CompilerOptions.versionToJdkLevel(sourceVersion) >= ClassFileConstants.JDK1_7
+					&& CompilerOptions.versionToJdkLevel(targetVersion) < ClassFileConstants.JDK1_7){
+				throw new InvalidInputException(this.bind("configure.incompatibleTargetForSource", (String) targetVersion, CompilerOptions.VERSION_1_7)); //$NON-NLS-1$
+			}
+			// target must be 1.6 if source is 1.6
+			if (CompilerOptions.versionToJdkLevel(sourceVersion) >= ClassFileConstants.JDK1_6
+					&& CompilerOptions.versionToJdkLevel(targetVersion) < ClassFileConstants.JDK1_6){
+				throw new InvalidInputException(this.bind("configure.incompatibleTargetForSource", (String) targetVersion, CompilerOptions.VERSION_1_6)); //$NON-NLS-1$
+			}
+			// target must be 1.5 if source is 1.5
+			if (CompilerOptions.versionToJdkLevel(sourceVersion) >= ClassFileConstants.JDK1_5
+					&& CompilerOptions.versionToJdkLevel(targetVersion) < ClassFileConstants.JDK1_5){
+				throw new InvalidInputException(this.bind("configure.incompatibleTargetForSource", (String) targetVersion, CompilerOptions.VERSION_1_5)); //$NON-NLS-1$
+			}
+			// target must be 1.4 if source is 1.4
+			if (CompilerOptions.versionToJdkLevel(sourceVersion) >= ClassFileConstants.JDK1_4
+					&& CompilerOptions.versionToJdkLevel(targetVersion) < ClassFileConstants.JDK1_4){
+				throw new InvalidInputException(this.bind("configure.incompatibleTargetForSource", (String) targetVersion, CompilerOptions.VERSION_1_4)); //$NON-NLS-1$
+			}
+			// target cannot be greater than compliance level
+			if (CompilerOptions.versionToJdkLevel(compliance) < CompilerOptions.versionToJdkLevel(targetVersion)){
+				throw new InvalidInputException(this.bind("configure.incompatibleComplianceForTarget", (String)this.options.get(CompilerOptions.OPTION_Compliance), (String) targetVersion)); //$NON-NLS-1$
+			}
+		}
+	}
+}
+}
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
index 7e5dad9..f6fb9ea 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2000, 2005 IBM Corporation and others.
+# Copyright (c) 2000, 2007 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
@@ -14,11 +14,8 @@
 #Format: compiler.name = word1 word2 word3
 compiler.name = Eclipse Java Compiler
 #Format: compiler.version = 0.XXX[, other words (don't forget the comma if adding other words)]
-compiler.version = v_574_R31x, pre-3.1.1 release
-compiler.copyright = Copyright IBM Corp 2000, 2005. All rights reserved.
-
-### scanning
-scanning.start = Collecting source files inside {0}
+compiler.version = 0.785_R33x, 3.3.2
+compiler.copyright = Copyright IBM Corp 2000, 2007. All rights reserved.
 
 ### progress
 progress.compiling = Compiling
@@ -46,83 +43,187 @@
 configure.duplicateCompliance = duplicate compliance setting specification: {0}
 configure.duplicateSource = duplicate source compliance setting specification: {0}
 configure.duplicateTarget = duplicate target compliance setting specification: {0}
-configure.source = source level should be comprised in between ''1.3'' and ''1.5'' (or ''5'' or ''5.0''): {0}
+configure.source = source level should be comprised in between ''1.3'' and ''1.6'' (or ''5'', ''5.0'', ..., ''7'' or ''7.0''): {0}
 configure.duplicateOutputPath = duplicate output path specification: {0}
 configure.duplicateBootClasspath = duplicate bootclasspath specification: {0}
-configure.duplicateExtdirs = duplicate extdirs specification: {0}
+configure.duplicateExtDirs = duplicate extdirs specification: {0}
 configure.duplicateSourcepath = duplicate sourcepath specification: {0}
 configure.invalidDebugOption = invalid debug option: {0}
 configure.invalidWarningConfiguration = invalid warning configuration: {0}
 configure.invalidWarning = invalid warning: {0}
 configure.invalidWarningOption = invalid warning option: {0}
-configure.targetJDK = target level should be comprised in between ''1.1'' and ''1.5'' (or ''5'' or ''5.0''): {0}
+configure.targetJDK = target level should be comprised in between ''1.1'' and ''1.7'' (or ''5'', ''5.0'', ..., ''7'' or ''7.0''): {0}
 configure.incompatibleTargetForSource = Target level ''{0}'' is incompatible with source level ''{1}''. A target level ''{1}'' or better is required
+configure.incompatibleTargetForGenericSource = Target level ''{0}'' is incompatible with source level ''{1}''. A source level ''1.5'' or better is required
 configure.incompatibleComplianceForSource = Compliance level ''{0}'' is incompatible with source level ''{1}''. A compliance level ''{1}'' or better is required
 configure.incompatibleComplianceForTarget = Compliance level ''{0}'' is incompatible with target level ''{1}''. A compliance level ''{1}'' or better is required
 configure.repetition = repetition must be a positive integer: {0}
 configure.maxProblems = max problems must be a positive integer: {0}
-configure.directoryNotExist = directory does not exist: {0}
-configure.IOError = i/o error : unable to retrieve .JAVA files in directory: {0}
+## configure.directoryNotExist = directory does not exist: {0}
+configure.unrecognizedOption = Unrecognized option : {0}
 configure.noClasspath = no classpath defined, using default directory instead
 configure.incorrectClasspath = incorrect classpath: {0}
-configure.invalidexpansionargumentname = expansion argument file {0} doesn''t exist or cannot be read
-configure.cannotOpenLog = cannot open .log file
+configure.invalidexpansionargumentname = expansion argument file {0} does not exist or cannot be read
+configure.cannotOpenLog = cannot open .log file: {0}
 configure.unexpectedCustomEncoding = unexpected custom encoding specification: {0}[{1}]
 configure.unsupportedEncoding = unsupported encoding format: {0}
 configure.duplicateDefaultEncoding = duplicate default encoding format specification: {0}
 configure.invalidTaskTag ={0} is an invalid task tag
+configure.incorrectExtDirsEntry = incorrect ext dir entry; {0} must be a directory
+configure.incorrectEndorsedDirsEntry = incorrect endorsed dir entry; {0} must be a directory
+configure.duplicateEndorsedDirs = duplicate endorseddirs specification: {0}
+configure.incorrectDestinationPathEntry = incorrect destination path entry: {0}
+configure.unexpectedBracket = unexpected bracket: {0}
+configure.unexpectedDestinationPathEntry = unexpected destination path entry in {0} option
+configure.unexpectedDestinationPathEntryFile = unexpected destination path entry for file: {0}
+configure.accessRuleAfterDestinationPath = access rules cannot follow destination path entries: {0}
+configure.duplicateDestinationPathEntry = duplicate destination path entry in {0} option
+configure.invalidClassName = invalid class name: {0}
+configure.incorrectVMVersionforAPT = Annotation processing got disabled, since it requires a 1.6 compliant JVM
 
 ### requestor
 requestor.error = {0}. ERROR in {1}
 requestor.warning = {0}. WARNING in {1}
 requestor.notRetrieveErrorMessage = Cannot retrieve the error message for {0}
+requestor.noFileNameSpecified = (original file name is not available)
+
+### EMACS STYLE
+output.emacs.error=error
+output.emacs.warning=warning
 
 ### unit
 unit.more = File {0} is specified more than once
 unit.missing = File {0} is missing
 
 ### output
-output.noClassFileCreated = No .class file created for file named {0} because of an IOException.
+output.noClassFileCreated = No .class file created for file {1} in {0} because of an IOException: {2}
 
 ### miscellaneous
 misc.version = {0} {1}, {2}
-misc.usage = {1} {2}, {3}\n\
+misc.usage = {1} {2}\n\
+{3}\n\
 \ \n\
 \ Usage: <options> <source files | directories>\n\
 \ If directories are specified, then their source contents are compiled.\n\
-\ Possible options are listed below. Options enabled by default are prefixed with ''+''\n\
+\ Possible options are listed below. Options enabled by default are prefixed\n\
+\ with ''+''.\n\
 \ \n\
 \ Classpath options:\n\
 \    -cp -classpath <directories and zip/jar files separated by {0}>\n\
-\                       specify location for application classes and sources. Each\n\
-\                       directory or file can specify access rules for types between\n\
-\                       ''['' and '']'' (e.g. [-X.java] to deny access to type X)\n\
+\                       specify location for application classes and sources.\n\
+\                       Each directory or file can specify access rules for\n\
+\                       types between ''['' and '']'' (e.g. [-X] to forbid\n\
+\                       access to type X, [~X] to discourage access to type X,\n\
+\                       [+p/X{0}-p/*] to forbid access to all types in package p\n\
+\                       but allow access to p/X)\n\
 \    -bootclasspath <directories and zip/jar files separated by {0}>\n\
-\                       specify location for system classes. Each directory or file can\n\
-\                       specify access rules for types between ''['' and '']'' (e.g. [-X.java]\n\
-\                       to deny access to type X)\n\
-\    -sourcepath <directories separated by {0}>\n\
-\                       specify location for application sources. Each directory can\n\
-\                       specify access rules for types between ''['' and '']'' (e.g. [-X.java]\n\
-\                       to deny access to type X)\n\
+\                       specify location for system classes. Each directory or\n\
+\                       file can specify access rules for types between ''[''\n\
+\                       and '']''\n\
+\    -sourcepath <directories and zip/jar files separated by {0}>\n\
+\                       specify location for application sources. Each directory\n\
+\                       or file can specify access rules for types between ''[''\n\
+\                       and '']''. Each directory can further specify a specific\n\
+\                       destination directory using a ''-d'' option between ''[''\n\
+\                       and '']''; this overrides the general ''-d'' option.\n\
+\                       .class files created from source files contained in a\n\
+\                       jar file are put in the user.dir folder in case no\n\
+\                       general ''-d'' option is specified. zip/jar files cannot\n\
+\                       override the general ''-d'' option\n\
 \    -extdirs <directories separated by {0}>\n\
 \                       specify location for extension zip/jar files\n\
-\    -d <dir>           destination directory (if omitted, no directory is created)\n\
+\    -endorseddirs <directories separated by {0}>\n\
+\                       specify location for endorsed zip/jar files\n\
+\    -d <dir>           destination directory (if omitted, no directory is\n\
+\                       created); this option can be overridden per source\n\
+\                       directory\n\
 \    -d none            generate no .class files\n\
-\    -encoding <enc>    specify custom encoding for all sources. Each file/directory can override it\n\
-\                       when suffixed with ''[''<enc>'']'' (e.g. X.java[utf8])\n\
+\    -encoding <enc>    specify custom encoding for all sources. Each\n\
+\                       file/directory can override it when suffixed with\n\
+\                       ''[''<enc>'']'' (e.g. X.java[utf8])\n\
 \ \n\
 \ Compliance options:\n\
-\    -1.3               use 1.3 compliance level (implicit -source 1.3 -target 1.1)\n\
-\    -1.4             + use 1.4 compliance level (implicit -source 1.3 -target 1.2)\n\
-\    -1.5               use 1.5 compliance level (implicit -source 1.5 -target 1.5)\n\
-\    -source <version>  set source level: 1.3 to 1.5 (or 5 or 5.0)\n\
-\    -target <version>  set classfile target level: 1.1 to 1.5 (or 5 or 5.0)\n\
+\    -1.3               use 1.3 compliance (-source 1.3 -target 1.1)\n\
+\    -1.4             + use 1.4 compliance (-source 1.3 -target 1.2)\n\
+\    -1.5 -5 -5.0       use 1.5 compliance (-source 1.5 -target 1.5)\n\
+\    -1.6 -6 -6.0       use 1.6 compliance (-source 1.6 -target 1.6)\n\
+\    -1.7 -7 -7.0       use 1.7 compliance (-source 1.7 -target 1.7)\n\
+\    -source <version>  set source level: 1.3 to 1.7 (or 5, 5.0, etc)\n\
+\    -target <version>  set classfile target: 1.1 to 1.7 (or 5, 5.0, etc)\n\
+\ \n\
+\ Warning options:\n\
+\    -deprecation     + deprecation outside deprecated code (equivalent to\n\
+\                       -warn:+deprecation)\n\
+\    -nowarn -warn:none disable all warnings\n\
+\    -?:warn -help:warn display advanced warning options\n\
+\ \n\
+\ Debug options:\n\
+\    -g[:lines,vars,source] custom debug info\n\
+\    -g:lines,source  + both lines table and source debug info\n\
+\    -g                 all debug info\n\
+\    -g:none            no debug info\n\
+\    -preserveAllLocals preserve unused local vars for debug purpose\n\
+\ \n\
+\ Annotation processing options:\n\
+\   These options are meaningful only in a 1.6 environment.\n\
+\    -Akey[=value]        annotation processors options that are made to\n\
+\                         annotation processors. key are identifiers separated\n\
+\                         by ''.''.\n\
+\    -processorpath <directories and zip/jar files separated by {0}>\n\
+\                         specify locations where to find annotation processors\n\
+\                         If this option is not used, the classpath will be\n\
+\                         searched for processors.\n\
+\    -processor <class1[,class2,...]>\n\
+\                         Qualified names of the annotation processors to run.\n\
+\                         This bypasses the default annotation discovery process\n\
+\    -proc:only           run annotation processors, but do not compile\n\
+\    -proc:none           perform compilation but do not run annotation\n\
+\                         processors\n\
+\    -s <dir>             specify a directory where to put the generated source\n\
+\                         files\n\
+\    -XprintProcessorInfo print information about which annotations and which\n\
+\                         elements a processor is asked to process\n\
+\    -XprintRounds        print information about annotation processing rounds.\n\
+\    -classNames <className1[,className2,...]>\n\
+\                         Qualified names of the classes that need\n\
+\                         to be processed\n\
+\ \n\
+\ Advanced options:\n\
+\    @<file>            read command line arguments from file\n\
+\    -maxProblems <n>   max number of problems per compilation unit (100 by\n\
+\                       default)\n\
+\    -log <file>        log to a file. If the file extension is ''.xml'', then\n\
+\                       the log will be a xml file.\n\
+\    -proceedOnError    do not stop at first error, dumping class files with\n\
+\                       problem methods\n\
+\    -verbose           enable verbose output\n\
+\    -referenceInfo     compute reference info\n\
+\    -progress          show progress (only in -log mode)\n\
+\    -time              display speed information \n\
+\    -noExit            do not call System.exit(n) at end of compilation (n==0\n\
+\                       if no error)\n\
+\    -repeat <n>        repeat compilation process <n> times for perf analysis\n\
+\    -inlineJSR         inline JSR bytecode (implicit if target >= 1.5)\n\
+\    -enableJavadoc     consider references in javadoc\n\
+\    -Xemacs            used to enable emacs-style output in the console.\n\
+\                       It does not affect the xml log output\n\
+\ \n\
+\    -? -help           print this help message\n\
+\    -v -version        print compiler version\n\
+\    -showversion       print compiler version and continue\n\
+\ \n\
+\ Ignored options:\n\
+\    -J<option>         pass option to virtual machine (ignored)\n\
+\    -X<option>         specify non-standard option (ignored\n\
+\                       except for listed -X options)\n\
+\    -X                 print non-standard options and exit (ignored)\n\
+\    -O                 optimize for execution time (ignored)\n
+misc.usage.warn = {1} {2}\n\
+{3}\n\
 \ \n\
 \ Warning options:\n\
 \    -deprecation     + deprecation outside deprecated code\n\
-\    -nowarn            disable all warnings\n\
-\    -warn:none         disable all warnings\n\
+\    -nowarn -warn:none disable all warnings\n\
 \    -warn:<warnings separated by ,>    enable exactly the listed warnings\n\
 \    -warn:+<warnings separated by ,>   enable additional warnings\n\
 \    -warn:-<warnings separated by ,>   disable specific warnings\n\
@@ -135,12 +236,16 @@
 \      constructorName    + method with constructor name\n\
 \      dep-ann              missing @Deprecated annotation\n\
 \      deprecation        + deprecation outside deprecated code\n\
+\      discouraged        + use of types matching a discouraged access rule\n\
 \      emptyBlock           undocumented empty block\n\
 \      enumSwitch           incomplete enum switch\n\
+\      fallthrough          possible fall-through case\n\
 \      fieldHiding          field hiding another variable\n\
 \      finalBound           type parameter with final bound\n\
 \      finally            + finally block not completing normally\n\
-\      hiding               macro for fieldHiding, localHiding, typeHiding and maskedCatchBlock\n\
+\      forbidden          + use of types matching a forbidden access rule\n\
+\      hiding               macro for fieldHiding, localHiding, typeHiding and\n\
+\                           maskedCatchBlock\n\
 \      incomplete-switch    same as enumSwitch\n\
 \      indirectStatic       indirect reference to static member\n\
 \      intfAnnotation     + annotation type used as super interface\n\
@@ -150,14 +255,18 @@
 \      maskedCatchBlock   + hidden catch block\n\
 \      nls                  string literal lacking non-nls tag //$NON-NLS-<n>$\n\
 \      noEffectAssign     + assignment without effect\n\
-\      null                 missing or redundant null check\n\
+\      null                 potential missing or redundant null check\n\
+\      nullDereference      missing null check\n\
 \      over-ann             missing @Override annotation\n\
+\      paramAssign          assignment to a parameter\n\
 \      pkgDefaultMethod   + attempt to override package-default method\n\
+\      raw                + usage of raw type\n\
 \      semicolon            unnecessary semicolon, empty statement\n\
 \      serial             + missing serialVersionUID\n\
 \      specialParamHiding   constructor or setter parameter hiding another field\n\
 \      static-access        macro for indirectStatic and staticReceiver\n\
 \      staticReceiver     + non-static reference to static member\n\
+\      super                overriding a method without making a super invocation\n\
 \      suppress           + enable @SuppressWarnings\n\
 \      synthetic-access     same as syntheticAccess\n\
 \      syntheticAccess      synthetic access for innerclass\n\
@@ -165,11 +274,13 @@
 \      typeHiding         + type parameter hiding another type\n\
 \      unchecked          + unchecked type operation\n\
 \      unnecessaryElse      unnecessary else clause\n\
-\      unqualified-field-access same as unQualifiedField\n\
+\      unqualified-field-access same as unqualifiedField\n\
 \      unqualifiedField     unqualified reference to field\n\
-\      unused               macro for unusedArgument, unusedImport, unusedLocal, unusedPrivate and unusedThrown\n\
+\      unused               macro for unusedArgument, unusedImport, unusedLabel,\n\
+\                               unusedLocal, unusedPrivate and unusedThrown\n\
 \      unusedArgument       unread method parameter\n\
 \      unusedImport       + unused import declaration\n\
+\      unusedLabel        + unused label\n\
 \      unusedLocal        + unread local variable\n\
 \      unusedPrivate      + unused private member declaration\n\
 \      unusedThrown         unused declared thrown exception\n\
@@ -177,35 +288,12 @@
 \      varargsCast        + varargs argument need explicit cast\n\
 \      warningToken       + unhandled warning token in @SuppressWarnings\n\
 \ \n\
-\ Debug options:\n\
-\    -g[:lines,vars,source] custom debug info\n\
-\    -g:lines,source  + both lines table and source debug info\n\
-\    -g                 all debug info\n\
-\    -g:none            no debug info\n\
-\    -preserveAllLocals preserve unused local vars for debug purpose\n\
-\ \n\
-\ Ignored options:\n\
-\    -J<option>         pass option to virtual machine (ignored)\n\
-\    -X<option>         specify non-standard option (ignored)\n\
-\    -X                 print non-standard options and exit (ignored)\n\
-\    -O                 optimize for execution time (ignored)\n\
-\ \n\
 \ Advanced options:\n\
-\    @<file>            read command line arguments from file\n\
-\    -maxProblems <n>   max number of problems per compilation unit (100 by default)\n\
-\    -log <file>        log to a file. If the file extension is ''.xml'', then the log\n\
-\                       will be a xml file.\n\
-\    -proceedOnError    do not stop at first error, dumping class files with problem methods\n\
-\    -verbose           enable verbose output\n\
-\    -referenceInfo     compute reference info\n\
-\    -progress          show progress (only in -log mode)\n\
-\    -time              display speed information \n\
-\    -noExit            do not call System.exit(n) at end of compilation (n==0 if no error)\n\
-\    -repeat <n>        repeat compilation process <n> times for perf analysis\n\
-\    -inlineJSR         inline JSR bytecode (implicit if target >= 1.5)\n\
-\    -enableJavadoc     consider references in javadoc\n\
-\ \n\
-\    -? -help           print this help message\n\
-\    -v -version        print compiler version\n\
-\    -showversion       print compiler version and continue\n
+\    -? -help           print the help message\n\
 
+# templates
+### access restrictions
+template.restrictedAccess.type = The type {0} is not accessible due to restriction on classpath entry {1}
+template.restrictedAccess.constructor = The constructor {0} is not accessible due to restriction on classpath entry {1}
+template.restrictedAccess.field = The field {0} from the type {1} is not accessible due to restriction on classpath entry {2}
+template.restrictedAccess.method = The method {0} from the type {1} is not accessible due to restriction on classpath entry {2}