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