1 /*******************************************************************************
2  * Copyright (c) 2000, 2014 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *     Tom Tromey - Contribution for bug 125961
11  *     Tom Tromey - Contribution for bug 159641
12  *     Benjamin Muskalla - Contribution for bug 239066
13  *     Stephan Herrmann  - Contributions for
14  *     							bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used
15  *     							bug 295551 - Add option to automatically promote all warnings to errors
16  *     							bug 359721 - [options] add command line option for new warning token "resource"
17  *								bug 365208 - [compiler][batch] command line options for annotation based null analysis
18  *								bug 374605 - Unreasonable warning for enum-based switch statements
19  *								bug 375366 - ECJ ignores unusedParameterIncludeDocCommentReference unless enableJavadoc option is set
20  *								bug 388281 - [compiler][null] inheritance of null annotations as an option
21  *								bug 381443 - [compiler][null] Allow parameter widening from @NonNull to unannotated
22  *     Jesper S Moller   - Contributions for
23  *								bug 407297 - [1.8][compiler] Control generation of parameter names by option
24  *    Mat Booth - Contribution for bug 405176
25  *******************************************************************************/
26 package org.eclipse.jdt.internal.compiler.batch;
27 
28 import java.io.BufferedInputStream;
29 import java.io.ByteArrayInputStream;
30 import java.io.File;
31 import java.io.FileInputStream;
32 import java.io.FileNotFoundException;
33 import java.io.FileOutputStream;
34 import java.io.FilenameFilter;
35 import java.io.IOException;
36 import java.io.InputStreamReader;
37 import java.io.LineNumberReader;
38 import java.io.OutputStreamWriter;
39 import java.io.PrintWriter;
40 import java.io.StringReader;
41 import java.io.StringWriter;
42 import java.io.UnsupportedEncodingException;
43 import java.lang.reflect.Field;
44 import java.text.DateFormat;
45 import java.text.MessageFormat;
46 import java.util.ArrayList;
47 import java.util.Arrays;
48 import java.util.Comparator;
49 import java.util.Date;
50 import java.util.HashMap;
51 import java.util.HashSet;
52 import java.util.Iterator;
53 import java.util.List;
54 import java.util.Locale;
55 import java.util.Map;
56 import java.util.MissingResourceException;
57 import java.util.Properties;
58 import java.util.ResourceBundle;
59 import java.util.Set;
60 import java.util.StringTokenizer;
61 
62 import org.eclipse.jdt.core.compiler.CategorizedProblem;
63 import org.eclipse.jdt.core.compiler.CharOperation;
64 import org.eclipse.jdt.core.compiler.CompilationProgress;
65 import org.eclipse.jdt.core.compiler.IProblem;
66 import org.eclipse.jdt.core.compiler.batch.BatchCompiler;
67 import org.eclipse.jdt.internal.compiler.AbstractAnnotationProcessorManager;
68 import org.eclipse.jdt.internal.compiler.ClassFile;
69 import org.eclipse.jdt.internal.compiler.CompilationResult;
70 import org.eclipse.jdt.internal.compiler.Compiler;
71 import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
72 import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
73 import org.eclipse.jdt.internal.compiler.IProblemFactory;
74 import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath;
75 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
76 import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
77 import org.eclipse.jdt.internal.compiler.env.AccessRule;
78 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
79 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
80 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
81 import org.eclipse.jdt.internal.compiler.impl.CompilerStats;
82 import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
83 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
84 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
85 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
86 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
87 import org.eclipse.jdt.internal.compiler.util.GenericXMLWriter;
88 import org.eclipse.jdt.internal.compiler.util.HashtableOfInt;
89 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
90 import org.eclipse.jdt.internal.compiler.util.Messages;
91 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
92 import org.eclipse.jdt.internal.compiler.util.Util;
93 
94 @SuppressWarnings({ "rawtypes", "unchecked" })
95 public class Main implements ProblemSeverities, SuffixConstants {
96 
97 	public static class Logger {
98 		private PrintWriter err;
99 		private PrintWriter log;
100 		private Main main;
101 		private PrintWriter out;
102 		private HashMap parameters;
103 		int tagBits;
104 		private static final String CLASS = "class"; //$NON-NLS-1$
105 		private static final String CLASS_FILE = "classfile"; //$NON-NLS-1$
106 		private static final String CLASSPATH = "classpath"; //$NON-NLS-1$
107 		private static final String CLASSPATH_FILE = "FILE"; //$NON-NLS-1$
108 		private static final String CLASSPATH_FOLDER = "FOLDER"; //$NON-NLS-1$
109 		private static final String CLASSPATH_ID = "id"; //$NON-NLS-1$
110 		private static final String CLASSPATH_JAR = "JAR"; //$NON-NLS-1$
111 		private static final String CLASSPATHS = "classpaths"; //$NON-NLS-1$
112 		private static final String COMMAND_LINE_ARGUMENT = "argument"; //$NON-NLS-1$
113 		private static final String COMMAND_LINE_ARGUMENTS = "command_line"; //$NON-NLS-1$
114 		private static final String COMPILER = "compiler"; //$NON-NLS-1$
115 		private static final String COMPILER_COPYRIGHT = "copyright"; //$NON-NLS-1$
116 		private static final String COMPILER_NAME = "name"; //$NON-NLS-1$
117 		private static final String COMPILER_VERSION = "version"; //$NON-NLS-1$
118 		public static final int EMACS = 2;
119 		private static final String ERROR = "ERROR"; //$NON-NLS-1$
120 		private static final String ERROR_TAG = "error"; //$NON-NLS-1$
121 		private static final String WARNING_TAG = "warning"; //$NON-NLS-1$
122 		private static final String EXCEPTION = "exception"; //$NON-NLS-1$
123 		private static final String EXTRA_PROBLEM_TAG = "extra_problem"; //$NON-NLS-1$
124 		private static final String EXTRA_PROBLEMS = "extra_problems"; //$NON-NLS-1$
125 		private static final HashtableOfInt FIELD_TABLE = new HashtableOfInt();
126 		private static final String KEY = "key"; //$NON-NLS-1$
127 		private static final String MESSAGE = "message"; //$NON-NLS-1$
128 		private static final String NUMBER_OF_CLASSFILES = "number_of_classfiles"; //$NON-NLS-1$
129 		private static final String NUMBER_OF_ERRORS = "errors"; //$NON-NLS-1$
130 		private static final String NUMBER_OF_LINES = "number_of_lines"; //$NON-NLS-1$
131 		private static final String NUMBER_OF_PROBLEMS = "problems"; //$NON-NLS-1$
132 		private static final String NUMBER_OF_TASKS = "tasks"; //$NON-NLS-1$
133 		private static final String NUMBER_OF_WARNINGS = "warnings"; //$NON-NLS-1$
134 		private static final String OPTION = "option"; //$NON-NLS-1$
135 		private static final String OPTIONS = "options"; //$NON-NLS-1$
136 		private static final String OUTPUT = "output"; //$NON-NLS-1$
137 		private static final String PACKAGE = "package"; //$NON-NLS-1$
138 		private static final String PATH = "path"; //$NON-NLS-1$
139 		private static final String PROBLEM_ARGUMENT = "argument"; //$NON-NLS-1$
140 		private static final String PROBLEM_ARGUMENT_VALUE = "value"; //$NON-NLS-1$
141 		private static final String PROBLEM_ARGUMENTS = "arguments"; //$NON-NLS-1$
142 		private static final String PROBLEM_CATEGORY_ID = "categoryID"; //$NON-NLS-1$
143 		private static final String ID = "id"; //$NON-NLS-1$
144 		private static final String PROBLEM_ID = "problemID"; //$NON-NLS-1$
145 		private static final String PROBLEM_LINE = "line"; //$NON-NLS-1$
146 		private static final String PROBLEM_OPTION_KEY = "optionKey"; //$NON-NLS-1$
147 		private static final String PROBLEM_MESSAGE = "message"; //$NON-NLS-1$
148 		private static final String PROBLEM_SEVERITY = "severity"; //$NON-NLS-1$
149 		private static final String PROBLEM_SOURCE_END = "charEnd"; //$NON-NLS-1$
150 		private static final String PROBLEM_SOURCE_START = "charStart"; //$NON-NLS-1$
151 		private static final String PROBLEM_SUMMARY = "problem_summary"; //$NON-NLS-1$
152 		private static final String PROBLEM_TAG = "problem"; //$NON-NLS-1$
153 		private static final String PROBLEMS = "problems"; //$NON-NLS-1$
154 		private static final String SOURCE = "source"; //$NON-NLS-1$
155 		private static final String SOURCE_CONTEXT = "source_context"; //$NON-NLS-1$
156 		private static final String SOURCE_END = "sourceEnd"; //$NON-NLS-1$
157 		private static final String SOURCE_START = "sourceStart"; //$NON-NLS-1$
158 		private static final String SOURCES = "sources"; //$NON-NLS-1$
159 
160 		private static final String STATS = "stats"; //$NON-NLS-1$
161 
162 		private static final String TASK = "task"; //$NON-NLS-1$
163 		private static final String TASKS = "tasks"; //$NON-NLS-1$
164 		private static final String TIME = "time"; //$NON-NLS-1$
165 		private static final String VALUE = "value"; //$NON-NLS-1$
166 		private static final String WARNING = "WARNING"; //$NON-NLS-1$
167 		public static final int XML = 1;
168 		private static final String XML_DTD_DECLARATION = "<!DOCTYPE compiler PUBLIC \"-//Eclipse.org//DTD Eclipse JDT 3.2.004 Compiler//EN\" \"http://www.eclipse.org/jdt/core/compiler_32_004.dtd\">"; //$NON-NLS-1$
169 		static {
170 			try {
171 				Class c = IProblem.class;
172 				Field[] fields = c.getFields();
173 				for (int i = 0, max = fields.length; i < max; i++) {
174 					Field field = fields[i];
175 					if (field.getType().equals(Integer.TYPE)) {
176 						Integer value = (Integer) field.get(null);
177 						int key2 = value.intValue() & IProblem.IgnoreCategoriesMask;
178 						if (key2 == 0) {
179 							key2 = Integer.MAX_VALUE;
180 						}
Logger.FIELD_TABLE.put(key2, field.getName())181 						Logger.FIELD_TABLE.put(key2, field.getName());
182 					}
183 				}
184 			} catch (SecurityException e) {
185 				e.printStackTrace();
186 			} catch (IllegalArgumentException e) {
187 				e.printStackTrace();
188 			} catch (IllegalAccessException e) {
189 				e.printStackTrace();
190 			}
191 		}
Logger(Main main, PrintWriter out, PrintWriter err)192 		public Logger(Main main, PrintWriter out, PrintWriter err) {
193 			this.out = out;
194 			this.err = err;
195 			this.parameters = new HashMap();
196 			this.main = main;
197 		}
198 
buildFileName( String outputPath, String relativeFileName)199 		public String buildFileName(
200 			String outputPath,
201 			String relativeFileName) {
202 			char fileSeparatorChar = File.separatorChar;
203 			String fileSeparator = File.separator;
204 
205 			outputPath = outputPath.replace('/', fileSeparatorChar);
206 			// To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
207 			StringBuffer outDir = new StringBuffer(outputPath);
208 			if (!outputPath.endsWith(fileSeparator)) {
209 				outDir.append(fileSeparator);
210 			}
211 			StringTokenizer tokenizer =
212 				new StringTokenizer(relativeFileName, fileSeparator);
213 			String token = tokenizer.nextToken();
214 			while (tokenizer.hasMoreTokens()) {
215 				outDir.append(token).append(fileSeparator);
216 				token = tokenizer.nextToken();
217 			}
218 			// token contains the last one
219 			return outDir.append(token).toString();
220 		}
221 
close()222 		public void close() {
223 			if (this.log != null) {
224 				if ((this.tagBits & Logger.XML) != 0) {
225 					endTag(Logger.COMPILER);
226 					flush();
227 				}
228 				this.log.close();
229 			}
230 		}
231 
232 		/**
233 		 *
234 		 */
compiling()235 		public void compiling() {
236 			printlnOut(this.main.bind("progress.compiling")); //$NON-NLS-1$
237 		}
endLoggingExtraProblems()238 		private void endLoggingExtraProblems() {
239 			endTag(Logger.EXTRA_PROBLEMS);
240 		}
241 		/**
242 		 * Used to stop logging problems.
243 		 * Only use in xml mode.
244 		 */
endLoggingProblems()245 		private void endLoggingProblems() {
246 			endTag(Logger.PROBLEMS);
247 		}
endLoggingSource()248 		public void endLoggingSource() {
249 			if ((this.tagBits & Logger.XML) != 0) {
250 				endTag(Logger.SOURCE);
251 			}
252 		}
253 
endLoggingSources()254 		public void endLoggingSources() {
255 			if ((this.tagBits & Logger.XML) != 0) {
256 				endTag(Logger.SOURCES);
257 			}
258 		}
259 
endLoggingTasks()260 		public void endLoggingTasks() {
261 			if ((this.tagBits & Logger.XML) != 0) {
262 				endTag(Logger.TASKS);
263 			}
264 		}
endTag(String name)265 		private void endTag(String name) {
266 			if (this.log != null) {
267 				((GenericXMLWriter) this.log).endTag(name, true, true);
268 			}
269 		}
errorReportSource(CategorizedProblem problem, char[] unitSource, int bits)270 		private String errorReportSource(CategorizedProblem problem, char[] unitSource, int bits) {
271 			//extra from the source the innacurate     token
272 			//and "highlight" it using some underneath ^^^^^
273 			//put some context around too.
274 
275 			//this code assumes that the font used in the console is fixed size
276 
277 			//sanity .....
278 			int startPosition = problem.getSourceStart();
279 			int endPosition = problem.getSourceEnd();
280 			if (unitSource == null) {
281 				if (problem.getOriginatingFileName() != null) {
282 					try {
283 						unitSource = Util.getFileCharContent(new File(new String(problem.getOriginatingFileName())), null);
284 					} catch (IOException e) {
285 						// ignore;
286 					}
287 				}
288 			}
289 			int length;
290 			if ((startPosition > endPosition)
291 				|| ((startPosition < 0) && (endPosition < 0))
292 				|| (unitSource == null)
293 				|| (length = unitSource.length) == 0)
294 				return Messages.problem_noSourceInformation;
295 
296 			StringBuffer errorBuffer = new StringBuffer();
297 			if ((bits & Main.Logger.EMACS) == 0) {
298 				errorBuffer.append(' ').append(Messages.bind(Messages.problem_atLine, String.valueOf(problem.getSourceLineNumber())));
299 				errorBuffer.append(Util.LINE_SEPARATOR);
300 			}
301 			errorBuffer.append('\t');
302 
303 			char c;
304 			final char SPACE = '\u0020';
305 			final char MARK = '^';
306 			final char TAB = '\t';
307 			//the next code tries to underline the token.....
308 			//it assumes (for a good display) that token source does not
309 			//contain any \r \n. This is false on statements !
310 			//(the code still works but the display is not optimal !)
311 
312 			// expand to line limits
313 			int begin;
314 			int end;
315 			for (begin = startPosition >= length ? length - 1 : startPosition; begin > 0; begin--) {
316 				if ((c = unitSource[begin - 1]) == '\n' || c == '\r') break;
317 			}
318 			for (end = endPosition >= length ? length - 1 : endPosition ; end+1 < length; end++) {
319 				if ((c = unitSource[end + 1]) == '\r' || c == '\n') break;
320 			}
321 
322 			// trim left and right spaces/tabs
323 			while ((c = unitSource[begin]) == ' ' || c == '\t') begin++;
324 			//while ((c = unitSource[end]) == ' ' || c == '\t') end--; TODO (philippe) should also trim right, but all tests are to be updated
325 
326 			// copy source
327 			errorBuffer.append(unitSource, begin, end-begin+1);
328 			errorBuffer.append(Util.LINE_SEPARATOR).append("\t"); //$NON-NLS-1$
329 
330 			// compute underline
331 			for (int i = begin; i <startPosition; i++) {
332 				errorBuffer.append((unitSource[i] == TAB) ? TAB : SPACE);
333 			}
334 			for (int i = startPosition; i <= (endPosition >= length ? length - 1 : endPosition); i++) {
335 				errorBuffer.append(MARK);
336 			}
337 			return errorBuffer.toString();
338 		}
339 
extractContext(CategorizedProblem problem, char[] unitSource)340 		private void extractContext(CategorizedProblem problem, char[] unitSource) {
341 			//sanity .....
342 			int startPosition = problem.getSourceStart();
343 			int endPosition = problem.getSourceEnd();
344 			if (unitSource == null) {
345 				if (problem.getOriginatingFileName() != null) {
346 					try {
347 						unitSource = Util.getFileCharContent(new File(new String(problem.getOriginatingFileName())), null);
348 					} catch(IOException e) {
349 						// ignore
350 					}
351 				}
352 			}
353 			int length;
354 			if ((startPosition > endPosition)
355 					|| ((startPosition < 0) && (endPosition < 0))
356 					|| (unitSource == null)
357 					|| ((length = unitSource.length) <= 0)
358 					|| (endPosition > length)) {
359 				this.parameters.put(Logger.VALUE, Messages.problem_noSourceInformation);
360 				this.parameters.put(Logger.SOURCE_START, "-1"); //$NON-NLS-1$
361 				this.parameters.put(Logger.SOURCE_END, "-1"); //$NON-NLS-1$
362 				printTag(Logger.SOURCE_CONTEXT, this.parameters, true, true);
363 				return;
364 			}
365 
366 			char c;
367 			//the next code tries to underline the token.....
368 			//it assumes (for a good display) that token source does not
369 			//contain any \r \n. This is false on statements !
370 			//(the code still works but the display is not optimal !)
371 
372 			// expand to line limits
373 			int begin, end;
374 			for (begin = startPosition >= length ? length - 1 : startPosition; begin > 0; begin--) {
375 				if ((c = unitSource[begin - 1]) == '\n' || c == '\r') break;
376 			}
377 			for (end = endPosition >= length ? length - 1 : endPosition ; end+1 < length; end++) {
378 				if ((c = unitSource[end + 1]) == '\r' || c == '\n') break;
379 			}
380 
381 			// trim left and right spaces/tabs
382 			while ((c = unitSource[begin]) == ' ' || c == '\t') begin++;
383 			while ((c = unitSource[end]) == ' ' || c == '\t') end--;
384 
385 			// copy source
386 			StringBuffer buffer = new StringBuffer();
387 			buffer.append(unitSource, begin, end - begin + 1);
388 
389 			this.parameters.put(Logger.VALUE, String.valueOf(buffer));
390 			this.parameters.put(Logger.SOURCE_START, Integer.toString(startPosition - begin));
391 			this.parameters.put(Logger.SOURCE_END, Integer.toString(endPosition - begin));
392 			printTag(Logger.SOURCE_CONTEXT, this.parameters, true, true);
393 		}
flush()394 		public void flush() {
395 			this.out.flush();
396 			this.err.flush();
397 			if (this.log != null) {
398 				this.log.flush();
399 			}
400 		}
401 
getFieldName(int id)402 		private String getFieldName(int id) {
403 			int key2 = id & IProblem.IgnoreCategoriesMask;
404 			if (key2 == 0) {
405 				key2 = Integer.MAX_VALUE;
406 			}
407 			return (String) Logger.FIELD_TABLE.get(key2);
408 		}
409 
410 		// find out an option name controlling a given problemID
getProblemOptionKey(int problemID)411 		private String getProblemOptionKey(int problemID) {
412 			int irritant = ProblemReporter.getIrritant(problemID);
413 			return CompilerOptions.optionKeyFromIrritant(irritant);
414 		}
415 
logAverage()416 		public void logAverage() {
417 			Arrays.sort(this.main.compilerStats);
418 			long lineCount = this.main.compilerStats[0].lineCount;
419 			final int length = this.main.maxRepetition;
420 			long sum = 0;
421 			long parseSum = 0, resolveSum = 0, analyzeSum = 0, generateSum = 0;
422 			for (int i = 1, max = length - 1; i < max; i++) {
423 				CompilerStats stats = this.main.compilerStats[i];
424 				sum += stats.elapsedTime();
425 				parseSum += stats.parseTime;
426 				resolveSum += stats.resolveTime;
427 				analyzeSum += stats.analyzeTime;
428 				generateSum += stats.generateTime;
429 			}
430 			long time = sum / (length - 2);
431 			long parseTime = parseSum/(length - 2);
432 			long resolveTime = resolveSum/(length - 2);
433 			long analyzeTime = analyzeSum/(length - 2);
434 			long generateTime = generateSum/(length - 2);
435 			printlnOut(this.main.bind(
436 				"compile.averageTime", //$NON-NLS-1$
437 				new String[] {
438 					String.valueOf(lineCount),
439 					String.valueOf(time),
440 					String.valueOf(((int) (lineCount * 10000.0 / time)) / 10.0),
441 				}));
442 			if ((this.main.timing & Main.TIMING_DETAILED) != 0) {
443 				printlnOut(
444 						this.main.bind("compile.detailedTime", //$NON-NLS-1$
445 							new String[] {
446 								String.valueOf(parseTime),
447 								String.valueOf(((int) (parseTime * 1000.0 / time)) / 10.0),
448 								String.valueOf(resolveTime),
449 								String.valueOf(((int) (resolveTime * 1000.0 / time)) / 10.0),
450 								String.valueOf(analyzeTime),
451 								String.valueOf(((int) (analyzeTime * 1000.0 / time)) / 10.0),
452 								String.valueOf(generateTime),
453 								String.valueOf(((int) (generateTime * 1000.0 / time)) / 10.0),
454 							}));
455 			}
456 		}
logClassFile(boolean generatePackagesStructure, String outputPath, String relativeFileName)457 		public void logClassFile(boolean generatePackagesStructure, String outputPath, String relativeFileName) {
458 			if ((this.tagBits & Logger.XML) != 0) {
459 				String fileName = null;
460 				if (generatePackagesStructure) {
461 					fileName = buildFileName(outputPath, relativeFileName);
462 				} else {
463 					char fileSeparatorChar = File.separatorChar;
464 					String fileSeparator = File.separator;
465 					// First we ensure that the outputPath exists
466 					outputPath = outputPath.replace('/', fileSeparatorChar);
467 					// To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
468 					int indexOfPackageSeparator = relativeFileName.lastIndexOf(fileSeparatorChar);
469 					if (indexOfPackageSeparator == -1) {
470 						if (outputPath.endsWith(fileSeparator)) {
471 							fileName = outputPath + relativeFileName;
472 						} else {
473 							fileName = outputPath + fileSeparator + relativeFileName;
474 						}
475 					} else {
476 						int length = relativeFileName.length();
477 						if (outputPath.endsWith(fileSeparator)) {
478 							fileName = outputPath + relativeFileName.substring(indexOfPackageSeparator + 1, length);
479 						} else {
480 							fileName = outputPath + fileSeparator + relativeFileName.substring(indexOfPackageSeparator + 1, length);
481 						}
482 					}
483 				}
484 				File f = new File(fileName);
485 				try {
486 					this.parameters.put(Logger.PATH, f.getCanonicalPath());
487 					printTag(Logger.CLASS_FILE, this.parameters, true, true);
488 				} catch (IOException e) {
489 					logNoClassFileCreated(outputPath, relativeFileName, e);
490 				}
491 			}
492 		}
logClasspath(FileSystem.Classpath[] classpaths)493 		public void logClasspath(FileSystem.Classpath[] classpaths) {
494 			if (classpaths == null) return;
495 			if ((this.tagBits & Logger.XML) != 0) {
496 				final int length = classpaths.length;
497 				if (length != 0) {
498 					// generate xml output
499 					printTag(Logger.CLASSPATHS, null, true, false);
500 					for (int i = 0; i < length; i++) {
501 						String classpath = classpaths[i].getPath();
502 						this.parameters.put(Logger.PATH, classpath);
503 						File f = new File(classpath);
504 						String id = null;
505 						if (f.isFile()) {
506 							if (Util.isPotentialZipArchive(classpath)) {
507 								id = Logger.CLASSPATH_JAR;
508 							} else {
509 								id = Logger.CLASSPATH_FILE;
510 							}
511 						} else if (f.isDirectory()) {
512 							id = Logger.CLASSPATH_FOLDER;
513 						}
514 						if (id != null) {
515 							this.parameters.put(Logger.CLASSPATH_ID, id);
516 							printTag(Logger.CLASSPATH, this.parameters, true, true);
517 						}
518 					}
519 					endTag(Logger.CLASSPATHS);
520 				}
521 			}
522 
523 		}
524 
logCommandLineArguments(String[] commandLineArguments)525 		public void logCommandLineArguments(String[] commandLineArguments) {
526 			if (commandLineArguments == null) return;
527 			if ((this.tagBits & Logger.XML) != 0) {
528 				final int length = commandLineArguments.length;
529 				if (length != 0) {
530 					// generate xml output
531 					printTag(Logger.COMMAND_LINE_ARGUMENTS, null, true, false);
532 					for (int i = 0; i < length; i++) {
533 						this.parameters.put(Logger.VALUE, commandLineArguments[i]);
534 						printTag(Logger.COMMAND_LINE_ARGUMENT, this.parameters, true, true);
535 					}
536 					endTag(Logger.COMMAND_LINE_ARGUMENTS);
537 				}
538 			}
539 		}
540 
541 		/**
542 		 * @param e the given exception to log
543 		 */
logException(Exception e)544 		public void logException(Exception e) {
545 			StringWriter writer = new StringWriter();
546 			PrintWriter printWriter = new PrintWriter(writer);
547 			e.printStackTrace(printWriter);
548 			printWriter.flush();
549 			printWriter.close();
550 			final String stackTrace = writer.toString();
551 			if ((this.tagBits & Logger.XML) != 0) {
552 				LineNumberReader reader = new LineNumberReader(new StringReader(stackTrace));
553 				String line;
554 				int i = 0;
555 				StringBuffer buffer = new StringBuffer();
556 				String message = e.getMessage();
557 				if (message != null) {
558 					buffer.append(message).append(Util.LINE_SEPARATOR);
559 				}
560 				try {
561 					while ((line = reader.readLine()) != null && i < 4) {
562 						buffer.append(line).append(Util.LINE_SEPARATOR);
563 						i++;
564 					}
565 					reader.close();
566 				} catch (IOException e1) {
567 					// ignore
568 				}
569 				message = buffer.toString();
570 				this.parameters.put(Logger.MESSAGE, message);
571 				this.parameters.put(Logger.CLASS, e.getClass());
572 				printTag(Logger.EXCEPTION, this.parameters, true, true);
573 			}
574 			String message = e.getMessage();
575 			if (message == null) {
576 				this.printlnErr(stackTrace);
577 			} else {
578 				this.printlnErr(message);
579 			}
580 		}
581 
logExtraProblem(CategorizedProblem problem, int localErrorCount, int globalErrorCount)582 		private void logExtraProblem(CategorizedProblem problem, int localErrorCount, int globalErrorCount) {
583 			char[] originatingFileName = problem.getOriginatingFileName();
584 			if (originatingFileName == null) {
585 				// simplified message output
586 				if (problem.isError()) {
587 					printErr(this.main.bind(
588 								"requestor.extraerror", //$NON-NLS-1$
589 								Integer.toString(globalErrorCount)));
590 				} else {
591 					// warning / mandatory warning / other
592 					printErr(this.main.bind(
593 							"requestor.extrawarning", //$NON-NLS-1$
594 							Integer.toString(globalErrorCount)));
595 				}
596 				printErr(" "); //$NON-NLS-1$
597 				this.printlnErr(problem.getMessage());
598 			} else {
599 				String fileName = new String(originatingFileName);
600 				if ((this.tagBits & Logger.EMACS) != 0) {
601 					String result = fileName
602 							+ ":" //$NON-NLS-1$
603 							+ problem.getSourceLineNumber()
604 							+ ": " //$NON-NLS-1$
605 							+ (problem.isError() ? this.main.bind("output.emacs.error") : this.main.bind("output.emacs.warning")) //$NON-NLS-1$ //$NON-NLS-2$
606 							+ ": " //$NON-NLS-1$
607 							+ problem.getMessage();
608 					this.printlnErr(result);
609 					final String errorReportSource = errorReportSource(problem, null, this.tagBits);
610 					this.printlnErr(errorReportSource);
611 				} else {
612 					if (localErrorCount == 0) {
613 						this.printlnErr("----------"); //$NON-NLS-1$
614 					}
615 					printErr(problem.isError() ?
616 							this.main.bind(
617 									"requestor.error", //$NON-NLS-1$
618 									Integer.toString(globalErrorCount),
619 									new String(fileName))
620 									: this.main.bind(
621 											"requestor.warning", //$NON-NLS-1$
622 											Integer.toString(globalErrorCount),
623 											new String(fileName)));
624 					final String errorReportSource = errorReportSource(problem, null, 0);
625 					this.printlnErr(errorReportSource);
626 					this.printlnErr(problem.getMessage());
627 					this.printlnErr("----------"); //$NON-NLS-1$
628 				}
629 			}
630 		}
631 
loggingExtraProblems(Main currentMain)632 		public void loggingExtraProblems(Main currentMain) {
633 			ArrayList problems = currentMain.extraProblems;
634 			final int count = problems.size();
635 			int localProblemCount = 0;
636 			if (count != 0) {
637 				int errors = 0;
638 				int warnings = 0;
639 				for (int i = 0; i < count; i++) {
640 					CategorizedProblem problem = (CategorizedProblem) problems.get(i);
641 					if (problem != null) {
642 						currentMain.globalProblemsCount++;
643 						logExtraProblem(problem, localProblemCount, currentMain.globalProblemsCount);
644 						localProblemCount++;
645 						if (problem.isError()) {
646 							errors++;
647 							currentMain.globalErrorsCount++;
648 						} else if (problem.isWarning()) {
649 							currentMain.globalWarningsCount++;
650 							warnings++;
651 						}
652 					}
653 				}
654 				if ((this.tagBits & Logger.XML) != 0) {
655 					if ((errors + warnings) != 0) {
656 						startLoggingExtraProblems(count);
657 						for (int i = 0; i < count; i++) {
658 							CategorizedProblem problem = (CategorizedProblem) problems.get(i);
659 							if (problem!= null) {
660 								if (problem.getID() != IProblem.Task) {
661 									logXmlExtraProblem(problem, localProblemCount, currentMain.globalProblemsCount);
662 								}
663 							}
664 						}
665 						endLoggingExtraProblems();
666 					}
667 				}
668 			}
669 		}
670 
logIncorrectVMVersionForAnnotationProcessing()671 		public void logIncorrectVMVersionForAnnotationProcessing() {
672 			if ((this.tagBits & Logger.XML) != 0) {
673 				this.parameters.put(Logger.MESSAGE, this.main.bind("configure.incorrectVMVersionforAPT")); //$NON-NLS-1$
674 				printTag(Logger.ERROR_TAG, this.parameters, true, true);
675 			}
676 			this.printlnErr(this.main.bind("configure.incorrectVMVersionforAPT")); //$NON-NLS-1$
677 		}
678 
679 		/**
680 		 *
681 		 */
logNoClassFileCreated(String outputDir, String relativeFileName, IOException e)682 		public void logNoClassFileCreated(String outputDir, String relativeFileName, IOException e) {
683 			if ((this.tagBits & Logger.XML) != 0) {
684 				this.parameters.put(Logger.MESSAGE, this.main.bind("output.noClassFileCreated", //$NON-NLS-1$
685 					new String[] {
686 						outputDir,
687 						relativeFileName,
688 						e.getMessage()
689 					}));
690 				printTag(Logger.ERROR_TAG, this.parameters, true, true);
691 			}
692 			this.printlnErr(this.main.bind("output.noClassFileCreated", //$NON-NLS-1$
693 				new String[] {
694 					outputDir,
695 					relativeFileName,
696 					e.getMessage()
697 				}));
698 		}
699 
700 		/**
701 		 * @param exportedClassFilesCounter
702 		 */
logNumberOfClassFilesGenerated(int exportedClassFilesCounter)703 		public void logNumberOfClassFilesGenerated(int exportedClassFilesCounter) {
704 			if ((this.tagBits & Logger.XML) != 0) {
705 				this.parameters.put(Logger.VALUE, new Integer(exportedClassFilesCounter));
706 				printTag(Logger.NUMBER_OF_CLASSFILES, this.parameters, true, true);
707 			}
708 			if (exportedClassFilesCounter == 1) {
709 				printlnOut(this.main.bind("compile.oneClassFileGenerated")); //$NON-NLS-1$
710 			} else {
711 				printlnOut(this.main.bind("compile.severalClassFilesGenerated", //$NON-NLS-1$
712 					String.valueOf(exportedClassFilesCounter)));
713 			}
714 		}
715 
716 		/**
717 		 * @param options the given compiler options
718 		 */
logOptions(Map options)719 		public void logOptions(Map options) {
720 			if ((this.tagBits & Logger.XML) != 0) {
721 				printTag(Logger.OPTIONS, null, true, false);
722 				final Set entriesSet = options.entrySet();
723 				Object[] entries = entriesSet.toArray();
724 				Arrays.sort(entries, new Comparator() {
725 					public int compare(Object o1, Object o2) {
726 						Map.Entry entry1 = (Map.Entry) o1;
727 						Map.Entry entry2 = (Map.Entry) o2;
728 						return ((String) entry1.getKey()).compareTo((String) entry2.getKey());
729 					}
730 				});
731 				for (int i = 0, max = entries.length; i < max; i++) {
732 					Map.Entry entry = (Map.Entry) entries[i];
733 					String key = (String) entry.getKey();
734 					this.parameters.put(Logger.KEY, key);
735 					this.parameters.put(Logger.VALUE, entry.getValue());
736 					printTag(Logger.OPTION, this.parameters, true, true);
737 				}
738 				endTag(Logger.OPTIONS);
739 			}
740 		}
741 
742 		/**
743 		 * @param error the given error
744 		 */
logPendingError(String error)745 		public void logPendingError(String error) {
746 			if ((this.tagBits & Logger.XML) != 0) {
747 				this.parameters.put(Logger.MESSAGE, error);
748 				printTag(Logger.ERROR_TAG, this.parameters, true, true);
749 			}
750 			this.printlnErr(error);
751 		}
752 
753 		/**
754 		 * @param message the given message
755 		 */
logWarning(String message)756 		public void logWarning(String message) {
757 			if ((this.tagBits & Logger.XML) != 0) {
758 				this.parameters.put(Logger.MESSAGE, message);
759 				printTag(Logger.WARNING_TAG, this.parameters, true, true);
760 			}
761 			this.printlnOut(message);
762 		}
763 
logProblem(CategorizedProblem problem, int localErrorCount, int globalErrorCount, char[] unitSource)764 		private void logProblem(CategorizedProblem problem, int localErrorCount,
765 			int globalErrorCount, char[] unitSource) {
766 			if ((this.tagBits & Logger.EMACS) != 0) {
767 				String result = (new String(problem.getOriginatingFileName())
768 						+ ":" //$NON-NLS-1$
769 						+ problem.getSourceLineNumber()
770 						+ ": " //$NON-NLS-1$
771 						+ (problem.isError() ? this.main.bind("output.emacs.error") : this.main.bind("output.emacs.warning")) //$NON-NLS-1$ //$NON-NLS-2$
772 						+ ": " //$NON-NLS-1$
773 						+ problem.getMessage());
774 				this.printlnErr(result);
775 				final String errorReportSource = errorReportSource(problem, unitSource, this.tagBits);
776 				if (errorReportSource.length() != 0) this.printlnErr(errorReportSource);
777 			} else {
778 				if (localErrorCount == 0) {
779 					this.printlnErr("----------"); //$NON-NLS-1$
780 				}
781 				printErr(problem.isError() ?
782 						this.main.bind(
783 								"requestor.error", //$NON-NLS-1$
784 								Integer.toString(globalErrorCount),
785 								new String(problem.getOriginatingFileName()))
786 								: this.main.bind(
787 										"requestor.warning", //$NON-NLS-1$
788 										Integer.toString(globalErrorCount),
789 										new String(problem.getOriginatingFileName())));
790 				try {
791 					final String errorReportSource = errorReportSource(problem, unitSource, 0);
792 					this.printlnErr(errorReportSource);
793 					this.printlnErr(problem.getMessage());
794 				} catch (Exception e) {
795 					this.printlnErr(this.main.bind(
796 						"requestor.notRetrieveErrorMessage", problem.toString())); //$NON-NLS-1$
797 				}
798 				this.printlnErr("----------"); //$NON-NLS-1$
799 			}
800 		}
801 
logProblems(CategorizedProblem[] problems, char[] unitSource, Main currentMain)802 		public int logProblems(CategorizedProblem[] problems, char[] unitSource, Main currentMain) {
803 			final int count = problems.length;
804 			int localErrorCount = 0;
805 			int localProblemCount = 0;
806 			if (count != 0) {
807 				int errors = 0;
808 				int warnings = 0;
809 				int tasks = 0;
810 				for (int i = 0; i < count; i++) {
811 					CategorizedProblem problem = problems[i];
812 					if (problem != null) {
813 						currentMain.globalProblemsCount++;
814 						logProblem(problem, localProblemCount, currentMain.globalProblemsCount, unitSource);
815 						localProblemCount++;
816 						if (problem.isError()) {
817 							localErrorCount++;
818 							errors++;
819 							currentMain.globalErrorsCount++;
820 						} else if (problem.getID() == IProblem.Task) {
821 							currentMain.globalTasksCount++;
822 							tasks++;
823 						} else {
824 							currentMain.globalWarningsCount++;
825 							warnings++;
826 						}
827 					}
828 				}
829 				if ((this.tagBits & Logger.XML) != 0) {
830 					if ((errors + warnings) != 0) {
831 						startLoggingProblems(errors, warnings);
832 						for (int i = 0; i < count; i++) {
833 							CategorizedProblem problem = problems[i];
834 							if (problem!= null) {
835 								if (problem.getID() != IProblem.Task) {
836 									logXmlProblem(problem, unitSource);
837 								}
838 							}
839 						}
840 						endLoggingProblems();
841 					}
842 					if (tasks != 0) {
843 						startLoggingTasks(tasks);
844 						for (int i = 0; i < count; i++) {
845 							CategorizedProblem problem = problems[i];
846 							if (problem!= null) {
847 								if (problem.getID() == IProblem.Task) {
848 									logXmlTask(problem, unitSource);
849 								}
850 							}
851 						}
852 						endLoggingTasks();
853 					}
854 				}
855 			}
856 			return localErrorCount;
857 		}
858 
859 		/**
860 		 * @param globalProblemsCount
861 		 * @param globalErrorsCount
862 		 * @param globalWarningsCount
863 		 */
logProblemsSummary(int globalProblemsCount, int globalErrorsCount, int globalWarningsCount, int globalTasksCount)864 		public void logProblemsSummary(int globalProblemsCount,
865 			int globalErrorsCount, int globalWarningsCount, int globalTasksCount) {
866 			if ((this.tagBits & Logger.XML) != 0) {
867 				// generate xml
868 				this.parameters.put(Logger.NUMBER_OF_PROBLEMS, new Integer(globalProblemsCount));
869 				this.parameters.put(Logger.NUMBER_OF_ERRORS, new Integer(globalErrorsCount));
870 				this.parameters.put(Logger.NUMBER_OF_WARNINGS, new Integer(globalWarningsCount));
871 				this.parameters.put(Logger.NUMBER_OF_TASKS, new Integer(globalTasksCount));
872 				printTag(Logger.PROBLEM_SUMMARY, this.parameters, true, true);
873 			}
874 			if (globalProblemsCount == 1) {
875 				String message = null;
876 				if (globalErrorsCount == 1) {
877 					message = this.main.bind("compile.oneError"); //$NON-NLS-1$
878 				} else {
879 					message = this.main.bind("compile.oneWarning"); //$NON-NLS-1$
880 				}
881 				printErr(this.main.bind("compile.oneProblem", message)); //$NON-NLS-1$
882 			} else {
883 				String errorMessage = null;
884 				String warningMessage = null;
885 				if (globalErrorsCount > 0) {
886 					if (globalErrorsCount == 1) {
887 						errorMessage = this.main.bind("compile.oneError"); //$NON-NLS-1$
888 					} else {
889 						errorMessage = this.main.bind("compile.severalErrors", String.valueOf(globalErrorsCount)); //$NON-NLS-1$
890 					}
891 				}
892 				int warningsNumber = globalWarningsCount + globalTasksCount;
893 				if (warningsNumber > 0) {
894 					if (warningsNumber == 1) {
895 						warningMessage = this.main.bind("compile.oneWarning"); //$NON-NLS-1$
896 					} else {
897 						warningMessage = this.main.bind("compile.severalWarnings", String.valueOf(warningsNumber)); //$NON-NLS-1$
898 					}
899 				}
900 				if (errorMessage == null || warningMessage == null) {
901 					if (errorMessage == null) {
902 						printErr(this.main.bind(
903 							"compile.severalProblemsErrorsOrWarnings", //$NON-NLS-1$
904 							String.valueOf(globalProblemsCount),
905 							warningMessage));
906 					} else {
907 						printErr(this.main.bind(
908 							"compile.severalProblemsErrorsOrWarnings", //$NON-NLS-1$
909 							String.valueOf(globalProblemsCount),
910 							errorMessage));
911 					}
912 				} else {
913 					printErr(this.main.bind(
914 						"compile.severalProblemsErrorsAndWarnings", //$NON-NLS-1$
915 						new String[] {
916 							String.valueOf(globalProblemsCount),
917 							errorMessage,
918 							warningMessage
919 						}));
920 				}
921 			}
922 			if ((this.tagBits & Logger.XML) == 0) {
923 				this.printlnErr();
924 			}
925 		}
926 
927 		/**
928 		 *
929 		 */
logProgress()930 		public void logProgress() {
931 			printOut('.');
932 		}
933 
934 		/**
935 		 * @param i
936 		 *            the current repetition number
937 		 * @param repetitions
938 		 *            the given number of repetitions
939 		 */
logRepetition(int i, int repetitions)940 		public void logRepetition(int i, int repetitions) {
941 			printlnOut(this.main.bind("compile.repetition", //$NON-NLS-1$
942 				String.valueOf(i + 1), String.valueOf(repetitions)));
943 		}
944 		/**
945 		 * @param compilerStats
946 		 */
logTiming(CompilerStats compilerStats)947 		public void logTiming(CompilerStats compilerStats) {
948 			long time = compilerStats.elapsedTime();
949 			long lineCount = compilerStats.lineCount;
950 			if ((this.tagBits & Logger.XML) != 0) {
951 				this.parameters.put(Logger.VALUE, new Long(time));
952 				printTag(Logger.TIME, this.parameters, true, true);
953 				this.parameters.put(Logger.VALUE, new Long(lineCount));
954 				printTag(Logger.NUMBER_OF_LINES, this.parameters, true, true);
955 			}
956 			if (lineCount != 0) {
957 				printlnOut(
958 					this.main.bind("compile.instantTime", //$NON-NLS-1$
959 						new String[] {
960 							String.valueOf(lineCount),
961 							String.valueOf(time),
962 							String.valueOf(((int) (lineCount * 10000.0 / time)) / 10.0),
963 						}));
964 			} else {
965 				printlnOut(
966 					this.main.bind("compile.totalTime", //$NON-NLS-1$
967 						new String[] {
968 							String.valueOf(time),
969 						}));
970 			}
971 			if ((this.main.timing & Main.TIMING_DETAILED) != 0) {
972 				printlnOut(
973 						this.main.bind("compile.detailedTime", //$NON-NLS-1$
974 							new String[] {
975 								String.valueOf(compilerStats.parseTime),
976 								String.valueOf(((int) (compilerStats.parseTime * 1000.0 / time)) / 10.0),
977 								String.valueOf(compilerStats.resolveTime),
978 								String.valueOf(((int) (compilerStats.resolveTime * 1000.0 / time)) / 10.0),
979 								String.valueOf(compilerStats.analyzeTime),
980 								String.valueOf(((int) (compilerStats.analyzeTime * 1000.0 / time)) / 10.0),
981 								String.valueOf(compilerStats.generateTime),
982 								String.valueOf(((int) (compilerStats.generateTime * 1000.0 / time)) / 10.0),
983 							}));
984 			}
985 		}
986 
987 		/**
988 		 * Print the usage of the compiler
989 		 * @param usage
990 		 */
logUsage(String usage)991 		public void logUsage(String usage) {
992 			printlnOut(usage);
993 		}
994 
995 		/**
996 		 * Print the version of the compiler in the log and/or the out field
997 		 */
logVersion(final boolean printToOut)998 		public void logVersion(final boolean printToOut) {
999 			if (this.log != null && (this.tagBits & Logger.XML) == 0) {
1000 				final String version = this.main.bind("misc.version", //$NON-NLS-1$
1001 					new String[] {
1002 						this.main.bind("compiler.name"), //$NON-NLS-1$
1003 						this.main.bind("compiler.version"), //$NON-NLS-1$
1004 						this.main.bind("compiler.copyright") //$NON-NLS-1$
1005 					}
1006 				);
1007 				this.log.println("# " + version); //$NON-NLS-1$
1008 				if (printToOut) {
1009 					this.out.println(version);
1010 					this.out.flush();
1011 				}
1012 			} else if (printToOut) {
1013 				final String version = this.main.bind("misc.version", //$NON-NLS-1$
1014 					new String[] {
1015 						this.main.bind("compiler.name"), //$NON-NLS-1$
1016 						this.main.bind("compiler.version"), //$NON-NLS-1$
1017 						this.main.bind("compiler.copyright") //$NON-NLS-1$
1018 					}
1019 				);
1020 				this.out.println(version);
1021 				this.out.flush();
1022 			}
1023 		}
1024 
1025 		/**
1026 		 * Print the usage of wrong JDK
1027 		 */
logWrongJDK()1028 		public void logWrongJDK() {
1029 			if ((this.tagBits & Logger.XML) != 0) {
1030 				this.parameters.put(Logger.MESSAGE, this.main.bind("configure.requiresJDK1.2orAbove")); //$NON-NLS-1$
1031 				printTag(Logger.ERROR, this.parameters, true, true);
1032 			}
1033 			this.printlnErr(this.main.bind("configure.requiresJDK1.2orAbove")); //$NON-NLS-1$
1034 		}
1035 
logXmlExtraProblem(CategorizedProblem problem, int globalErrorCount, int localErrorCount)1036 		private void logXmlExtraProblem(CategorizedProblem problem, int globalErrorCount, int localErrorCount) {
1037 			final int sourceStart = problem.getSourceStart();
1038 			final int sourceEnd = problem.getSourceEnd();
1039 			boolean isError = problem.isError();
1040 			this.parameters.put(Logger.PROBLEM_SEVERITY, isError ? Logger.ERROR : Logger.WARNING);
1041 			this.parameters.put(Logger.PROBLEM_LINE, new Integer(problem.getSourceLineNumber()));
1042 			this.parameters.put(Logger.PROBLEM_SOURCE_START, new Integer(sourceStart));
1043 			this.parameters.put(Logger.PROBLEM_SOURCE_END, new Integer(sourceEnd));
1044 			printTag(Logger.EXTRA_PROBLEM_TAG, this.parameters, true, false);
1045 			this.parameters.put(Logger.VALUE, problem.getMessage());
1046 			printTag(Logger.PROBLEM_MESSAGE, this.parameters, true, true);
1047 			extractContext(problem, null);
1048 			endTag(Logger.EXTRA_PROBLEM_TAG);
1049 		}
1050 		/**
1051 		 * @param problem
1052 		 *            the given problem to log
1053 		 * @param unitSource
1054 		 *            the given unit source
1055 		 */
logXmlProblem(CategorizedProblem problem, char[] unitSource)1056 		private void logXmlProblem(CategorizedProblem problem, char[] unitSource) {
1057 			final int sourceStart = problem.getSourceStart();
1058 			final int sourceEnd = problem.getSourceEnd();
1059 			final int id = problem.getID();
1060 			this.parameters.put(Logger.ID, getFieldName(id)); // ID as field name
1061 			this.parameters.put(Logger.PROBLEM_ID, new Integer(id)); // ID as numeric value
1062 			boolean isError = problem.isError();
1063 			int severity = isError ? ProblemSeverities.Error : ProblemSeverities.Warning;
1064 			this.parameters.put(Logger.PROBLEM_SEVERITY, isError ? Logger.ERROR : Logger.WARNING);
1065 			this.parameters.put(Logger.PROBLEM_LINE, new Integer(problem.getSourceLineNumber()));
1066 			this.parameters.put(Logger.PROBLEM_SOURCE_START, new Integer(sourceStart));
1067 			this.parameters.put(Logger.PROBLEM_SOURCE_END, new Integer(sourceEnd));
1068 			String problemOptionKey = getProblemOptionKey(id);
1069 			if (problemOptionKey != null) {
1070 				this.parameters.put(Logger.PROBLEM_OPTION_KEY, problemOptionKey);
1071 			}
1072 			int categoryID = ProblemReporter.getProblemCategory(severity, id);
1073 			this.parameters.put(Logger.PROBLEM_CATEGORY_ID, new Integer(categoryID));
1074 			printTag(Logger.PROBLEM_TAG, this.parameters, true, false);
1075 			this.parameters.put(Logger.VALUE, problem.getMessage());
1076 			printTag(Logger.PROBLEM_MESSAGE, this.parameters, true, true);
1077 			extractContext(problem, unitSource);
1078 			String[] arguments = problem.getArguments();
1079 			final int length = arguments.length;
1080 			if (length != 0) {
1081 				printTag(Logger.PROBLEM_ARGUMENTS, null, true, false);
1082 				for (int i = 0; i < length; i++) {
1083 					this.parameters.put(Logger.PROBLEM_ARGUMENT_VALUE, arguments[i]);
1084 					printTag(Logger.PROBLEM_ARGUMENT, this.parameters, true, true);
1085 				}
1086 				endTag(Logger.PROBLEM_ARGUMENTS);
1087 			}
1088 			endTag(Logger.PROBLEM_TAG);
1089 		}
1090 		/**
1091 		 * @param problem
1092 		 *            the given problem to log
1093 		 * @param unitSource
1094 		 *            the given unit source
1095 		 */
logXmlTask(CategorizedProblem problem, char[] unitSource)1096 		private void logXmlTask(CategorizedProblem problem, char[] unitSource) {
1097 			this.parameters.put(Logger.PROBLEM_LINE, new Integer(problem.getSourceLineNumber()));
1098 			this.parameters.put(Logger.PROBLEM_SOURCE_START, new Integer(problem.getSourceStart()));
1099 			this.parameters.put(Logger.PROBLEM_SOURCE_END, new Integer(problem.getSourceEnd()));
1100 			String problemOptionKey = getProblemOptionKey(problem.getID());
1101 			if (problemOptionKey != null) {
1102 				this.parameters.put(Logger.PROBLEM_OPTION_KEY, problemOptionKey);
1103 			}
1104 			printTag(Logger.TASK, this.parameters, true, false);
1105 			this.parameters.put(Logger.VALUE, problem.getMessage());
1106 			printTag(Logger.PROBLEM_MESSAGE, this.parameters, true, true);
1107 			extractContext(problem, unitSource);
1108 			endTag(Logger.TASK);
1109 		}
1110 
printErr(String s)1111 		private void printErr(String s) {
1112 			this.err.print(s);
1113 			if ((this.tagBits & Logger.XML) == 0 && this.log != null) {
1114 				this.log.print(s);
1115 			}
1116 		}
1117 
printlnErr()1118 		private void printlnErr() {
1119 			this.err.println();
1120 			if ((this.tagBits & Logger.XML) == 0 && this.log != null) {
1121 				this.log.println();
1122 			}
1123 		}
1124 
printlnErr(String s)1125 		private void printlnErr(String s) {
1126 			this.err.println(s);
1127 			if ((this.tagBits & Logger.XML) == 0 && this.log != null) {
1128 				this.log.println(s);
1129 			}
1130 		}
1131 
printlnOut(String s)1132 		private void printlnOut(String s) {
1133 			this.out.println(s);
1134 			if ((this.tagBits & Logger.XML) == 0 && this.log != null) {
1135 				this.log.println(s);
1136 			}
1137 		}
1138 
1139 		/**
1140 		 *
1141 		 */
printNewLine()1142 		public void printNewLine() {
1143 			this.out.println();
1144 		}
1145 
printOut(char c)1146 		private void printOut(char c) {
1147 			this.out.print(c);
1148 		}
1149 
printStats()1150 		public void printStats() {
1151 			final boolean isTimed = (this.main.timing & TIMING_ENABLED) != 0;
1152 			if ((this.tagBits & Logger.XML) != 0) {
1153 				printTag(Logger.STATS, null, true, false);
1154 			}
1155 			if (isTimed) {
1156 				CompilerStats compilerStats = this.main.batchCompiler.stats;
1157 				compilerStats.startTime = this.main.startTime; // also include batch initialization times
1158 				compilerStats.endTime = System.currentTimeMillis(); // also include batch output times
1159 				logTiming(compilerStats);
1160 			}
1161 			if (this.main.globalProblemsCount > 0) {
1162 				logProblemsSummary(this.main.globalProblemsCount, this.main.globalErrorsCount, this.main.globalWarningsCount, this.main.globalTasksCount);
1163 			}
1164 			if (this.main.exportedClassFilesCounter != 0
1165 					&& (this.main.showProgress || isTimed || this.main.verbose)) {
1166 				logNumberOfClassFilesGenerated(this.main.exportedClassFilesCounter);
1167 			}
1168 			if ((this.tagBits & Logger.XML) != 0) {
1169 				endTag(Logger.STATS);
1170 			}
1171 		}
1172 
printTag(String name, HashMap params, boolean insertNewLine, boolean closeTag)1173 		private void printTag(String name, HashMap params, boolean insertNewLine, boolean closeTag) {
1174 			if (this.log != null) {
1175 				((GenericXMLWriter) this.log).printTag(name, this.parameters, true, insertNewLine, closeTag);
1176 			}
1177 			this.parameters.clear();
1178 		}
1179 
setEmacs()1180 		public void setEmacs() {
1181 			this.tagBits |= Logger.EMACS;
1182 		}
setLog(String logFileName)1183 		public void setLog(String logFileName) {
1184 			final Date date = new Date();
1185 			final DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.LONG, Locale.getDefault());
1186 			try {
1187 				int index = logFileName.lastIndexOf('.');
1188 				if (index != -1) {
1189 					if (logFileName.substring(index).toLowerCase().equals(".xml")) { //$NON-NLS-1$
1190 						this.log = new GenericXMLWriter(new OutputStreamWriter(new FileOutputStream(logFileName, false), Util.UTF_8), Util.LINE_SEPARATOR, true);
1191 						this.tagBits |= Logger.XML;
1192 						// insert time stamp as comment
1193 						this.log.println("<!-- " + dateFormat.format(date) + " -->");//$NON-NLS-1$//$NON-NLS-2$
1194 						this.log.println(Logger.XML_DTD_DECLARATION);
1195 						this.parameters.put(Logger.COMPILER_NAME, this.main.bind("compiler.name")); //$NON-NLS-1$
1196 						this.parameters.put(Logger.COMPILER_VERSION, this.main.bind("compiler.version")); //$NON-NLS-1$
1197 						this.parameters.put(Logger.COMPILER_COPYRIGHT, this.main.bind("compiler.copyright")); //$NON-NLS-1$
1198 						printTag(Logger.COMPILER, this.parameters, true, false);
1199 					} else {
1200 						this.log = new PrintWriter(new FileOutputStream(logFileName, false));
1201 						this.log.println("# " + dateFormat.format(date));//$NON-NLS-1$
1202 					}
1203 				} else {
1204 					this.log = new PrintWriter(new FileOutputStream(logFileName, false));
1205 					this.log.println("# " + dateFormat.format(date));//$NON-NLS-1$
1206 				}
1207 			} catch (FileNotFoundException e) {
1208 				throw new IllegalArgumentException(this.main.bind("configure.cannotOpenLog", logFileName)); //$NON-NLS-1$
1209 			} catch (UnsupportedEncodingException e) {
1210 				throw new IllegalArgumentException(this.main.bind("configure.cannotOpenLogInvalidEncoding", logFileName)); //$NON-NLS-1$
1211 			}
1212 		}
startLoggingExtraProblems(int count)1213 		private void startLoggingExtraProblems(int count) {
1214 			this.parameters.put(Logger.NUMBER_OF_PROBLEMS, new Integer(count));
1215 			printTag(Logger.EXTRA_PROBLEMS, this.parameters, true, false);
1216 		}
1217 
1218 		/**
1219 		 * Used to start logging problems.
1220 		 * Only use in xml mode.
1221 		 */
startLoggingProblems(int errors, int warnings)1222 		private void startLoggingProblems(int errors, int warnings) {
1223 			this.parameters.put(Logger.NUMBER_OF_PROBLEMS, new Integer(errors + warnings));
1224 			this.parameters.put(Logger.NUMBER_OF_ERRORS, new Integer(errors));
1225 			this.parameters.put(Logger.NUMBER_OF_WARNINGS, new Integer(warnings));
1226 			printTag(Logger.PROBLEMS, this.parameters, true, false);
1227 		}
1228 
startLoggingSource(CompilationResult compilationResult)1229 		public void startLoggingSource(CompilationResult compilationResult) {
1230 			if ((this.tagBits & Logger.XML) != 0) {
1231 				ICompilationUnit compilationUnit = compilationResult.compilationUnit;
1232 				if (compilationUnit != null) {
1233     				char[] fileName = compilationUnit.getFileName();
1234     				File f = new File(new String(fileName));
1235     				if (fileName != null) {
1236     					this.parameters.put(Logger.PATH, f.getAbsolutePath());
1237     				}
1238     				char[][] packageName = compilationResult.packageName;
1239     				if (packageName != null) {
1240     					this.parameters.put(
1241     							Logger.PACKAGE,
1242     							new String(CharOperation.concatWith(packageName, File.separatorChar)));
1243     				}
1244     				CompilationUnit unit = (CompilationUnit) compilationUnit;
1245     				String destinationPath = unit.destinationPath;
1246 					if (destinationPath == null) {
1247 						destinationPath = this.main.destinationPath;
1248 					}
1249 					if (destinationPath != null && destinationPath != NONE) {
1250 						if (File.separatorChar == '/') {
1251 							this.parameters.put(Logger.OUTPUT, destinationPath);
1252 						} else {
1253 							this.parameters.put(Logger.OUTPUT, destinationPath.replace('/', File.separatorChar));
1254 						}
1255 					}
1256 				}
1257 				printTag(Logger.SOURCE, this.parameters, true, false);
1258 			}
1259 		}
1260 
startLoggingSources()1261 		public void startLoggingSources() {
1262 			if ((this.tagBits & Logger.XML) != 0) {
1263 				printTag(Logger.SOURCES, null, true, false);
1264 			}
1265 		}
1266 
startLoggingTasks(int tasks)1267 		public void startLoggingTasks(int tasks) {
1268 			if ((this.tagBits & Logger.XML) != 0) {
1269 				this.parameters.put(Logger.NUMBER_OF_TASKS, new Integer(tasks));
1270 				printTag(Logger.TASKS, this.parameters, true, false);
1271 			}
1272 		}
1273 	}
1274 
1275 	/**
1276 	 * Resource bundle factory to share bundles for the same locale
1277 	 */
1278 	public static class ResourceBundleFactory {
1279 		private static HashMap Cache = new HashMap();
getBundle(Locale locale)1280 		public static synchronized ResourceBundle getBundle(Locale locale) {
1281 			ResourceBundle bundle = (ResourceBundle) Cache.get(locale);
1282 			if (bundle == null) {
1283 				bundle = ResourceBundle.getBundle(Main.bundleName, locale);
1284 				Cache.put(locale, bundle);
1285 			}
1286 			return bundle;
1287 		}
1288 	}
1289 	// javadoc analysis tuning
1290 	boolean enableJavadocOn;
1291 
1292 	boolean warnJavadocOn;
1293 	boolean warnAllJavadocOn;
1294 
1295 	public Compiler batchCompiler;
1296 	/* Bundle containing messages */
1297 	public ResourceBundle bundle;
1298 	protected FileSystem.Classpath[] checkedClasspaths;
1299 
1300 	public Locale compilerLocale;
1301 	public CompilerOptions compilerOptions; // read-only
1302 	public CompilationProgress progress;
1303 	public String destinationPath;
1304 	public String[] destinationPaths;
1305 	// destination path for compilation units that get no more specific
1306 	// one (through directory arguments or various classpath options);
1307 	// coding is:
1308 	// == null: unspecified, write class files close to their respective
1309 	//          source files;
1310 	// == Main.NONE: absorbent element, do not output class files;
1311 	// else: use as the path of the directory into which class files must
1312 	//       be written.
1313 	private boolean didSpecifySource;
1314 	private boolean didSpecifyTarget;
1315 	public String[] encodings;
1316 	public int exportedClassFilesCounter;
1317 	public String[] filenames;
1318 	public String[] classNames;
1319 	// overrides of destinationPath on a directory argument basis
1320 	public int globalErrorsCount;
1321 	public int globalProblemsCount;
1322 	public int globalTasksCount;
1323 	public int globalWarningsCount;
1324 
1325 	private File javaHomeCache;
1326 
1327 	private boolean javaHomeChecked = false;
1328 	public long lineCount0;
1329 
1330 	public String log;
1331 
1332 	public Logger logger;
1333 	public int maxProblems;
1334 	public Map options;
1335 	public char[][] ignoreOptionalProblemsFromFolders;
1336 	protected PrintWriter out;
1337 	public boolean proceed = true;
1338 	public boolean proceedOnError = false;
1339 	public boolean produceRefInfo = false;
1340 	public int currentRepetition, maxRepetition;
1341 	public boolean showProgress = false;
1342 	public long startTime;
1343 	public ArrayList pendingErrors;
1344 	public boolean systemExitWhenFinished = true;
1345 
1346 	public static final int TIMING_DISABLED = 0;
1347 	public static final int TIMING_ENABLED = 1;
1348 	public static final int TIMING_DETAILED = 2;
1349 
1350 	public int timing = TIMING_DISABLED;
1351 	public CompilerStats[] compilerStats;
1352 	public boolean verbose = false;
1353 	private String[] expandedCommandLine;
1354 
1355 	private PrintWriter err;
1356 
1357 	protected ArrayList extraProblems;
1358 	public final static String bundleName = "org.eclipse.jdt.internal.compiler.batch.messages"; //$NON-NLS-1$
1359 	// two uses: recognize 'none' in options; code the singleton none
1360 	// for the '-d none' option (wherever it may be found)
1361 	public static final int DEFAULT_SIZE_CLASSPATH = 4;
1362 
1363 	public static final String NONE = "none"; //$NON-NLS-1$
1364 
1365 /**
1366  * @deprecated - use {@link BatchCompiler#compile(String, PrintWriter, PrintWriter, CompilationProgress)} instead
1367  * 						  e.g. BatchCompiler.compile(commandLine, new PrintWriter(System.out), new PrintWriter(System.err), null);
1368  */
compile(String commandLine)1369 public static boolean compile(String commandLine) {
1370 	return new Main(new PrintWriter(System.out), new PrintWriter(System.err), false /* systemExit */, null /* options */, null /* progress */).compile(tokenize(commandLine));
1371 }
1372 
1373 /**
1374  * @deprecated - use {@link BatchCompiler#compile(String, PrintWriter, PrintWriter, CompilationProgress)} instead
1375  *                       e.g. BatchCompiler.compile(commandLine, outWriter, errWriter, null);
1376  */
compile(String commandLine, PrintWriter outWriter, PrintWriter errWriter)1377 public static boolean compile(String commandLine, PrintWriter outWriter, PrintWriter errWriter) {
1378 	return new Main(outWriter, errWriter, false /* systemExit */, null /* options */, null /* progress */).compile(tokenize(commandLine));
1379 }
1380 
1381 /*
1382  * Internal API for public API BatchCompiler#compile(String[], PrintWriter, PrintWriter, CompilationProgress)
1383  */
compile(String[] commandLineArguments, PrintWriter outWriter, PrintWriter errWriter, CompilationProgress progress)1384 public static boolean compile(String[] commandLineArguments, PrintWriter outWriter, PrintWriter errWriter, CompilationProgress progress) {
1385 	return new Main(outWriter, errWriter, false /* systemExit */, null /* options */, progress).compile(commandLineArguments);
1386 }
getLibrariesFiles(File[] files)1387 public static File[][] getLibrariesFiles(File[] files) {
1388 	FilenameFilter filter = new FilenameFilter() {
1389 		public boolean accept(File dir, String name) {
1390 			return Util.isPotentialZipArchive(name);
1391 		}
1392 	};
1393 	final int filesLength = files.length;
1394 	File[][] result = new File[filesLength][];
1395 	for (int i = 0; i < filesLength; i++) {
1396 		File currentFile = files[i];
1397 		if (currentFile.exists() && currentFile.isDirectory()) {
1398 			result[i] = currentFile.listFiles(filter);
1399 		}
1400 	}
1401 	return result;
1402 }
1403 
main(String[] argv)1404 public static void main(String[] argv) {
1405 	new Main(new PrintWriter(System.out), new PrintWriter(System.err), true/*systemExit*/, null/*options*/, null/*progress*/).compile(argv);
1406 }
1407 
tokenize(String commandLine)1408 public static String[] tokenize(String commandLine) {
1409 
1410 	int count = 0;
1411 	String[] arguments = new String[10];
1412 	StringTokenizer tokenizer = new StringTokenizer(commandLine, " \"", true); //$NON-NLS-1$
1413 	String token = Util.EMPTY_STRING;
1414 	boolean insideQuotes = false;
1415 	boolean startNewToken = true;
1416 
1417 	// take care to quotes on the command line
1418 	// 'xxx "aaa bbb";ccc yyy' --->  {"xxx", "aaa bbb;ccc", "yyy" }
1419 	// 'xxx "aaa bbb;ccc" yyy' --->  {"xxx", "aaa bbb;ccc", "yyy" }
1420 	// 'xxx "aaa bbb";"ccc" yyy' --->  {"xxx", "aaa bbb;ccc", "yyy" }
1421 	// 'xxx/"aaa bbb";"ccc" yyy' --->  {"xxx/aaa bbb;ccc", "yyy" }
1422 	while (tokenizer.hasMoreTokens()) {
1423 		token = tokenizer.nextToken();
1424 
1425 		if (token.equals(" ")) { //$NON-NLS-1$
1426 			if (insideQuotes) {
1427 				arguments[count - 1] += token;
1428 				startNewToken = false;
1429 			} else {
1430 				startNewToken = true;
1431 			}
1432 		} else if (token.equals("\"")) { //$NON-NLS-1$
1433 			if (!insideQuotes && startNewToken) {
1434 				if (count == arguments.length)
1435 					System.arraycopy(arguments, 0, (arguments = new String[count * 2]), 0, count);
1436 				arguments[count++] = Util.EMPTY_STRING;
1437 			}
1438 			insideQuotes = !insideQuotes;
1439 			startNewToken = false;
1440 		} else {
1441 			if (insideQuotes) {
1442 				arguments[count - 1] += token;
1443 			} else {
1444 				if (token.length() > 0 && !startNewToken) {
1445 					arguments[count - 1] += token;
1446 				} else {
1447 					if (count == arguments.length)
1448 						System.arraycopy(arguments, 0, (arguments = new String[count * 2]), 0, count);
1449 					String trimmedToken = token.trim();
1450 					if (trimmedToken.length() != 0) {
1451 						arguments[count++] = trimmedToken;
1452 					}
1453 				}
1454 			}
1455 			startNewToken = false;
1456 		}
1457 	}
1458 	System.arraycopy(arguments, 0, arguments = new String[count], 0, count);
1459 	return arguments;
1460 }
1461 
1462 /**
1463  * @deprecated - use {@link #Main(PrintWriter, PrintWriter, boolean, Map, CompilationProgress)} instead
1464  *                       e.g. Main(outWriter, errWriter, systemExitWhenFinished, null, null)
1465  */
Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhenFinished)1466 public Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhenFinished) {
1467 	this(outWriter, errWriter, systemExitWhenFinished, null /* options */, null /* progress */);
1468 }
1469 
1470 /**
1471  * @deprecated - use {@link #Main(PrintWriter, PrintWriter, boolean, Map, CompilationProgress)} instead
1472  *                       e.g. Main(outWriter, errWriter, systemExitWhenFinished, customDefaultOptions, null)
1473  */
Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhenFinished, Map customDefaultOptions)1474 public Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhenFinished, Map customDefaultOptions) {
1475 	this(outWriter, errWriter, systemExitWhenFinished, customDefaultOptions, null /* progress */);
1476 }
1477 
Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhenFinished, Map customDefaultOptions, CompilationProgress compilationProgress)1478 public Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhenFinished, Map customDefaultOptions, CompilationProgress compilationProgress) {
1479 	this.initialize(outWriter, errWriter, systemExitWhenFinished, customDefaultOptions, compilationProgress);
1480 	this.relocalize();
1481 }
1482 
addExtraProblems(CategorizedProblem problem)1483 public void addExtraProblems(CategorizedProblem problem) {
1484 	if (this.extraProblems == null) {
1485 		this.extraProblems = new ArrayList();
1486 	}
1487 	this.extraProblems.add(problem);
1488 }
addNewEntry(ArrayList paths, String currentClasspathName, ArrayList currentRuleSpecs, String customEncoding, String destPath, boolean isSourceOnly, boolean rejectDestinationPathOnJars)1489 protected void addNewEntry(ArrayList paths, String currentClasspathName,
1490 		ArrayList currentRuleSpecs, String customEncoding,
1491 		String destPath, boolean isSourceOnly,
1492 		boolean rejectDestinationPathOnJars) {
1493 
1494 	int rulesSpecsSize = currentRuleSpecs.size();
1495 	AccessRuleSet accessRuleSet = null;
1496 	if (rulesSpecsSize != 0) {
1497 		AccessRule[] accessRules = new AccessRule[currentRuleSpecs.size()];
1498 		boolean rulesOK = true;
1499 		Iterator i = currentRuleSpecs.iterator();
1500 		int j = 0;
1501 		while (i.hasNext()) {
1502 			String ruleSpec = (String) i.next();
1503 			char key = ruleSpec.charAt(0);
1504 			String pattern = ruleSpec.substring(1);
1505 			if (pattern.length() > 0) {
1506 				switch (key) {
1507 					case '+':
1508 						accessRules[j++] = new AccessRule(pattern
1509 								.toCharArray(), 0);
1510 						break;
1511 					case '~':
1512 						accessRules[j++] = new AccessRule(pattern
1513 								.toCharArray(),
1514 								IProblem.DiscouragedReference);
1515 						break;
1516 					case '-':
1517 						accessRules[j++] = new AccessRule(pattern
1518 								.toCharArray(),
1519 								IProblem.ForbiddenReference);
1520 						break;
1521 					case '?':
1522 						accessRules[j++] = new AccessRule(pattern
1523 								.toCharArray(),
1524 								IProblem.ForbiddenReference, true/*keep looking for accessible type*/);
1525 						break;
1526 					default:
1527 						rulesOK = false;
1528 				}
1529 			} else {
1530 				rulesOK = false;
1531 			}
1532 		}
1533 		if (rulesOK) {
1534     		accessRuleSet = new AccessRuleSet(accessRules, AccessRestriction.COMMAND_LINE, currentClasspathName);
1535 		} else {
1536 			if (currentClasspathName.length() != 0) {
1537 				// we go on anyway
1538 				addPendingErrors(this.bind("configure.incorrectClasspath", currentClasspathName));//$NON-NLS-1$
1539 			}
1540 			return;
1541 		}
1542 	}
1543 	if (NONE.equals(destPath)) {
1544 		destPath = NONE; // keep == comparison valid
1545 	}
1546 	if (rejectDestinationPathOnJars && destPath != null &&
1547 			Util.isPotentialZipArchive(currentClasspathName)) {
1548 		throw new IllegalArgumentException(
1549 			this.bind("configure.unexpectedDestinationPathEntryFile", //$NON-NLS-1$
1550 						currentClasspathName));
1551 	}
1552 	FileSystem.Classpath currentClasspath = FileSystem.getClasspath(
1553 			currentClasspathName,
1554 			customEncoding,
1555 			isSourceOnly,
1556 			accessRuleSet,
1557 			destPath);
1558 	if (currentClasspath != null) {
1559 		paths.add(currentClasspath);
1560 	} else if (currentClasspathName.length() != 0) {
1561 		// we go on anyway
1562 		addPendingErrors(this.bind("configure.incorrectClasspath", currentClasspathName));//$NON-NLS-1$
1563 	}
1564 }
addPendingErrors(String message)1565 void addPendingErrors(String message) {
1566 	if (this.pendingErrors == null) {
1567 		this.pendingErrors = new ArrayList();
1568 	}
1569 	this.pendingErrors.add(message);
1570 }
1571 /*
1572  * Lookup the message with the given ID in this catalog
1573  */
bind(String id)1574 public String bind(String id) {
1575 	return bind(id, (String[]) null);
1576 }
1577 /*
1578  * Lookup the message with the given ID in this catalog and bind its
1579  * substitution locations with the given string.
1580  */
bind(String id, String binding)1581 public String bind(String id, String binding) {
1582 	return bind(id, new String[] { binding });
1583 }
1584 
1585 /*
1586  * Lookup the message with the given ID in this catalog and bind its
1587  * substitution locations with the given strings.
1588  */
bind(String id, String binding1, String binding2)1589 public String bind(String id, String binding1, String binding2) {
1590 	return bind(id, new String[] { binding1, binding2 });
1591 }
1592 
1593 /*
1594  * Lookup the message with the given ID in this catalog and bind its
1595  * substitution locations with the given string values.
1596  */
bind(String id, String[] arguments)1597 public String bind(String id, String[] arguments) {
1598 	if (id == null)
1599 		return "No message available"; //$NON-NLS-1$
1600 	String message = null;
1601 	try {
1602 		message = this.bundle.getString(id);
1603 	} catch (MissingResourceException e) {
1604 		// If we got an exception looking for the message, fail gracefully by just returning
1605 		// the id we were looking for.  In most cases this is semi-informative so is not too bad.
1606 		return "Missing message: " + id + " in: " + Main.bundleName; //$NON-NLS-2$ //$NON-NLS-1$
1607 	}
1608 	return MessageFormat.format(message, (Object[]) arguments);
1609 }
1610 /**
1611  * Return true if and only if the running VM supports the given minimal version.
1612  *
1613  * <p>This only checks the major version, since the minor version is always 0 (at least for the useful cases).</p>
1614  * <p>The given minimalSupportedVersion is one of the constants:</p>
1615  * <ul>
1616  * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_1</code></li>
1617  * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_2</code></li>
1618  * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_3</code></li>
1619  * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_4</code></li>
1620  * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_5</code></li>
1621  * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_6</code></li>
1622  * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_7</code></li>
1623  * </ul>
1624  * @param minimalSupportedVersion the given minimal version
1625  * @return true if and only if the running VM supports the given minimal version, false otherwise
1626  */
checkVMVersion(long minimalSupportedVersion)1627 private boolean checkVMVersion(long minimalSupportedVersion) {
1628 	// the format of this property is supposed to be xx.x where x are digits.
1629 	String classFileVersion = System.getProperty("java.class.version"); //$NON-NLS-1$
1630 	if (classFileVersion == null) {
1631 		// by default we don't support a class file version we cannot recognize
1632 		return false;
1633 	}
1634 	int index = classFileVersion.indexOf('.');
1635 	if (index == -1) {
1636 		// by default we don't support a class file version we cannot recognize
1637 		return false;
1638 	}
1639 	int majorVersion;
1640 	try {
1641 		majorVersion = Integer.parseInt(classFileVersion.substring(0, index));
1642 	} catch (NumberFormatException e) {
1643 		// by default we don't support a class file version we cannot recognize
1644 		return false;
1645 	}
1646 	switch(majorVersion) {
1647 		case ClassFileConstants.MAJOR_VERSION_1_1 : // 1.0 and 1.1
1648 			return ClassFileConstants.JDK1_1 >= minimalSupportedVersion;
1649 		case ClassFileConstants.MAJOR_VERSION_1_2 : // 1.2
1650 			return ClassFileConstants.JDK1_2 >= minimalSupportedVersion;
1651 		case ClassFileConstants.MAJOR_VERSION_1_3 : // 1.3
1652 			return ClassFileConstants.JDK1_3 >= minimalSupportedVersion;
1653 		case ClassFileConstants.MAJOR_VERSION_1_4 : // 1.4
1654 			return ClassFileConstants.JDK1_4 >= minimalSupportedVersion;
1655 		case ClassFileConstants.MAJOR_VERSION_1_5 : // 1.5
1656 			return ClassFileConstants.JDK1_5 >= minimalSupportedVersion;
1657 		case ClassFileConstants.MAJOR_VERSION_1_6 : // 1.6
1658 			return ClassFileConstants.JDK1_6 >= minimalSupportedVersion;
1659 		case ClassFileConstants.MAJOR_VERSION_1_7 : // 1.7
1660 			return ClassFileConstants.JDK1_7 >= minimalSupportedVersion;
1661 		case ClassFileConstants.MAJOR_VERSION_1_8: // 1.8
1662 			return ClassFileConstants.JDK1_8 >= minimalSupportedVersion;
1663 	}
1664 	// unknown version
1665 	return false;
1666 }
1667 /*
1668  *  Low-level API performing the actual compilation
1669  */
compile(String[] argv)1670 public boolean compile(String[] argv) {
1671 
1672 	// decode command line arguments
1673 	try {
1674 		configure(argv);
1675 		if (this.progress != null)
1676 			this.progress.begin(this.filenames == null ? 0 : this.filenames.length * this.maxRepetition);
1677 		if (this.proceed) {
1678 //				if (this.verbose) {
1679 //					System.out.println(new CompilerOptions(this.options));
1680 //				}
1681 			if (this.showProgress) this.logger.compiling();
1682 			for (this.currentRepetition = 0; this.currentRepetition < this.maxRepetition; this.currentRepetition++) {
1683 				this.globalProblemsCount = 0;
1684 				this.globalErrorsCount = 0;
1685 				this.globalWarningsCount = 0;
1686 				this.globalTasksCount = 0;
1687 				this.exportedClassFilesCounter = 0;
1688 
1689 				if (this.maxRepetition > 1) {
1690 					this.logger.flush();
1691 					this.logger.logRepetition(this.currentRepetition, this.maxRepetition);
1692 				}
1693 				// request compilation
1694 				performCompilation();
1695 			}
1696 			if (this.compilerStats != null) {
1697 				this.logger.logAverage();
1698 			}
1699 			if (this.showProgress) this.logger.printNewLine();
1700 		}
1701 		if (this.systemExitWhenFinished) {
1702 			this.logger.flush();
1703 			this.logger.close();
1704 			System.exit(this.globalErrorsCount > 0 ? -1 : 0);
1705 		}
1706 	} catch (IllegalArgumentException e) {
1707 		this.logger.logException(e);
1708 		if (this.systemExitWhenFinished) {
1709 			this.logger.flush();
1710 			this.logger.close();
1711 			System.exit(-1);
1712 		}
1713 		return false;
1714 	} catch (RuntimeException e) { // internal compiler failure
1715 		this.logger.logException(e);
1716 		if (this.systemExitWhenFinished) {
1717 			this.logger.flush();
1718 			this.logger.close();
1719 			System.exit(-1);
1720 		}
1721 		return false;
1722 	} finally {
1723 		this.logger.flush();
1724 		this.logger.close();
1725 		if (this.progress != null)
1726 			this.progress.done();
1727 	}
1728 	if (this.globalErrorsCount == 0 && (this.progress == null || !this.progress.isCanceled()))
1729 		return true;
1730 	return false;
1731 }
1732 
1733 /*
1734 Decode the command line arguments
1735  */
configure(String[] argv)1736 public void configure(String[] argv) {
1737 
1738 	if ((argv == null) || (argv.length == 0)) {
1739 		printUsage();
1740 		return;
1741 	}
1742 
1743 	final int INSIDE_CLASSPATH_start = 1;
1744 	final int INSIDE_DESTINATION_PATH = 3;
1745 	final int INSIDE_TARGET = 4;
1746 	final int INSIDE_LOG = 5;
1747 	final int INSIDE_REPETITION = 6;
1748 	final int INSIDE_SOURCE = 7;
1749 	final int INSIDE_DEFAULT_ENCODING = 8;
1750 	final int INSIDE_BOOTCLASSPATH_start = 9;
1751 	final int INSIDE_MAX_PROBLEMS = 11;
1752 	final int INSIDE_EXT_DIRS = 12;
1753 	final int INSIDE_SOURCE_PATH_start = 13;
1754 	final int INSIDE_ENDORSED_DIRS = 15;
1755 	final int INSIDE_SOURCE_DIRECTORY_DESTINATION_PATH = 16;
1756 	final int INSIDE_PROCESSOR_PATH_start = 17;
1757 	final int INSIDE_PROCESSOR_start = 18;
1758 	final int INSIDE_S_start = 19;
1759 	final int INSIDE_CLASS_NAMES = 20;
1760 	final int INSIDE_WARNINGS_PROPERTIES = 21;
1761 
1762 	final int DEFAULT = 0;
1763 	ArrayList bootclasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
1764 	String sourcepathClasspathArg = null;
1765 	ArrayList sourcepathClasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
1766 	ArrayList classpaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
1767 	ArrayList extdirsClasspaths = null;
1768 	ArrayList endorsedDirClasspaths = null;
1769 
1770 	int index = -1;
1771 	int filesCount = 0;
1772 	int classCount = 0;
1773 	int argCount = argv.length;
1774 	int mode = DEFAULT;
1775 	this.maxRepetition = 0;
1776 	boolean printUsageRequired = false;
1777 	String usageSection = null;
1778 	boolean printVersionRequired = false;
1779 
1780 	boolean didSpecifyDeprecation = false;
1781 	boolean didSpecifyCompliance = false;
1782 	boolean didSpecifyDisabledAnnotationProcessing = false;
1783 
1784 	String customEncoding = null;
1785 	String customDestinationPath = null;
1786 	String currentSourceDirectory = null;
1787 	String currentArg = Util.EMPTY_STRING;
1788 
1789 	Set specifiedEncodings = null;
1790 
1791 	// expand the command line if necessary
1792 	boolean needExpansion = false;
1793 	loop: for (int i = 0; i < argCount; i++) {
1794 			if (argv[i].startsWith("@")) { //$NON-NLS-1$
1795 				needExpansion = true;
1796 				break loop;
1797 			}
1798 	}
1799 
1800 	String[] newCommandLineArgs = null;
1801 	if (needExpansion) {
1802 		newCommandLineArgs = new String[argCount];
1803 		index = 0;
1804 		for (int i = 0; i < argCount; i++) {
1805 			String[] newArgs = null;
1806 			String arg = argv[i].trim();
1807 			if (arg.startsWith("@")) { //$NON-NLS-1$
1808 				try {
1809 					LineNumberReader reader = new LineNumberReader(new StringReader(new String(Util.getFileCharContent(new File(arg.substring(1)), null))));
1810 					StringBuffer buffer = new StringBuffer();
1811 					String line;
1812 					while((line = reader.readLine()) != null) {
1813 						line = line.trim();
1814 						if (!line.startsWith("#")) { //$NON-NLS-1$
1815 							buffer.append(line).append(" "); //$NON-NLS-1$
1816 						}
1817 					}
1818 					newArgs = tokenize(buffer.toString());
1819 				} catch(IOException e) {
1820 					throw new IllegalArgumentException(
1821 						this.bind("configure.invalidexpansionargumentname", arg)); //$NON-NLS-1$
1822 				}
1823 			}
1824 			if (newArgs != null) {
1825 				int newCommandLineArgsLength = newCommandLineArgs.length;
1826 				int newArgsLength = newArgs.length;
1827 				System.arraycopy(newCommandLineArgs, 0, (newCommandLineArgs = new String[newCommandLineArgsLength + newArgsLength - 1]), 0, index);
1828 				System.arraycopy(newArgs, 0, newCommandLineArgs, index, newArgsLength);
1829 				index += newArgsLength;
1830 			} else {
1831 				newCommandLineArgs[index++] = arg;
1832 			}
1833 		}
1834 		index = -1;
1835 	} else {
1836 		newCommandLineArgs = argv;
1837 		for (int i = 0; i < argCount; i++) {
1838 			newCommandLineArgs[i] = newCommandLineArgs[i].trim();
1839 		}
1840 	}
1841 	argCount = newCommandLineArgs.length;
1842 	this.expandedCommandLine = newCommandLineArgs;
1843 	while (++index < argCount) {
1844 
1845 		if (customEncoding != null) {
1846 			throw new IllegalArgumentException(
1847 				this.bind("configure.unexpectedCustomEncoding", currentArg, customEncoding)); //$NON-NLS-1$
1848 		}
1849 
1850 		currentArg = newCommandLineArgs[index];
1851 
1852 		switch(mode) {
1853 			case DEFAULT :
1854 				if (currentArg.startsWith("-nowarn")) { //$NON-NLS-1$
1855 					switch (currentArg.length()) {
1856 						case 7:
1857 							disableAll(ProblemSeverities.Warning);
1858 							break;
1859 						case 8:
1860 							throw new IllegalArgumentException(this.bind(
1861 									"configure.invalidNowarnOption", currentArg)); //$NON-NLS-1$
1862 						default:
1863 							int foldersStart = currentArg.indexOf('[') + 1;
1864 							int foldersEnd = currentArg.lastIndexOf(']');
1865 							if (foldersStart <= 8 || foldersEnd == -1 || foldersStart > foldersEnd
1866 									|| foldersEnd < currentArg.length() - 1) {
1867 								throw new IllegalArgumentException(this.bind(
1868 										"configure.invalidNowarnOption", currentArg)); //$NON-NLS-1$
1869 							}
1870 							String folders = currentArg.substring(foldersStart, foldersEnd);
1871 							if (folders.length() > 0) {
1872 								char[][] currentFolders = decodeIgnoreOptionalProblemsFromFolders(folders);
1873 								if (this.ignoreOptionalProblemsFromFolders != null) {
1874 									int length = this.ignoreOptionalProblemsFromFolders.length + currentFolders.length;
1875 									char[][] tempFolders = new char[length][];
1876 									System.arraycopy(this.ignoreOptionalProblemsFromFolders, 0, tempFolders, 0, this.ignoreOptionalProblemsFromFolders.length);
1877 									System.arraycopy(currentFolders, 0, tempFolders, this.ignoreOptionalProblemsFromFolders.length, currentFolders.length);
1878 									this.ignoreOptionalProblemsFromFolders = tempFolders;
1879 								} else {
1880 									this.ignoreOptionalProblemsFromFolders = currentFolders;
1881 								}
1882 							} else {
1883 								throw new IllegalArgumentException(this.bind(
1884 										"configure.invalidNowarnOption", currentArg)); //$NON-NLS-1$
1885 							}
1886 					}
1887 					mode = DEFAULT;
1888 					continue;
1889 				}
1890 				if (currentArg.startsWith("[")) { //$NON-NLS-1$
1891 					throw new IllegalArgumentException(
1892 						this.bind("configure.unexpectedBracket", //$NON-NLS-1$
1893 									currentArg));
1894 				}
1895 
1896 				if (currentArg.endsWith("]")) { //$NON-NLS-1$
1897 					// look for encoding specification
1898 					int encodingStart = currentArg.indexOf('[') + 1;
1899 					if (encodingStart <= 1) {
1900 						throw new IllegalArgumentException(
1901 								this.bind("configure.unexpectedBracket", currentArg)); //$NON-NLS-1$
1902 					}
1903 					int encodingEnd = currentArg.length() - 1;
1904 					if (encodingStart >= 1) {
1905 						if (encodingStart < encodingEnd) {
1906 							customEncoding = currentArg.substring(encodingStart, encodingEnd);
1907 							try { // ensure encoding is supported
1908 								new InputStreamReader(new ByteArrayInputStream(new byte[0]), customEncoding);
1909 							} catch (UnsupportedEncodingException e) {
1910 								throw new IllegalArgumentException(
1911 									this.bind("configure.unsupportedEncoding", customEncoding)); //$NON-NLS-1$
1912 							}
1913 						}
1914 						currentArg = currentArg.substring(0, encodingStart - 1);
1915 					}
1916 				}
1917 
1918 				if (currentArg.endsWith(SuffixConstants.SUFFIX_STRING_java)) {
1919 					if (this.filenames == null) {
1920 						this.filenames = new String[argCount - index];
1921 						this.encodings = new String[argCount - index];
1922 						this.destinationPaths = new String[argCount - index];
1923 					} else if (filesCount == this.filenames.length) {
1924 						int length = this.filenames.length;
1925 						System.arraycopy(
1926 							this.filenames,
1927 							0,
1928 							(this.filenames = new String[length + argCount - index]),
1929 							0,
1930 							length);
1931 						System.arraycopy(
1932 							this.encodings,
1933 							0,
1934 							(this.encodings = new String[length + argCount - index]),
1935 							0,
1936 							length);
1937 						System.arraycopy(
1938 							this.destinationPaths,
1939 							0,
1940 							(this.destinationPaths = new String[length + argCount - index]),
1941 							0,
1942 							length);
1943 					}
1944 					this.filenames[filesCount] = currentArg;
1945 					this.encodings[filesCount++] = customEncoding;
1946 					// destination path cannot be specified upon an individual file
1947 					customEncoding = null;
1948 					mode = DEFAULT;
1949 					continue;
1950 				}
1951 				if (currentArg.equals("-log")) { //$NON-NLS-1$
1952 					if (this.log != null)
1953 						throw new IllegalArgumentException(
1954 							this.bind("configure.duplicateLog", currentArg)); //$NON-NLS-1$
1955 					mode = INSIDE_LOG;
1956 					continue;
1957 				}
1958 				if (currentArg.equals("-repeat")) { //$NON-NLS-1$
1959 					if (this.maxRepetition > 0)
1960 						throw new IllegalArgumentException(
1961 							this.bind("configure.duplicateRepeat", currentArg)); //$NON-NLS-1$
1962 					mode = INSIDE_REPETITION;
1963 					continue;
1964 				}
1965 				if (currentArg.equals("-maxProblems")) { //$NON-NLS-1$
1966 					if (this.maxProblems > 0)
1967 						throw new IllegalArgumentException(
1968 							this.bind("configure.duplicateMaxProblems", currentArg)); //$NON-NLS-1$
1969 					mode = INSIDE_MAX_PROBLEMS;
1970 					continue;
1971 				}
1972 				if (currentArg.equals("-source")) { //$NON-NLS-1$
1973 					mode = INSIDE_SOURCE;
1974 					continue;
1975 				}
1976 				if (currentArg.equals("-encoding")) { //$NON-NLS-1$
1977 					mode = INSIDE_DEFAULT_ENCODING;
1978 					continue;
1979 				}
1980 				if (currentArg.equals("-1.3")) { //$NON-NLS-1$
1981 					if (didSpecifyCompliance) {
1982 						throw new IllegalArgumentException(
1983 							this.bind("configure.duplicateCompliance", currentArg));//$NON-NLS-1$
1984 					}
1985 					didSpecifyCompliance = true;
1986 					this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_3);
1987 					mode = DEFAULT;
1988 					continue;
1989 				}
1990 				if (currentArg.equals("-1.4")) { //$NON-NLS-1$
1991 					if (didSpecifyCompliance) {
1992 						throw new IllegalArgumentException(
1993 							this.bind("configure.duplicateCompliance", currentArg)); //$NON-NLS-1$
1994 					}
1995 					didSpecifyCompliance = true;
1996 					this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
1997 					mode = DEFAULT;
1998 					continue;
1999 				}
2000 				if (currentArg.equals("-1.5") || currentArg.equals("-5") || currentArg.equals("-5.0")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
2001 					if (didSpecifyCompliance) {
2002 						throw new IllegalArgumentException(
2003 							this.bind("configure.duplicateCompliance", currentArg)); //$NON-NLS-1$
2004 					}
2005 					didSpecifyCompliance = true;
2006 					this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_5);
2007 					mode = DEFAULT;
2008 					continue;
2009 				}
2010 				if (currentArg.equals("-1.6") || currentArg.equals("-6") || currentArg.equals("-6.0")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
2011 					if (didSpecifyCompliance) {
2012 						throw new IllegalArgumentException(
2013 							this.bind("configure.duplicateCompliance", currentArg)); //$NON-NLS-1$
2014 					}
2015 					didSpecifyCompliance = true;
2016 					this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_6);
2017 					mode = DEFAULT;
2018 					continue;
2019 				}
2020 				if (currentArg.equals("-1.7") || currentArg.equals("-7") || currentArg.equals("-7.0")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
2021 					if (didSpecifyCompliance) {
2022 						throw new IllegalArgumentException(
2023 							this.bind("configure.duplicateCompliance", currentArg)); //$NON-NLS-1$
2024 					}
2025 					didSpecifyCompliance = true;
2026 					this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_7);
2027 					mode = DEFAULT;
2028 					continue;
2029 				}
2030 				if (currentArg.equals("-1.8") || currentArg.equals("-8") || currentArg.equals("-8.0")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
2031 					if (didSpecifyCompliance) {
2032 						throw new IllegalArgumentException(
2033 							this.bind("configure.duplicateCompliance", currentArg)); //$NON-NLS-1$
2034 					}
2035 					didSpecifyCompliance = true;
2036 					this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_8);
2037 					mode = DEFAULT;
2038 					continue;
2039 				}
2040 				if (currentArg.equals("-d")) { //$NON-NLS-1$
2041 					if (this.destinationPath != null) {
2042 						StringBuffer errorMessage = new StringBuffer();
2043 						errorMessage.append(currentArg);
2044 						if ((index + 1) < argCount) {
2045 							errorMessage.append(' ');
2046 							errorMessage.append(newCommandLineArgs[index + 1]);
2047 						}
2048 						throw new IllegalArgumentException(
2049 							this.bind("configure.duplicateOutputPath", errorMessage.toString())); //$NON-NLS-1$
2050 					}
2051 					mode = INSIDE_DESTINATION_PATH;
2052 					continue;
2053 				}
2054 				if (currentArg.equals("-classpath") //$NON-NLS-1$
2055 					|| currentArg.equals("-cp")) { //$NON-NLS-1$
2056 					mode = INSIDE_CLASSPATH_start;
2057 					continue;
2058 				}
2059 				if (currentArg.equals("-bootclasspath")) {//$NON-NLS-1$
2060 					if (bootclasspaths.size() > 0) {
2061 						StringBuffer errorMessage = new StringBuffer();
2062 						errorMessage.append(currentArg);
2063 						if ((index + 1) < argCount) {
2064 							errorMessage.append(' ');
2065 							errorMessage.append(newCommandLineArgs[index + 1]);
2066 						}
2067 						throw new IllegalArgumentException(
2068 							this.bind("configure.duplicateBootClasspath", errorMessage.toString())); //$NON-NLS-1$
2069 					}
2070 					mode = INSIDE_BOOTCLASSPATH_start;
2071 					continue;
2072 				}
2073 				if (currentArg.equals("-sourcepath")) {//$NON-NLS-1$
2074 					if (sourcepathClasspathArg != null) {
2075 						StringBuffer errorMessage = new StringBuffer();
2076 						errorMessage.append(currentArg);
2077 						if ((index + 1) < argCount) {
2078 							errorMessage.append(' ');
2079 							errorMessage.append(newCommandLineArgs[index + 1]);
2080 						}
2081 						throw new IllegalArgumentException(
2082 							this.bind("configure.duplicateSourcepath", errorMessage.toString())); //$NON-NLS-1$
2083 					}
2084 					mode = INSIDE_SOURCE_PATH_start;
2085 					continue;
2086 				}
2087 				if (currentArg.equals("-extdirs")) {//$NON-NLS-1$
2088 					if (extdirsClasspaths != null) {
2089 						StringBuffer errorMessage = new StringBuffer();
2090 						errorMessage.append(currentArg);
2091 						if ((index + 1) < argCount) {
2092 							errorMessage.append(' ');
2093 							errorMessage.append(newCommandLineArgs[index + 1]);
2094 						}
2095 						throw new IllegalArgumentException(
2096 							this.bind("configure.duplicateExtDirs", errorMessage.toString())); //$NON-NLS-1$
2097 					}
2098 					mode = INSIDE_EXT_DIRS;
2099 					continue;
2100 				}
2101 				if (currentArg.equals("-endorseddirs")) { //$NON-NLS-1$
2102 					if (endorsedDirClasspaths != null) {
2103 						StringBuffer errorMessage = new StringBuffer();
2104 						errorMessage.append(currentArg);
2105 						if ((index + 1) < argCount) {
2106 							errorMessage.append(' ');
2107 							errorMessage.append(newCommandLineArgs[index + 1]);
2108 						}
2109 						throw new IllegalArgumentException(
2110 							this.bind("configure.duplicateEndorsedDirs", errorMessage.toString())); //$NON-NLS-1$
2111 					}
2112 					mode = INSIDE_ENDORSED_DIRS;
2113 					continue;
2114 				}
2115 				if (currentArg.equals("-progress")) { //$NON-NLS-1$
2116 					mode = DEFAULT;
2117 					this.showProgress = true;
2118 					continue;
2119 				}
2120 				if (currentArg.startsWith("-proceedOnError")) { //$NON-NLS-1$
2121 					mode = DEFAULT;
2122 					int length = currentArg.length();
2123 					if (length > 15) {
2124 						if (currentArg.equals("-proceedOnError:Fatal")) { //$NON-NLS-1$
2125 							this.options.put(CompilerOptions.OPTION_FatalOptionalError, CompilerOptions.ENABLED);
2126 						} else {
2127 							throw new IllegalArgumentException(
2128 									this.bind("configure.invalidWarningConfiguration", currentArg)); //$NON-NLS-1$
2129 						}
2130 					} else {
2131 						this.options.put(CompilerOptions.OPTION_FatalOptionalError, CompilerOptions.DISABLED);
2132 					}
2133 					this.proceedOnError = true;
2134 					continue;
2135 				}
2136 				if (currentArg.equals("-time")) { //$NON-NLS-1$
2137 					mode = DEFAULT;
2138 					this.timing = TIMING_ENABLED;
2139 					continue;
2140 				}
2141 				if (currentArg.equals("-time:detail")) { //$NON-NLS-1$
2142 					mode = DEFAULT;
2143 					this.timing = TIMING_ENABLED|TIMING_DETAILED;
2144 					continue;
2145 				}
2146 				if (currentArg.equals("-version") //$NON-NLS-1$
2147 						|| currentArg.equals("-v")) { //$NON-NLS-1$
2148 					this.logger.logVersion(true);
2149 					this.proceed = false;
2150 					return;
2151 				}
2152 				if (currentArg.equals("-showversion")) { //$NON-NLS-1$
2153 					printVersionRequired = true;
2154 					mode = DEFAULT;
2155 					continue;
2156 				}
2157 				if ("-deprecation".equals(currentArg)) { //$NON-NLS-1$
2158 					didSpecifyDeprecation = true;
2159 					this.options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
2160 					mode = DEFAULT;
2161 					continue;
2162 				}
2163 				if (currentArg.equals("-help") || currentArg.equals("-?")) { //$NON-NLS-1$ //$NON-NLS-2$
2164 					printUsageRequired = true;
2165 					mode = DEFAULT;
2166 					continue;
2167 				}
2168 				if (currentArg.equals("-help:warn") || //$NON-NLS-1$
2169 						currentArg.equals("-?:warn")) { //$NON-NLS-1$
2170 					printUsageRequired = true;
2171 					usageSection = "misc.usage.warn"; //$NON-NLS-1$
2172 					continue;
2173 				}
2174 				if (currentArg.equals("-noExit")) { //$NON-NLS-1$
2175 					this.systemExitWhenFinished = false;
2176 					mode = DEFAULT;
2177 					continue;
2178 				}
2179 				if (currentArg.equals("-verbose")) { //$NON-NLS-1$
2180 					this.verbose = true;
2181 					mode = DEFAULT;
2182 					continue;
2183 				}
2184 				if (currentArg.equals("-referenceInfo")) { //$NON-NLS-1$
2185 					this.produceRefInfo = true;
2186 					mode = DEFAULT;
2187 					continue;
2188 				}
2189 				if (currentArg.equals("-inlineJSR")) { //$NON-NLS-1$
2190 					mode = DEFAULT;
2191 					this.options.put(
2192 							CompilerOptions.OPTION_InlineJsr,
2193 							CompilerOptions.ENABLED);
2194 					continue;
2195 				}
2196 				if (currentArg.equals("-parameters")) { //$NON-NLS-1$
2197 					mode = DEFAULT;
2198 					this.options.put(
2199 							CompilerOptions.OPTION_MethodParametersAttribute,
2200 							CompilerOptions.GENERATE);
2201 					continue;
2202 				}
2203 				if (currentArg.equals("-genericsignature")) { //$NON-NLS-1$
2204 					mode = DEFAULT;
2205 					this.options.put(
2206 							CompilerOptions.OPTION_LambdaGenericSignature,
2207 							CompilerOptions.GENERATE);
2208 					continue;
2209 				}
2210 				if (currentArg.startsWith("-g")) { //$NON-NLS-1$
2211 					mode = DEFAULT;
2212 					String debugOption = currentArg;
2213 					int length = currentArg.length();
2214 					if (length == 2) {
2215 						this.options.put(
2216 							CompilerOptions.OPTION_LocalVariableAttribute,
2217 							CompilerOptions.GENERATE);
2218 						this.options.put(
2219 							CompilerOptions.OPTION_LineNumberAttribute,
2220 							CompilerOptions.GENERATE);
2221 						this.options.put(
2222 							CompilerOptions.OPTION_SourceFileAttribute,
2223 							CompilerOptions.GENERATE);
2224 						continue;
2225 					}
2226 					if (length > 3) {
2227 						this.options.put(
2228 							CompilerOptions.OPTION_LocalVariableAttribute,
2229 							CompilerOptions.DO_NOT_GENERATE);
2230 						this.options.put(
2231 							CompilerOptions.OPTION_LineNumberAttribute,
2232 							CompilerOptions.DO_NOT_GENERATE);
2233 						this.options.put(
2234 							CompilerOptions.OPTION_SourceFileAttribute,
2235 							CompilerOptions.DO_NOT_GENERATE);
2236 						if (length == 7 && debugOption.equals("-g:" + NONE)) //$NON-NLS-1$
2237 							continue;
2238 						StringTokenizer tokenizer =
2239 							new StringTokenizer(debugOption.substring(3, debugOption.length()), ","); //$NON-NLS-1$
2240 						while (tokenizer.hasMoreTokens()) {
2241 							String token = tokenizer.nextToken();
2242 							if (token.equals("vars")) { //$NON-NLS-1$
2243 								this.options.put(
2244 									CompilerOptions.OPTION_LocalVariableAttribute,
2245 									CompilerOptions.GENERATE);
2246 							} else if (token.equals("lines")) { //$NON-NLS-1$
2247 								this.options.put(
2248 									CompilerOptions.OPTION_LineNumberAttribute,
2249 									CompilerOptions.GENERATE);
2250 							} else if (token.equals("source")) { //$NON-NLS-1$
2251 								this.options.put(
2252 									CompilerOptions.OPTION_SourceFileAttribute,
2253 									CompilerOptions.GENERATE);
2254 							} else {
2255 								throw new IllegalArgumentException(
2256 									this.bind("configure.invalidDebugOption", debugOption)); //$NON-NLS-1$
2257 							}
2258 						}
2259 						continue;
2260 					}
2261 					throw new IllegalArgumentException(
2262 						this.bind("configure.invalidDebugOption", debugOption)); //$NON-NLS-1$
2263 				}
2264 				if (currentArg.startsWith("-warn")) { //$NON-NLS-1$
2265 					mode = DEFAULT;
2266 					String warningOption = currentArg;
2267 					int length = currentArg.length();
2268 					if (length == 10 && warningOption.equals("-warn:" + NONE)) { //$NON-NLS-1$
2269 						disableAll(ProblemSeverities.Warning);
2270 						continue;
2271 					}
2272 					if (length <= 6) {
2273 						throw new IllegalArgumentException(
2274 							this.bind("configure.invalidWarningConfiguration", warningOption)); //$NON-NLS-1$
2275 					}
2276 					int warnTokenStart;
2277 					boolean isEnabling;
2278 					switch (warningOption.charAt(6)) {
2279 						case '+' :
2280 							warnTokenStart = 7;
2281 							isEnabling = true;
2282 							break;
2283 						case '-' :
2284 							warnTokenStart = 7;
2285 							isEnabling = false; // specified warnings are disabled
2286 							break;
2287 						default:
2288 							disableAll(ProblemSeverities.Warning);
2289 							warnTokenStart = 6;
2290 							isEnabling = true;
2291 					}
2292 
2293 					StringTokenizer tokenizer =
2294 						new StringTokenizer(warningOption.substring(warnTokenStart, warningOption.length()), ","); //$NON-NLS-1$
2295 					int tokenCounter = 0;
2296 
2297 					if (didSpecifyDeprecation) {  // deprecation could have also been set through -deprecation option
2298 						this.options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
2299 					}
2300 
2301 					while (tokenizer.hasMoreTokens()) {
2302 						String token = tokenizer.nextToken();
2303 						tokenCounter++;
2304 						switch(token.charAt(0)) {
2305 							case '+' :
2306 								isEnabling = true;
2307 								token = token.substring(1);
2308 								break;
2309 							case '-' :
2310 								isEnabling = false;
2311 								token = token.substring(1);
2312 						}
2313 						handleWarningToken(token, isEnabling);
2314 					}
2315 					if (tokenCounter == 0) {
2316 						throw new IllegalArgumentException(
2317 							this.bind("configure.invalidWarningOption", currentArg)); //$NON-NLS-1$
2318 					}
2319 					continue;
2320 				}
2321 				if (currentArg.startsWith("-err")) { //$NON-NLS-1$
2322 					mode = DEFAULT;
2323 					String errorOption = currentArg;
2324 					int length = currentArg.length();
2325 					if (length <= 5) {
2326 						throw new IllegalArgumentException(
2327 							this.bind("configure.invalidErrorConfiguration", errorOption)); //$NON-NLS-1$
2328 					}
2329 					int errorTokenStart;
2330 					boolean isEnabling;
2331 					switch (errorOption.charAt(5)) {
2332 						case '+' :
2333 							errorTokenStart = 6;
2334 							isEnabling = true;
2335 							break;
2336 						case '-' :
2337 							errorTokenStart = 6;
2338 							isEnabling = false; // specified errors are disabled
2339 							break;
2340 						default:
2341 							disableAll(ProblemSeverities.Error);
2342 							errorTokenStart = 5;
2343 							isEnabling = true;
2344 					}
2345 
2346 					StringTokenizer tokenizer =
2347 						new StringTokenizer(errorOption.substring(errorTokenStart, errorOption.length()), ","); //$NON-NLS-1$
2348 					int tokenCounter = 0;
2349 
2350 					while (tokenizer.hasMoreTokens()) {
2351 						String token = tokenizer.nextToken();
2352 						tokenCounter++;
2353 						switch(token.charAt(0)) {
2354 							case '+' :
2355 								isEnabling = true;
2356 								token = token.substring(1);
2357 								break;
2358 							case '-' :
2359 								isEnabling = false;
2360 								token = token.substring(1);
2361 								break;
2362 						}
2363 						handleErrorToken(token, isEnabling);
2364 					}
2365 					if (tokenCounter == 0) {
2366 						throw new IllegalArgumentException(
2367 							this.bind("configure.invalidErrorOption", currentArg)); //$NON-NLS-1$
2368 					}
2369 					continue;
2370 				}
2371 				if (currentArg.equals("-target")) { //$NON-NLS-1$
2372 					mode = INSIDE_TARGET;
2373 					continue;
2374 				}
2375 				if (currentArg.equals("-preserveAllLocals")) { //$NON-NLS-1$
2376 					this.options.put(
2377 						CompilerOptions.OPTION_PreserveUnusedLocal,
2378 						CompilerOptions.PRESERVE);
2379 					mode = DEFAULT;
2380 					continue;
2381 				}
2382 				if (currentArg.equals("-enableJavadoc")) {//$NON-NLS-1$
2383 					mode = DEFAULT;
2384 					this.enableJavadocOn = true;
2385 					continue;
2386 				}
2387 				if (currentArg.equals("-Xemacs")) { //$NON-NLS-1$
2388 					mode = DEFAULT;
2389 					this.logger.setEmacs();
2390 					continue;
2391 				}
2392 				// annotation processing
2393 				if (currentArg.startsWith("-A")) { //$NON-NLS-1$
2394 					mode = DEFAULT;
2395 					continue;
2396 				}
2397 				if (currentArg.equals("-processorpath")) { //$NON-NLS-1$
2398 					mode = INSIDE_PROCESSOR_PATH_start;
2399 					continue;
2400 				}
2401 				if (currentArg.equals("-processor")) { //$NON-NLS-1$
2402 					mode = INSIDE_PROCESSOR_start;
2403 					continue;
2404 				}
2405 				if (currentArg.equals("-proc:only")) { //$NON-NLS-1$
2406 					this.options.put(
2407 						CompilerOptions.OPTION_GenerateClassFiles,
2408 						CompilerOptions.DISABLED);
2409 					mode = DEFAULT;
2410 					continue;
2411 				}
2412 				if (currentArg.equals("-proc:none")) { //$NON-NLS-1$
2413 					didSpecifyDisabledAnnotationProcessing = true;
2414 					this.options.put(
2415 						CompilerOptions.OPTION_Process_Annotations,
2416 						CompilerOptions.DISABLED);
2417 					mode = DEFAULT;
2418 					continue;
2419 				}
2420 				if (currentArg.equals("-s")) { //$NON-NLS-1$
2421 					mode = INSIDE_S_start;
2422 					continue;
2423 				}
2424 				if (currentArg.equals("-XprintProcessorInfo") //$NON-NLS-1$
2425 						|| currentArg.equals("-XprintRounds")) { //$NON-NLS-1$
2426 					mode = DEFAULT;
2427 					continue;
2428 				}
2429 				// tolerated javac options - quietly filtered out
2430 				if (currentArg.startsWith("-X")) { //$NON-NLS-1$
2431 					mode = DEFAULT;
2432 					continue;
2433 				}
2434 				if (currentArg.startsWith("-J")) { //$NON-NLS-1$
2435 					mode = DEFAULT;
2436 					continue;
2437 				}
2438 				if (currentArg.equals("-O")) { //$NON-NLS-1$
2439 					mode = DEFAULT;
2440 					continue;
2441 				}
2442 				if (currentArg.equals("-classNames")) { //$NON-NLS-1$
2443 					mode = INSIDE_CLASS_NAMES;
2444 					continue;
2445 				}
2446 				if (currentArg.equals("-properties")) { //$NON-NLS-1$
2447 					mode = INSIDE_WARNINGS_PROPERTIES;
2448 					continue;
2449 				}
2450 				if (currentArg.equals("-missingNullDefault")) { //$NON-NLS-1$
2451 					this.options.put(CompilerOptions.OPTION_ReportMissingNonNullByDefaultAnnotation, CompilerOptions.WARNING);
2452 					continue;
2453 				}
2454 				break;
2455 			case INSIDE_TARGET :
2456 				if (this.didSpecifyTarget) {
2457 					throw new IllegalArgumentException(
2458 						this.bind("configure.duplicateTarget", currentArg));//$NON-NLS-1$
2459 				}
2460 				this.didSpecifyTarget = true;
2461 				if (currentArg.equals("1.1")) { //$NON-NLS-1$
2462 					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_1);
2463 				} else if (currentArg.equals("1.2")) { //$NON-NLS-1$
2464 					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2);
2465 				} else if (currentArg.equals("1.3")) { //$NON-NLS-1$
2466 					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_3);
2467 				} else if (currentArg.equals("1.4")) { //$NON-NLS-1$
2468 					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
2469 				} else if (currentArg.equals("1.5") || currentArg.equals("5") || currentArg.equals("5.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
2470 					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
2471 				} else if (currentArg.equals("1.6") || currentArg.equals("6") || currentArg.equals("6.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
2472 					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
2473 				} else if (currentArg.equals("1.7") || currentArg.equals("7") || currentArg.equals("7.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
2474 					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_7);
2475 				} else if (currentArg.equals("1.8") || currentArg.equals("8") || currentArg.equals("8.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
2476 					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_8);
2477 				}
2478 				else if (currentArg.equals("jsr14")) { //$NON-NLS-1$
2479 					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_JSR14);
2480 				} else if (currentArg.equals("cldc1.1")) { //$NON-NLS-1$
2481 					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_CLDC1_1);
2482 					this.options.put(CompilerOptions.OPTION_InlineJsr, CompilerOptions.ENABLED);
2483 				}else {
2484 					throw new IllegalArgumentException(this.bind("configure.targetJDK", currentArg)); //$NON-NLS-1$
2485 				}
2486 				mode = DEFAULT;
2487 				continue;
2488 			case INSIDE_LOG :
2489 				this.log = currentArg;
2490 				mode = DEFAULT;
2491 				continue;
2492 			case INSIDE_REPETITION :
2493 				try {
2494 					this.maxRepetition = Integer.parseInt(currentArg);
2495 					if (this.maxRepetition <= 0) {
2496 						throw new IllegalArgumentException(this.bind("configure.repetition", currentArg)); //$NON-NLS-1$
2497 					}
2498 				} catch (NumberFormatException e) {
2499 					throw new IllegalArgumentException(this.bind("configure.repetition", currentArg)); //$NON-NLS-1$
2500 				}
2501 				mode = DEFAULT;
2502 				continue;
2503 			case INSIDE_MAX_PROBLEMS :
2504 				try {
2505 					this.maxProblems = Integer.parseInt(currentArg);
2506 					if (this.maxProblems <= 0) {
2507 						throw new IllegalArgumentException(this.bind("configure.maxProblems", currentArg)); //$NON-NLS-1$
2508 					}
2509 					this.options.put(CompilerOptions.OPTION_MaxProblemPerUnit, currentArg);
2510 				} catch (NumberFormatException e) {
2511 					throw new IllegalArgumentException(this.bind("configure.maxProblems", currentArg)); //$NON-NLS-1$
2512 				}
2513 				mode = DEFAULT;
2514 				continue;
2515 			case INSIDE_SOURCE :
2516 				if (this.didSpecifySource) {
2517 					throw new IllegalArgumentException(
2518 						this.bind("configure.duplicateSource", currentArg));//$NON-NLS-1$
2519 				}
2520 				this.didSpecifySource = true;
2521 				if (currentArg.equals("1.3")) { //$NON-NLS-1$
2522 					this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
2523 				} else if (currentArg.equals("1.4")) { //$NON-NLS-1$
2524 					this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_4);
2525 				} else if (currentArg.equals("1.5") || currentArg.equals("5") || currentArg.equals("5.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
2526 					this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_5);
2527 				} else if (currentArg.equals("1.6") || currentArg.equals("6") || currentArg.equals("6.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
2528 					this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_6);
2529 				} else if (currentArg.equals("1.7") || currentArg.equals("7") || currentArg.equals("7.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
2530 					this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_7);
2531 				} else if (currentArg.equals("1.8") || currentArg.equals("8") || currentArg.equals("8.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
2532 					this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_8);
2533 				} else {
2534 					throw new IllegalArgumentException(this.bind("configure.source", currentArg)); //$NON-NLS-1$
2535 				}
2536 				mode = DEFAULT;
2537 				continue;
2538 			case INSIDE_DEFAULT_ENCODING :
2539 				if (specifiedEncodings != null) {
2540 					// check already defined encoding
2541 					if (!specifiedEncodings.contains(currentArg)) {
2542 						if (specifiedEncodings.size() > 1) {
2543 							this.logger.logWarning(
2544 									this.bind("configure.differentencodings", //$NON-NLS-1$
2545 									currentArg,
2546 									getAllEncodings(specifiedEncodings)));
2547 						} else {
2548 							this.logger.logWarning(
2549 									this.bind("configure.differentencoding", //$NON-NLS-1$
2550 									currentArg,
2551 									getAllEncodings(specifiedEncodings)));
2552 						}
2553 					}
2554 				} else {
2555 					specifiedEncodings = new HashSet();
2556 				}
2557 				try { // ensure encoding is supported
2558 					new InputStreamReader(new ByteArrayInputStream(new byte[0]), currentArg);
2559 				} catch (UnsupportedEncodingException e) {
2560 					throw new IllegalArgumentException(
2561 						this.bind("configure.unsupportedEncoding", currentArg)); //$NON-NLS-1$
2562 				}
2563 				specifiedEncodings.add(currentArg);
2564 				this.options.put(CompilerOptions.OPTION_Encoding, currentArg);
2565 				mode = DEFAULT;
2566 				continue;
2567 			case INSIDE_DESTINATION_PATH :
2568 				setDestinationPath(currentArg.equals(NONE) ? NONE : currentArg);
2569 				mode = DEFAULT;
2570 				continue;
2571 			case INSIDE_CLASSPATH_start:
2572 				mode = DEFAULT;
2573 				index += processPaths(newCommandLineArgs, index, currentArg, classpaths);
2574 				continue;
2575 			case INSIDE_BOOTCLASSPATH_start:
2576 				mode = DEFAULT;
2577 				index += processPaths(newCommandLineArgs, index, currentArg, bootclasspaths);
2578 				continue;
2579 			case INSIDE_SOURCE_PATH_start:
2580 				mode = DEFAULT;
2581 				String[] sourcePaths = new String[1];
2582 				index += processPaths(newCommandLineArgs, index, currentArg, sourcePaths);
2583 				sourcepathClasspathArg = sourcePaths[0];
2584 				continue;
2585 			case INSIDE_EXT_DIRS:
2586 				if (currentArg.indexOf("[-d") != -1) { //$NON-NLS-1$
2587 					throw new IllegalArgumentException(
2588 						this.bind("configure.unexpectedDestinationPathEntry", //$NON-NLS-1$
2589 							"-extdir")); //$NON-NLS-1$
2590 				}
2591 				StringTokenizer tokenizer = new StringTokenizer(currentArg,	File.pathSeparator, false);
2592 				extdirsClasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
2593 				while (tokenizer.hasMoreTokens())
2594 					extdirsClasspaths.add(tokenizer.nextToken());
2595 				mode = DEFAULT;
2596 				continue;
2597 			case INSIDE_ENDORSED_DIRS:
2598 				if (currentArg.indexOf("[-d") != -1) { //$NON-NLS-1$
2599 					throw new IllegalArgumentException(
2600 						this.bind("configure.unexpectedDestinationPathEntry", //$NON-NLS-1$
2601 							"-endorseddirs")); //$NON-NLS-1$
2602 				}				tokenizer = new StringTokenizer(currentArg,	File.pathSeparator, false);
2603 				endorsedDirClasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
2604 				while (tokenizer.hasMoreTokens())
2605 					endorsedDirClasspaths.add(tokenizer.nextToken());
2606 				mode = DEFAULT;
2607 				continue;
2608 			case INSIDE_SOURCE_DIRECTORY_DESTINATION_PATH:
2609 				if (currentArg.endsWith("]")) { //$NON-NLS-1$
2610 					customDestinationPath = currentArg.substring(0,
2611 						currentArg.length() - 1);
2612 				} else {
2613 					throw new IllegalArgumentException(
2614 						this.bind("configure.incorrectDestinationPathEntry", //$NON-NLS-1$
2615 							"[-d " + currentArg)); //$NON-NLS-1$
2616 				}
2617 				break;
2618 			case INSIDE_PROCESSOR_PATH_start :
2619 				// nothing to do here. This is consumed again by the AnnotationProcessorManager
2620 				mode = DEFAULT;
2621 				continue;
2622 			case INSIDE_PROCESSOR_start :
2623 				// nothing to do here. This is consumed again by the AnnotationProcessorManager
2624 				mode = DEFAULT;
2625 				continue;
2626 			case INSIDE_S_start :
2627 				// nothing to do here. This is consumed again by the AnnotationProcessorManager
2628 				mode = DEFAULT;
2629 				continue;
2630 			case INSIDE_CLASS_NAMES :
2631 				tokenizer = new StringTokenizer(currentArg, ","); //$NON-NLS-1$
2632 				if (this.classNames == null) {
2633 					this.classNames = new String[DEFAULT_SIZE_CLASSPATH];
2634 				}
2635 				while (tokenizer.hasMoreTokens()) {
2636 					if (this.classNames.length == classCount) {
2637 						// resize
2638 						System.arraycopy(
2639 							this.classNames,
2640 							0,
2641 							(this.classNames = new String[classCount * 2]),
2642 							0,
2643 							classCount);
2644 					}
2645 					this.classNames[classCount++] = tokenizer.nextToken();
2646 				}
2647 				mode = DEFAULT;
2648 				continue;
2649 			case INSIDE_WARNINGS_PROPERTIES :
2650 				initializeWarnings(currentArg);
2651 				mode = DEFAULT;
2652 				continue;
2653 		}
2654 
2655 		// default is input directory, if no custom destination path exists
2656 		if (customDestinationPath == null) {
2657 			if (File.separatorChar != '/') {
2658 				currentArg = currentArg.replace('/', File.separatorChar);
2659 			}
2660 			if (currentArg.endsWith("[-d")) { //$NON-NLS-1$
2661 				currentSourceDirectory = currentArg.substring(0,
2662 					currentArg.length() - 3);
2663 				mode = INSIDE_SOURCE_DIRECTORY_DESTINATION_PATH;
2664 				continue;
2665 			}
2666 			currentSourceDirectory = currentArg;
2667 		}
2668 		File dir = new File(currentSourceDirectory);
2669 		if (!dir.isDirectory()) {
2670 			throw new IllegalArgumentException(
2671 				this.bind("configure.unrecognizedOption", currentSourceDirectory)); //$NON-NLS-1$
2672 		}
2673 		String[] result = FileFinder.find(dir, SuffixConstants.SUFFIX_STRING_JAVA);
2674 		if (NONE.equals(customDestinationPath)) {
2675 			customDestinationPath = NONE; // ensure == comparison
2676 		}
2677 		if (this.filenames != null) {
2678 			// some source files were specified explicitly
2679 			int length = result.length;
2680 			System.arraycopy(
2681 				this.filenames,
2682 				0,
2683 				(this.filenames = new String[length + filesCount]),
2684 				0,
2685 				filesCount);
2686 			System.arraycopy(
2687 				this.encodings,
2688 				0,
2689 				(this.encodings = new String[length + filesCount]),
2690 				0,
2691 				filesCount);
2692 			System.arraycopy(
2693 				this.destinationPaths,
2694 				0,
2695 				(this.destinationPaths = new String[length + filesCount]),
2696 				0,
2697 				filesCount);
2698 			System.arraycopy(result, 0, this.filenames, filesCount, length);
2699 			for (int i = 0; i < length; i++) {
2700 				this.encodings[filesCount + i] = customEncoding;
2701 				this.destinationPaths[filesCount + i] = customDestinationPath;
2702 			}
2703 			filesCount += length;
2704 			customEncoding = null;
2705 			customDestinationPath = null;
2706 			currentSourceDirectory = null;
2707 		} else {
2708 			this.filenames = result;
2709 			filesCount = this.filenames.length;
2710 			this.encodings = new String[filesCount];
2711 			this.destinationPaths = new String[filesCount];
2712 			for (int i = 0; i < filesCount; i++) {
2713 				this.encodings[i] = customEncoding;
2714 				this.destinationPaths[i] = customDestinationPath;
2715 			}
2716 			customEncoding = null;
2717 			customDestinationPath = null;
2718 			currentSourceDirectory = null;
2719 		}
2720 		mode = DEFAULT;
2721 		continue;
2722 	}
2723 
2724 	// set DocCommentSupport, with appropriate side effects on defaults if
2725 	// javadoc is not enabled
2726 	if (this.enableJavadocOn) {
2727 		this.options.put(
2728 			CompilerOptions.OPTION_DocCommentSupport,
2729 			CompilerOptions.ENABLED);
2730 	} else if (this.warnJavadocOn || this.warnAllJavadocOn) {
2731 		this.options.put(
2732 			CompilerOptions.OPTION_DocCommentSupport,
2733 			CompilerOptions.ENABLED);
2734 		// override defaults: references that are embedded in javadoc are ignored
2735 		// from the perspective of parameters and thrown exceptions usage
2736 		this.options.put(
2737 			CompilerOptions.OPTION_ReportUnusedParameterIncludeDocCommentReference,
2738 			CompilerOptions.DISABLED);
2739 		this.options.put(
2740 			CompilerOptions.OPTION_ReportUnusedDeclaredThrownExceptionIncludeDocCommentReference,
2741 			CompilerOptions.DISABLED);
2742 	}
2743 	// configure warnings for javadoc contents
2744 	if (this.warnJavadocOn) {
2745 		this.options.put(
2746 			CompilerOptions.OPTION_ReportInvalidJavadocTags,
2747 			CompilerOptions.ENABLED);
2748 		this.options.put(
2749 			CompilerOptions.OPTION_ReportInvalidJavadocTagsDeprecatedRef,
2750 			CompilerOptions.ENABLED);
2751 		this.options.put(
2752 			CompilerOptions.OPTION_ReportInvalidJavadocTagsNotVisibleRef,
2753 			CompilerOptions.ENABLED);
2754 		this.options.put(
2755 			CompilerOptions.OPTION_ReportMissingJavadocTagsVisibility,
2756 			CompilerOptions.PRIVATE);
2757 	}
2758 
2759 	if (printUsageRequired || (filesCount == 0 && classCount == 0)) {
2760 		if (usageSection ==  null) {
2761 			printUsage(); // default
2762 		} else {
2763 			printUsage(usageSection);
2764 		}
2765 		this.proceed = false;
2766 		return;
2767 	}
2768 
2769 	if (this.log != null) {
2770 		this.logger.setLog(this.log);
2771 	} else {
2772 		this.showProgress = false;
2773 	}
2774 	this.logger.logVersion(printVersionRequired);
2775 
2776 	validateOptions(didSpecifyCompliance);
2777 
2778 	// Enable annotation processing by default in batch mode when compliance is at least 1.6
2779 	// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=185768
2780 	if (!didSpecifyDisabledAnnotationProcessing
2781 			&& CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Compliance)) >= ClassFileConstants.JDK1_6) {
2782 		this.options.put(CompilerOptions.OPTION_Process_Annotations, CompilerOptions.ENABLED);
2783 	}
2784 
2785 	this.logger.logCommandLineArguments(newCommandLineArgs);
2786 	this.logger.logOptions(this.options);
2787 
2788 	if (this.maxRepetition == 0) {
2789 		this.maxRepetition = 1;
2790 	}
2791 	if (this.maxRepetition >= 3 && (this.timing & TIMING_ENABLED) != 0) {
2792 		this.compilerStats = new CompilerStats[this.maxRepetition];
2793 	}
2794 
2795 	if (filesCount != 0) {
2796 		System.arraycopy(
2797 			this.filenames,
2798 			0,
2799 			(this.filenames = new String[filesCount]),
2800 			0,
2801 			filesCount);
2802 	}
2803 
2804 	if (classCount != 0) {
2805 		System.arraycopy(
2806 			this.classNames,
2807 			0,
2808 			(this.classNames = new String[classCount]),
2809 			0,
2810 			classCount);
2811 	}
2812 
2813 	setPaths(bootclasspaths,
2814 			sourcepathClasspathArg,
2815 			sourcepathClasspaths,
2816 			classpaths,
2817 			extdirsClasspaths,
2818 			endorsedDirClasspaths,
2819 			customEncoding);
2820 
2821 	if (specifiedEncodings != null && specifiedEncodings.size() > 1) {
2822 		this.logger.logWarning(this.bind("configure.multipleencodings", //$NON-NLS-1$
2823 				(String) this.options.get(CompilerOptions.OPTION_Encoding),
2824 				getAllEncodings(specifiedEncodings)));
2825 	}
2826 	if (this.pendingErrors != null) {
2827 		for (Iterator iterator = this.pendingErrors.iterator(); iterator.hasNext(); ) {
2828 			String message = (String) iterator.next();
2829 			this.logger.logPendingError(message);
2830 		}
2831 		this.pendingErrors = null;
2832 	}
2833 }
2834 
decodeIgnoreOptionalProblemsFromFolders(String folders)2835 private static char[][] decodeIgnoreOptionalProblemsFromFolders(String folders) {
2836 	StringTokenizer tokenizer = new StringTokenizer(folders, File.pathSeparator);
2837 	char[][] result = new char[tokenizer.countTokens()][];
2838 	int count = 0;
2839 	while (tokenizer.hasMoreTokens()) {
2840 		String fileName = tokenizer.nextToken();
2841 		// relative folder names are created relative to the current user dir
2842 		File file = new File(fileName);
2843 		if (file.exists()) {
2844 			// if the file exists, we should try to use its canonical path
2845 			try {
2846 				result[count++] = file.getCanonicalPath().toCharArray();
2847 			} catch (IOException e) {
2848 				// if we got exception during canonicalization, fall back to the name that was specified
2849 				result[count++] = fileName.toCharArray();
2850 			}
2851 		} else {
2852 			// if the file does not exist, use the name that was specified
2853 			result[count++] = fileName.toCharArray();
2854 		}
2855 	}
2856 	return result;
2857 }
2858 
getAllEncodings(Set encodings)2859 private static String getAllEncodings(Set encodings) {
2860 	int size = encodings.size();
2861 	String[] allEncodings = new String[size];
2862 	encodings.toArray(allEncodings);
2863 	Arrays.sort(allEncodings);
2864 	StringBuffer buffer = new StringBuffer();
2865 	for (int i = 0; i < size; i++) {
2866 		if (i > 0) {
2867 			buffer.append(", "); //$NON-NLS-1$
2868 		}
2869 		buffer.append(allEncodings[i]);
2870 	}
2871 	return String.valueOf(buffer);
2872 }
2873 
initializeWarnings(String propertiesFile)2874 private void initializeWarnings(String propertiesFile) {
2875 	File file = new File(propertiesFile);
2876 	if (!file.exists()) {
2877 		throw new IllegalArgumentException(this.bind("configure.missingwarningspropertiesfile", propertiesFile)); //$NON-NLS-1$
2878 	}
2879 	BufferedInputStream stream = null;
2880 	Properties properties = null;
2881 	try {
2882 		stream = new BufferedInputStream(new FileInputStream(propertiesFile));
2883 		properties = new Properties();
2884 		properties.load(stream);
2885 	} catch(IOException e) {
2886 		e.printStackTrace();
2887 		throw new IllegalArgumentException(this.bind("configure.ioexceptionwarningspropertiesfile", propertiesFile)); //$NON-NLS-1$
2888 	} finally {
2889 		if (stream != null) {
2890 			try {
2891 				stream.close();
2892 			} catch(IOException e) {
2893 				// ignore
2894 			}
2895 		}
2896 	}
2897 	for (Iterator iterator = properties.entrySet().iterator(); iterator.hasNext(); ) {
2898 		Map.Entry entry = (Map.Entry) iterator.next();
2899 		final String key = (String) entry.getKey();
2900 		if (key.startsWith("org.eclipse.jdt.core.compiler.")) { //$NON-NLS-1$
2901 			this.options.put(key, entry.getValue());
2902 		}
2903 	}
2904 	// when using a properties file mimic relevant defaults from JavaCorePreferenceInitializer:
2905 	if (!properties.containsKey(CompilerOptions.OPTION_LocalVariableAttribute)) {
2906 		this.options.put(CompilerOptions.OPTION_LocalVariableAttribute, CompilerOptions.GENERATE);
2907 	}
2908 	if (!properties.containsKey(CompilerOptions.OPTION_PreserveUnusedLocal)) {
2909 		this.options.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.PRESERVE);
2910 	}
2911 	if (!properties.containsKey(CompilerOptions.OPTION_DocCommentSupport)) {
2912 		this.options.put(CompilerOptions.OPTION_DocCommentSupport, CompilerOptions.ENABLED);
2913 	}
2914 	if (!properties.containsKey(CompilerOptions.OPTION_ReportForbiddenReference)) {
2915 		this.options.put(CompilerOptions.OPTION_ReportForbiddenReference, CompilerOptions.ERROR);
2916 	}
2917 }
enableAll(int severity)2918 protected void enableAll(int severity) {
2919 	String newValue = null;
2920 	switch(severity) {
2921 		case ProblemSeverities.Error :
2922 			newValue = CompilerOptions.ERROR;
2923 			break;
2924 		case ProblemSeverities.Warning :
2925 			newValue = CompilerOptions.WARNING;
2926 			break;
2927 	}
2928 	Object[] entries = this.options.entrySet().toArray();
2929 	for (int i = 0, max = entries.length; i < max; i++) {
2930 		Map.Entry entry = (Map.Entry) entries[i];
2931 		if (!(entry.getKey() instanceof String))
2932 			continue;
2933 		if (!(entry.getValue() instanceof String))
2934 			continue;
2935 		if (((String) entry.getValue()).equals(CompilerOptions.IGNORE)) {
2936 			this.options.put(entry.getKey(), newValue);
2937 		}
2938 	}
2939 	this.options.put(CompilerOptions.OPTION_TaskTags, Util.EMPTY_STRING);
2940 }
disableAll(int severity)2941 protected void disableAll(int severity) {
2942 	String checkedValue = null;
2943 	switch(severity) {
2944 		case ProblemSeverities.Error :
2945 			checkedValue = CompilerOptions.ERROR;
2946 			break;
2947 		case ProblemSeverities.Warning :
2948 			checkedValue = CompilerOptions.WARNING;
2949 			break;
2950 	}
2951 	Object[] entries = this.options.entrySet().toArray();
2952 	for (int i = 0, max = entries.length; i < max; i++) {
2953 		Map.Entry entry = (Map.Entry) entries[i];
2954 		if (!(entry.getKey() instanceof String))
2955 			continue;
2956 		if (!(entry.getValue() instanceof String))
2957 			continue;
2958 		if (((String) entry.getValue()).equals(checkedValue)) {
2959 			this.options.put(entry.getKey(), CompilerOptions.IGNORE);
2960 		}
2961 	}
2962 }
extractDestinationPathFromSourceFile(CompilationResult result)2963 public String extractDestinationPathFromSourceFile(CompilationResult result) {
2964 	ICompilationUnit compilationUnit = result.compilationUnit;
2965 	if (compilationUnit != null) {
2966 		char[] fileName = compilationUnit.getFileName();
2967 		int lastIndex = CharOperation.lastIndexOf(java.io.File.separatorChar, fileName);
2968 		if (lastIndex != -1) {
2969 			final String outputPathName = new String(fileName, 0, lastIndex);
2970 			final File output = new File(outputPathName);
2971 			if (output.exists() && output.isDirectory()) {
2972 				return outputPathName;
2973 			}
2974 		}
2975 	}
2976 	return System.getProperty("user.dir"); //$NON-NLS-1$
2977 }
2978 /*
2979  * Answer the component to which will be handed back compilation results from the compiler
2980  */
getBatchRequestor()2981 public ICompilerRequestor getBatchRequestor() {
2982 	return new ICompilerRequestor() {
2983 		int lineDelta = 0;
2984 		public void acceptResult(CompilationResult compilationResult) {
2985 			if (compilationResult.lineSeparatorPositions != null) {
2986 				int unitLineCount = compilationResult.lineSeparatorPositions.length;
2987 				this.lineDelta += unitLineCount;
2988 				if (Main.this.showProgress && this.lineDelta > 2000) {
2989 					// in -log mode, dump a dot every 2000 lines compiled
2990 					Main.this.logger.logProgress();
2991 					this.lineDelta = 0;
2992 				}
2993 			}
2994 			Main.this.logger.startLoggingSource(compilationResult);
2995 			if (compilationResult.hasProblems() || compilationResult.hasTasks()) {
2996 				Main.this.logger.logProblems(compilationResult.getAllProblems(), compilationResult.compilationUnit.getContents(), Main.this);
2997 			}
2998 			outputClassFiles(compilationResult);
2999 			Main.this.logger.endLoggingSource();
3000 		}
3001 	};
3002 }
3003 /*
3004  *  Build the set of compilation source units
3005  */
getCompilationUnits()3006 public CompilationUnit[] getCompilationUnits() {
3007 	int fileCount = this.filenames.length;
3008 	CompilationUnit[] units = new CompilationUnit[fileCount];
3009 	HashtableOfObject knownFileNames = new HashtableOfObject(fileCount);
3010 
3011 	String defaultEncoding = (String) this.options.get(CompilerOptions.OPTION_Encoding);
3012 	if (Util.EMPTY_STRING.equals(defaultEncoding))
3013 		defaultEncoding = null;
3014 
3015 	for (int i = 0; i < fileCount; i++) {
3016 		char[] charName = this.filenames[i].toCharArray();
3017 		if (knownFileNames.get(charName) != null)
3018 			throw new IllegalArgumentException(this.bind("unit.more", this.filenames[i])); //$NON-NLS-1$
3019 		knownFileNames.put(charName, charName);
3020 		File file = new File(this.filenames[i]);
3021 		if (!file.exists())
3022 			throw new IllegalArgumentException(this.bind("unit.missing", this.filenames[i])); //$NON-NLS-1$
3023 		String encoding = this.encodings[i];
3024 		if (encoding == null)
3025 			encoding = defaultEncoding;
3026 		String fileName;
3027 		try {
3028 			fileName = file.getCanonicalPath();
3029 		} catch (IOException e) {
3030 			// if we got exception during canonicalization, fall back to the name that was specified
3031 			fileName = this.filenames[i];
3032 		}
3033 		units[i] = new CompilationUnit(null, fileName, encoding, this.destinationPaths[i],
3034 				shouldIgnoreOptionalProblems(this.ignoreOptionalProblemsFromFolders, fileName.toCharArray()));
3035 	}
3036 	return units;
3037 }
3038 
3039 /*
3040  *  Low-level API performing the actual compilation
3041  */
getHandlingPolicy()3042 public IErrorHandlingPolicy getHandlingPolicy() {
3043 
3044 	// passes the initial set of files to the batch oracle (to avoid finding more than once the same units when case insensitive match)
3045 	return new IErrorHandlingPolicy() {
3046 		public boolean proceedOnErrors() {
3047 			return Main.this.proceedOnError; // stop if there are some errors
3048 		}
3049 		public boolean stopOnFirstError() {
3050 			return false;
3051 		}
3052 		public boolean ignoreAllErrors() {
3053 			return false;
3054 		}
3055 	};
3056 }
3057 
3058 /*
3059  * External API
3060  */
3061 public File getJavaHome() {
3062 	if (!this.javaHomeChecked) {
3063 		this.javaHomeChecked = true;
3064 		this.javaHomeCache = Util.getJavaHome();
3065 	}
3066 	return this.javaHomeCache;
3067 }
3068 
3069 public FileSystem getLibraryAccess() {
3070 	return new FileSystem(this.checkedClasspaths, this.filenames);
3071 }
3072 
3073 /*
3074  *  Low-level API performing the actual compilation
3075  */
3076 public IProblemFactory getProblemFactory() {
3077 	return new DefaultProblemFactory(this.compilerLocale);
3078 }
3079 
3080 /*
3081  * External API
3082  */
3083 protected ArrayList handleBootclasspath(ArrayList bootclasspaths, String customEncoding) {
3084  	final int bootclasspathsSize;
3085 	if ((bootclasspaths != null)
3086 		&& ((bootclasspathsSize = bootclasspaths.size()) != 0))
3087 	{
3088 		String[] paths = new String[bootclasspathsSize];
3089 		bootclasspaths.toArray(paths);
3090 		bootclasspaths.clear();
3091 		for (int i = 0; i < bootclasspathsSize; i++) {
3092 			processPathEntries(DEFAULT_SIZE_CLASSPATH, bootclasspaths,
3093 				paths[i], customEncoding, false, true);
3094 		}
3095 	} else {
3096 		bootclasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
3097 		try {
3098 			Util.collectRunningVMBootclasspath(bootclasspaths);
3099 		} catch(IllegalStateException e) {
3100 			this.logger.logWrongJDK();
3101 			this.proceed = false;
3102 			return null;
3103 		}
3104 	}
3105 	return bootclasspaths;
3106 }
3107 
3108 /*
3109  * External API
3110  */
3111 protected ArrayList handleClasspath(ArrayList classpaths, String customEncoding) {
3112 	final int classpathsSize;
3113 	if ((classpaths != null)
3114 		&& ((classpathsSize = classpaths.size()) != 0))
3115 	{
3116 		String[] paths = new String[classpathsSize];
3117 		classpaths.toArray(paths);
3118 		classpaths.clear();
3119 		for (int i = 0; i < classpathsSize; i++) {
3120 			processPathEntries(DEFAULT_SIZE_CLASSPATH, classpaths, paths[i],
3121 					customEncoding, false, true);
3122 		}
3123 	} else {
3124 		// no user classpath specified.
3125 		classpaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
3126 		String classProp = System.getProperty("java.class.path"); //$NON-NLS-1$
3127 		if ((classProp == null) || (classProp.length() == 0)) {
3128 			addPendingErrors(this.bind("configure.noClasspath")); //$NON-NLS-1$
3129 			final Classpath classpath = FileSystem.getClasspath(System.getProperty("user.dir"), customEncoding, null);//$NON-NLS-1$
3130 			if (classpath != null) {
3131 				classpaths.add(classpath);
3132 			}
3133 		} else {
3134 			StringTokenizer tokenizer = new StringTokenizer(classProp, File.pathSeparator);
3135 			String token;
3136 			while (tokenizer.hasMoreTokens()) {
3137 				token = tokenizer.nextToken();
3138 				FileSystem.Classpath currentClasspath = FileSystem
3139 						.getClasspath(token, customEncoding, null);
3140 				if (currentClasspath != null) {
3141 					classpaths.add(currentClasspath);
3142 				} else if (token.length() != 0) {
3143 					addPendingErrors(this.bind("configure.incorrectClasspath", token));//$NON-NLS-1$
3144 				}
3145 			}
3146 		}
3147 	}
3148 	ArrayList result = new ArrayList();
3149 	HashMap knownNames = new HashMap();
3150 	FileSystem.ClasspathSectionProblemReporter problemReporter =
3151 		new FileSystem.ClasspathSectionProblemReporter() {
3152 			public void invalidClasspathSection(String jarFilePath) {
3153 				addPendingErrors(bind("configure.invalidClasspathSection", jarFilePath)); //$NON-NLS-1$
3154 			}
3155 			public void multipleClasspathSections(String jarFilePath) {
3156 				addPendingErrors(bind("configure.multipleClasspathSections", jarFilePath)); //$NON-NLS-1$
3157 			}
3158 		};
3159 	while (! classpaths.isEmpty()) {
3160 		Classpath current = (Classpath) classpaths.remove(0);
3161 		String currentPath = current.getPath();
3162 		if (knownNames.get(currentPath) == null) {
3163 			knownNames.put(currentPath, current);
3164 			result.add(current);
3165 			List linkedJars = current.fetchLinkedJars(problemReporter);
3166 			if (linkedJars != null) {
3167 				classpaths.addAll(0, linkedJars);
3168 			}
3169 		}
3170 	}
3171 	return result;
3172 }
3173 /*
3174  * External API
3175  */
3176 protected ArrayList handleEndorseddirs(ArrayList endorsedDirClasspaths) {
3177  	final File javaHome = getJavaHome();
3178 	/*
3179 	 * Feed endorsedDirClasspath according to:
3180 	 * - -endorseddirs first if present;
3181 	 * - else java.endorsed.dirs if defined;
3182 	 * - else default extensions directory for the platform. (/lib/endorsed)
3183 	 */
3184 	if (endorsedDirClasspaths == null) {
3185 		endorsedDirClasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
3186 		String endorsedDirsStr = System.getProperty("java.endorsed.dirs"); //$NON-NLS-1$
3187 		if (endorsedDirsStr == null) {
3188 			if (javaHome != null) {
3189 				endorsedDirClasspaths.add(javaHome.getAbsolutePath() + "/lib/endorsed"); //$NON-NLS-1$
3190 			}
3191 		} else {
3192 			StringTokenizer tokenizer = new StringTokenizer(endorsedDirsStr, File.pathSeparator);
3193 			while (tokenizer.hasMoreTokens()) {
3194 				endorsedDirClasspaths.add(tokenizer.nextToken());
3195 			}
3196 		}
3197 	}
3198 
3199 	/*
3200 	 * Feed extdirsClasspath with the entries found into the directories listed by
3201 	 * extdirsNames.
3202 	 */
3203 	if (endorsedDirClasspaths.size() != 0) {
3204 		File[] directoriesToCheck = new File[endorsedDirClasspaths.size()];
3205 		for (int i = 0; i < directoriesToCheck.length; i++)
3206 			directoriesToCheck[i] = new File((String) endorsedDirClasspaths.get(i));
3207 		endorsedDirClasspaths.clear();
3208 		File[][] endorsedDirsJars = getLibrariesFiles(directoriesToCheck);
3209 		if (endorsedDirsJars != null) {
3210 			for (int i = 0, max = endorsedDirsJars.length; i < max; i++) {
3211 				File[] current = endorsedDirsJars[i];
3212 				if (current != null) {
3213 					for (int j = 0, max2 = current.length; j < max2; j++) {
3214 						FileSystem.Classpath classpath =
3215 							FileSystem.getClasspath(
3216 									current[j].getAbsolutePath(),
3217 									null, null);
3218 						if (classpath != null) {
3219 							endorsedDirClasspaths.add(classpath);
3220 						}
3221 					}
3222 				} else if (directoriesToCheck[i].isFile()) {
3223 					addPendingErrors(
3224 						this.bind(
3225 							"configure.incorrectEndorsedDirsEntry", //$NON-NLS-1$
3226 							directoriesToCheck[i].getAbsolutePath()));
3227 				}
3228 			}
3229 		}
3230 	}
3231 	return endorsedDirClasspaths;
3232 }
3233 
3234 /*
3235  * External API
3236  * Handle extdirs processing
3237  */
3238 protected ArrayList handleExtdirs(ArrayList extdirsClasspaths) {
3239  	final File javaHome = getJavaHome();
3240 
3241 	/*
3242 	 * Feed extDirClasspath according to:
3243 	 * - -extdirs first if present;
3244 	 * - else java.ext.dirs if defined;
3245 	 * - else default extensions directory for the platform.
3246 	 */
3247 	if (extdirsClasspaths == null) {
3248 		extdirsClasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
3249 		String extdirsStr = System.getProperty("java.ext.dirs"); //$NON-NLS-1$
3250 		if (extdirsStr == null) {
3251 			extdirsClasspaths.add(javaHome.getAbsolutePath() + "/lib/ext"); //$NON-NLS-1$
3252 		} else {
3253 			StringTokenizer tokenizer = new StringTokenizer(extdirsStr, File.pathSeparator);
3254 			while (tokenizer.hasMoreTokens())
3255 				extdirsClasspaths.add(tokenizer.nextToken());
3256 		}
3257 	}
3258 
3259 	/*
3260 	 * Feed extdirsClasspath with the entries found into the directories listed by
3261 	 * extdirsNames.
3262 	 */
3263 	if (extdirsClasspaths.size() != 0) {
3264 		File[] directoriesToCheck = new File[extdirsClasspaths.size()];
3265 		for (int i = 0; i < directoriesToCheck.length; i++)
3266 			directoriesToCheck[i] = new File((String) extdirsClasspaths.get(i));
3267 		extdirsClasspaths.clear();
3268 		File[][] extdirsJars = getLibrariesFiles(directoriesToCheck);
3269 		if (extdirsJars != null) {
3270 			for (int i = 0, max = extdirsJars.length; i < max; i++) {
3271 				File[] current = extdirsJars[i];
3272 				if (current != null) {
3273 					for (int j = 0, max2 = current.length; j < max2; j++) {
3274 						FileSystem.Classpath classpath =
3275 							FileSystem.getClasspath(
3276 									current[j].getAbsolutePath(),
3277 									null, null);
3278 						if (classpath != null) {
3279 							extdirsClasspaths.add(classpath);
3280 						}
3281 					}
3282 				} else if (directoriesToCheck[i].isFile()) {
3283 					addPendingErrors(this.bind(
3284 							"configure.incorrectExtDirsEntry", //$NON-NLS-1$
3285 							directoriesToCheck[i].getAbsolutePath()));
3286 				}
3287 			}
3288 		}
3289 	}
3290 
3291 	return extdirsClasspaths;
3292 }
3293 
3294 /*
3295  * External API
3296  * Handle a single warning token.
3297 */
3298 protected void handleWarningToken(String token, boolean isEnabling) {
3299 	handleErrorOrWarningToken(token, isEnabling, ProblemSeverities.Warning);
3300 }
3301 protected void handleErrorToken(String token, boolean isEnabling) {
3302 	handleErrorOrWarningToken(token, isEnabling, ProblemSeverities.Error);
3303 }
3304 private void setSeverity(String compilerOptions, int severity, boolean isEnabling) {
3305 	if (isEnabling) {
3306 		switch(severity) {
3307 			case ProblemSeverities.Error :
3308 				this.options.put(compilerOptions, CompilerOptions.ERROR);
3309 				break;
3310 			case ProblemSeverities.Warning :
3311 				this.options.put(compilerOptions, CompilerOptions.WARNING);
3312 				break;
3313 			default:
3314 				this.options.put(compilerOptions, CompilerOptions.IGNORE);
3315 		}
3316 	} else {
3317 		switch(severity) {
3318 			case ProblemSeverities.Error :
3319 				String currentValue = (String) this.options.get(compilerOptions);
3320 				if (CompilerOptions.ERROR.equals(currentValue)) {
3321 					this.options.put(compilerOptions, CompilerOptions.IGNORE);
3322 				}
3323 				break;
3324 			case ProblemSeverities.Warning :
3325 				currentValue = (String) this.options.get(compilerOptions);
3326 				if (CompilerOptions.WARNING.equals(currentValue)) {
3327 					this.options.put(compilerOptions, CompilerOptions.IGNORE);
3328 				}
3329 				break;
3330 			default:
3331 				this.options.put(compilerOptions, CompilerOptions.IGNORE);
3332 		}
3333 	}
3334 }
3335 private void handleErrorOrWarningToken(String token, boolean isEnabling, int severity) {
3336 	if (token.length() == 0) return;
3337 	switch(token.charAt(0)) {
3338 		case 'a' :
3339 			if (token.equals("allDeprecation")) { //$NON-NLS-1$
3340 				setSeverity(CompilerOptions.OPTION_ReportDeprecation, severity, isEnabling);
3341 				this.options.put(
3342 					CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode,
3343 					isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3344 				this.options.put(
3345 					CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod,
3346 					isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3347 				return;
3348 			} else if (token.equals("allJavadoc")) { //$NON-NLS-1$
3349 				this.warnAllJavadocOn = this.warnJavadocOn = isEnabling;
3350 				setSeverity(CompilerOptions.OPTION_ReportInvalidJavadoc, severity, isEnabling);
3351 				setSeverity(CompilerOptions.OPTION_ReportMissingJavadocTags, severity, isEnabling);
3352 				setSeverity(CompilerOptions.OPTION_ReportMissingJavadocComments, severity, isEnabling);
3353 				return;
3354 			} else if (token.equals("assertIdentifier")) { //$NON-NLS-1$
3355 				setSeverity(CompilerOptions.OPTION_ReportAssertIdentifier, severity, isEnabling);
3356 				return;
3357 			} else if (token.equals("allDeadCode")) { //$NON-NLS-1$
3358 				setSeverity(CompilerOptions.OPTION_ReportDeadCode, severity, isEnabling);
3359 				this.options.put(
3360 					CompilerOptions.OPTION_ReportDeadCodeInTrivialIfStatement,
3361 					isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3362 				return;
3363 			} else if (token.equals("allOver-ann")) { //$NON-NLS-1$
3364 				setSeverity(CompilerOptions.OPTION_ReportMissingOverrideAnnotation, severity, isEnabling);
3365 				this.options.put(
3366 					CompilerOptions.OPTION_ReportMissingOverrideAnnotationForInterfaceMethodImplementation,
3367 					isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3368 				return;
3369 			} else if (token.equals("all-static-method")) { //$NON-NLS-1$
3370 				setSeverity(CompilerOptions.OPTION_ReportMethodCanBeStatic, severity, isEnabling);
3371 				setSeverity(CompilerOptions.OPTION_ReportMethodCanBePotentiallyStatic, severity, isEnabling);
3372 				return;
3373 			} else if (token.equals("all")) { //$NON-NLS-1$
3374 				if (isEnabling) {
3375 					enableAll(severity);
3376 				} else {
3377 					disableAll(severity);
3378 				}
3379 				return;
3380 			}
3381 			break;
3382 		case 'b' :
3383 			if (token.equals("boxing")) { //$NON-NLS-1$
3384 				setSeverity(CompilerOptions.OPTION_ReportAutoboxing, severity, isEnabling);
3385 				return;
3386 			}
3387 			break;
3388 		case 'c' :
3389 			if (token.equals("constructorName")) { //$NON-NLS-1$
3390 				setSeverity(CompilerOptions.OPTION_ReportMethodWithConstructorName, severity, isEnabling);
3391 				return;
3392 			} else if (token.equals("conditionAssign")) { //$NON-NLS-1$
3393 				setSeverity(CompilerOptions.OPTION_ReportPossibleAccidentalBooleanAssignment, severity, isEnabling);
3394 				return;
3395 			} else if (token.equals("compareIdentical")) { //$NON-NLS-1$
3396 				setSeverity(CompilerOptions.OPTION_ReportComparingIdentical, severity, isEnabling);
3397 				return;
3398 			} else if (token.equals("charConcat") /*|| token.equals("noImplicitStringConversion")/*backward compatible*/) {//$NON-NLS-1$
3399 				setSeverity(CompilerOptions.OPTION_ReportNoImplicitStringConversion, severity, isEnabling);
3400 				return;
3401 			}
3402 			break;
3403 		case 'd' :
3404 			if (token.equals("deprecation")) { //$NON-NLS-1$
3405 				setSeverity(CompilerOptions.OPTION_ReportDeprecation, severity, isEnabling);
3406 				this.options.put(
3407 					CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode,
3408 					CompilerOptions.DISABLED);
3409 				this.options.put(
3410 					CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod,
3411 					CompilerOptions.DISABLED);
3412 				return;
3413 			} else if (token.equals("dep-ann")) { //$NON-NLS-1$
3414 				setSeverity(CompilerOptions.OPTION_ReportMissingDeprecatedAnnotation, severity, isEnabling);
3415 				return;
3416 			} else if (token.equals("discouraged")) { //$NON-NLS-1$
3417 				setSeverity(CompilerOptions.OPTION_ReportDiscouragedReference, severity, isEnabling);
3418 				return;
3419 			} else if (token.equals("deadCode")) { //$NON-NLS-1$
3420 				setSeverity(CompilerOptions.OPTION_ReportDeadCode, severity, isEnabling);
3421 				this.options.put(
3422 					CompilerOptions.OPTION_ReportDeadCodeInTrivialIfStatement,
3423 					CompilerOptions.DISABLED);
3424 				return;
3425 			}
3426 			break;
3427 		case 'e' :
3428 			if (token.equals("enumSwitch")) { //$NON-NLS-1$
3429 				setSeverity(CompilerOptions.OPTION_ReportIncompleteEnumSwitch, severity, isEnabling);
3430 				return;
3431 			} else if (token.equals("enumSwitchPedantic")) { //$NON-NLS-1$
3432 				if (isEnabling) {
3433 					switch (severity) {
3434 						case ProblemSeverities.Error:
3435 							setSeverity(CompilerOptions.OPTION_ReportIncompleteEnumSwitch, severity, isEnabling);
3436 							break;
3437 						case ProblemSeverities.Warning:
3438 							if (CompilerOptions.IGNORE.equals(this.options.get(CompilerOptions.OPTION_ReportIncompleteEnumSwitch))) {
3439 								setSeverity(CompilerOptions.OPTION_ReportIncompleteEnumSwitch, severity, isEnabling);
3440 							}
3441 							break;
3442 						default: // no severity update
3443 					}
3444 				}
3445 				this.options.put(CompilerOptions.OPTION_ReportMissingEnumCaseDespiteDefault,
3446 								 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3447 				return;
3448 			} else if (token.equals("emptyBlock")) {//$NON-NLS-1$
3449 				setSeverity(CompilerOptions.OPTION_ReportUndocumentedEmptyBlock, severity, isEnabling);
3450 				return;
3451 			} else if (token.equals("enumIdentifier")) { //$NON-NLS-1$
3452 				setSeverity(CompilerOptions.OPTION_ReportEnumIdentifier, severity, isEnabling);
3453 				return;
3454 			}
3455 			break;
3456 		case 'f' :
3457 			if (token.equals("fieldHiding")) { //$NON-NLS-1$
3458 				setSeverity(CompilerOptions.OPTION_ReportFieldHiding, severity, isEnabling);
3459 				return;
3460 			} else if (token.equals("finalBound")) {//$NON-NLS-1$
3461 				setSeverity(CompilerOptions.OPTION_ReportFinalParameterBound, severity, isEnabling);
3462 				return;
3463 			} else if (token.equals("finally")) { //$NON-NLS-1$
3464 				setSeverity(CompilerOptions.OPTION_ReportFinallyBlockNotCompletingNormally, severity, isEnabling);
3465 				return;
3466 			} else if (token.equals("forbidden")) { //$NON-NLS-1$
3467 				setSeverity(CompilerOptions.OPTION_ReportForbiddenReference, severity, isEnabling);
3468 				return;
3469 			} else if (token.equals("fallthrough")) { //$NON-NLS-1$
3470 				setSeverity(CompilerOptions.OPTION_ReportFallthroughCase, severity, isEnabling);
3471 				return;
3472 			}
3473 			break;
3474 		case 'h' :
3475 			if (token.equals("hiding")) { //$NON-NLS-1$
3476 				setSeverity(CompilerOptions.OPTION_ReportHiddenCatchBlock, severity, isEnabling);
3477 				setSeverity(CompilerOptions.OPTION_ReportLocalVariableHiding, severity, isEnabling);
3478 				setSeverity(CompilerOptions.OPTION_ReportFieldHiding, severity, isEnabling);
3479 				setSeverity(CompilerOptions.OPTION_ReportTypeParameterHiding, severity, isEnabling);
3480 				return;
3481 			} else if (token.equals("hashCode")) { //$NON-NLS-1$
3482 				setSeverity(CompilerOptions.OPTION_ReportMissingHashCodeMethod, severity, isEnabling);
3483 				return;
3484 			}
3485 			break;
3486 		case 'i' :
3487 			if (token.equals("indirectStatic")) { //$NON-NLS-1$
3488 				setSeverity(CompilerOptions.OPTION_ReportIndirectStaticAccess, severity, isEnabling);
3489 				return;
3490 			} else if (token.equals("inheritNullAnnot")) { //$NON-NLS-1$
3491 				this.options.put(
3492 						CompilerOptions.OPTION_InheritNullAnnotations,
3493 						isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3494 				return;
3495 			} else if (token.equals("intfNonInherited") || token.equals("interfaceNonInherited")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
3496 				setSeverity(CompilerOptions.OPTION_ReportIncompatibleNonInheritedInterfaceMethod, severity, isEnabling);
3497 				return;
3498 			} else if (token.equals("intfAnnotation")) { //$NON-NLS-1$
3499 				setSeverity(CompilerOptions.OPTION_ReportAnnotationSuperInterface, severity, isEnabling);
3500 				return;
3501 			} else if (token.equals("intfRedundant") /*|| token.equals("redundantSuperinterface")*/) { //$NON-NLS-1$
3502 				setSeverity(CompilerOptions.OPTION_ReportRedundantSuperinterface, severity, isEnabling);
3503 				return;
3504 			} else if (token.equals("includeAssertNull")) { //$NON-NLS-1$
3505 				this.options.put(
3506 						CompilerOptions.OPTION_IncludeNullInfoFromAsserts,
3507 						isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3508 				return;
3509 			} else if (token.equals("invalidJavadoc")) { //$NON-NLS-1$
3510 				setSeverity(CompilerOptions.OPTION_ReportInvalidJavadoc, severity, isEnabling);
3511 				this.options.put(
3512 					CompilerOptions.OPTION_ReportInvalidJavadocTags,
3513 					isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3514 				this.options.put(
3515 					CompilerOptions.OPTION_ReportInvalidJavadocTagsDeprecatedRef,
3516 					isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3517 				this.options.put(
3518 					CompilerOptions.OPTION_ReportInvalidJavadocTagsNotVisibleRef,
3519 					isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3520 				if (isEnabling) {
3521 					this.options.put(
3522 							CompilerOptions.OPTION_DocCommentSupport,
3523 							CompilerOptions.ENABLED);
3524 					this.options.put(
3525 						CompilerOptions.OPTION_ReportInvalidJavadocTagsVisibility,
3526 						CompilerOptions.PRIVATE);
3527 				}
3528 				return;
3529 			} else if (token.equals("invalidJavadocTag")) { //$NON-NLS-1$
3530 				this.options.put(
3531 					CompilerOptions.OPTION_ReportInvalidJavadocTags,
3532 					isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3533 				return;
3534 			} else if (token.equals("invalidJavadocTagDep")) { //$NON-NLS-1$
3535 				this.options.put(
3536 						CompilerOptions.OPTION_ReportInvalidJavadocTagsDeprecatedRef,
3537 						isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3538 				return;
3539 			} else if (token.equals("invalidJavadocTagNotVisible")) { //$NON-NLS-1$
3540 				this.options.put(
3541 						CompilerOptions.OPTION_ReportInvalidJavadocTagsNotVisibleRef,
3542 						isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3543 				return;
3544 			} else if (token.startsWith("invalidJavadocTagVisibility")) { //$NON-NLS-1$
3545 				int start = token.indexOf('(');
3546 				int end = token.indexOf(')');
3547 				String visibility = null;
3548 				if (isEnabling && start >= 0 && end >= 0 && start < end){
3549 					visibility = token.substring(start+1, end).trim();
3550 				}
3551 				if (visibility != null && visibility.equals(CompilerOptions.PUBLIC)
3552 						|| visibility.equals(CompilerOptions.PRIVATE)
3553 						|| visibility.equals(CompilerOptions.PROTECTED)
3554 						|| visibility.equals(CompilerOptions.DEFAULT)) {
3555 					this.options.put(
3556 							CompilerOptions.OPTION_ReportInvalidJavadocTagsVisibility,
3557 							visibility);
3558 					return;
3559 				} else {
3560 					throw new IllegalArgumentException(this.bind("configure.invalidJavadocTagVisibility", token)); //$NON-NLS-1$
3561 				}
3562 			}
3563 			break;
3564 		case 'j' :
3565 			if (token.equals("javadoc")) {//$NON-NLS-1$
3566 				this.warnJavadocOn = isEnabling;
3567 				setSeverity(CompilerOptions.OPTION_ReportInvalidJavadoc, severity, isEnabling);
3568 				setSeverity(CompilerOptions.OPTION_ReportMissingJavadocTags, severity, isEnabling);
3569 				return;
3570 			}
3571 			break;
3572 		case 'l' :
3573 			if (token.equals("localHiding")) { //$NON-NLS-1$
3574 				setSeverity(CompilerOptions.OPTION_ReportLocalVariableHiding, severity, isEnabling);
3575 				return;
3576 			}
3577 			break;
3578 		case 'm' :
3579 			if (token.equals("maskedCatchBlock") || token.equals("maskedCatchBlocks")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
3580 				setSeverity(CompilerOptions.OPTION_ReportHiddenCatchBlock, severity, isEnabling);
3581 				return;
3582 			} else if (token.equals("missingJavadocTags")) { //$NON-NLS-1$
3583 				setSeverity(CompilerOptions.OPTION_ReportMissingJavadocTags, severity, isEnabling);
3584 				this.options.put(
3585 					CompilerOptions.OPTION_ReportMissingJavadocTagsOverriding,
3586 					isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3587 				this.options.put(
3588 					CompilerOptions.OPTION_ReportMissingJavadocTagsMethodTypeParameters,
3589 					isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3590 				if (isEnabling) {
3591 					this.options.put(
3592 							CompilerOptions.OPTION_DocCommentSupport,
3593 							CompilerOptions.ENABLED);
3594 					this.options.put(
3595 						CompilerOptions.OPTION_ReportMissingJavadocTagsVisibility,
3596 						CompilerOptions.PRIVATE);
3597 				}
3598 				return;
3599 			} else if (token.equals("missingJavadocTagsOverriding")) { //$NON-NLS-1$
3600 				this.options.put(
3601 					CompilerOptions.OPTION_ReportMissingJavadocTagsOverriding,
3602 					isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3603 				return;
3604 			} else if (token.equals("missingJavadocTagsMethod")) { //$NON-NLS-1$
3605 				this.options.put(
3606 					CompilerOptions.OPTION_ReportMissingJavadocTagsMethodTypeParameters,
3607 					isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3608 				return;
3609 			} else if (token.startsWith("missingJavadocTagsVisibility")) { //$NON-NLS-1$
3610 				int start = token.indexOf('(');
3611 				int end = token.indexOf(')');
3612 				String visibility = null;
3613 				if (isEnabling && start >= 0 && end >= 0 && start < end){
3614 					visibility = token.substring(start+1, end).trim();
3615 				}
3616 				if (visibility != null && visibility.equals(CompilerOptions.PUBLIC)
3617 						|| visibility.equals(CompilerOptions.PRIVATE)
3618 						|| visibility.equals(CompilerOptions.PROTECTED)
3619 						|| visibility.equals(CompilerOptions.DEFAULT)) {
3620 					this.options.put(
3621 							CompilerOptions.OPTION_ReportMissingJavadocTagsVisibility,
3622 							visibility);
3623 					return;
3624 				} else {
3625 					throw new IllegalArgumentException(this.bind("configure.missingJavadocTagsVisibility", token)); //$NON-NLS-1$
3626 				}
3627 			} else if (token.equals("missingJavadocComments")) { //$NON-NLS-1$
3628 				setSeverity(CompilerOptions.OPTION_ReportMissingJavadocComments, severity, isEnabling);
3629 				this.options.put(
3630 					CompilerOptions.OPTION_ReportMissingJavadocCommentsOverriding,
3631 					isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3632 				if (isEnabling) {
3633 					this.options.put(
3634 							CompilerOptions.OPTION_DocCommentSupport,
3635 							CompilerOptions.ENABLED);
3636 					this.options.put(
3637 						CompilerOptions.OPTION_ReportMissingJavadocCommentsVisibility,
3638 						CompilerOptions.PRIVATE);
3639 				}
3640 				return;
3641 			} else if (token.equals("missingJavadocCommentsOverriding")) { //$NON-NLS-1$
3642 				setSeverity(CompilerOptions.OPTION_ReportMissingJavadocComments, severity, isEnabling);
3643 				this.options.put(
3644 					CompilerOptions.OPTION_ReportMissingJavadocCommentsOverriding,
3645 					isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3646 				return;
3647 			} else if (token.startsWith("missingJavadocCommentsVisibility")) { //$NON-NLS-1$
3648 				int start = token.indexOf('(');
3649 				int end = token.indexOf(')');
3650 				String visibility = null;
3651 				if (isEnabling && start >= 0 && end >= 0 && start < end){
3652 					visibility = token.substring(start+1, end).trim();
3653 				}
3654 				if (visibility != null && visibility.equals(CompilerOptions.PUBLIC)
3655 						|| visibility.equals(CompilerOptions.PRIVATE)
3656 						|| visibility.equals(CompilerOptions.PROTECTED)
3657 						|| visibility.equals(CompilerOptions.DEFAULT)) {
3658 					this.options.put(
3659 							CompilerOptions.OPTION_ReportMissingJavadocCommentsVisibility,
3660 							visibility);
3661 					return;
3662 				} else {
3663 					throw new IllegalArgumentException(this.bind("configure.missingJavadocCommentsVisibility", token)); //$NON-NLS-1$
3664 				}
3665 			}
3666 			break;
3667 		case 'n' :
3668 			if (token.equals("nls")) { //$NON-NLS-1$
3669 				setSeverity(CompilerOptions.OPTION_ReportNonExternalizedStringLiteral, severity, isEnabling);
3670 				return;
3671 			} else if (token.equals("noEffectAssign")) { //$NON-NLS-1$
3672 				setSeverity(CompilerOptions.OPTION_ReportNoEffectAssignment, severity, isEnabling);
3673 				return;
3674 			} else if (/*token.equals("charConcat") ||*/ token.equals("noImplicitStringConversion")/*backward compatible*/) {//$NON-NLS-1$
3675 				setSeverity(CompilerOptions.OPTION_ReportNoImplicitStringConversion, severity, isEnabling);
3676 				return;
3677 			} else if (token.equals("null")) { //$NON-NLS-1$
3678 				setSeverity(CompilerOptions.OPTION_ReportNullReference, severity, isEnabling);
3679 				setSeverity(CompilerOptions.OPTION_ReportPotentialNullReference, severity, isEnabling);
3680 				setSeverity(CompilerOptions.OPTION_ReportRedundantNullCheck, severity, isEnabling);
3681 				return;
3682 			} else if (token.equals("nullDereference")) { //$NON-NLS-1$
3683 				setSeverity(CompilerOptions.OPTION_ReportNullReference, severity, isEnabling);
3684 				if (!isEnabling) {
3685 					setSeverity(CompilerOptions.OPTION_ReportPotentialNullReference, ProblemSeverities.Ignore, isEnabling);
3686 					setSeverity(CompilerOptions.OPTION_ReportRedundantNullCheck, ProblemSeverities.Ignore, isEnabling);
3687 				}
3688 				return;
3689 			}else if (token.equals("nullAnnotConflict")) { //$NON-NLS-1$
3690 				setSeverity(CompilerOptions.OPTION_ReportNullAnnotationInferenceConflict, severity, isEnabling);
3691 				return;
3692 			} else if (token.equals("nullAnnotRedundant")) { //$NON-NLS-1$
3693 				setSeverity(CompilerOptions.OPTION_ReportRedundantNullAnnotation, severity, isEnabling);
3694 				return;
3695 			} else if (token.startsWith("nullAnnot")) { //$NON-NLS-1$
3696 				String annotationNames = Util.EMPTY_STRING;
3697 				int start = token.indexOf('(');
3698 				int end = token.indexOf(')');
3699 				String nonNullAnnotName = null, nullableAnnotName = null, nonNullByDefaultAnnotName = null;
3700 				if (isEnabling && start >= 0 && end >= 0 && start < end){
3701 					annotationNames = token.substring(start+1, end).trim();
3702 					int separator1 = annotationNames.indexOf('|');
3703 					if (separator1 == -1) throw new IllegalArgumentException(this.bind("configure.invalidNullAnnot", token)); //$NON-NLS-1$
3704 					nullableAnnotName = annotationNames.substring(0, separator1).trim();
3705 					if (nullableAnnotName.length() == 0) throw new IllegalArgumentException(this.bind("configure.invalidNullAnnot", token)); //$NON-NLS-1$
3706 					int separator2 = annotationNames.indexOf('|', separator1 + 1);
3707 					if (separator2 == -1) throw new IllegalArgumentException(this.bind("configure.invalidNullAnnot", token)); //$NON-NLS-1$
3708 					nonNullAnnotName = annotationNames.substring(separator1 + 1, separator2).trim();
3709 					if (nonNullAnnotName.length() == 0) throw new IllegalArgumentException(this.bind("configure.invalidNullAnnot", token)); //$NON-NLS-1$
3710 					nonNullByDefaultAnnotName = annotationNames.substring(separator2 + 1).trim();
3711 					if (nonNullByDefaultAnnotName.length() == 0) throw new IllegalArgumentException(this.bind("configure.invalidNullAnnot", token)); //$NON-NLS-1$
3712 					this.options.put(CompilerOptions.OPTION_NullableAnnotationName, nullableAnnotName);
3713 					this.options.put(CompilerOptions.OPTION_NonNullAnnotationName, nonNullAnnotName);
3714 					this.options.put(CompilerOptions.OPTION_NonNullByDefaultAnnotationName, nonNullByDefaultAnnotName);
3715 				}
3716 				this.options.put(
3717 						CompilerOptions.OPTION_AnnotationBasedNullAnalysis,
3718 						isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3719 				setSeverity(CompilerOptions.OPTION_ReportNullSpecViolation, severity, isEnabling);
3720 				setSeverity(CompilerOptions.OPTION_ReportNullAnnotationInferenceConflict, severity, isEnabling);
3721 				setSeverity(CompilerOptions.OPTION_ReportNullUncheckedConversion, severity, isEnabling);
3722 				setSeverity(CompilerOptions.OPTION_ReportRedundantNullAnnotation, severity, isEnabling);
3723 				return;
3724 			} else if (token.equals("nullUncheckedConversion")) { //$NON-NLS-1$
3725 				setSeverity(CompilerOptions.OPTION_ReportNullUncheckedConversion, severity, isEnabling);
3726 				return;
3727 			} else if (token.equals("nonnullNotRepeated")) { //$NON-NLS-1$
3728 				setSeverity(CompilerOptions.OPTION_ReportNonnullParameterAnnotationDropped, severity, isEnabling);
3729 				return;
3730 			}
3731 
3732 			break;
3733 		case 'o' :
3734 			if (token.equals("over-sync") /*|| token.equals("syncOverride")*/) { //$NON-NLS-1$
3735 				setSeverity(CompilerOptions.OPTION_ReportMissingSynchronizedOnInheritedMethod, severity, isEnabling);
3736 				return;
3737 			} else if (token.equals("over-ann")) { //$NON-NLS-1$
3738 				setSeverity(CompilerOptions.OPTION_ReportMissingOverrideAnnotation, severity, isEnabling);
3739 				this.options.put(
3740 					CompilerOptions.OPTION_ReportMissingOverrideAnnotationForInterfaceMethodImplementation,
3741 					CompilerOptions.DISABLED);
3742 				return;
3743 			}
3744 			break;
3745 		case 'p' :
3746 			if (token.equals("pkgDefaultMethod") || token.equals("packageDefaultMethod")/*backward compatible*/ ) { //$NON-NLS-1$ //$NON-NLS-2$
3747 				setSeverity(CompilerOptions.OPTION_ReportOverridingPackageDefaultMethod, severity, isEnabling);
3748 				return;
3749 			} else if (token.equals("paramAssign")) { //$NON-NLS-1$
3750 				setSeverity(CompilerOptions.OPTION_ReportParameterAssignment, severity, isEnabling);
3751 				return;
3752 			}
3753 			break;
3754 		case 'r' :
3755 			if (token.equals("raw")) {//$NON-NLS-1$
3756 				setSeverity(CompilerOptions.OPTION_ReportRawTypeReference, severity, isEnabling);
3757 				return;
3758 			} else if (/*token.equals("intfRedundant") ||*/ token.equals("redundantSuperinterface")) { //$NON-NLS-1$
3759 				setSeverity(CompilerOptions.OPTION_ReportRedundantSuperinterface, severity, isEnabling);
3760 				return;
3761 			} else if (token.equals("resource")) { //$NON-NLS-1$
3762 				setSeverity(CompilerOptions.OPTION_ReportUnclosedCloseable, severity, isEnabling);
3763 				setSeverity(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, severity, isEnabling);
3764 				setSeverity(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, severity, isEnabling);
3765 				return;
3766 			}
3767 			break;
3768 		case 's' :
3769 			if (token.equals("specialParamHiding")) { //$NON-NLS-1$
3770 				this.options.put(
3771 					CompilerOptions.OPTION_ReportSpecialParameterHidingField,
3772 					isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3773 				return;
3774 			} else if (token.equals("syntheticAccess") || token.equals("synthetic-access")) { //$NON-NLS-1$ //$NON-NLS-2$
3775 				setSeverity(CompilerOptions.OPTION_ReportSyntheticAccessEmulation, severity, isEnabling);
3776 				return;
3777 			} else if (token.equals("staticReceiver")) { //$NON-NLS-1$
3778 				setSeverity(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, severity, isEnabling);
3779 				return;
3780 			} else 	if (/*token.equals("over-sync") ||*/ token.equals("syncOverride")) { //$NON-NLS-1$
3781 				setSeverity(CompilerOptions.OPTION_ReportMissingSynchronizedOnInheritedMethod, severity, isEnabling);
3782 				return;
3783 			} else if (token.equals("semicolon")) {//$NON-NLS-1$
3784 				setSeverity(CompilerOptions.OPTION_ReportEmptyStatement, severity, isEnabling);
3785 				return;
3786 			} else if (token.equals("serial")) {//$NON-NLS-1$
3787 				setSeverity(CompilerOptions.OPTION_ReportMissingSerialVersion, severity, isEnabling);
3788 				return;
3789 			} else if (token.equals("suppress")) {//$NON-NLS-1$
3790 				switch(severity) {
3791 					case ProblemSeverities.Warning :
3792 						this.options.put(
3793 								CompilerOptions.OPTION_SuppressWarnings,
3794 								isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3795 						this.options.put(
3796 								CompilerOptions.OPTION_SuppressOptionalErrors,
3797 								CompilerOptions.DISABLED);
3798 						break;
3799 					case ProblemSeverities.Error :
3800 						this.options.put(
3801 								CompilerOptions.OPTION_SuppressWarnings,
3802 								isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3803 						this.options.put(
3804 							CompilerOptions.OPTION_SuppressOptionalErrors,
3805 							isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3806 				}
3807 				return;
3808 			} else if (token.equals("static-access")) { //$NON-NLS-1$
3809 				setSeverity(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, severity, isEnabling);
3810 				setSeverity(CompilerOptions.OPTION_ReportIndirectStaticAccess, severity, isEnabling);
3811 				return;
3812 			} else if (token.equals("super")) { //$NON-NLS-1$
3813 				setSeverity(CompilerOptions.OPTION_ReportOverridingMethodWithoutSuperInvocation, severity, isEnabling);
3814 				return;
3815 			} else if (token.equals("static-method")) { //$NON-NLS-1$
3816 				setSeverity(CompilerOptions.OPTION_ReportMethodCanBeStatic, severity, isEnabling);
3817 				return;
3818 			} else if (token.equals("switchDefault")) { //$NON-NLS-1$
3819 				setSeverity(CompilerOptions.OPTION_ReportMissingDefaultCase, severity, isEnabling);
3820 				return;
3821 			}
3822 			break;
3823 		case 't' :
3824 			if (token.startsWith("tasks")) { //$NON-NLS-1$
3825 				String taskTags = Util.EMPTY_STRING;
3826 				int start = token.indexOf('(');
3827 				int end = token.indexOf(')');
3828 				if (start >= 0 && end >= 0 && start < end){
3829 					taskTags = token.substring(start+1, end).trim();
3830 					taskTags = taskTags.replace('|',',');
3831 				}
3832 				if (taskTags.length() == 0){
3833 					throw new IllegalArgumentException(this.bind("configure.invalidTaskTag", token)); //$NON-NLS-1$
3834 				}
3835 				this.options.put(
3836 					CompilerOptions.OPTION_TaskTags,
3837 					isEnabling ? taskTags : Util.EMPTY_STRING);
3838 
3839 				setSeverity(CompilerOptions.OPTION_ReportTasks, severity, isEnabling);
3840 				return;
3841 			} else if (token.equals("typeHiding")) { //$NON-NLS-1$
3842 				setSeverity(CompilerOptions.OPTION_ReportTypeParameterHiding, severity, isEnabling);
3843 				return;
3844 			}
3845 			break;
3846 		case 'u' :
3847 			if (token.equals("unusedLocal") || token.equals("unusedLocals")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
3848 				setSeverity(CompilerOptions.OPTION_ReportUnusedLocal, severity, isEnabling);
3849 				return;
3850 			} else if (token.equals("unusedArgument") || token.equals("unusedArguments")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
3851 				setSeverity(CompilerOptions.OPTION_ReportUnusedParameter, severity, isEnabling);
3852 				return;
3853 			} else if (token.equals("unusedImport") || token.equals("unusedImports")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
3854 				setSeverity(CompilerOptions.OPTION_ReportUnusedImport, severity, isEnabling);
3855 				return;
3856 			} else if (token.equals("unusedAllocation")) { //$NON-NLS-1$
3857 				setSeverity(CompilerOptions.OPTION_ReportUnusedObjectAllocation, severity, isEnabling);
3858 				return;
3859 			} else if (token.equals("unusedPrivate")) { //$NON-NLS-1$
3860 				setSeverity(CompilerOptions.OPTION_ReportUnusedPrivateMember, severity, isEnabling);
3861 				return;
3862 			} else if (token.equals("unusedLabel")) { //$NON-NLS-1$
3863 				setSeverity(CompilerOptions.OPTION_ReportUnusedLabel, severity, isEnabling);
3864 				return;
3865 			} else if (token.equals("uselessTypeCheck")) {//$NON-NLS-1$
3866 				setSeverity(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, severity, isEnabling);
3867 				return;
3868 			} else if (token.equals("unchecked") || token.equals("unsafe")) {//$NON-NLS-1$ //$NON-NLS-2$
3869 				setSeverity(CompilerOptions.OPTION_ReportUncheckedTypeOperation, severity, isEnabling);
3870 				return;
3871 			} else if (token.equals("unnecessaryElse")) {//$NON-NLS-1$
3872 				setSeverity(CompilerOptions.OPTION_ReportUnnecessaryElse, severity, isEnabling);
3873 				return;
3874 			} else if (token.equals("unusedThrown")) { //$NON-NLS-1$
3875 				setSeverity(CompilerOptions.OPTION_ReportUnusedDeclaredThrownException, severity, isEnabling);
3876 				return;
3877 			} else if (token.equals("unusedThrownWhenOverriding")) { //$NON-NLS-1$
3878 				this.options.put(
3879 						CompilerOptions.OPTION_ReportUnusedDeclaredThrownExceptionWhenOverriding,
3880 						isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3881 				return;
3882 			} else if (token.equals("unusedThrownIncludeDocComment")) { //$NON-NLS-1$
3883 				this.options.put(
3884 						CompilerOptions.OPTION_ReportUnusedDeclaredThrownExceptionIncludeDocCommentReference,
3885 						isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3886 				return;
3887 			} else if (token.equals("unusedThrownExemptExceptionThrowable")) { //$NON-NLS-1$
3888 				this.options.put(
3889 						CompilerOptions.OPTION_ReportUnusedDeclaredThrownExceptionExemptExceptionAndThrowable,
3890 						isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3891 				return;
3892 			} else if (token.equals("unqualifiedField") || token.equals("unqualified-field-access")) { //$NON-NLS-1$ //$NON-NLS-2$
3893 				setSeverity(CompilerOptions.OPTION_ReportUnqualifiedFieldAccess, severity, isEnabling);
3894 				return;
3895 			} else if (token.equals("unused")) { //$NON-NLS-1$
3896 				setSeverity(CompilerOptions.OPTION_ReportUnusedLocal, severity, isEnabling);
3897 				setSeverity(CompilerOptions.OPTION_ReportUnusedParameter, severity, isEnabling);
3898 				setSeverity(CompilerOptions.OPTION_ReportUnusedImport, severity, isEnabling);
3899 				setSeverity(CompilerOptions.OPTION_ReportUnusedPrivateMember, severity, isEnabling);
3900 				setSeverity(CompilerOptions.OPTION_ReportUnusedDeclaredThrownException, severity, isEnabling);
3901 				setSeverity(CompilerOptions.OPTION_ReportUnusedLabel, severity, isEnabling);
3902 				setSeverity(CompilerOptions.OPTION_ReportUnusedTypeArgumentsForMethodInvocation, severity, isEnabling);
3903 				setSeverity(CompilerOptions.OPTION_ReportRedundantSpecificationOfTypeArguments, severity, isEnabling);
3904 				setSeverity(CompilerOptions.OPTION_ReportUnusedTypeParameter, severity,isEnabling);
3905 				return;
3906 			} else if (token.equals("unusedParam")) { //$NON-NLS-1$
3907 				setSeverity(CompilerOptions.OPTION_ReportUnusedParameter, severity, isEnabling);
3908 				return;
3909 			} else if (token.equals("unusedTypeParameter")) { //$NON-NLS-1$
3910 				setSeverity(CompilerOptions.OPTION_ReportUnusedTypeParameter, severity, isEnabling);
3911 				return;
3912 			} else if (token.equals("unusedParamIncludeDoc")) { //$NON-NLS-1$
3913 				this.options.put(
3914 						CompilerOptions.OPTION_ReportUnusedParameterIncludeDocCommentReference,
3915 						isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3916 				return;
3917 			} else if (token.equals("unusedParamOverriding")) { //$NON-NLS-1$
3918 				this.options.put(
3919 						CompilerOptions.OPTION_ReportUnusedParameterWhenOverridingConcrete,
3920 						isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3921 				return;
3922 			} else if (token.equals("unusedParamImplementing")) { //$NON-NLS-1$
3923 				this.options.put(
3924 						CompilerOptions.OPTION_ReportUnusedParameterWhenImplementingAbstract,
3925 						isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3926 				return;
3927 			}  else if (token.equals("unusedTypeArgs")) { //$NON-NLS-1$
3928 				setSeverity(CompilerOptions.OPTION_ReportUnusedTypeArgumentsForMethodInvocation, severity, isEnabling);
3929 				setSeverity(CompilerOptions.OPTION_ReportRedundantSpecificationOfTypeArguments, severity, isEnabling);
3930 				return;
3931 			} else if (token.equals("unavoidableGenericProblems")) { //$NON-NLS-1$
3932 				this.options.put(
3933 					CompilerOptions.OPTION_ReportUnavoidableGenericTypeProblems,
3934 					isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3935 				return;
3936 			}
3937 			break;
3938 		case 'v' :
3939 			if (token.equals("varargsCast")) { //$NON-NLS-1$
3940 				setSeverity(CompilerOptions.OPTION_ReportVarargsArgumentNeedCast, severity, isEnabling);
3941 				return;
3942 			}
3943 			break;
3944 		case 'w' :
3945 			if (token.equals("warningToken")) {//$NON-NLS-1$
3946 				setSeverity(CompilerOptions.OPTION_ReportUnhandledWarningToken, severity, isEnabling);
3947 				setSeverity(CompilerOptions.OPTION_ReportUnusedWarningToken, severity, isEnabling);
3948 				return;
3949 			}
3950 			break;
3951 	}
3952 	String message = null;
3953 	switch(severity) {
3954 		case ProblemSeverities.Warning :
3955 			message = this.bind("configure.invalidWarning", token); //$NON-NLS-1$
3956 			break;
3957 		case ProblemSeverities.Error :
3958 			message = this.bind("configure.invalidError", token); //$NON-NLS-1$
3959 	}
3960 	addPendingErrors(message);
3961 }
3962 /**
3963  * @deprecated - use {@link #initialize(PrintWriter, PrintWriter, boolean, Map, CompilationProgress)} instead
3964  *                       e.g. initialize(outWriter, errWriter, systemExit, null, null)
3965  */
3966 protected void initialize(PrintWriter outWriter, PrintWriter errWriter, boolean systemExit) {
3967 	this.initialize(outWriter, errWriter, systemExit, null /* options */, null /* progress */);
3968 }
3969 /**
3970  * @deprecated - use {@link #initialize(PrintWriter, PrintWriter, boolean, Map, CompilationProgress)} instead
3971  *                       e.g. initialize(outWriter, errWriter, systemExit, customDefaultOptions, null)
3972  */
3973 protected void initialize(PrintWriter outWriter, PrintWriter errWriter, boolean systemExit, Map customDefaultOptions) {
3974 	this.initialize(outWriter, errWriter, systemExit, customDefaultOptions, null /* progress */);
3975 }
3976 protected void initialize(PrintWriter outWriter, PrintWriter errWriter, boolean systemExit, Map customDefaultOptions, CompilationProgress compilationProgress) {
3977 	this.logger = new Logger(this, outWriter, errWriter);
3978 	this.proceed = true;
3979 	this.out = outWriter;
3980 	this.err = errWriter;
3981 	this.systemExitWhenFinished = systemExit;
3982 	this.options = new CompilerOptions().getMap();
3983 	this.ignoreOptionalProblemsFromFolders = null;
3984 
3985 	this.progress = compilationProgress;
3986 	if (customDefaultOptions != null) {
3987 		this.didSpecifySource = customDefaultOptions.get(CompilerOptions.OPTION_Source) != null;
3988 		this.didSpecifyTarget = customDefaultOptions.get(CompilerOptions.OPTION_TargetPlatform) != null;
3989 		for (Iterator iter = customDefaultOptions.entrySet().iterator(); iter.hasNext();) {
3990 			Map.Entry entry = (Map.Entry) iter.next();
3991 			this.options.put(entry.getKey(), entry.getValue());
3992 		}
3993 	} else {
3994 		this.didSpecifySource = false;
3995 		this.didSpecifyTarget = false;
3996 	}
3997 	this.classNames = null;
3998 }
3999 protected void initializeAnnotationProcessorManager() {
4000 	try {
4001 		Class c = Class.forName("org.eclipse.jdt.internal.compiler.apt.dispatch.BatchAnnotationProcessorManager"); //$NON-NLS-1$
4002 		AbstractAnnotationProcessorManager annotationManager = (AbstractAnnotationProcessorManager) c.newInstance();
4003 		annotationManager.configure(this, this.expandedCommandLine);
4004 		annotationManager.setErr(this.err);
4005 		annotationManager.setOut(this.out);
4006 		this.batchCompiler.annotationProcessorManager = annotationManager;
4007 	} catch (ClassNotFoundException e) {
4008 		// ignore
4009 	} catch (InstantiationException e) {
4010 		// should not happen
4011 		throw new org.eclipse.jdt.internal.compiler.problem.AbortCompilation();
4012 	} catch (IllegalAccessException e) {
4013 		// should not happen
4014 		throw new org.eclipse.jdt.internal.compiler.problem.AbortCompilation();
4015 	} catch(UnsupportedClassVersionError e) {
4016 		// report a warning
4017 		this.logger.logIncorrectVMVersionForAnnotationProcessing();
4018 	}
4019 }
4020 private static boolean isParentOf(char[] folderName, char[] fileName) {
4021 	if (folderName.length >= fileName.length) {
4022 		return false;
4023 	}
4024 	if (fileName[folderName.length] != '\\' && fileName[folderName.length] != '/') {
4025 		return false;
4026 	}
4027 	for (int i = folderName.length - 1; i >= 0; i--) {
4028 		if (folderName[i] != fileName[i]) {
4029 			return false;
4030 		}
4031 	}
4032 	return true;
4033 }
4034 // Dump classfiles onto disk for all compilation units that where successful
4035 // and do not carry a -d none spec, either directly or inherited from Main.
4036 public void outputClassFiles(CompilationResult unitResult) {
4037 	if (!((unitResult == null) || (unitResult.hasErrors() && !this.proceedOnError))) {
4038 		ClassFile[] classFiles = unitResult.getClassFiles();
4039 		String currentDestinationPath = null;
4040 		boolean generateClasspathStructure = false;
4041 		CompilationUnit compilationUnit =
4042 			(CompilationUnit) unitResult.compilationUnit;
4043 		if (compilationUnit.destinationPath == null) {
4044 			if (this.destinationPath == null) {
4045 				currentDestinationPath =
4046 					extractDestinationPathFromSourceFile(unitResult);
4047 			} else if (this.destinationPath != NONE) {
4048 				currentDestinationPath = this.destinationPath;
4049 				generateClasspathStructure = true;
4050 			} // else leave currentDestinationPath null
4051 		} else if (compilationUnit.destinationPath != NONE) {
4052 			currentDestinationPath = compilationUnit.destinationPath;
4053 			generateClasspathStructure = true;
4054 		} // else leave currentDestinationPath null
4055 		if (currentDestinationPath != null) {
4056 			for (int i = 0, fileCount = classFiles.length; i < fileCount; i++) {
4057 				// retrieve the key and the corresponding classfile
4058 				ClassFile classFile = classFiles[i];
4059 				char[] filename = classFile.fileName();
4060 				int length = filename.length;
4061 				char[] relativeName = new char[length + 6];
4062 				System.arraycopy(filename, 0, relativeName, 0, length);
4063 				System.arraycopy(SuffixConstants.SUFFIX_class, 0, relativeName, length, 6);
4064 				CharOperation.replace(relativeName, '/', File.separatorChar);
4065 				String relativeStringName = new String(relativeName);
4066 				try {
4067 					if (this.compilerOptions.verbose)
4068 						this.out.println(
4069 							Messages.bind(
4070 								Messages.compilation_write,
4071 								new String[] {
4072 									String.valueOf(this.exportedClassFilesCounter+1),
4073 									relativeStringName
4074 								}));
4075 					Util.writeToDisk(
4076 						generateClasspathStructure,
4077 						currentDestinationPath,
4078 						relativeStringName,
4079 						classFile);
4080 					this.logger.logClassFile(
4081 						generateClasspathStructure,
4082 						currentDestinationPath,
4083 						relativeStringName);
4084 					this.exportedClassFilesCounter++;
4085 				} catch (IOException e) {
4086 					this.logger.logNoClassFileCreated(currentDestinationPath, relativeStringName, e);
4087 				}
4088 			}
4089 			this.batchCompiler.lookupEnvironment.releaseClassFiles(classFiles);
4090 		}
4091 	}
4092 }
4093 /*
4094  *  Low-level API performing the actual compilation
4095  */
4096 public void performCompilation() {
4097 
4098 	this.startTime = System.currentTimeMillis();
4099 
4100 	FileSystem environment = getLibraryAccess();
4101 	this.compilerOptions = new CompilerOptions(this.options);
4102 	this.compilerOptions.performMethodsFullRecovery = false;
4103 	this.compilerOptions.performStatementsRecovery = false;
4104 	this.batchCompiler =
4105 		new Compiler(
4106 			environment,
4107 			getHandlingPolicy(),
4108 			this.compilerOptions,
4109 			getBatchRequestor(),
4110 			getProblemFactory(),
4111 			this.out,
4112 			this.progress);
4113 	this.batchCompiler.remainingIterations = this.maxRepetition-this.currentRepetition/*remaining iterations including this one*/;
4114 	// temporary code to allow the compiler to revert to a single thread
4115 	String setting = System.getProperty("jdt.compiler.useSingleThread"); //$NON-NLS-1$
4116 	this.batchCompiler.useSingleThread = setting != null && setting.equals("true"); //$NON-NLS-1$
4117 
4118 	if (this.compilerOptions.complianceLevel >= ClassFileConstants.JDK1_6
4119 			&& this.compilerOptions.processAnnotations) {
4120 		if (checkVMVersion(ClassFileConstants.JDK1_6)) {
4121 			initializeAnnotationProcessorManager();
4122 			if (this.classNames != null) {
4123 				this.batchCompiler.setBinaryTypes(processClassNames(this.batchCompiler.lookupEnvironment));
4124 			}
4125 		} else {
4126 			// report a warning
4127 			this.logger.logIncorrectVMVersionForAnnotationProcessing();
4128 		}
4129 	}
4130 
4131 	// set the non-externally configurable options.
4132 	this.compilerOptions.verbose = this.verbose;
4133 	this.compilerOptions.produceReferenceInfo = this.produceRefInfo;
4134 	try {
4135 		this.logger.startLoggingSources();
4136 		this.batchCompiler.compile(getCompilationUnits());
4137 	} finally {
4138 		this.logger.endLoggingSources();
4139 	}
4140 
4141 	if (this.extraProblems != null) {
4142 		loggingExtraProblems();
4143 		this.extraProblems = null;
4144 	}
4145 	if (this.compilerStats != null) {
4146 		this.compilerStats[this.currentRepetition] = this.batchCompiler.stats;
4147 	}
4148 	this.logger.printStats();
4149 
4150 	// cleanup
4151 	environment.cleanup();
4152 }
4153 protected void loggingExtraProblems() {
4154 	this.logger.loggingExtraProblems(this);
4155 }
4156 public void printUsage() {
4157 	printUsage("misc.usage"); //$NON-NLS-1$
4158 }
4159 private void printUsage(String sectionID) {
4160 	this.logger.logUsage(
4161 		this.bind(
4162 			sectionID,
4163 			new String[] {
4164 				System.getProperty("path.separator"), //$NON-NLS-1$
4165 				this.bind("compiler.name"), //$NON-NLS-1$
4166 				this.bind("compiler.version"), //$NON-NLS-1$
4167 				this.bind("compiler.copyright") //$NON-NLS-1$
4168 			}));
4169 	this.logger.flush();
4170 }
4171 private ReferenceBinding[] processClassNames(LookupEnvironment environment) {
4172 	// check for .class file presence in case of apt processing
4173 	int length = this.classNames.length;
4174 	ReferenceBinding[] referenceBindings = new ReferenceBinding[length];
4175 	for (int i = 0; i < length; i++) {
4176 		String currentName = this.classNames[i];
4177 		char[][] compoundName = null;
4178 		if (currentName.indexOf('.') != -1) {
4179 			// consider names with '.' as fully qualified names
4180 			char[] typeName = currentName.toCharArray();
4181 			compoundName = CharOperation.splitOn('.', typeName);
4182 		} else {
4183 			compoundName = new char[][] { currentName.toCharArray() };
4184 		}
4185 		ReferenceBinding type = environment.getType(compoundName);
4186 		if (type != null && type.isValidBinding()) {
4187 			if (type.isBinaryBinding()) {
4188 				referenceBindings[i] = type;
4189 			}
4190 		} else {
4191 			throw new IllegalArgumentException(
4192 					this.bind("configure.invalidClassName", currentName));//$NON-NLS-1$
4193 		}
4194 	}
4195 	return referenceBindings;
4196 }
4197 /*
4198  * External API
4199  */
4200 public void processPathEntries(final int defaultSize, final ArrayList paths,
4201 			final String currentPath, String customEncoding, boolean isSourceOnly,
4202 			boolean rejectDestinationPathOnJars) {
4203 	String currentClasspathName = null;
4204 	String currentDestinationPath = null;
4205 	ArrayList currentRuleSpecs = new ArrayList(defaultSize);
4206 	StringTokenizer tokenizer = new StringTokenizer(currentPath,
4207 			File.pathSeparator + "[]", true); //$NON-NLS-1$
4208 	ArrayList tokens = new ArrayList();
4209 	while (tokenizer.hasMoreTokens()) {
4210 		tokens.add(tokenizer.nextToken());
4211 	}
4212 	// state machine
4213 	final int start = 0;
4214 	final int readyToClose = 1;
4215 	// 'path' 'path1[rule];path2'
4216 	final int readyToCloseEndingWithRules = 2;
4217 	// 'path[rule]' 'path1;path2[rule]'
4218 	final int readyToCloseOrOtherEntry = 3;
4219 	// 'path[rule];' 'path;' 'path1;path2;'
4220 	final int rulesNeedAnotherRule = 4;
4221 	// 'path[rule1;'
4222 	final int rulesStart = 5;
4223 	// 'path[' 'path1;path2['
4224 	final int rulesReadyToClose = 6;
4225 	// 'path[rule' 'path[rule1;rule2'
4226 	final int destinationPathReadyToClose = 7;
4227 	// 'path[-d bin'
4228 	final int readyToCloseEndingWithDestinationPath = 8;
4229 	// 'path[-d bin]' 'path[rule][-d bin]'
4230 	final int destinationPathStart = 9;
4231 	// 'path[rule]['
4232 	final int bracketOpened = 10;
4233 	// '.*[.*'
4234 	final int bracketClosed = 11;
4235 	// '.*([.*])+'
4236 
4237 	final int error = 99;
4238 	int state = start;
4239 	String token = null;
4240 	int cursor = 0, tokensNb = tokens.size(), bracket = -1;
4241 	while (cursor < tokensNb && state != error) {
4242 		token = (String) tokens.get(cursor++);
4243 		if (token.equals(File.pathSeparator)) {
4244 			switch (state) {
4245 			case start:
4246 			case readyToCloseOrOtherEntry:
4247 			case bracketOpened:
4248 				break;
4249 			case readyToClose:
4250 			case readyToCloseEndingWithRules:
4251 			case readyToCloseEndingWithDestinationPath:
4252 				state = readyToCloseOrOtherEntry;
4253 				addNewEntry(paths, currentClasspathName, currentRuleSpecs,
4254 						customEncoding, currentDestinationPath, isSourceOnly,
4255 						rejectDestinationPathOnJars);
4256 				currentRuleSpecs.clear();
4257 				break;
4258 			case rulesReadyToClose:
4259 				state = rulesNeedAnotherRule;
4260 				break;
4261 			case destinationPathReadyToClose:
4262 				throw new IllegalArgumentException(
4263 					this.bind("configure.incorrectDestinationPathEntry", //$NON-NLS-1$
4264 						currentPath));
4265 			case bracketClosed:
4266 				cursor = bracket + 1;
4267 				state = rulesStart;
4268 				break;
4269 			default:
4270 				state = error;
4271 			}
4272 		} else if (token.equals("[")) { //$NON-NLS-1$
4273 			switch (state) {
4274 			case start:
4275 				currentClasspathName = ""; //$NON-NLS-1$
4276 				//$FALL-THROUGH$
4277 				case readyToClose:
4278 				bracket = cursor - 1;
4279 				//$FALL-THROUGH$
4280 				case bracketClosed:
4281 				state = bracketOpened;
4282 				break;
4283 			case readyToCloseEndingWithRules:
4284 				state = destinationPathStart;
4285 				break;
4286 			case readyToCloseEndingWithDestinationPath:
4287 				state = rulesStart;
4288 				break;
4289 			case bracketOpened:
4290 			default:
4291 				state = error;
4292 			}
4293 		} else if (token.equals("]")) { //$NON-NLS-1$
4294 			switch (state) {
4295 			case rulesReadyToClose:
4296 				state = readyToCloseEndingWithRules;
4297 				break;
4298 			case destinationPathReadyToClose:
4299 				state = readyToCloseEndingWithDestinationPath;
4300 				break;
4301 			case bracketOpened:
4302 				state = bracketClosed;
4303 				break;
4304 			case bracketClosed:
4305 			default:
4306 				state = error;
4307 			}
4308 		} else {
4309 			// regular word
4310 			switch (state) {
4311 			case start:
4312 			case readyToCloseOrOtherEntry:
4313 				state = readyToClose;
4314 				currentClasspathName = token;
4315 				break;
4316 			case rulesStart:
4317 				if (token.startsWith("-d ")) { //$NON-NLS-1$
4318 					if (currentDestinationPath != null) {
4319 						throw new IllegalArgumentException(
4320 								this.bind("configure.duplicateDestinationPathEntry", //$NON-NLS-1$
4321 										currentPath));
4322 					}
4323 					currentDestinationPath = token.substring(3).trim();
4324 					state = destinationPathReadyToClose;
4325 					break;
4326 				} // else we proceed with a rule
4327 				//$FALL-THROUGH$
4328 			case rulesNeedAnotherRule:
4329 				if (currentDestinationPath != null) {
4330 					throw new IllegalArgumentException(
4331 							this.bind("configure.accessRuleAfterDestinationPath", //$NON-NLS-1$
4332 								currentPath));
4333 				}
4334 				state = rulesReadyToClose;
4335 				currentRuleSpecs.add(token);
4336 				break;
4337 			case destinationPathStart:
4338 				if (!token.startsWith("-d ")) { //$NON-NLS-1$
4339 					state = error;
4340 				} else {
4341 					currentDestinationPath = token.substring(3).trim();
4342 					state = destinationPathReadyToClose;
4343 				}
4344 				break;
4345 			case bracketClosed:
4346 				for (int i = bracket; i < cursor ; i++) {
4347 					currentClasspathName += (String) tokens.get(i);
4348 				}
4349 				state = readyToClose;
4350 				break;
4351 			case bracketOpened:
4352 				break;
4353 			default:
4354 				state = error;
4355 			}
4356 		}
4357 		if (state == bracketClosed && cursor == tokensNb) {
4358 			cursor = bracket + 1;
4359 			state = rulesStart;
4360 		}
4361 	}
4362 	switch(state) {
4363 		case readyToCloseOrOtherEntry:
4364 			break;
4365 		case readyToClose:
4366 		case readyToCloseEndingWithRules:
4367 		case readyToCloseEndingWithDestinationPath:
4368 			addNewEntry(paths, currentClasspathName, currentRuleSpecs,
4369 				customEncoding, currentDestinationPath, isSourceOnly,
4370 				rejectDestinationPathOnJars);
4371 			break;
4372 		case bracketOpened:
4373 		case bracketClosed:
4374 		default :
4375 			// we go on anyway
4376 			if (currentPath.length() != 0) {
4377 				addPendingErrors(this.bind("configure.incorrectClasspath", currentPath));//$NON-NLS-1$
4378 			}
4379 	}
4380 }
4381 
4382 private int processPaths(String[] args, int index, String currentArg, ArrayList paths) {
4383 	int localIndex = index;
4384 	int count = 0;
4385 	for (int i = 0, max = currentArg.length(); i < max; i++) {
4386 		switch(currentArg.charAt(i)) {
4387 			case '[' :
4388 				count++;
4389 				break;
4390 			case ']' :
4391 				count--;
4392 				break;
4393 		}
4394 	}
4395 	if (count == 0) {
4396 		paths.add(currentArg);
4397 	} else if (count > 1) {
4398 		throw new IllegalArgumentException(
4399 				this.bind("configure.unexpectedBracket", //$NON-NLS-1$
4400 							currentArg));
4401 	} else {
4402 		StringBuffer currentPath = new StringBuffer(currentArg);
4403 		while (true) {
4404 			if (localIndex >= args.length) {
4405 				throw new IllegalArgumentException(
4406 						this.bind("configure.unexpectedBracket", //$NON-NLS-1$
4407 								currentArg));
4408 			}
4409 			localIndex++;
4410 			String nextArg = args[localIndex];
4411 			for (int i = 0, max = nextArg.length(); i < max; i++) {
4412 				switch(nextArg.charAt(i)) {
4413 					case '[' :
4414 						if (count > 1) {
4415 							throw new IllegalArgumentException(
4416 									this.bind("configure.unexpectedBracket", //$NON-NLS-1$
4417 											nextArg));
4418 						}
4419 						count++;
4420 						break;
4421 					case ']' :
4422 						count--;
4423 						break;
4424 				}
4425 			}
4426 			if (count == 0) {
4427 				currentPath.append(' ');
4428 				currentPath.append(nextArg);
4429 				paths.add(currentPath.toString());
4430 				return localIndex - index;
4431 			} else if (count < 0) {
4432 				throw new IllegalArgumentException(
4433 						this.bind("configure.unexpectedBracket", //$NON-NLS-1$
4434 									nextArg));
4435 			} else {
4436 				currentPath.append(' ');
4437 				currentPath.append(nextArg);
4438 			}
4439 		}
4440 
4441 	}
4442 	return localIndex - index;
4443 }
4444 private int processPaths(String[] args, int index, String currentArg, String[] paths) {
4445 	int localIndex = index;
4446 	int count = 0;
4447 	for (int i = 0, max = currentArg.length(); i < max; i++) {
4448 		switch(currentArg.charAt(i)) {
4449 			case '[' :
4450 				count++;
4451 				break;
4452 			case ']' :
4453 				count--;
4454 				break;
4455 		}
4456 	}
4457 	if (count == 0) {
4458 		paths[0] = currentArg;
4459 	} else {
4460 		StringBuffer currentPath = new StringBuffer(currentArg);
4461 		while (true) {
4462 			localIndex++;
4463 			if (localIndex >= args.length) {
4464 				throw new IllegalArgumentException(
4465 						this.bind("configure.unexpectedBracket", //$NON-NLS-1$
4466 								currentArg));
4467 			}
4468 			String nextArg = args[localIndex];
4469 			for (int i = 0, max = nextArg.length(); i < max; i++) {
4470 				switch(nextArg.charAt(i)) {
4471 					case '[' :
4472 						if (count > 1) {
4473 							throw new IllegalArgumentException(
4474 									this.bind("configure.unexpectedBracket", //$NON-NLS-1$
4475 											currentArg));
4476 						}
4477 						count++;
4478 						break;
4479 					case ']' :
4480 						count--;
4481 						break;
4482 				}
4483 			}
4484 			if (count == 0) {
4485 				currentPath.append(' ');
4486 				currentPath.append(nextArg);
4487 				paths[0] = currentPath.toString();
4488 				return localIndex - index;
4489 			} else if (count < 0) {
4490 				throw new IllegalArgumentException(
4491 						this.bind("configure.unexpectedBracket", //$NON-NLS-1$
4492 									currentArg));
4493 			} else {
4494 				currentPath.append(' ');
4495 				currentPath.append(nextArg);
4496 			}
4497 		}
4498 
4499 	}
4500 	return localIndex - index;
4501 }
4502 /**
4503  * Creates a NLS catalog for the given locale.
4504  */
4505 public void relocalize() {
4506 	relocalize(Locale.getDefault());
4507 }
4508 
4509 private void relocalize(Locale locale) {
4510 	this.compilerLocale = locale;
4511 	try {
4512 		this.bundle = ResourceBundleFactory.getBundle(locale);
4513 	} catch(MissingResourceException e) {
4514 		System.out.println("Missing resource : " + Main.bundleName.replace('.', '/') + ".properties for locale " + locale); //$NON-NLS-1$//$NON-NLS-2$
4515 		throw e;
4516 	}
4517 }
4518 /*
4519  * External API
4520  */
4521 public void setDestinationPath(String dest) {
4522 	this.destinationPath = dest;
4523 }
4524 /*
4525  * External API
4526  */
4527 public void setLocale(Locale locale) {
4528 	relocalize(locale);
4529 }
4530 /*
4531  * External API
4532  */
4533 protected void setPaths(ArrayList bootclasspaths,
4534 		String sourcepathClasspathArg,
4535 		ArrayList sourcepathClasspaths,
4536 		ArrayList classpaths,
4537 		ArrayList extdirsClasspaths,
4538 		ArrayList endorsedDirClasspaths,
4539 		String customEncoding) {
4540 
4541 	// process bootclasspath, classpath and sourcepaths
4542  	bootclasspaths = handleBootclasspath(bootclasspaths, customEncoding);
4543 
4544 	classpaths = handleClasspath(classpaths, customEncoding);
4545 
4546 	if (sourcepathClasspathArg != null) {
4547 		processPathEntries(DEFAULT_SIZE_CLASSPATH, sourcepathClasspaths,
4548 			sourcepathClasspathArg, customEncoding, true, false);
4549 	}
4550 
4551 	/*
4552 	 * Feed endorsedDirClasspath according to:
4553 	 * - -extdirs first if present;
4554 	 * - else java.ext.dirs if defined;
4555 	 * - else default extensions directory for the platform.
4556 	 */
4557 	extdirsClasspaths = handleExtdirs(extdirsClasspaths);
4558 
4559 	endorsedDirClasspaths = handleEndorseddirs(endorsedDirClasspaths);
4560 
4561 	/*
4562 	 * Concatenate classpath entries
4563 	 * We put the bootclasspath at the beginning of the classpath
4564 	 * entries, followed by the extension libraries, followed by
4565 	 * the sourcepath followed by the classpath.  All classpath
4566 	 * entries are searched for both sources and binaries except
4567 	 * the sourcepath entries which are searched for sources only.
4568 	 */
4569 	bootclasspaths.addAll(0, endorsedDirClasspaths);
4570 	bootclasspaths.addAll(extdirsClasspaths);
4571 	bootclasspaths.addAll(sourcepathClasspaths);
4572 	bootclasspaths.addAll(classpaths);
4573 	classpaths = bootclasspaths;
4574 	classpaths = FileSystem.ClasspathNormalizer.normalize(classpaths);
4575 	this.checkedClasspaths = new FileSystem.Classpath[classpaths.size()];
4576 	classpaths.toArray(this.checkedClasspaths);
4577 	this.logger.logClasspath(this.checkedClasspaths);
4578 }
4579 private static boolean shouldIgnoreOptionalProblems(char[][] folderNames, char[] fileName) {
4580 	if (folderNames == null || fileName == null) {
4581 		return false;
4582 	}
4583 	for (int i = 0, max = folderNames.length; i < max; i++) {
4584 		char[] folderName = folderNames[i];
4585 		if (isParentOf(folderName, fileName)) {
4586 			return true;
4587 		}
4588 	}
4589 	return false;
4590 }
4591 protected void validateOptions(boolean didSpecifyCompliance) {
4592 	if (didSpecifyCompliance) {
4593 		Object version = this.options.get(CompilerOptions.OPTION_Compliance);
4594 		if (CompilerOptions.VERSION_1_3.equals(version)) {
4595 			if (!this.didSpecifySource) this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
4596 			if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_1);
4597 		} else if (CompilerOptions.VERSION_1_4.equals(version)) {
4598 			if (this.didSpecifySource) {
4599 				Object source = this.options.get(CompilerOptions.OPTION_Source);
4600 				if (CompilerOptions.VERSION_1_3.equals(source)) {
4601 					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2);
4602 				} else if (CompilerOptions.VERSION_1_4.equals(source)) {
4603 					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
4604 				}
4605 			} else {
4606 				this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
4607 				if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2);
4608 			}
4609 		} else if (CompilerOptions.VERSION_1_5.equals(version)) {
4610 			if (this.didSpecifySource) {
4611 				Object source = this.options.get(CompilerOptions.OPTION_Source);
4612 				if (CompilerOptions.VERSION_1_3.equals(source)
4613 						|| CompilerOptions.VERSION_1_4.equals(source)) {
4614 					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
4615 				} else if (CompilerOptions.VERSION_1_5.equals(source)) {
4616 					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
4617 				}
4618 			} else {
4619 				this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_5);
4620 				if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
4621 			}
4622 		} else if (CompilerOptions.VERSION_1_6.equals(version)) {
4623 			if (this.didSpecifySource) {
4624 				Object source = this.options.get(CompilerOptions.OPTION_Source);
4625 				if (CompilerOptions.VERSION_1_3.equals(source)
4626 						|| CompilerOptions.VERSION_1_4.equals(source)) {
4627 					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
4628 				} else if (CompilerOptions.VERSION_1_5.equals(source)
4629 						|| CompilerOptions.VERSION_1_6.equals(source)) {
4630 					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
4631 				}
4632 			} else {
4633 				this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_6);
4634 				if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
4635 			}
4636 		} else if (CompilerOptions.VERSION_1_7.equals(version)) {
4637 			if (this.didSpecifySource) {
4638 				Object source = this.options.get(CompilerOptions.OPTION_Source);
4639 				if (CompilerOptions.VERSION_1_3.equals(source)
4640 						|| CompilerOptions.VERSION_1_4.equals(source)) {
4641 					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
4642 				} else if (CompilerOptions.VERSION_1_5.equals(source)
4643 						|| CompilerOptions.VERSION_1_6.equals(source)) {
4644 					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
4645 				} else if (CompilerOptions.VERSION_1_7.equals(source)) {
4646 					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_7);
4647 				}
4648 			} else {
4649 				this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_7);
4650 				if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_7);
4651 			}
4652 		} else if (CompilerOptions.VERSION_1_8.equals(version)) {
4653 			if (this.didSpecifySource) {
4654 				Object source = this.options.get(CompilerOptions.OPTION_Source);
4655 				if (CompilerOptions.VERSION_1_3.equals(source)
4656 						|| CompilerOptions.VERSION_1_4.equals(source)) {
4657 					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
4658 				} else if (CompilerOptions.VERSION_1_5.equals(source)
4659 						|| CompilerOptions.VERSION_1_6.equals(source)) {
4660 					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
4661 				} else if (CompilerOptions.VERSION_1_7.equals(source)) {
4662 					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_7);
4663 				} else if (CompilerOptions.VERSION_1_8.equals(source)) {
4664 					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_8);
4665 				}
4666 			} else {
4667 				this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_8);
4668 				if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_8);
4669 			}
4670 		}
4671 	} else if (this.didSpecifySource) {
4672 		Object version = this.options.get(CompilerOptions.OPTION_Source);
4673 		// default is source 1.3 target 1.2 and compliance 1.4
4674 		if (CompilerOptions.VERSION_1_4.equals(version)) {
4675 			if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
4676 			if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
4677 		} else if (CompilerOptions.VERSION_1_5.equals(version)) {
4678 			if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_5);
4679 			if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
4680 		} else if (CompilerOptions.VERSION_1_6.equals(version)) {
4681 			if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_6);
4682 			if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
4683 		} else if (CompilerOptions.VERSION_1_7.equals(version)) {
4684 			if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_7);
4685 			if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_7);
4686 		} else if (CompilerOptions.VERSION_1_8.equals(version)) {
4687 			if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_8);
4688 			if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_8);
4689 		}
4690 	}
4691 
4692 	final Object sourceVersion = this.options.get(CompilerOptions.OPTION_Source);
4693 	final Object compliance = this.options.get(CompilerOptions.OPTION_Compliance);
4694 	if (sourceVersion.equals(CompilerOptions.VERSION_1_8)
4695 			&& CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK1_8) {
4696 		// compliance must be 1.8 if source is 1.8
4697 		throw new IllegalArgumentException(this.bind("configure.incompatibleComplianceForSource", (String)this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_8)); //$NON-NLS-1$
4698 	} else if (sourceVersion.equals(CompilerOptions.VERSION_1_7)
4699 			&& CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK1_7) {
4700 		// compliance must be 1.7 if source is 1.7
4701 		throw new IllegalArgumentException(this.bind("configure.incompatibleComplianceForSource", (String)this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_7)); //$NON-NLS-1$
4702 	} else if (sourceVersion.equals(CompilerOptions.VERSION_1_6)
4703 			&& CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK1_6) {
4704 		// compliance must be 1.6 if source is 1.6
4705 		throw new IllegalArgumentException(this.bind("configure.incompatibleComplianceForSource", (String)this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_6)); //$NON-NLS-1$
4706 	} else if (sourceVersion.equals(CompilerOptions.VERSION_1_5)
4707 			&& CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK1_5) {
4708 		// compliance must be 1.5 if source is 1.5
4709 		throw new IllegalArgumentException(this.bind("configure.incompatibleComplianceForSource", (String)this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_5)); //$NON-NLS-1$
4710 	} else if (sourceVersion.equals(CompilerOptions.VERSION_1_4)
4711 			&& CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK1_4) {
4712 		// compliance must be 1.4 if source is 1.4
4713 		throw new IllegalArgumentException(this.bind("configure.incompatibleComplianceForSource", (String)this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_4)); //$NON-NLS-1$
4714 	}
4715 
4716 	// check and set compliance/source/target compatibilities
4717 	if (this.didSpecifyTarget) {
4718 		final Object targetVersion = this.options.get(CompilerOptions.OPTION_TargetPlatform);
4719 		// tolerate jsr14 target
4720 		if (CompilerOptions.VERSION_JSR14.equals(targetVersion)) {
4721 			// expecting source >= 1.5
4722 			if (CompilerOptions.versionToJdkLevel(sourceVersion) < ClassFileConstants.JDK1_5) {
4723 				throw new IllegalArgumentException(this.bind("configure.incompatibleTargetForGenericSource", (String) targetVersion, (String) sourceVersion)); //$NON-NLS-1$
4724 			}
4725 		} else if (CompilerOptions.VERSION_CLDC1_1.equals(targetVersion)) {
4726 			if (this.didSpecifySource && CompilerOptions.versionToJdkLevel(sourceVersion) >= ClassFileConstants.JDK1_4) {
4727 				throw new IllegalArgumentException(this.bind("configure.incompatibleSourceForCldcTarget", (String) targetVersion, (String) sourceVersion)); //$NON-NLS-1$
4728 			}
4729 			if (CompilerOptions.versionToJdkLevel(compliance) >= ClassFileConstants.JDK1_5) {
4730 				throw new IllegalArgumentException(this.bind("configure.incompatibleComplianceForCldcTarget", (String) targetVersion, (String) sourceVersion)); //$NON-NLS-1$
4731 			}
4732 		} else {
4733 			// target must be 1.8 if source is 1.8
4734 			if (CompilerOptions.versionToJdkLevel(sourceVersion) >= ClassFileConstants.JDK1_8
4735 					&& CompilerOptions.versionToJdkLevel(targetVersion) < ClassFileConstants.JDK1_8){
4736 				throw new IllegalArgumentException(this.bind("configure.incompatibleTargetForSource", (String) targetVersion, CompilerOptions.VERSION_1_8)); //$NON-NLS-1$
4737 			}
4738 			// target must be 1.7 if source is 1.7
4739 			if (CompilerOptions.versionToJdkLevel(sourceVersion) >= ClassFileConstants.JDK1_7
4740 					&& CompilerOptions.versionToJdkLevel(targetVersion) < ClassFileConstants.JDK1_7){
4741 				throw new IllegalArgumentException(this.bind("configure.incompatibleTargetForSource", (String) targetVersion, CompilerOptions.VERSION_1_7)); //$NON-NLS-1$
4742 			}
4743 			// target must be 1.6 if source is 1.6
4744 			if (CompilerOptions.versionToJdkLevel(sourceVersion) >= ClassFileConstants.JDK1_6
4745 					&& CompilerOptions.versionToJdkLevel(targetVersion) < ClassFileConstants.JDK1_6){
4746 				throw new IllegalArgumentException(this.bind("configure.incompatibleTargetForSource", (String) targetVersion, CompilerOptions.VERSION_1_6)); //$NON-NLS-1$
4747 			}
4748 			// target must be 1.5 if source is 1.5
4749 			if (CompilerOptions.versionToJdkLevel(sourceVersion) >= ClassFileConstants.JDK1_5
4750 					&& CompilerOptions.versionToJdkLevel(targetVersion) < ClassFileConstants.JDK1_5){
4751 				throw new IllegalArgumentException(this.bind("configure.incompatibleTargetForSource", (String) targetVersion, CompilerOptions.VERSION_1_5)); //$NON-NLS-1$
4752 			}
4753 			// target must be 1.4 if source is 1.4
4754 			if (CompilerOptions.versionToJdkLevel(sourceVersion) >= ClassFileConstants.JDK1_4
4755 					&& CompilerOptions.versionToJdkLevel(targetVersion) < ClassFileConstants.JDK1_4){
4756 				throw new IllegalArgumentException(this.bind("configure.incompatibleTargetForSource", (String) targetVersion, CompilerOptions.VERSION_1_4)); //$NON-NLS-1$
4757 			}
4758 			// target cannot be greater than compliance level
4759 			if (CompilerOptions.versionToJdkLevel(compliance) < CompilerOptions.versionToJdkLevel(targetVersion)){
4760 				throw new IllegalArgumentException(this.bind("configure.incompatibleComplianceForTarget", (String)this.options.get(CompilerOptions.OPTION_Compliance), (String) targetVersion)); //$NON-NLS-1$
4761 			}
4762 		}
4763 	}
4764 }
4765 }
4766