0001: /*******************************************************************************
0002: * Copyright (c) 2000, 2007 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: * Tom Tromey - Contribution for bug 125961
0011: * Tom Tromey - Contribution for bug 159641
0012: *******************************************************************************/package org.eclipse.jdt.internal.compiler.batch;
0013:
0014: import java.io.ByteArrayInputStream;
0015: import java.io.File;
0016: import java.io.FileNotFoundException;
0017: import java.io.FileOutputStream;
0018: import java.io.FilenameFilter;
0019: import java.io.IOException;
0020: import java.io.InputStreamReader;
0021: import java.io.LineNumberReader;
0022: import java.io.PrintWriter;
0023: import java.io.StringReader;
0024: import java.io.StringWriter;
0025: import java.io.UnsupportedEncodingException;
0026: import java.lang.reflect.Field;
0027: import java.text.DateFormat;
0028: import java.text.MessageFormat;
0029: import java.util.ArrayList;
0030: import java.util.Arrays;
0031: import java.util.Comparator;
0032: import java.util.Date;
0033: import java.util.HashMap;
0034: import java.util.Iterator;
0035: import java.util.Locale;
0036: import java.util.Map;
0037: import java.util.MissingResourceException;
0038: import java.util.ResourceBundle;
0039: import java.util.Set;
0040: import java.util.StringTokenizer;
0041:
0042: import org.eclipse.jdt.core.compiler.CategorizedProblem;
0043: import org.eclipse.jdt.core.compiler.CharOperation;
0044: import org.eclipse.jdt.core.compiler.InvalidInputException;
0045: import org.eclipse.jdt.core.compiler.IProblem;
0046: import org.eclipse.jdt.internal.compiler.AbstractAnnotationProcessorManager;
0047: import org.eclipse.jdt.internal.compiler.ClassFile;
0048: import org.eclipse.jdt.internal.compiler.CompilationResult;
0049: import org.eclipse.jdt.internal.compiler.Compiler;
0050: import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
0051: import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
0052: import org.eclipse.jdt.internal.compiler.IProblemFactory;
0053: import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
0054: import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath;
0055: import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
0056: import org.eclipse.jdt.internal.compiler.env.AccessRule;
0057: import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
0058: import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
0059: import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
0060: import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
0061: import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
0062: import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
0063: import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
0064: import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
0065: import org.eclipse.jdt.internal.compiler.util.GenericXMLWriter;
0066: import org.eclipse.jdt.internal.compiler.util.HashtableOfInt;
0067: import org.eclipse.jdt.internal.compiler.util.Messages;
0068: import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
0069: import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
0070: import org.eclipse.jdt.internal.compiler.util.Util;
0071:
0072: public class Main implements ProblemSeverities, SuffixConstants {
0073: /**
0074: * Resource bundle factory to share bundles for the same locale
0075: */
0076: public static class ResourceBundleFactory {
0077: private static HashMap Cache = new HashMap();
0078:
0079: public static synchronized ResourceBundle getBundle(
0080: Locale locale) {
0081: ResourceBundle bundle = (ResourceBundle) Cache.get(locale);
0082: if (bundle == null) {
0083: bundle = ResourceBundle.getBundle(Main.bundleName,
0084: locale);
0085: Cache.put(locale, bundle);
0086: }
0087: return bundle;
0088: }
0089: }
0090:
0091: public static class Logger {
0092: private static final String CLASS = "class"; //$NON-NLS-1$
0093: private static final String CLASS_FILE = "classfile"; //$NON-NLS-1$
0094: private static final String CLASSPATH = "classpath"; //$NON-NLS-1$
0095: private static final String CLASSPATH_FILE = "FILE"; //$NON-NLS-1$
0096: private static final String CLASSPATH_FOLDER = "FOLDER"; //$NON-NLS-1$
0097: private static final String CLASSPATH_ID = "id"; //$NON-NLS-1$
0098: private static final String CLASSPATH_JAR = "JAR"; //$NON-NLS-1$
0099: private static final String CLASSPATHS = "classpaths"; //$NON-NLS-1$
0100: private static final String COMMAND_LINE_ARGUMENT = "argument"; //$NON-NLS-1$
0101: private static final String COMMAND_LINE_ARGUMENTS = "command_line"; //$NON-NLS-1$
0102: private static final String COMPILER = "compiler"; //$NON-NLS-1$
0103: private static final String COMPILER_COPYRIGHT = "copyright"; //$NON-NLS-1$
0104: private static final String COMPILER_NAME = "name"; //$NON-NLS-1$
0105: private static final String COMPILER_VERSION = "version"; //$NON-NLS-1$
0106: public static final int EMACS = 2;
0107: private static final String ERROR = "ERROR"; //$NON-NLS-1$
0108: private static final String ERROR_TAG = "error"; //$NON-NLS-1$
0109: private static final String EXCEPTION = "exception"; //$NON-NLS-1$
0110: private static final String EXTRA_PROBLEM_TAG = "extra_problem"; //$NON-NLS-1$
0111: private static final String EXTRA_PROBLEMS = "extra_problems"; //$NON-NLS-1$
0112: private static final HashtableOfInt FIELD_TABLE = new HashtableOfInt();
0113: private static final String KEY = "key"; //$NON-NLS-1$
0114: private static final String MESSAGE = "message"; //$NON-NLS-1$
0115: private static final String NUMBER_OF_CLASSFILES = "number_of_classfiles"; //$NON-NLS-1$
0116: private static final String NUMBER_OF_ERRORS = "errors"; //$NON-NLS-1$
0117: private static final String NUMBER_OF_LINES = "number_of_lines"; //$NON-NLS-1$
0118: private static final String NUMBER_OF_PROBLEMS = "problems"; //$NON-NLS-1$
0119: private static final String NUMBER_OF_TASKS = "tasks"; //$NON-NLS-1$
0120: private static final String NUMBER_OF_WARNINGS = "warnings"; //$NON-NLS-1$
0121: private static final String OPTION = "option"; //$NON-NLS-1$
0122: private static final String OPTIONS = "options"; //$NON-NLS-1$
0123: private static final String OUTPUT = "output"; //$NON-NLS-1$
0124: private static final String PACKAGE = "package"; //$NON-NLS-1$
0125: private static final String PATH = "path"; //$NON-NLS-1$
0126: private static final String PROBLEM_ARGUMENT = "argument"; //$NON-NLS-1$
0127: private static final String PROBLEM_ARGUMENT_VALUE = "value"; //$NON-NLS-1$
0128: private static final String PROBLEM_ARGUMENTS = "arguments"; //$NON-NLS-1$
0129: private static final String PROBLEM_CATEGORY_ID = "categoryID"; //$NON-NLS-1$
0130: private static final String ID = "id"; //$NON-NLS-1$
0131: private static final String PROBLEM_ID = "problemID"; //$NON-NLS-1$
0132: private static final String PROBLEM_LINE = "line"; //$NON-NLS-1$
0133: private static final String PROBLEM_OPTION_KEY = "optionKey"; //$NON-NLS-1$
0134: private static final String PROBLEM_MESSAGE = "message"; //$NON-NLS-1$
0135: private static final String PROBLEM_SEVERITY = "severity"; //$NON-NLS-1$
0136: private static final String PROBLEM_SOURCE_END = "charEnd"; //$NON-NLS-1$
0137: private static final String PROBLEM_SOURCE_START = "charStart"; //$NON-NLS-1$
0138: private static final String PROBLEM_SUMMARY = "problem_summary"; //$NON-NLS-1$
0139: private static final String PROBLEM_TAG = "problem"; //$NON-NLS-1$
0140: private static final String PROBLEMS = "problems"; //$NON-NLS-1$
0141: private static final String SOURCE = "source"; //$NON-NLS-1$
0142: private static final String SOURCE_CONTEXT = "source_context"; //$NON-NLS-1$
0143: private static final String SOURCE_END = "sourceEnd"; //$NON-NLS-1$
0144: private static final String SOURCE_START = "sourceStart"; //$NON-NLS-1$
0145: private static final String SOURCES = "sources"; //$NON-NLS-1$
0146: private static final String STATS = "stats"; //$NON-NLS-1$
0147: private static final String TASK = "task"; //$NON-NLS-1$
0148: private static final String TASKS = "tasks"; //$NON-NLS-1$
0149: private static final String TIME = "time"; //$NON-NLS-1$
0150: private static final String VALUE = "value"; //$NON-NLS-1$
0151: private static final String WARNING = "WARNING"; //$NON-NLS-1$
0152:
0153: public static final int XML = 1;
0154:
0155: private static final String XML_DTD_DECLARATION = "<!DOCTYPE compiler PUBLIC \"-//Eclipse.org//DTD Eclipse JDT 3.2.003 Compiler//EN\" \"http://www.eclipse.org/jdt/core/compiler_32_003.dtd\">"; //$NON-NLS-1$
0156: static {
0157: try {
0158: Class c = IProblem.class;
0159: Field[] fields = c.getFields();
0160: for (int i = 0, max = fields.length; i < max; i++) {
0161: Field field = fields[i];
0162: if (field.getType().equals(Integer.TYPE)) {
0163: Integer value = (Integer) field.get(null);
0164: Logger.FIELD_TABLE.put(value.intValue()
0165: & IProblem.IgnoreCategoriesMask, field
0166: .getName());
0167: }
0168: }
0169: } catch (SecurityException e) {
0170: e.printStackTrace();
0171: } catch (IllegalArgumentException e) {
0172: e.printStackTrace();
0173: } catch (IllegalAccessException e) {
0174: e.printStackTrace();
0175: }
0176: }
0177: private PrintWriter err;
0178: private PrintWriter log;
0179: private Main main;
0180: private PrintWriter out;
0181: private HashMap parameters;
0182: int tagBits;
0183:
0184: public Logger(Main main, PrintWriter out, PrintWriter err) {
0185: this .out = out;
0186: this .err = err;
0187: this .parameters = new HashMap();
0188: this .main = main;
0189: }
0190:
0191: public String buildFileName(String outputPath,
0192: String relativeFileName) {
0193: char fileSeparatorChar = File.separatorChar;
0194: String fileSeparator = File.separator;
0195:
0196: outputPath = outputPath.replace('/', fileSeparatorChar);
0197: // To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
0198: StringBuffer outDir = new StringBuffer(outputPath);
0199: if (!outputPath.endsWith(fileSeparator)) {
0200: outDir.append(fileSeparator);
0201: }
0202: StringTokenizer tokenizer = new StringTokenizer(
0203: relativeFileName, fileSeparator);
0204: String token = tokenizer.nextToken();
0205: while (tokenizer.hasMoreTokens()) {
0206: outDir.append(token).append(fileSeparator);
0207: token = tokenizer.nextToken();
0208: }
0209: // token contains the last one
0210: return outDir.append(token).toString();
0211: }
0212:
0213: public void close() {
0214: if (this .log != null) {
0215: if ((this .tagBits & Logger.XML) != 0) {
0216: this .endTag(Logger.COMPILER);
0217: this .flush();
0218: }
0219: this .log.close();
0220: }
0221: }
0222:
0223: /**
0224: *
0225: */
0226: public void compiling() {
0227: this .printlnOut(this .main.bind("progress.compiling")); //$NON-NLS-1$
0228: }
0229:
0230: /**
0231: * Used to stop logging problems.
0232: * Only use in xml mode.
0233: */
0234: private void endLoggingProblems() {
0235: this .endTag(Logger.PROBLEMS);
0236: }
0237:
0238: private void endLoggingExtraProblems() {
0239: this .endTag(Logger.EXTRA_PROBLEMS);
0240: }
0241:
0242: public void endLoggingSource() {
0243: if ((this .tagBits & Logger.XML) != 0) {
0244: this .endTag(Logger.SOURCE);
0245: }
0246: }
0247:
0248: public void endLoggingSources() {
0249: if ((this .tagBits & Logger.XML) != 0) {
0250: this .endTag(Logger.SOURCES);
0251: }
0252: }
0253:
0254: public void endLoggingTasks() {
0255: if ((this .tagBits & Logger.XML) != 0) {
0256: this .endTag(Logger.TASKS);
0257: }
0258: }
0259:
0260: private void endTag(String name) {
0261: ((GenericXMLWriter) this .log).endTag(name, true, true);
0262: }
0263:
0264: private void extractContext(CategorizedProblem problem,
0265: char[] unitSource) {
0266: //sanity .....
0267: int startPosition = problem.getSourceStart();
0268: int endPosition = problem.getSourceEnd();
0269: if (unitSource == null) {
0270: if (problem.getOriginatingFileName() != null) {
0271: try {
0272: unitSource = Util.getFileCharContent(new File(
0273: new String(problem
0274: .getOriginatingFileName())),
0275: null);
0276: } catch (IOException e) {
0277: // ignore
0278: }
0279: }
0280: }
0281: int length = unitSource == null ? 0 : unitSource.length;
0282: if ((startPosition > endPosition)
0283: || ((startPosition < 0) && (endPosition < 0))
0284: || (length <= 0) || (endPosition > length)) {
0285: this .parameters.put(Logger.VALUE,
0286: Messages.problem_noSourceInformation);
0287: this .parameters.put(Logger.SOURCE_START, "-1"); //$NON-NLS-1$
0288: this .parameters.put(Logger.SOURCE_END, "-1"); //$NON-NLS-1$
0289: this .printTag(Logger.SOURCE_CONTEXT, this .parameters,
0290: true, true);
0291: return;
0292: }
0293:
0294: char c;
0295: //the next code tries to underline the token.....
0296: //it assumes (for a good display) that token source does not
0297: //contain any \r \n. This is false on statements !
0298: //(the code still works but the display is not optimal !)
0299:
0300: // expand to line limits
0301: int begin, end;
0302: for (begin = startPosition >= length ? length - 1
0303: : startPosition; begin > 0; begin--) {
0304: if ((c = unitSource[begin - 1]) == '\n' || c == '\r')
0305: break;
0306: }
0307: for (end = endPosition >= length ? length - 1 : endPosition; end + 1 < length; end++) {
0308: if ((c = unitSource[end + 1]) == '\r' || c == '\n')
0309: break;
0310: }
0311:
0312: // trim left and right spaces/tabs
0313: while ((c = unitSource[begin]) == ' ' || c == '\t')
0314: begin++;
0315: while ((c = unitSource[end]) == ' ' || c == '\t')
0316: end--;
0317:
0318: // copy source
0319: StringBuffer buffer = new StringBuffer();
0320: buffer.append(unitSource, begin, end - begin + 1);
0321:
0322: this .parameters.put(Logger.VALUE, String.valueOf(buffer));
0323: this .parameters.put(Logger.SOURCE_START, Integer
0324: .toString(startPosition - begin));
0325: this .parameters.put(Logger.SOURCE_END, Integer
0326: .toString(endPosition - begin));
0327: this .printTag(Logger.SOURCE_CONTEXT, this .parameters, true,
0328: true);
0329: }
0330:
0331: public void flush() {
0332: this .out.flush();
0333: this .err.flush();
0334: if (this .log != null) {
0335: this .log.flush();
0336: }
0337: }
0338:
0339: private String getFieldName(int id) {
0340: return (String) Logger.FIELD_TABLE.get(id
0341: & IProblem.IgnoreCategoriesMask);
0342: }
0343:
0344: // find out an option name controlling a given problemID
0345: private String getProblemOptionKey(int problemID) {
0346: long irritant = ProblemReporter.getIrritant(problemID);
0347: return CompilerOptions.optionKeyFromIrritant(irritant);
0348: }
0349:
0350: public void logAverage(long[] times, long lineCount) {
0351: Arrays.sort(times);
0352: final int length = times.length;
0353: long sum = 0;
0354: for (int i = 1, max = length - 1; i < max; i++) {
0355: sum += times[i];
0356: }
0357: long time = sum / (length - 2);
0358: this
0359: .printlnOut(this .main
0360: .bind(
0361: "compile.averageTime", //$NON-NLS-1$
0362: new String[] {
0363: String.valueOf(lineCount),
0364: String.valueOf(time),
0365: String
0366: .valueOf(((int) (lineCount * 10000.0 / time)) / 10.0) }));
0367: }
0368:
0369: public void logClassFile(boolean generatePackagesStructure,
0370: String outputPath, String relativeFileName) {
0371: if ((this .tagBits & Logger.XML) != 0) {
0372: String fileName = null;
0373: if (generatePackagesStructure) {
0374: fileName = buildFileName(outputPath,
0375: relativeFileName);
0376: } else {
0377: char fileSeparatorChar = File.separatorChar;
0378: String fileSeparator = File.separator;
0379: // First we ensure that the outputPath exists
0380: outputPath = outputPath.replace('/',
0381: fileSeparatorChar);
0382: // To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
0383: int indexOfPackageSeparator = relativeFileName
0384: .lastIndexOf(fileSeparatorChar);
0385: if (indexOfPackageSeparator == -1) {
0386: if (outputPath.endsWith(fileSeparator)) {
0387: fileName = outputPath + relativeFileName;
0388: } else {
0389: fileName = outputPath + fileSeparator
0390: + relativeFileName;
0391: }
0392: } else {
0393: int length = relativeFileName.length();
0394: if (outputPath.endsWith(fileSeparator)) {
0395: fileName = outputPath
0396: + relativeFileName
0397: .substring(
0398: indexOfPackageSeparator + 1,
0399: length);
0400: } else {
0401: fileName = outputPath
0402: + fileSeparator
0403: + relativeFileName
0404: .substring(
0405: indexOfPackageSeparator + 1,
0406: length);
0407: }
0408: }
0409: }
0410: File f = new File(fileName);
0411: try {
0412: this .parameters.put(Logger.PATH, f
0413: .getCanonicalPath());
0414: this .printTag(Logger.CLASS_FILE, this .parameters,
0415: true, true);
0416: } catch (IOException e) {
0417: this .logNoClassFileCreated(outputPath,
0418: relativeFileName, e);
0419: }
0420: }
0421: }
0422:
0423: public void logClasspath(FileSystem.Classpath[] classpaths) {
0424: if (classpaths == null)
0425: return;
0426: if ((this .tagBits & Logger.XML) != 0) {
0427: final int length = classpaths.length;
0428: if (length != 0) {
0429: // generate xml output
0430: this .printTag(Logger.CLASSPATHS, null, true, false);
0431: for (int i = 0; i < length; i++) {
0432: String classpath = classpaths[i].getPath();
0433: this .parameters.put(Logger.PATH, classpath);
0434: File f = new File(classpath);
0435: String id = null;
0436: if (f.isFile()) {
0437: if (Util.isArchiveFileName(classpath)) {
0438: id = Logger.CLASSPATH_JAR;
0439: } else {
0440: id = Logger.CLASSPATH_FILE;
0441: }
0442: } else if (f.isDirectory()) {
0443: id = Logger.CLASSPATH_FOLDER;
0444: }
0445: if (id != null) {
0446: this .parameters
0447: .put(Logger.CLASSPATH_ID, id);
0448: this .printTag(Logger.CLASSPATH,
0449: this .parameters, true, true);
0450: }
0451: }
0452: this .endTag(Logger.CLASSPATHS);
0453: }
0454: }
0455:
0456: }
0457:
0458: public void logCommandLineArguments(
0459: String[] commandLineArguments) {
0460: if (commandLineArguments == null)
0461: return;
0462: if ((this .tagBits & Logger.XML) != 0) {
0463: final int length = commandLineArguments.length;
0464: if (length != 0) {
0465: // generate xml output
0466: this .printTag(Logger.COMMAND_LINE_ARGUMENTS, null,
0467: true, false);
0468: for (int i = 0; i < length; i++) {
0469: this .parameters.put(Logger.VALUE,
0470: commandLineArguments[i]);
0471: this .printTag(Logger.COMMAND_LINE_ARGUMENT,
0472: this .parameters, true, true);
0473: }
0474: this .endTag(Logger.COMMAND_LINE_ARGUMENTS);
0475: }
0476: }
0477: }
0478:
0479: /**
0480: * @param e the given exception to log
0481: */
0482: public void logException(Exception e) {
0483: StringWriter writer = new StringWriter();
0484: PrintWriter printWriter = new PrintWriter(writer);
0485: e.printStackTrace(printWriter);
0486: printWriter.flush();
0487: printWriter.close();
0488: final String stackTrace = writer.getBuffer().toString();
0489: if ((this .tagBits & Logger.XML) != 0) {
0490: LineNumberReader reader = new LineNumberReader(
0491: new StringReader(stackTrace));
0492: String line;
0493: int i = 0;
0494: StringBuffer buffer = new StringBuffer();
0495: String message = e.getMessage();
0496: if (message != null) {
0497: buffer.append(message).append(Util.LINE_SEPARATOR);
0498: }
0499: try {
0500: while ((line = reader.readLine()) != null && i < 4) {
0501: buffer.append(line).append(Util.LINE_SEPARATOR);
0502: i++;
0503: }
0504: reader.close();
0505: } catch (IOException e1) {
0506: // ignore
0507: }
0508: message = buffer.toString();
0509: this .parameters.put(Logger.MESSAGE, message);
0510: this .parameters.put(Logger.CLASS, e.getClass());
0511: this .printTag(Logger.EXCEPTION, this .parameters, true,
0512: true);
0513: }
0514: String message = e.getMessage();
0515: if (message == null) {
0516: this .printlnErr(stackTrace);
0517: } else {
0518: this .printlnErr(message);
0519: }
0520: }
0521:
0522: /**
0523: * @param wrongClasspath
0524: * the given wrong classpath entry
0525: */
0526: public void logIncorrectClasspath(String wrongClasspath) {
0527: if ((this .tagBits & Logger.XML) != 0) {
0528: this .parameters
0529: .put(
0530: Logger.MESSAGE,
0531: this .main
0532: .bind(
0533: "configure.incorrectClasspath", wrongClasspath)); //$NON-NLS-1$
0534: this .printTag(Logger.ERROR_TAG, this .parameters, true,
0535: true);
0536: }
0537: this .printlnErr(this .main.bind(
0538: "configure.incorrectClasspath", wrongClasspath)); //$NON-NLS-1$
0539: }
0540:
0541: /**
0542: * @param wrongPath
0543: * the given wrong path entry
0544: */
0545: public void logIncorrectEndorsedDirsEntry(String wrongPath) {
0546: if ((this .tagBits & Logger.XML) != 0) {
0547: this .parameters
0548: .put(
0549: Logger.MESSAGE,
0550: this .main
0551: .bind(
0552: "configure.incorrectEndorsedDirsEntry", wrongPath)); //$NON-NLS-1$
0553: this .printTag(Logger.ERROR_TAG, this .parameters, true,
0554: true);
0555: }
0556: this .printlnErr(this .main.bind(
0557: "configure.incorrectEndorsedDirsEntry", wrongPath)); //$NON-NLS-1$
0558: }
0559:
0560: /**
0561: * @param wrongPath
0562: * the given wrong path entry
0563: */
0564: public void logIncorrectExtDirsEntry(String wrongPath) {
0565: if ((this .tagBits & Logger.XML) != 0) {
0566: this .parameters.put(Logger.MESSAGE, this .main.bind(
0567: "configure.incorrectExtDirsEntry", wrongPath)); //$NON-NLS-1$
0568: this .printTag(Logger.ERROR_TAG, this .parameters, true,
0569: true);
0570: }
0571: this .printlnErr(this .main.bind(
0572: "configure.incorrectExtDirsEntry", wrongPath)); //$NON-NLS-1$
0573: }
0574:
0575: public void logIncorrectVMVersionForAnnotationProcessing() {
0576: if ((this .tagBits & Logger.XML) != 0) {
0577: this .parameters.put(Logger.MESSAGE, this .main
0578: .bind("configure.incorrectVMVersionforAPT")); //$NON-NLS-1$
0579: this .printTag(Logger.ERROR_TAG, this .parameters, true,
0580: true);
0581: }
0582: this .printlnErr(this .main
0583: .bind("configure.incorrectVMVersionforAPT")); //$NON-NLS-1$
0584: }
0585:
0586: /**
0587: *
0588: */
0589: public void logNoClassFileCreated(String outputDir,
0590: String relativeFileName, IOException e) {
0591: if ((this .tagBits & Logger.XML) != 0) {
0592: this .parameters.put(Logger.MESSAGE, this .main.bind(
0593: "output.noClassFileCreated", //$NON-NLS-1$
0594: new String[] { outputDir, relativeFileName,
0595: e.getMessage() }));
0596: this .printTag(Logger.ERROR_TAG, this .parameters, true,
0597: true);
0598: }
0599: this .printlnErr(this .main.bind("output.noClassFileCreated", //$NON-NLS-1$
0600: new String[] { outputDir, relativeFileName,
0601: e.getMessage() }));
0602: }
0603:
0604: public void logNoClasspath() {
0605: if ((this .tagBits & Logger.XML) != 0) {
0606: this .parameters.put(Logger.MESSAGE, this .main
0607: .bind("configure.noClasspath")); //$NON-NLS-1$
0608: this .printTag(Logger.ERROR_TAG, this .parameters, true,
0609: true);
0610: }
0611: this .printlnErr(this .main.bind("configure.noClasspath")); //$NON-NLS-1$
0612: }
0613:
0614: /**
0615: * @param exportedClassFilesCounter
0616: */
0617: public void logNumberOfClassFilesGenerated(
0618: int exportedClassFilesCounter) {
0619: if ((this .tagBits & Logger.XML) != 0) {
0620: this .parameters.put(Logger.VALUE, new Integer(
0621: exportedClassFilesCounter));
0622: this .printTag(Logger.NUMBER_OF_CLASSFILES,
0623: this .parameters, true, true);
0624: }
0625: if (exportedClassFilesCounter == 1) {
0626: this .printlnOut(this .main
0627: .bind("compile.oneClassFileGenerated")); //$NON-NLS-1$
0628: } else {
0629: this .printlnOut(this .main.bind(
0630: "compile.severalClassFilesGenerated", //$NON-NLS-1$
0631: String.valueOf(exportedClassFilesCounter)));
0632: }
0633: }
0634:
0635: /**
0636: * @param options the given compiler options
0637: */
0638: public void logOptions(Map options) {
0639: if ((this .tagBits & Logger.XML) != 0) {
0640: this .printTag(Logger.OPTIONS, null, true, false);
0641: final Set entriesSet = options.entrySet();
0642: Object[] entries = entriesSet.toArray();
0643: Arrays.sort(entries, new Comparator() {
0644: public int compare(Object o1, Object o2) {
0645: Map.Entry entry1 = (Map.Entry) o1;
0646: Map.Entry entry2 = (Map.Entry) o2;
0647: return ((String) entry1.getKey())
0648: .compareTo((String) entry2.getKey());
0649: }
0650: });
0651: for (int i = 0, max = entries.length; i < max; i++) {
0652: Map.Entry entry = (Map.Entry) entries[i];
0653: String key = (String) entry.getKey();
0654: this .parameters.put(Logger.KEY, key);
0655: this .parameters.put(Logger.VALUE, entry.getValue());
0656: this .printTag(Logger.OPTION, this .parameters, true,
0657: true);
0658: }
0659: this .endTag(Logger.OPTIONS);
0660: }
0661: }
0662:
0663: private void logProblem(CategorizedProblem problem,
0664: int localErrorCount, int globalErrorCount,
0665: char[] unitSource) {
0666: if ((this .tagBits & Logger.EMACS) != 0) {
0667: String result = (new String(problem
0668: .getOriginatingFileName())
0669: + ":" //$NON-NLS-1$
0670: + problem.getSourceLineNumber()
0671: + ": " //$NON-NLS-1$
0672: + (problem.isError() ? this .main
0673: .bind("output.emacs.error") : this .main.bind("output.emacs.warning")) //$NON-NLS-1$ //$NON-NLS-2$
0674: + ": " //$NON-NLS-1$
0675: + problem.getMessage());
0676: this .printlnErr(result);
0677: final String errorReportSource = errorReportSource(
0678: problem, unitSource, this .tagBits);
0679: if (errorReportSource.length() != 0)
0680: this .printlnErr(errorReportSource);
0681: } else {
0682: if (localErrorCount == 0) {
0683: this .printlnErr("----------"); //$NON-NLS-1$
0684: }
0685: this .printErr(problem.isError() ? this .main.bind(
0686: "requestor.error", //$NON-NLS-1$
0687: Integer.toString(globalErrorCount), new String(
0688: problem.getOriginatingFileName()))
0689: : this .main.bind(
0690: "requestor.warning", //$NON-NLS-1$
0691: Integer.toString(globalErrorCount),
0692: new String(problem
0693: .getOriginatingFileName())));
0694: try {
0695: final String errorReportSource = errorReportSource(
0696: problem, unitSource, 0);
0697: this .printlnErr(errorReportSource);
0698: this .printlnErr(problem.getMessage());
0699: } catch (Exception e) {
0700: this
0701: .printlnErr(this .main
0702: .bind(
0703: "requestor.notRetrieveErrorMessage", problem.toString())); //$NON-NLS-1$
0704: }
0705: this .printlnErr("----------"); //$NON-NLS-1$
0706: }
0707: }
0708:
0709: public int logProblems(CategorizedProblem[] problems,
0710: char[] unitSource, Main currentMain) {
0711: final int count = problems.length;
0712: int localErrorCount = 0;
0713: int localProblemCount = 0;
0714: if (count != 0) {
0715: int errors = 0;
0716: int warnings = 0;
0717: int tasks = 0;
0718: for (int i = 0; i < count; i++) {
0719: CategorizedProblem problem = problems[i];
0720: if (problem != null) {
0721: currentMain.globalProblemsCount++;
0722: this .logProblem(problem, localProblemCount,
0723: currentMain.globalProblemsCount,
0724: unitSource);
0725: localProblemCount++;
0726: if (problem.isError()) {
0727: localErrorCount++;
0728: errors++;
0729: currentMain.globalErrorsCount++;
0730: } else if (problem.getID() == IProblem.Task) {
0731: currentMain.globalTasksCount++;
0732: tasks++;
0733: } else {
0734: currentMain.globalWarningsCount++;
0735: warnings++;
0736: }
0737: }
0738: }
0739: if ((this .tagBits & Logger.XML) != 0) {
0740: if ((errors + warnings) != 0) {
0741: this .startLoggingProblems(errors, warnings);
0742: for (int i = 0; i < count; i++) {
0743: CategorizedProblem problem = problems[i];
0744: if (problem != null) {
0745: if (problem.getID() != IProblem.Task) {
0746: this .logXmlProblem(problem,
0747: unitSource);
0748: }
0749: }
0750: }
0751: this .endLoggingProblems();
0752: }
0753: if (tasks != 0) {
0754: this .startLoggingTasks(tasks);
0755: for (int i = 0; i < count; i++) {
0756: CategorizedProblem problem = problems[i];
0757: if (problem != null) {
0758: if (problem.getID() == IProblem.Task) {
0759: this
0760: .logXmlTask(problem,
0761: unitSource);
0762: }
0763: }
0764: }
0765: this .endLoggingTasks();
0766: }
0767: }
0768: }
0769: return localErrorCount;
0770: }
0771:
0772: /**
0773: * @param globalProblemsCount
0774: * @param globalErrorsCount
0775: * @param globalWarningsCount
0776: */
0777: public void logProblemsSummary(int globalProblemsCount,
0778: int globalErrorsCount, int globalWarningsCount,
0779: int globalTasksCount) {
0780: if ((this .tagBits & Logger.XML) != 0) {
0781: // generate xml
0782: this .parameters.put(Logger.NUMBER_OF_PROBLEMS,
0783: new Integer(globalProblemsCount));
0784: this .parameters.put(Logger.NUMBER_OF_ERRORS,
0785: new Integer(globalErrorsCount));
0786: this .parameters.put(Logger.NUMBER_OF_WARNINGS,
0787: new Integer(globalWarningsCount));
0788: this .parameters.put(Logger.NUMBER_OF_TASKS,
0789: new Integer(globalTasksCount));
0790: this .printTag(Logger.PROBLEM_SUMMARY, this .parameters,
0791: true, true);
0792: }
0793: if (globalProblemsCount == 1) {
0794: String message = null;
0795: if (globalErrorsCount == 1) {
0796: message = this .main.bind("compile.oneError"); //$NON-NLS-1$
0797: } else {
0798: message = this .main.bind("compile.oneWarning"); //$NON-NLS-1$
0799: }
0800: this .printErr(this .main.bind(
0801: "compile.oneProblem", message)); //$NON-NLS-1$
0802: } else {
0803: String errorMessage = null;
0804: String warningMessage = null;
0805: if (globalErrorsCount > 0) {
0806: if (globalErrorsCount == 1) {
0807: errorMessage = this .main
0808: .bind("compile.oneError"); //$NON-NLS-1$
0809: } else {
0810: errorMessage = this .main
0811: .bind(
0812: "compile.severalErrors", String.valueOf(globalErrorsCount)); //$NON-NLS-1$
0813: }
0814: }
0815: int warningsNumber = globalWarningsCount
0816: + globalTasksCount;
0817: if (warningsNumber > 0) {
0818: if (warningsNumber == 1) {
0819: warningMessage = this .main
0820: .bind("compile.oneWarning"); //$NON-NLS-1$
0821: } else {
0822: warningMessage = this .main
0823: .bind(
0824: "compile.severalWarnings", String.valueOf(warningsNumber)); //$NON-NLS-1$
0825: }
0826: }
0827: if (errorMessage == null || warningMessage == null) {
0828: if (errorMessage == null) {
0829: this
0830: .printErr(this .main
0831: .bind(
0832: "compile.severalProblemsErrorsOrWarnings", //$NON-NLS-1$
0833: String
0834: .valueOf(globalProblemsCount),
0835: warningMessage));
0836: } else {
0837: this
0838: .printErr(this .main
0839: .bind(
0840: "compile.severalProblemsErrorsOrWarnings", //$NON-NLS-1$
0841: String
0842: .valueOf(globalProblemsCount),
0843: errorMessage));
0844: }
0845: } else {
0846: this
0847: .printErr(this .main
0848: .bind(
0849: "compile.severalProblemsErrorsAndWarnings", //$NON-NLS-1$
0850: new String[] {
0851: String
0852: .valueOf(globalProblemsCount),
0853: errorMessage,
0854: warningMessage }));
0855: }
0856: }
0857: if ((this .tagBits & Logger.EMACS) != 0) {
0858: this .printlnErr();
0859: }
0860: }
0861:
0862: /**
0863: *
0864: */
0865: public void logProgress() {
0866: this .printOut('.');
0867: }
0868:
0869: /**
0870: * @param i
0871: * the current repetition number
0872: * @param repetitions
0873: * the given number of repetitions
0874: */
0875: public void logRepetition(int i, int repetitions) {
0876: this
0877: .printlnOut(this .main.bind("compile.repetition", //$NON-NLS-1$
0878: String.valueOf(i + 1), String
0879: .valueOf(repetitions)));
0880: }
0881:
0882: /**
0883: * @param time
0884: * @param lineCount
0885: */
0886: public void logTiming(long time, long lineCount) {
0887: if ((this .tagBits & Logger.XML) != 0) {
0888: this .parameters.put(Logger.VALUE, new Long(time));
0889: this .printTag(Logger.TIME, this .parameters, true, true);
0890: this .parameters.put(Logger.VALUE, new Long(lineCount));
0891: this .printTag(Logger.NUMBER_OF_LINES, this .parameters,
0892: true, true);
0893: }
0894: if (lineCount != 0) {
0895: this
0896: .printlnOut(this .main
0897: .bind(
0898: "compile.instantTime", //$NON-NLS-1$
0899: new String[] {
0900: String
0901: .valueOf(lineCount),
0902: String.valueOf(time),
0903: String
0904: .valueOf(((int) (lineCount * 10000.0 / time)) / 10.0) }));
0905: } else {
0906: this .printlnOut(this .main.bind(
0907: "compile.totalTime", String.valueOf(time))); //$NON-NLS-1$
0908: }
0909: }
0910:
0911: /**
0912: * Print the usage of the compiler
0913: * @param usage
0914: */
0915: public void logUsage(String usage) {
0916: this .printlnOut(usage);
0917: }
0918:
0919: /**
0920: * Print the version of the compiler in the log and/or the out field
0921: */
0922: public void logVersion(final boolean printToOut) {
0923: if (this .log != null && (this .tagBits & Logger.XML) == 0) {
0924: final String version = this .main.bind("misc.version", //$NON-NLS-1$
0925: new String[] { this .main.bind("compiler.name"), //$NON-NLS-1$
0926: this .main.bind("compiler.version"), //$NON-NLS-1$
0927: this .main.bind("compiler.copyright") //$NON-NLS-1$
0928: });
0929: this .log.println("# " + version); //$NON-NLS-1$
0930: if (printToOut) {
0931: this .out.println(version);
0932: this .out.flush();
0933: }
0934: } else if (printToOut) {
0935: final String version = this .main.bind("misc.version", //$NON-NLS-1$
0936: new String[] { this .main.bind("compiler.name"), //$NON-NLS-1$
0937: this .main.bind("compiler.version"), //$NON-NLS-1$
0938: this .main.bind("compiler.copyright") //$NON-NLS-1$
0939: });
0940: this .out.println(version);
0941: this .out.flush();
0942: }
0943: }
0944:
0945: /**
0946: * Print the usage of wrong JDK
0947: */
0948: public void logWrongJDK() {
0949: if ((this .tagBits & Logger.XML) != 0) {
0950: this .parameters.put(Logger.MESSAGE, this .main
0951: .bind("configure.requiresJDK1.2orAbove")); //$NON-NLS-1$
0952: this
0953: .printTag(Logger.ERROR, this .parameters, true,
0954: true);
0955: }
0956: this .printlnErr(this .main
0957: .bind("configure.requiresJDK1.2orAbove")); //$NON-NLS-1$
0958: }
0959:
0960: /**
0961: * @param problem
0962: * the given problem to log
0963: * @param unitSource
0964: * the given unit source
0965: */
0966: private void logXmlProblem(CategorizedProblem problem,
0967: char[] unitSource) {
0968: final int sourceStart = problem.getSourceStart();
0969: final int sourceEnd = problem.getSourceEnd();
0970: final int id = problem.getID();
0971: this .parameters.put(Logger.ID, getFieldName(id)); // ID as field name
0972: this .parameters.put(Logger.PROBLEM_ID, new Integer(id)); // ID as numeric value
0973: boolean isError = problem.isError();
0974: int severity = isError ? ProblemSeverities.Error
0975: : ProblemSeverities.Warning;
0976: this .parameters.put(Logger.PROBLEM_SEVERITY,
0977: isError ? Logger.ERROR : Logger.WARNING);
0978: this .parameters.put(Logger.PROBLEM_LINE, new Integer(
0979: problem.getSourceLineNumber()));
0980: this .parameters.put(Logger.PROBLEM_SOURCE_START,
0981: new Integer(sourceStart));
0982: this .parameters.put(Logger.PROBLEM_SOURCE_END, new Integer(
0983: sourceEnd));
0984: String problemOptionKey = getProblemOptionKey(id);
0985: if (problemOptionKey != null) {
0986: this .parameters.put(Logger.PROBLEM_OPTION_KEY,
0987: problemOptionKey);
0988: }
0989: int categoryID = ProblemReporter.getProblemCategory(
0990: severity, id);
0991: this .parameters.put(Logger.PROBLEM_CATEGORY_ID,
0992: new Integer(categoryID));
0993: this .printTag(Logger.PROBLEM_TAG, this .parameters, true,
0994: false);
0995: this .parameters.put(Logger.VALUE, problem.getMessage());
0996: this .printTag(Logger.PROBLEM_MESSAGE, this .parameters,
0997: true, true);
0998: extractContext(problem, unitSource);
0999: String[] arguments = problem.getArguments();
1000: final int length = arguments.length;
1001: if (length != 0) {
1002: this .printTag(Logger.PROBLEM_ARGUMENTS, null, true,
1003: false);
1004: for (int i = 0; i < length; i++) {
1005: this .parameters.put(Logger.PROBLEM_ARGUMENT_VALUE,
1006: arguments[i]);
1007: this .printTag(Logger.PROBLEM_ARGUMENT,
1008: this .parameters, true, true);
1009: }
1010: this .endTag(Logger.PROBLEM_ARGUMENTS);
1011: }
1012: this .endTag(Logger.PROBLEM_TAG);
1013: }
1014:
1015: /**
1016: * @param problem
1017: * the given problem to log
1018: * @param unitSource
1019: * the given unit source
1020: */
1021: private void logXmlTask(CategorizedProblem problem,
1022: char[] unitSource) {
1023: this .parameters.put(Logger.PROBLEM_LINE, new Integer(
1024: problem.getSourceLineNumber()));
1025: this .parameters.put(Logger.PROBLEM_SOURCE_START,
1026: new Integer(problem.getSourceStart()));
1027: this .parameters.put(Logger.PROBLEM_SOURCE_END, new Integer(
1028: problem.getSourceEnd()));
1029: String problemOptionKey = getProblemOptionKey(problem
1030: .getID());
1031: if (problemOptionKey != null) {
1032: this .parameters.put(Logger.PROBLEM_OPTION_KEY,
1033: problemOptionKey);
1034: }
1035: this .printTag(Logger.TASK, this .parameters, true, false);
1036: this .parameters.put(Logger.VALUE, problem.getMessage());
1037: this .printTag(Logger.PROBLEM_MESSAGE, this .parameters,
1038: true, true);
1039: extractContext(problem, unitSource);
1040: this .endTag(Logger.TASK);
1041: }
1042:
1043: private void printErr(String s) {
1044: this .err.print(s);
1045: if ((this .tagBits & Logger.XML) == 0 && this .log != null) {
1046: this .log.print(s);
1047: }
1048: }
1049:
1050: private void printlnErr() {
1051: this .err.println();
1052: if ((this .tagBits & Logger.XML) == 0 && this .log != null) {
1053: this .log.println();
1054: }
1055: }
1056:
1057: private void printlnErr(String s) {
1058: this .err.println(s);
1059: if ((this .tagBits & Logger.XML) == 0 && this .log != null) {
1060: this .log.println(s);
1061: }
1062: }
1063:
1064: private void printlnOut(String s) {
1065: this .out.println(s);
1066: if ((this .tagBits & Logger.XML) == 0 && this .log != null) {
1067: this .log.println(s);
1068: }
1069: }
1070:
1071: /**
1072: *
1073: */
1074: public void printNewLine() {
1075: this .out.println();
1076: }
1077:
1078: private void printOut(char c) {
1079: this .out.print(c);
1080: }
1081:
1082: public void printStats() {
1083: final boolean isTimed = this .main.timing;
1084: if ((this .tagBits & Logger.XML) != 0) {
1085: this .printTag(Logger.STATS, null, true, false);
1086: }
1087: if (isTimed) {
1088: long time = System.currentTimeMillis()
1089: - this .main.startTime;
1090: this .logTiming(time, this .main.lineCount);
1091: if (this .main.times != null) {
1092: this .main.times[this .main.timesCounter++] = time;
1093: }
1094: }
1095: if (this .main.globalProblemsCount > 0) {
1096: this .logProblemsSummary(this .main.globalProblemsCount,
1097: this .main.globalErrorsCount,
1098: this .main.globalWarningsCount,
1099: main.globalTasksCount);
1100: }
1101: if (this .main.exportedClassFilesCounter != 0
1102: && (this .main.showProgress || isTimed || this .main.verbose)) {
1103: this
1104: .logNumberOfClassFilesGenerated(this .main.exportedClassFilesCounter);
1105: }
1106: if ((this .tagBits & Logger.XML) != 0) {
1107: this .endTag(Logger.STATS);
1108: }
1109: }
1110:
1111: private void printTag(String name, HashMap params,
1112: boolean insertNewLine, boolean closeTag) {
1113: ((GenericXMLWriter) this .log).printTag(name, parameters,
1114: true, insertNewLine, closeTag);
1115: this .parameters.clear();
1116: }
1117:
1118: public void setEmacs() {
1119: this .tagBits |= Logger.EMACS;
1120: }
1121:
1122: public void setLog(String logFileName)
1123: throws InvalidInputException {
1124: final Date date = new Date();
1125: final DateFormat dateFormat = DateFormat
1126: .getDateTimeInstance(DateFormat.SHORT,
1127: DateFormat.LONG, Locale.getDefault());
1128: try {
1129: int index = logFileName.lastIndexOf('.');
1130: if (index != -1) {
1131: if (logFileName.substring(index).toLowerCase()
1132: .equals(".xml")) { //$NON-NLS-1$
1133: this .log = new GenericXMLWriter(
1134: new FileOutputStream(logFileName, false),
1135: Util.LINE_SEPARATOR, true);
1136: this .tagBits |= Logger.XML;
1137: // insert time stamp as comment
1138: try {
1139: this .log
1140: .println("<!-- " + new String(dateFormat.format(date).getBytes(), "UTF-8") + " -->");//$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
1141: } catch (UnsupportedEncodingException e) {
1142: e.printStackTrace();
1143: }
1144: this .log.println(Logger.XML_DTD_DECLARATION);
1145: this .parameters.put(Logger.COMPILER_NAME,
1146: this .main.bind("compiler.name")); //$NON-NLS-1$
1147: this .parameters.put(Logger.COMPILER_VERSION,
1148: this .main.bind("compiler.version")); //$NON-NLS-1$
1149: this .parameters.put(Logger.COMPILER_COPYRIGHT,
1150: this .main.bind("compiler.copyright")); //$NON-NLS-1$
1151: this .printTag(Logger.COMPILER, this .parameters,
1152: true, false);
1153: } else {
1154: this .log = new PrintWriter(
1155: new FileOutputStream(logFileName, false));
1156: this .log
1157: .println("# " + dateFormat.format(date));//$NON-NLS-1$
1158: }
1159: } else {
1160: this .log = new PrintWriter(new FileOutputStream(
1161: logFileName, false));
1162: this .log.println("# " + dateFormat.format(date));//$NON-NLS-1$
1163: }
1164: } catch (FileNotFoundException e) {
1165: throw new InvalidInputException(this .main.bind(
1166: "configure.cannotOpenLog", logFileName)); //$NON-NLS-1$
1167: }
1168: }
1169:
1170: /**
1171: * Used to start logging problems.
1172: * Only use in xml mode.
1173: */
1174: private void startLoggingProblems(int errors, int warnings) {
1175: this .parameters.put(Logger.NUMBER_OF_PROBLEMS, new Integer(
1176: errors + warnings));
1177: this .parameters.put(Logger.NUMBER_OF_ERRORS, new Integer(
1178: errors));
1179: this .parameters.put(Logger.NUMBER_OF_WARNINGS, new Integer(
1180: warnings));
1181: this
1182: .printTag(Logger.PROBLEMS, this .parameters, true,
1183: false);
1184: }
1185:
1186: private void startLoggingExtraProblems(int count) {
1187: this .parameters.put(Logger.NUMBER_OF_PROBLEMS, new Integer(
1188: count));
1189: this .printTag(Logger.EXTRA_PROBLEMS, this .parameters, true,
1190: false);
1191: }
1192:
1193: public void startLoggingSource(
1194: CompilationResult compilationResult) {
1195: if ((this .tagBits & Logger.XML) != 0) {
1196: ICompilationUnit compilationUnit = compilationResult.compilationUnit;
1197: if (compilationUnit != null) {
1198: char[] fileName = compilationUnit.getFileName();
1199: File f = new File(new String(fileName));
1200: if (fileName != null) {
1201: this .parameters.put(Logger.PATH, f
1202: .getAbsolutePath());
1203: }
1204: char[][] packageName = compilationResult.packageName;
1205: if (packageName != null) {
1206: this .parameters.put(Logger.PACKAGE, new String(
1207: CharOperation.concatWith(packageName,
1208: File.separatorChar)));
1209: }
1210: CompilationUnit unit = (CompilationUnit) compilationUnit;
1211: String destinationPath = unit.destinationPath;
1212: if (destinationPath == null) {
1213: destinationPath = this .main.destinationPath;
1214: }
1215: if (destinationPath != null
1216: && destinationPath != NONE) {
1217: if (File.separatorChar == '/') {
1218: this .parameters.put(Logger.OUTPUT,
1219: destinationPath);
1220: } else {
1221: this .parameters.put(Logger.OUTPUT,
1222: destinationPath.replace('/',
1223: File.separatorChar));
1224: }
1225: }
1226: }
1227: this .printTag(Logger.SOURCE, this .parameters, true,
1228: false);
1229: }
1230: }
1231:
1232: public void startLoggingSources() {
1233: if ((this .tagBits & Logger.XML) != 0) {
1234: this .printTag(Logger.SOURCES, null, true, false);
1235: }
1236: }
1237:
1238: public void startLoggingTasks(int tasks) {
1239: if ((this .tagBits & Logger.XML) != 0) {
1240: this .parameters.put(Logger.NUMBER_OF_TASKS,
1241: new Integer(tasks));
1242: this .printTag(Logger.TASKS, this .parameters, true,
1243: false);
1244: }
1245: }
1246:
1247: public void loggingExtraProblems(Main currentMain) {
1248: ArrayList problems = currentMain.extraProblems;
1249: final int count = problems.size();
1250: int localErrorCount = 0;
1251: int localProblemCount = 0;
1252: if (count != 0) {
1253: int errors = 0;
1254: int warnings = 0;
1255: for (int i = 0; i < count; i++) {
1256: CategorizedProblem problem = (CategorizedProblem) problems
1257: .get(i);
1258: if (problem != null) {
1259: currentMain.globalProblemsCount++;
1260: this .logExtraProblem(problem,
1261: localProblemCount,
1262: currentMain.globalProblemsCount);
1263: localProblemCount++;
1264: if (problem.isError()) {
1265: localErrorCount++;
1266: errors++;
1267: currentMain.globalErrorsCount++;
1268: } else if (problem.isWarning()) {
1269: currentMain.globalWarningsCount++;
1270: warnings++;
1271: }
1272: }
1273: }
1274: if ((this .tagBits & Logger.XML) != 0) {
1275: if ((errors + warnings) != 0) {
1276: this .startLoggingExtraProblems(count);
1277: for (int i = 0; i < count; i++) {
1278: CategorizedProblem problem = (CategorizedProblem) problems
1279: .get(i);
1280: if (problem != null) {
1281: if (problem.getID() != IProblem.Task) {
1282: this
1283: .logXmlExtraProblem(
1284: problem,
1285: localProblemCount,
1286: currentMain.globalProblemsCount);
1287: }
1288: }
1289: }
1290: this .endLoggingExtraProblems();
1291: }
1292: }
1293: }
1294: }
1295:
1296: private void logXmlExtraProblem(CategorizedProblem problem,
1297: int globalErrorCount, int localErrorCount) {
1298: final int sourceStart = problem.getSourceStart();
1299: final int sourceEnd = problem.getSourceEnd();
1300: boolean isError = problem.isError();
1301: this .parameters.put(Logger.PROBLEM_SEVERITY,
1302: isError ? Logger.ERROR : Logger.WARNING);
1303: this .parameters.put(Logger.PROBLEM_LINE, new Integer(
1304: problem.getSourceLineNumber()));
1305: this .parameters.put(Logger.PROBLEM_SOURCE_START,
1306: new Integer(sourceStart));
1307: this .parameters.put(Logger.PROBLEM_SOURCE_END, new Integer(
1308: sourceEnd));
1309: this .printTag(Logger.EXTRA_PROBLEM_TAG, this .parameters,
1310: true, false);
1311: this .parameters.put(Logger.VALUE, problem.getMessage());
1312: this .printTag(Logger.PROBLEM_MESSAGE, this .parameters,
1313: true, true);
1314: extractContext(problem, null);
1315: this .endTag(Logger.EXTRA_PROBLEM_TAG);
1316: }
1317:
1318: private void logExtraProblem(CategorizedProblem problem,
1319: int localErrorCount, int globalErrorCount) {
1320: char[] originatingFileName = problem
1321: .getOriginatingFileName();
1322: String fileName = originatingFileName == null ? this .main
1323: .bind("requestor.noFileNameSpecified")//$NON-NLS-1$
1324: : new String(originatingFileName);
1325: if ((this .tagBits & Logger.EMACS) != 0) {
1326: String result = fileName
1327: + ":" //$NON-NLS-1$
1328: + problem.getSourceLineNumber()
1329: + ": " //$NON-NLS-1$
1330: + (problem.isError() ? this .main
1331: .bind("output.emacs.error") : this .main.bind("output.emacs.warning")) //$NON-NLS-1$ //$NON-NLS-2$
1332: + ": " //$NON-NLS-1$
1333: + problem.getMessage();
1334: this .printlnErr(result);
1335: final String errorReportSource = errorReportSource(
1336: problem, null, this .tagBits);
1337: this .printlnErr(errorReportSource);
1338: } else {
1339: if (localErrorCount == 0) {
1340: this .printlnErr("----------"); //$NON-NLS-1$
1341: }
1342: this .printErr(problem.isError() ? this .main.bind(
1343: "requestor.error", //$NON-NLS-1$
1344: Integer.toString(globalErrorCount), new String(
1345: fileName)) : this .main.bind(
1346: "requestor.warning", //$NON-NLS-1$
1347: Integer.toString(globalErrorCount), new String(
1348: fileName)));
1349: final String errorReportSource = errorReportSource(
1350: problem, null, 0);
1351: this .printlnErr(errorReportSource);
1352: this .printlnErr(problem.getMessage());
1353: this .printlnErr("----------"); //$NON-NLS-1$
1354: }
1355: }
1356:
1357: private String errorReportSource(CategorizedProblem problem,
1358: char[] unitSource, int bits) {
1359: //extra from the source the innacurate token
1360: //and "highlight" it using some underneath ^^^^^
1361: //put some context around too.
1362:
1363: //this code assumes that the font used in the console is fixed size
1364:
1365: //sanity .....
1366: int startPosition = problem.getSourceStart();
1367: int endPosition = problem.getSourceEnd();
1368: if (unitSource == null) {
1369: if (problem.getOriginatingFileName() != null) {
1370: try {
1371: unitSource = Util.getFileCharContent(new File(
1372: new String(problem
1373: .getOriginatingFileName())),
1374: null);
1375: } catch (IOException e) {
1376: // ignore;
1377: }
1378: }
1379: }
1380: int length = unitSource == null ? 0 : unitSource.length;
1381: if ((startPosition > endPosition)
1382: || ((startPosition < 0) && (endPosition < 0))
1383: || length == 0)
1384: return Messages.problem_noSourceInformation;
1385:
1386: StringBuffer errorBuffer = new StringBuffer();
1387: if ((bits & Main.Logger.EMACS) == 0) {
1388: errorBuffer
1389: .append(' ')
1390: .append(
1391: Messages
1392: .bind(
1393: Messages.problem_atLine,
1394: String
1395: .valueOf(problem
1396: .getSourceLineNumber())));
1397: errorBuffer.append(Util.LINE_SEPARATOR);
1398: }
1399: errorBuffer.append('\t');
1400:
1401: char c;
1402: final char SPACE = '\u0020';
1403: final char MARK = '^';
1404: final char TAB = '\t';
1405: //the next code tries to underline the token.....
1406: //it assumes (for a good display) that token source does not
1407: //contain any \r \n. This is false on statements !
1408: //(the code still works but the display is not optimal !)
1409:
1410: // expand to line limits
1411: int begin;
1412: int end;
1413: for (begin = startPosition >= length ? length - 1
1414: : startPosition; begin > 0; begin--) {
1415: if ((c = unitSource[begin - 1]) == '\n' || c == '\r')
1416: break;
1417: }
1418: for (end = endPosition >= length ? length - 1 : endPosition; end + 1 < length; end++) {
1419: if ((c = unitSource[end + 1]) == '\r' || c == '\n')
1420: break;
1421: }
1422:
1423: // trim left and right spaces/tabs
1424: while ((c = unitSource[begin]) == ' ' || c == '\t')
1425: begin++;
1426: //while ((c = unitSource[end]) == ' ' || c == '\t') end--; TODO (philippe) should also trim right, but all tests are to be updated
1427:
1428: // copy source
1429: errorBuffer.append(unitSource, begin, end - begin + 1);
1430: errorBuffer.append(Util.LINE_SEPARATOR).append("\t"); //$NON-NLS-1$
1431:
1432: // compute underline
1433: for (int i = begin; i < startPosition; i++) {
1434: errorBuffer
1435: .append((unitSource[i] == TAB) ? TAB : SPACE);
1436: }
1437: for (int i = startPosition; i <= (endPosition >= length ? length - 1
1438: : endPosition); i++) {
1439: errorBuffer.append(MARK);
1440: }
1441: return errorBuffer.toString();
1442: }
1443: }
1444:
1445: public final static String bundleName = "org.eclipse.jdt.internal.compiler.batch.messages"; //$NON-NLS-1$
1446:
1447: // two uses: recognize 'none' in options; code the singleton none
1448: // for the '-d none' option (wherever it may be found)
1449: public static final int DEFAULT_SIZE_CLASSPATH = 4;
1450: public static final String NONE = "none"; //$NON-NLS-1$
1451:
1452: /*
1453: * Internal IDE API
1454: */
1455: public static boolean compile(String commandLine) {
1456:
1457: return compile(commandLine, new PrintWriter(System.out),
1458: new PrintWriter(System.err));
1459: }
1460:
1461: /*
1462: * Internal IDE API for test harness purpose
1463: */
1464: public static boolean compile(String commandLine,
1465: PrintWriter outWriter, PrintWriter errWriter) {
1466:
1467: return new Main(outWriter, errWriter, false)
1468: .compile(tokenize(commandLine));
1469: }
1470:
1471: public static File[][] getLibrariesFiles(File[] files) {
1472: FilenameFilter filter = new FilenameFilter() {
1473: public boolean accept(File dir, String name) {
1474: String lowerCaseName = name.toLowerCase();
1475: if (lowerCaseName
1476: .endsWith(SuffixConstants.SUFFIX_STRING_jar)
1477: || lowerCaseName
1478: .endsWith(SuffixConstants.SUFFIX_STRING_zip)) {
1479: return true;
1480: }
1481: return false;
1482: }
1483: };
1484: final int filesLength = files.length;
1485: File[][] result = new File[filesLength][];
1486: for (int i = 0; i < filesLength; i++) {
1487: File currentFile = files[i];
1488: if (currentFile.exists() && currentFile.isDirectory()) {
1489: result[i] = currentFile.listFiles(filter);
1490: }
1491: }
1492: return result;
1493: }
1494:
1495: public static void main(String[] argv) {
1496: new Main(new PrintWriter(System.out), new PrintWriter(
1497: System.err), true).compile(argv);
1498: }
1499:
1500: public static String[] tokenize(String commandLine) {
1501:
1502: int count = 0;
1503: String[] arguments = new String[10];
1504: StringTokenizer tokenizer = new StringTokenizer(commandLine,
1505: " \"", true); //$NON-NLS-1$
1506: String token = Util.EMPTY_STRING;
1507: boolean insideQuotes = false;
1508: boolean startNewToken = true;
1509:
1510: // take care to quotes on the command line
1511: // 'xxx "aaa bbb";ccc yyy' ---> {"xxx", "aaa bbb;ccc", "yyy" }
1512: // 'xxx "aaa bbb;ccc" yyy' ---> {"xxx", "aaa bbb;ccc", "yyy" }
1513: // 'xxx "aaa bbb";"ccc" yyy' ---> {"xxx", "aaa bbb;ccc", "yyy" }
1514: // 'xxx/"aaa bbb";"ccc" yyy' ---> {"xxx/aaa bbb;ccc", "yyy" }
1515: while (tokenizer.hasMoreTokens()) {
1516: token = tokenizer.nextToken();
1517:
1518: if (token.equals(" ")) { //$NON-NLS-1$
1519: if (insideQuotes) {
1520: arguments[count - 1] += token;
1521: startNewToken = false;
1522: } else {
1523: startNewToken = true;
1524: }
1525: } else if (token.equals("\"")) { //$NON-NLS-1$
1526: if (!insideQuotes && startNewToken) {
1527: if (count == arguments.length)
1528: System.arraycopy(arguments, 0,
1529: (arguments = new String[count * 2]), 0,
1530: count);
1531: arguments[count++] = Util.EMPTY_STRING;
1532: }
1533: insideQuotes = !insideQuotes;
1534: startNewToken = false;
1535: } else {
1536: if (insideQuotes) {
1537: arguments[count - 1] += token;
1538: } else {
1539: if (token.length() > 0 && !startNewToken) {
1540: arguments[count - 1] += token;
1541: } else {
1542: if (count == arguments.length)
1543: System
1544: .arraycopy(
1545: arguments,
1546: 0,
1547: (arguments = new String[count * 2]),
1548: 0, count);
1549: String trimmedToken = token.trim();
1550: if (trimmedToken.length() != 0) {
1551: arguments[count++] = trimmedToken;
1552: }
1553: }
1554: }
1555: startNewToken = false;
1556: }
1557: }
1558: System.arraycopy(arguments, 0, arguments = new String[count],
1559: 0, count);
1560: return arguments;
1561: }
1562:
1563: public Compiler batchCompiler;
1564: /* Bundle containing messages */
1565: public ResourceBundle bundle;
1566: protected FileSystem.Classpath[] checkedClasspaths;
1567: public Locale compilerLocale;
1568: public CompilerOptions compilerOptions; // read-only
1569: public String destinationPath;
1570: public String[] destinationPaths;
1571: // destination path for compilation units that get no more specific
1572: // one (through directory arguments or various classpath options);
1573: // coding is:
1574: // == null: unspecified, write class files close to their respective
1575: // source files;
1576: // == Main.NONE: absorbent element, do not output class files;
1577: // else: use as the path of the directory into which class files must
1578: // be written.
1579: private boolean didSpecifySource;
1580: private boolean didSpecifyTarget;
1581:
1582: public String[] encodings;
1583:
1584: public int exportedClassFilesCounter;
1585: public String[] filenames;
1586:
1587: public String[] classNames;
1588:
1589: // overrides of destinationPath on a directory argument basis
1590: public int globalErrorsCount;
1591: public int globalProblemsCount;
1592: public int globalTasksCount;
1593: public int globalWarningsCount;
1594: private File javaHomeCache;
1595: private boolean javaHomeChecked = false;
1596: public long lineCount;
1597: public String log;
1598: public Logger logger;
1599: public int maxProblems;
1600: public boolean noWarn = false;
1601: public Map options;
1602: protected PrintWriter out;
1603: public boolean proceed = true;
1604: public boolean proceedOnError = false;
1605: public boolean produceRefInfo = false;
1606: public int repetitions;
1607:
1608: public boolean showProgress = false;
1609: public long startTime;
1610:
1611: public boolean systemExitWhenFinished = true;
1612:
1613: public long[] times;
1614:
1615: public int timesCounter;
1616:
1617: public boolean timing = false;
1618:
1619: public boolean verbose = false;
1620:
1621: private String[] expandedCommandLine;
1622:
1623: private PrintWriter err;
1624:
1625: ArrayList extraProblems;
1626:
1627: public Main(PrintWriter outWriter, PrintWriter errWriter,
1628: boolean systemExitWhenFinished) {
1629: this (outWriter, errWriter, systemExitWhenFinished, null);
1630: }
1631:
1632: public Main(PrintWriter outWriter, PrintWriter errWriter,
1633: boolean systemExitWhenFinished, Map customDefaultOptions) {
1634: this .initialize(outWriter, errWriter, systemExitWhenFinished,
1635: customDefaultOptions);
1636: this .relocalize();
1637: }
1638:
1639: public void addExtraProblems(CategorizedProblem problem) {
1640: if (this .extraProblems == null) {
1641: this .extraProblems = new ArrayList();
1642: }
1643: this .extraProblems.add(problem);
1644: }
1645:
1646: protected void addNewEntry(ArrayList paths,
1647: String currentClasspathName, ArrayList currentRuleSpecs,
1648: String customEncoding, String destPath,
1649: boolean isSourceOnly, boolean rejectDestinationPathOnJars)
1650: throws InvalidInputException {
1651:
1652: int rulesSpecsSize = currentRuleSpecs.size();
1653: AccessRuleSet accessRuleSet = null;
1654: if (rulesSpecsSize != 0) {
1655: AccessRule[] accessRules = new AccessRule[currentRuleSpecs
1656: .size()];
1657: boolean rulesOK = true;
1658: Iterator i = currentRuleSpecs.iterator();
1659: int j = 0;
1660: while (i.hasNext()) {
1661: String ruleSpec = (String) i.next();
1662: char key = ruleSpec.charAt(0);
1663: String pattern = ruleSpec.substring(1);
1664: if (pattern.length() > 0) {
1665: switch (key) {
1666: case '+':
1667: accessRules[j++] = new AccessRule(pattern
1668: .toCharArray(), 0);
1669: break;
1670: case '~':
1671: accessRules[j++] = new AccessRule(pattern
1672: .toCharArray(),
1673: IProblem.DiscouragedReference);
1674: break;
1675: case '-':
1676: accessRules[j++] = new AccessRule(pattern
1677: .toCharArray(),
1678: IProblem.ForbiddenReference);
1679: break;
1680: case '?':
1681: accessRules[j++] = new AccessRule(pattern
1682: .toCharArray(),
1683: IProblem.ForbiddenReference, true/*keep looking for accessible type*/);
1684: break;
1685: default:
1686: rulesOK = false;
1687: }
1688: } else {
1689: rulesOK = false;
1690: }
1691: }
1692: if (rulesOK) {
1693: String templates[] = new String[AccessRuleSet.MESSAGE_TEMPLATES_LENGTH];
1694: templates[0] = this .bind(
1695: "template.restrictedAccess.type", //$NON-NLS-1$
1696: new String[] { "{0}", currentClasspathName }); //$NON-NLS-1$
1697: templates[1] = this .bind(
1698: "template.restrictedAccess.constructor", //$NON-NLS-1$
1699: new String[] { "{0}", currentClasspathName }); //$NON-NLS-1$
1700: templates[2] = this .bind(
1701: "template.restrictedAccess.method", //$NON-NLS-1$
1702: new String[] {
1703: "{0}", "{1}", currentClasspathName }); //$NON-NLS-1$ //$NON-NLS-2$
1704: templates[3] = this .bind(
1705: "template.restrictedAccess.field", //$NON-NLS-1$
1706: new String[] {
1707: "{0}", "{1}", currentClasspathName }); //$NON-NLS-1$ //$NON-NLS-2$
1708: accessRuleSet = new AccessRuleSet(accessRules,
1709: templates);
1710: } else {
1711: if (currentClasspathName.length() != 0) {
1712: // we go on anyway
1713: this .logger
1714: .logIncorrectClasspath(currentClasspathName);
1715: }
1716: return;
1717: }
1718: }
1719: if (NONE.equals(destPath)) {
1720: destPath = NONE; // keep == comparison valid
1721: }
1722: if (rejectDestinationPathOnJars && destPath != null
1723: && (currentClasspathName.endsWith(".jar") || //$NON-NLS-1$
1724: currentClasspathName.endsWith(".zip"))) { //$NON-NLS-1$
1725: throw new InvalidInputException(this .bind(
1726: "configure.unexpectedDestinationPathEntryFile", //$NON-NLS-1$
1727: currentClasspathName));
1728: }
1729: FileSystem.Classpath currentClasspath = FileSystem
1730: .getClasspath(currentClasspathName, customEncoding,
1731: isSourceOnly, accessRuleSet, destPath);
1732: if (currentClasspath != null) {
1733: paths.add(currentClasspath);
1734: } else if (currentClasspathName.length() != 0) {
1735: // we go on anyway
1736: this .logger.logIncorrectClasspath(currentClasspathName);
1737: }
1738: }
1739:
1740: /*
1741: * Lookup the message with the given ID in this catalog
1742: */
1743: public String bind(String id) {
1744: return bind(id, (String[]) null);
1745: }
1746:
1747: /*
1748: * Lookup the message with the given ID in this catalog and bind its
1749: * substitution locations with the given string.
1750: */
1751: public String bind(String id, String binding) {
1752: return bind(id, new String[] { binding });
1753: }
1754:
1755: /*
1756: * Lookup the message with the given ID in this catalog and bind its
1757: * substitution locations with the given strings.
1758: */
1759: public String bind(String id, String binding1, String binding2) {
1760: return bind(id, new String[] { binding1, binding2 });
1761: }
1762:
1763: /*
1764: * Lookup the message with the given ID in this catalog and bind its
1765: * substitution locations with the given string values.
1766: */
1767: public String bind(String id, String[] arguments) {
1768: if (id == null)
1769: return "No message available"; //$NON-NLS-1$
1770: String message = null;
1771: try {
1772: message = this .bundle.getString(id);
1773: } catch (MissingResourceException e) {
1774: // If we got an exception looking for the message, fail gracefully by just returning
1775: // the id we were looking for. In most cases this is semi-informative so is not too bad.
1776: return "Missing message: " + id + " in: " + Main.bundleName; //$NON-NLS-2$ //$NON-NLS-1$
1777: }
1778: return MessageFormat.format(message, arguments);
1779: }
1780:
1781: /**
1782: * Return true if and only if the running VM supports the given minimal version.
1783: *
1784: * <p>This only checks the major version, since the minor version is always 0 (at least for the useful cases).</p>
1785: * <p>The given minimalSupportedVersion is one of the constants:</p>
1786: * <ul>
1787: * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_1</code></li>
1788: * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_2</code></li>
1789: * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_3</code></li>
1790: * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_4</code></li>
1791: * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_5</code></li>
1792: * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_6</code></li>
1793: * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_7</code></li>
1794: * </ul>
1795: * @param minimalSupportedVersion the given minimal version
1796: * @return true if and only if the running VM supports the given minimal version, false otherwise
1797: */
1798: private boolean checkVMVersion(long minimalSupportedVersion) {
1799: // the format of this property is supposed to be xx.x where x are digits.
1800: String classFileVersion = System
1801: .getProperty("java.class.version"); //$NON-NLS-1$
1802: if (classFileVersion == null) {
1803: // by default we don't support a class file version we cannot recognize
1804: return false;
1805: }
1806: int index = classFileVersion.indexOf('.');
1807: if (index == -1) {
1808: // by default we don't support a class file version we cannot recognize
1809: return false;
1810: }
1811: int majorVersion;
1812: try {
1813: majorVersion = Integer.parseInt(classFileVersion.substring(
1814: 0, index));
1815: } catch (NumberFormatException e) {
1816: // by default we don't support a class file version we cannot recognize
1817: return false;
1818: }
1819: switch (majorVersion) {
1820: case 45: // 1.0 and 1.1
1821: return ClassFileConstants.JDK1_1 >= minimalSupportedVersion;
1822: case 46: // 1.2
1823: return ClassFileConstants.JDK1_2 >= minimalSupportedVersion;
1824: case 47: // 1.3
1825: return ClassFileConstants.JDK1_3 >= minimalSupportedVersion;
1826: case 48: // 1.4
1827: return ClassFileConstants.JDK1_4 >= minimalSupportedVersion;
1828: case 49: // 1.5
1829: return ClassFileConstants.JDK1_5 >= minimalSupportedVersion;
1830: case 50: // 1.6
1831: return ClassFileConstants.JDK1_6 >= minimalSupportedVersion;
1832: case 51: // 1.7
1833: return ClassFileConstants.JDK1_7 >= minimalSupportedVersion;
1834: }
1835: // unknown version
1836: return false;
1837: }
1838:
1839: /*
1840: * Low-level API performing the actual compilation
1841: */
1842: public boolean compile(String[] argv) {
1843:
1844: // decode command line arguments
1845: try {
1846: configure(argv);
1847: if (this .proceed) {
1848: // if (this.verbose) {
1849: // System.out.println(new CompilerOptions(this.options));
1850: // }
1851: if (this .showProgress)
1852: this .logger.compiling();
1853: for (int i = 0; i < this .repetitions; i++) {
1854: this .globalProblemsCount = 0;
1855: this .globalErrorsCount = 0;
1856: this .globalWarningsCount = 0;
1857: this .globalTasksCount = 0;
1858: this .lineCount = 0;
1859: this .exportedClassFilesCounter = 0;
1860:
1861: if (this .repetitions > 1) {
1862: this .logger.flush();
1863: this .logger.logRepetition(i, this .repetitions);
1864: }
1865: // request compilation
1866: performCompilation();
1867: }
1868: if (this .times != null) {
1869: this .logger.logAverage(this .times, this .lineCount);
1870: }
1871: if (this .showProgress)
1872: this .logger.printNewLine();
1873: }
1874: if (this .systemExitWhenFinished) {
1875: this .logger.flush();
1876: this .logger.close();
1877: System.exit(this .globalErrorsCount > 0 ? -1 : 0);
1878: }
1879: } catch (InvalidInputException e) {
1880: this .logger.logException(e);
1881: if (this .systemExitWhenFinished) {
1882: this .logger.flush();
1883: this .logger.close();
1884: System.exit(-1);
1885: }
1886: return false;
1887: } catch (RuntimeException e) { // internal compiler failure
1888: this .logger.logException(e);
1889: if (this .systemExitWhenFinished) {
1890: this .logger.flush();
1891: this .logger.close();
1892: System.exit(-1);
1893: }
1894: return false;
1895: } finally {
1896: this .logger.flush();
1897: this .logger.close();
1898: }
1899: if (this .globalErrorsCount == 0)
1900: return true;
1901: return false;
1902: }
1903:
1904: /*
1905: * External API
1906: * Handle a single warning token.
1907: */
1908: protected void handleWarningToken(String token, boolean isEnabling,
1909: boolean useEnableJavadoc) throws InvalidInputException {
1910: if (token.equals("constructorName")) { //$NON-NLS-1$
1911: this .options
1912: .put(
1913: CompilerOptions.OPTION_ReportMethodWithConstructorName,
1914: isEnabling ? CompilerOptions.WARNING
1915: : CompilerOptions.IGNORE);
1916: } else if (token.equals("pkgDefaultMethod") || token.equals("packageDefaultMethod")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
1917: this .options
1918: .put(
1919: CompilerOptions.OPTION_ReportOverridingPackageDefaultMethod,
1920: isEnabling ? CompilerOptions.WARNING
1921: : CompilerOptions.IGNORE);
1922: } else if (token.equals("maskedCatchBlock") || token.equals("maskedCatchBlocks")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
1923: this .options.put(
1924: CompilerOptions.OPTION_ReportHiddenCatchBlock,
1925: isEnabling ? CompilerOptions.WARNING
1926: : CompilerOptions.IGNORE);
1927: } else if (token.equals("deprecation")) { //$NON-NLS-1$
1928: this .options.put(CompilerOptions.OPTION_ReportDeprecation,
1929: isEnabling ? CompilerOptions.WARNING
1930: : CompilerOptions.IGNORE);
1931: this .options
1932: .put(
1933: CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode,
1934: CompilerOptions.DISABLED);
1935: this .options
1936: .put(
1937: CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod,
1938: CompilerOptions.DISABLED);
1939: } else if (token.equals("allDeprecation")) { //$NON-NLS-1$
1940: this .options.put(CompilerOptions.OPTION_ReportDeprecation,
1941: isEnabling ? CompilerOptions.WARNING
1942: : CompilerOptions.IGNORE);
1943: this .options
1944: .put(
1945: CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode,
1946: isEnabling ? CompilerOptions.ENABLED
1947: : CompilerOptions.DISABLED);
1948: this .options
1949: .put(
1950: CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod,
1951: isEnabling ? CompilerOptions.ENABLED
1952: : CompilerOptions.DISABLED);
1953: } else if (token.equals("unusedLocal") || token.equals("unusedLocals")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
1954: this .options.put(CompilerOptions.OPTION_ReportUnusedLocal,
1955: isEnabling ? CompilerOptions.WARNING
1956: : CompilerOptions.IGNORE);
1957: } else if (token.equals("unusedArgument") || token.equals("unusedArguments")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
1958: this .options.put(
1959: CompilerOptions.OPTION_ReportUnusedParameter,
1960: isEnabling ? CompilerOptions.WARNING
1961: : CompilerOptions.IGNORE);
1962: } else if (token.equals("unusedImport") || token.equals("unusedImports")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
1963: this .options.put(CompilerOptions.OPTION_ReportUnusedImport,
1964: isEnabling ? CompilerOptions.WARNING
1965: : CompilerOptions.IGNORE);
1966: } else if (token.equals("unusedPrivate")) { //$NON-NLS-1$
1967: this .options.put(
1968: CompilerOptions.OPTION_ReportUnusedPrivateMember,
1969: isEnabling ? CompilerOptions.WARNING
1970: : CompilerOptions.IGNORE);
1971: } else if (token.equals("unusedLabel")) { //$NON-NLS-1$
1972: this .options.put(CompilerOptions.OPTION_ReportUnusedLabel,
1973: isEnabling ? CompilerOptions.WARNING
1974: : CompilerOptions.IGNORE);
1975: } else if (token.equals("localHiding")) { //$NON-NLS-1$
1976: this .options.put(
1977: CompilerOptions.OPTION_ReportLocalVariableHiding,
1978: isEnabling ? CompilerOptions.WARNING
1979: : CompilerOptions.IGNORE);
1980: } else if (token.equals("fieldHiding")) { //$NON-NLS-1$
1981: this .options.put(CompilerOptions.OPTION_ReportFieldHiding,
1982: isEnabling ? CompilerOptions.WARNING
1983: : CompilerOptions.IGNORE);
1984: } else if (token.equals("specialParamHiding")) { //$NON-NLS-1$
1985: this .options
1986: .put(
1987: CompilerOptions.OPTION_ReportSpecialParameterHidingField,
1988: isEnabling ? CompilerOptions.ENABLED
1989: : CompilerOptions.DISABLED);
1990: } else if (token.equals("conditionAssign")) { //$NON-NLS-1$
1991: this .options
1992: .put(
1993: CompilerOptions.OPTION_ReportPossibleAccidentalBooleanAssignment,
1994: isEnabling ? CompilerOptions.WARNING
1995: : CompilerOptions.IGNORE);
1996: } else if (token.equals("syntheticAccess") //$NON-NLS-1$
1997: || token.equals("synthetic-access")) { //$NON-NLS-1$
1998: this .options
1999: .put(
2000: CompilerOptions.OPTION_ReportSyntheticAccessEmulation,
2001: isEnabling ? CompilerOptions.WARNING
2002: : CompilerOptions.IGNORE);
2003: } else if (token.equals("nls")) { //$NON-NLS-1$
2004: this .options
2005: .put(
2006: CompilerOptions.OPTION_ReportNonExternalizedStringLiteral,
2007: isEnabling ? CompilerOptions.WARNING
2008: : CompilerOptions.IGNORE);
2009: } else if (token.equals("staticReceiver")) { //$NON-NLS-1$
2010: this .options
2011: .put(
2012: CompilerOptions.OPTION_ReportNonStaticAccessToStatic,
2013: isEnabling ? CompilerOptions.WARNING
2014: : CompilerOptions.IGNORE);
2015: } else if (token.equals("indirectStatic")) { //$NON-NLS-1$
2016: this .options.put(
2017: CompilerOptions.OPTION_ReportIndirectStaticAccess,
2018: isEnabling ? CompilerOptions.WARNING
2019: : CompilerOptions.IGNORE);
2020: } else if (token.equals("noEffectAssign")) { //$NON-NLS-1$
2021: this .options.put(
2022: CompilerOptions.OPTION_ReportNoEffectAssignment,
2023: isEnabling ? CompilerOptions.WARNING
2024: : CompilerOptions.IGNORE);
2025: } else if (token.equals("intfNonInherited") || token.equals("interfaceNonInherited")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
2026: this .options
2027: .put(
2028: CompilerOptions.OPTION_ReportIncompatibleNonInheritedInterfaceMethod,
2029: isEnabling ? CompilerOptions.WARNING
2030: : CompilerOptions.IGNORE);
2031: } else if (token.equals("charConcat") || token.equals("noImplicitStringConversion")/*backward compatible*/) {//$NON-NLS-1$ //$NON-NLS-2$
2032: this .options
2033: .put(
2034: CompilerOptions.OPTION_ReportNoImplicitStringConversion,
2035: isEnabling ? CompilerOptions.WARNING
2036: : CompilerOptions.IGNORE);
2037: } else if (token.equals("semicolon")) {//$NON-NLS-1$
2038: this .options.put(
2039: CompilerOptions.OPTION_ReportEmptyStatement,
2040: isEnabling ? CompilerOptions.WARNING
2041: : CompilerOptions.IGNORE);
2042: } else if (token.equals("serial")) {//$NON-NLS-1$
2043: this .options.put(
2044: CompilerOptions.OPTION_ReportMissingSerialVersion,
2045: isEnabling ? CompilerOptions.WARNING
2046: : CompilerOptions.IGNORE);
2047: } else if (token.equals("emptyBlock")) {//$NON-NLS-1$
2048: this .options
2049: .put(
2050: CompilerOptions.OPTION_ReportUndocumentedEmptyBlock,
2051: isEnabling ? CompilerOptions.WARNING
2052: : CompilerOptions.IGNORE);
2053: } else if (token.equals("uselessTypeCheck")) {//$NON-NLS-1$
2054: this .options.put(
2055: CompilerOptions.OPTION_ReportUnnecessaryTypeCheck,
2056: isEnabling ? CompilerOptions.WARNING
2057: : CompilerOptions.IGNORE);
2058: } else if (token.equals("unchecked") || token.equals("unsafe")) {//$NON-NLS-1$ //$NON-NLS-2$
2059: this .options
2060: .put(
2061: CompilerOptions.OPTION_ReportUncheckedTypeOperation,
2062: isEnabling ? CompilerOptions.WARNING
2063: : CompilerOptions.IGNORE);
2064: } else if (token.equals("raw")) {//$NON-NLS-1$
2065: this .options.put(
2066: CompilerOptions.OPTION_ReportRawTypeReference,
2067: isEnabling ? CompilerOptions.WARNING
2068: : CompilerOptions.IGNORE);
2069: } else if (token.equals("finalBound")) {//$NON-NLS-1$
2070: this .options.put(
2071: CompilerOptions.OPTION_ReportFinalParameterBound,
2072: isEnabling ? CompilerOptions.WARNING
2073: : CompilerOptions.IGNORE);
2074: } else if (token.equals("suppress")) {//$NON-NLS-1$
2075: this .options.put(CompilerOptions.OPTION_SuppressWarnings,
2076: isEnabling ? CompilerOptions.ENABLED
2077: : CompilerOptions.DISABLED);
2078: } else if (token.equals("warningToken")) {//$NON-NLS-1$
2079: this .options.put(
2080: CompilerOptions.OPTION_ReportUnhandledWarningToken,
2081: isEnabling ? CompilerOptions.WARNING
2082: : CompilerOptions.IGNORE);
2083: } else if (token.equals("unnecessaryElse")) {//$NON-NLS-1$
2084: this .options.put(
2085: CompilerOptions.OPTION_ReportUnnecessaryElse,
2086: isEnabling ? CompilerOptions.WARNING
2087: : CompilerOptions.IGNORE);
2088: } else if (token.equals("javadoc")) {//$NON-NLS-1$
2089: if (!useEnableJavadoc) {
2090: this .options.put(
2091: CompilerOptions.OPTION_DocCommentSupport,
2092: isEnabling ? CompilerOptions.ENABLED
2093: : CompilerOptions.DISABLED);
2094: }
2095: // if disabling then it's not necessary to set other javadoc options
2096: if (isEnabling) {
2097: this .options.put(
2098: CompilerOptions.OPTION_ReportInvalidJavadoc,
2099: CompilerOptions.WARNING);
2100: this .options
2101: .put(
2102: CompilerOptions.OPTION_ReportInvalidJavadocTags,
2103: CompilerOptions.ENABLED);
2104: this .options
2105: .put(
2106: CompilerOptions.OPTION_ReportInvalidJavadocTagsDeprecatedRef,
2107: CompilerOptions.DISABLED);
2108: this .options
2109: .put(
2110: CompilerOptions.OPTION_ReportInvalidJavadocTagsNotVisibleRef,
2111: CompilerOptions.DISABLED);
2112: this .options
2113: .put(
2114: CompilerOptions.OPTION_ReportInvalidJavadocTagsVisibility,
2115: CompilerOptions.PRIVATE);
2116: this .options
2117: .put(
2118: CompilerOptions.OPTION_ReportMissingJavadocTags,
2119: CompilerOptions.WARNING);
2120: this .options
2121: .put(
2122: CompilerOptions.OPTION_ReportMissingJavadocTagsVisibility,
2123: CompilerOptions.PRIVATE);
2124: }
2125: } else if (token.equals("allJavadoc")) { //$NON-NLS-1$
2126: if (!useEnableJavadoc) {
2127: this .options.put(
2128: CompilerOptions.OPTION_DocCommentSupport,
2129: isEnabling ? CompilerOptions.ENABLED
2130: : CompilerOptions.DISABLED);
2131: }
2132: // if disabling then it's not necessary to set other javadoc options
2133: if (isEnabling) {
2134: this .options.put(
2135: CompilerOptions.OPTION_ReportInvalidJavadoc,
2136: CompilerOptions.WARNING);
2137: this .options
2138: .put(
2139: CompilerOptions.OPTION_ReportInvalidJavadocTags,
2140: CompilerOptions.ENABLED);
2141: this .options
2142: .put(
2143: CompilerOptions.OPTION_ReportInvalidJavadocTagsVisibility,
2144: CompilerOptions.PRIVATE);
2145: this .options
2146: .put(
2147: CompilerOptions.OPTION_ReportMissingJavadocTags,
2148: CompilerOptions.WARNING);
2149: this .options
2150: .put(
2151: CompilerOptions.OPTION_ReportMissingJavadocTagsVisibility,
2152: CompilerOptions.PRIVATE);
2153: this .options
2154: .put(
2155: CompilerOptions.OPTION_ReportMissingJavadocComments,
2156: CompilerOptions.WARNING);
2157: }
2158: } else if (token.startsWith("tasks")) { //$NON-NLS-1$
2159: String taskTags = Util.EMPTY_STRING;
2160: int start = token.indexOf('(');
2161: int end = token.indexOf(')');
2162: if (start >= 0 && end >= 0 && start < end) {
2163: taskTags = token.substring(start + 1, end).trim();
2164: taskTags = taskTags.replace('|', ',');
2165: }
2166: if (taskTags.length() == 0) {
2167: throw new InvalidInputException(this .bind(
2168: "configure.invalidTaskTag", token)); //$NON-NLS-1$
2169: }
2170: this .options.put(CompilerOptions.OPTION_TaskTags,
2171: isEnabling ? taskTags : Util.EMPTY_STRING);
2172: } else if (token.equals("assertIdentifier")) { //$NON-NLS-1$
2173: this .options.put(
2174: CompilerOptions.OPTION_ReportAssertIdentifier,
2175: isEnabling ? CompilerOptions.WARNING
2176: : CompilerOptions.IGNORE);
2177: } else if (token.equals("enumIdentifier")) { //$NON-NLS-1$
2178: this .options.put(
2179: CompilerOptions.OPTION_ReportEnumIdentifier,
2180: isEnabling ? CompilerOptions.WARNING
2181: : CompilerOptions.IGNORE);
2182: } else if (token.equals("finally")) { //$NON-NLS-1$
2183: this .options
2184: .put(
2185: CompilerOptions.OPTION_ReportFinallyBlockNotCompletingNormally,
2186: isEnabling ? CompilerOptions.WARNING
2187: : CompilerOptions.IGNORE);
2188: } else if (token.equals("unusedThrown")) { //$NON-NLS-1$
2189: this .options
2190: .put(
2191: CompilerOptions.OPTION_ReportUnusedDeclaredThrownException,
2192: isEnabling ? CompilerOptions.WARNING
2193: : CompilerOptions.IGNORE);
2194: } else if (token.equals("unqualifiedField") //$NON-NLS-1$
2195: || token.equals("unqualified-field-access")) { //$NON-NLS-1$
2196: this .options
2197: .put(
2198: CompilerOptions.OPTION_ReportUnqualifiedFieldAccess,
2199: isEnabling ? CompilerOptions.WARNING
2200: : CompilerOptions.IGNORE);
2201: } else if (token.equals("typeHiding")) { //$NON-NLS-1$
2202: this .options.put(
2203: CompilerOptions.OPTION_ReportTypeParameterHiding,
2204: isEnabling ? CompilerOptions.WARNING
2205: : CompilerOptions.IGNORE);
2206: } else if (token.equals("varargsCast")) { //$NON-NLS-1$
2207: this .options
2208: .put(
2209: CompilerOptions.OPTION_ReportVarargsArgumentNeedCast,
2210: isEnabling ? CompilerOptions.WARNING
2211: : CompilerOptions.IGNORE);
2212: } else if (token.equals("null")) { //$NON-NLS-1$
2213: if (isEnabling) {
2214: this .options.put(
2215: CompilerOptions.OPTION_ReportNullReference,
2216: CompilerOptions.WARNING);
2217: this .options
2218: .put(
2219: CompilerOptions.OPTION_ReportPotentialNullReference,
2220: CompilerOptions.WARNING);
2221: this .options
2222: .put(
2223: CompilerOptions.OPTION_ReportRedundantNullCheck,
2224: CompilerOptions.WARNING);
2225: } else {
2226: this .options.put(
2227: CompilerOptions.OPTION_ReportNullReference,
2228: CompilerOptions.IGNORE);
2229: this .options
2230: .put(
2231: CompilerOptions.OPTION_ReportPotentialNullReference,
2232: CompilerOptions.IGNORE);
2233: this .options
2234: .put(
2235: CompilerOptions.OPTION_ReportRedundantNullCheck,
2236: CompilerOptions.IGNORE);
2237: }
2238: } else if (token.equals("nullDereference")) { //$NON-NLS-1$
2239: if (isEnabling) {
2240: this .options.put(
2241: CompilerOptions.OPTION_ReportNullReference,
2242: CompilerOptions.WARNING);
2243: } else {
2244: this .options.put(
2245: CompilerOptions.OPTION_ReportNullReference,
2246: CompilerOptions.IGNORE);
2247: this .options
2248: .put(
2249: CompilerOptions.OPTION_ReportPotentialNullReference,
2250: CompilerOptions.IGNORE);
2251: this .options
2252: .put(
2253: CompilerOptions.OPTION_ReportRedundantNullCheck,
2254: CompilerOptions.IGNORE);
2255: }
2256: } else if (token.equals("boxing")) { //$NON-NLS-1$
2257: this .options.put(CompilerOptions.OPTION_ReportAutoboxing,
2258: isEnabling ? CompilerOptions.WARNING
2259: : CompilerOptions.IGNORE);
2260: } else if (token.equals("over-ann")) { //$NON-NLS-1$
2261: this .options
2262: .put(
2263: CompilerOptions.OPTION_ReportMissingOverrideAnnotation,
2264: isEnabling ? CompilerOptions.WARNING
2265: : CompilerOptions.IGNORE);
2266: } else if (token.equals("dep-ann")) { //$NON-NLS-1$
2267: this .options
2268: .put(
2269: CompilerOptions.OPTION_ReportMissingDeprecatedAnnotation,
2270: isEnabling ? CompilerOptions.WARNING
2271: : CompilerOptions.IGNORE);
2272: } else if (token.equals("intfAnnotation")) { //$NON-NLS-1$
2273: this .options
2274: .put(
2275: CompilerOptions.OPTION_ReportAnnotationSuperInterface,
2276: isEnabling ? CompilerOptions.WARNING
2277: : CompilerOptions.IGNORE);
2278: } else if (token.equals("enumSwitch") //$NON-NLS-1$
2279: || token.equals("incomplete-switch")) { //$NON-NLS-1$
2280: this .options.put(
2281: CompilerOptions.OPTION_ReportIncompleteEnumSwitch,
2282: isEnabling ? CompilerOptions.WARNING
2283: : CompilerOptions.IGNORE);
2284: } else if (token.equals("hiding")) { //$NON-NLS-1$
2285: this .options.put(
2286: CompilerOptions.OPTION_ReportHiddenCatchBlock,
2287: isEnabling ? CompilerOptions.WARNING
2288: : CompilerOptions.IGNORE);
2289: this .options.put(
2290: CompilerOptions.OPTION_ReportLocalVariableHiding,
2291: isEnabling ? CompilerOptions.WARNING
2292: : CompilerOptions.IGNORE);
2293: this .options.put(CompilerOptions.OPTION_ReportFieldHiding,
2294: isEnabling ? CompilerOptions.WARNING
2295: : CompilerOptions.IGNORE);
2296: this .options.put(
2297: CompilerOptions.OPTION_ReportTypeParameterHiding,
2298: isEnabling ? CompilerOptions.WARNING
2299: : CompilerOptions.IGNORE);
2300: } else if (token.equals("static-access")) { //$NON-NLS-1$
2301: this .options
2302: .put(
2303: CompilerOptions.OPTION_ReportNonStaticAccessToStatic,
2304: isEnabling ? CompilerOptions.WARNING
2305: : CompilerOptions.IGNORE);
2306: this .options.put(
2307: CompilerOptions.OPTION_ReportIndirectStaticAccess,
2308: isEnabling ? CompilerOptions.WARNING
2309: : CompilerOptions.IGNORE);
2310: } else if (token.equals("unused")) { //$NON-NLS-1$
2311: this .options.put(CompilerOptions.OPTION_ReportUnusedLocal,
2312: isEnabling ? CompilerOptions.WARNING
2313: : CompilerOptions.IGNORE);
2314: this .options.put(
2315: CompilerOptions.OPTION_ReportUnusedParameter,
2316: isEnabling ? CompilerOptions.WARNING
2317: : CompilerOptions.IGNORE);
2318: this .options.put(CompilerOptions.OPTION_ReportUnusedImport,
2319: isEnabling ? CompilerOptions.WARNING
2320: : CompilerOptions.IGNORE);
2321: this .options.put(
2322: CompilerOptions.OPTION_ReportUnusedPrivateMember,
2323: isEnabling ? CompilerOptions.WARNING
2324: : CompilerOptions.IGNORE);
2325: this .options
2326: .put(
2327: CompilerOptions.OPTION_ReportUnusedDeclaredThrownException,
2328: isEnabling ? CompilerOptions.WARNING
2329: : CompilerOptions.IGNORE);
2330: this .options.put(CompilerOptions.OPTION_ReportUnusedLabel,
2331: isEnabling ? CompilerOptions.WARNING
2332: : CompilerOptions.IGNORE);
2333: } else if (token.equals("paramAssign")) { //$NON-NLS-1$
2334: this .options.put(
2335: CompilerOptions.OPTION_ReportParameterAssignment,
2336: isEnabling ? CompilerOptions.WARNING
2337: : CompilerOptions.IGNORE);
2338: } else if (token.equals("discouraged")) { //$NON-NLS-1$
2339: this .options.put(
2340: CompilerOptions.OPTION_ReportDiscouragedReference,
2341: isEnabling ? CompilerOptions.WARNING
2342: : CompilerOptions.IGNORE);
2343: } else if (token.equals("forbidden")) { //$NON-NLS-1$
2344: this .options.put(
2345: CompilerOptions.OPTION_ReportForbiddenReference,
2346: isEnabling ? CompilerOptions.WARNING
2347: : CompilerOptions.IGNORE);
2348: } else if (token.equals("fallthrough")) { //$NON-NLS-1$
2349: this .options.put(
2350: CompilerOptions.OPTION_ReportFallthroughCase,
2351: isEnabling ? CompilerOptions.WARNING
2352: : CompilerOptions.IGNORE);
2353: } else if (token.equals("super")) { //$NON-NLS-1$
2354: this .options
2355: .put(
2356: CompilerOptions.OPTION_ReportOverridingMethodWithoutSuperInvocation,
2357: isEnabling ? CompilerOptions.WARNING
2358: : CompilerOptions.IGNORE);
2359: } else {
2360: throw new InvalidInputException(this .bind(
2361: "configure.invalidWarning", token)); //$NON-NLS-1$
2362: }
2363: }
2364:
2365: /*
2366: * External API
2367: */
2368: protected ArrayList handleBootclasspath(ArrayList bootclasspaths,
2369: String customEncoding) throws InvalidInputException {
2370: final int bootclasspathsSize = bootclasspaths == null ? 0
2371: : bootclasspaths.size();
2372: if (bootclasspathsSize != 0) {
2373: String[] paths = new String[bootclasspathsSize];
2374: bootclasspaths.toArray(paths);
2375: bootclasspaths.clear();
2376: for (int i = 0; i < bootclasspathsSize; i++) {
2377: processPathEntries(DEFAULT_SIZE_CLASSPATH,
2378: bootclasspaths, paths[i], customEncoding,
2379: false, true);
2380: }
2381: } else {
2382: bootclasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
2383: /* no bootclasspath specified
2384: * we can try to retrieve the default librairies of the VM used to run
2385: * the batch compiler
2386: */
2387: String javaversion = System.getProperty("java.version");//$NON-NLS-1$
2388: if (javaversion != null
2389: && javaversion.equalsIgnoreCase("1.1.8")) { //$NON-NLS-1$
2390: this .logger.logWrongJDK();
2391: this .proceed = false;
2392: return null;
2393: }
2394:
2395: /*
2396: * Handle >= JDK 1.2.2 settings: retrieve the bootclasspath
2397: */
2398: // check bootclasspath properties for Sun, JRockit and Harmony VMs
2399: String bootclasspathProperty = System
2400: .getProperty("sun.boot.class.path"); //$NON-NLS-1$
2401: if ((bootclasspathProperty == null)
2402: || (bootclasspathProperty.length() == 0)) {
2403: // IBM J9 VMs
2404: bootclasspathProperty = System
2405: .getProperty("vm.boot.class.path"); //$NON-NLS-1$
2406: if ((bootclasspathProperty == null)
2407: || (bootclasspathProperty.length() == 0)) {
2408: // Harmony using IBM VME
2409: bootclasspathProperty = System
2410: .getProperty("org.apache.harmony.boot.class.path"); //$NON-NLS-1$
2411: }
2412: }
2413: if ((bootclasspathProperty != null)
2414: && (bootclasspathProperty.length() != 0)) {
2415: StringTokenizer tokenizer = new StringTokenizer(
2416: bootclasspathProperty, File.pathSeparator);
2417: String token;
2418: while (tokenizer.hasMoreTokens()) {
2419: token = tokenizer.nextToken();
2420: FileSystem.Classpath currentClasspath = FileSystem
2421: .getClasspath(token, customEncoding, null);
2422: if (currentClasspath != null) {
2423: bootclasspaths.add(currentClasspath);
2424: }
2425: }
2426: } else {
2427: // try to get all jars inside the lib folder of the java home
2428: final File javaHome = getJavaHome();
2429: if (javaHome != null) {
2430: File[] directoriesToCheck = null;
2431: if (System.getProperty("os.name").startsWith("Mac")) {//$NON-NLS-1$//$NON-NLS-2$
2432: directoriesToCheck = new File[] { new File(
2433: javaHome, "../Classes"), //$NON-NLS-1$
2434: };
2435: } else {
2436: // fall back to try to retrieve them out of the lib directory
2437: directoriesToCheck = new File[] { new File(
2438: javaHome, "lib") //$NON-NLS-1$
2439: };
2440: }
2441: File[][] systemLibrariesJars = getLibrariesFiles(directoriesToCheck);
2442: if (systemLibrariesJars != null) {
2443: for (int i = 0, max = systemLibrariesJars.length; i < max; i++) {
2444: File[] current = systemLibrariesJars[i];
2445: if (current != null) {
2446: for (int j = 0, max2 = current.length; j < max2; j++) {
2447: FileSystem.Classpath classpath = FileSystem
2448: .getClasspath(current[j]
2449: .getAbsolutePath(),
2450: null, false, null,
2451: null);
2452: if (classpath != null) {
2453: bootclasspaths.add(classpath);
2454: }
2455: }
2456: }
2457: }
2458: }
2459: }
2460: }
2461: }
2462: return bootclasspaths;
2463: }
2464:
2465: /*
2466: * External API
2467: */
2468: protected ArrayList handleClasspath(ArrayList classpaths,
2469: String customEncoding) throws InvalidInputException {
2470: final int classpathsSize = classpaths == null ? 0 : classpaths
2471: .size();
2472: if (classpathsSize != 0) {
2473: String[] paths = new String[classpathsSize];
2474: classpaths.toArray(paths);
2475: classpaths.clear();
2476: for (int i = 0; i < classpathsSize; i++) {
2477: processPathEntries(DEFAULT_SIZE_CLASSPATH, classpaths,
2478: paths[i], customEncoding, false, true);
2479: }
2480: } else {
2481: // no user classpath specified.
2482: classpaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
2483: String classProp = System.getProperty("java.class.path"); //$NON-NLS-1$
2484: if ((classProp == null) || (classProp.length() == 0)) {
2485: this .logger.logNoClasspath();
2486: final Classpath classpath = FileSystem
2487: .getClasspath(
2488: System.getProperty("user.dir"), customEncoding, null);//$NON-NLS-1$
2489: if (classpath != null) {
2490: classpaths.add(classpath);
2491: }
2492: } else {
2493: StringTokenizer tokenizer = new StringTokenizer(
2494: classProp, File.pathSeparator);
2495: String token;
2496: while (tokenizer.hasMoreTokens()) {
2497: token = tokenizer.nextToken();
2498: FileSystem.Classpath currentClasspath = FileSystem
2499: .getClasspath(token, customEncoding, null);
2500: if (currentClasspath != null) {
2501: classpaths.add(currentClasspath);
2502: } else if (token.length() != 0) {
2503: this .logger.logIncorrectClasspath(token);
2504: }
2505: }
2506: }
2507: }
2508: return classpaths;
2509: }
2510:
2511: /*
2512: * External API
2513: * Handle extdirs processing
2514: */
2515: protected ArrayList handleExtdirs(ArrayList extdirsClasspaths) {
2516: final File javaHome = getJavaHome();
2517:
2518: /*
2519: * Feed extDirClasspath according to:
2520: * - -extdirs first if present;
2521: * - else java.ext.dirs if defined;
2522: * - else default extensions directory for the platform.
2523: */
2524: if (extdirsClasspaths == null) {
2525: extdirsClasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
2526: String extdirsStr = System.getProperty("java.ext.dirs"); //$NON-NLS-1$
2527: if (extdirsStr == null) {
2528: extdirsClasspaths.add(javaHome.getAbsolutePath()
2529: + "/lib/ext"); //$NON-NLS-1$
2530: } else {
2531: StringTokenizer tokenizer = new StringTokenizer(
2532: extdirsStr, File.pathSeparator);
2533: while (tokenizer.hasMoreTokens())
2534: extdirsClasspaths.add(tokenizer.nextToken());
2535: }
2536: }
2537:
2538: /*
2539: * Feed extdirsClasspath with the entries found into the directories listed by
2540: * extdirsNames.
2541: */
2542: if (extdirsClasspaths.size() != 0) {
2543: File[] directoriesToCheck = new File[extdirsClasspaths
2544: .size()];
2545: for (int i = 0; i < directoriesToCheck.length; i++)
2546: directoriesToCheck[i] = new File(
2547: (String) extdirsClasspaths.get(i));
2548: extdirsClasspaths.clear();
2549: File[][] extdirsJars = getLibrariesFiles(directoriesToCheck);
2550: if (extdirsJars != null) {
2551: for (int i = 0, max = extdirsJars.length; i < max; i++) {
2552: File[] current = extdirsJars[i];
2553: if (current != null) {
2554: for (int j = 0, max2 = current.length; j < max2; j++) {
2555: FileSystem.Classpath classpath = FileSystem
2556: .getClasspath(current[j]
2557: .getAbsolutePath(), null,
2558: null);
2559: if (classpath != null) {
2560: extdirsClasspaths.add(classpath);
2561: }
2562: }
2563: } else if (directoriesToCheck[i].isFile()) {
2564: this .logger
2565: .logIncorrectExtDirsEntry(directoriesToCheck[i]
2566: .getAbsolutePath());
2567: }
2568: }
2569: }
2570: }
2571:
2572: return extdirsClasspaths;
2573: }
2574:
2575: /*
2576: * External API
2577: */
2578: protected ArrayList handleEndorseddirs(
2579: ArrayList endorsedDirClasspaths) {
2580: final File javaHome = getJavaHome();
2581: /*
2582: * Feed endorsedDirClasspath according to:
2583: * - -endorseddirs first if present;
2584: * - else java.endorsed.dirs if defined;
2585: * - else default extensions directory for the platform. (/lib/endorsed)
2586: */
2587: if (endorsedDirClasspaths == null) {
2588: endorsedDirClasspaths = new ArrayList(
2589: DEFAULT_SIZE_CLASSPATH);
2590: String endorsedDirsStr = System
2591: .getProperty("java.endorsed.dirs"); //$NON-NLS-1$
2592: if (endorsedDirsStr == null) {
2593: if (javaHome != null) {
2594: endorsedDirClasspaths.add(javaHome
2595: .getAbsolutePath()
2596: + "/lib/endorsed"); //$NON-NLS-1$
2597: }
2598: } else {
2599: StringTokenizer tokenizer = new StringTokenizer(
2600: endorsedDirsStr, File.pathSeparator);
2601: while (tokenizer.hasMoreTokens()) {
2602: endorsedDirClasspaths.add(tokenizer.nextToken());
2603: }
2604: }
2605: }
2606:
2607: /*
2608: * Feed extdirsClasspath with the entries found into the directories listed by
2609: * extdirsNames.
2610: */
2611: if (endorsedDirClasspaths.size() != 0) {
2612: File[] directoriesToCheck = new File[endorsedDirClasspaths
2613: .size()];
2614: for (int i = 0; i < directoriesToCheck.length; i++)
2615: directoriesToCheck[i] = new File(
2616: (String) endorsedDirClasspaths.get(i));
2617: endorsedDirClasspaths.clear();
2618: File[][] endorsedDirsJars = getLibrariesFiles(directoriesToCheck);
2619: if (endorsedDirsJars != null) {
2620: for (int i = 0, max = endorsedDirsJars.length; i < max; i++) {
2621: File[] current = endorsedDirsJars[i];
2622: if (current != null) {
2623: for (int j = 0, max2 = current.length; j < max2; j++) {
2624: FileSystem.Classpath classpath = FileSystem
2625: .getClasspath(current[j]
2626: .getAbsolutePath(), null,
2627: null);
2628: if (classpath != null) {
2629: endorsedDirClasspaths.add(classpath);
2630: }
2631: }
2632: } else if (directoriesToCheck[i].isFile()) {
2633: this .logger
2634: .logIncorrectEndorsedDirsEntry(directoriesToCheck[i]
2635: .getAbsolutePath());
2636: }
2637: }
2638: }
2639: }
2640: return endorsedDirClasspaths;
2641: }
2642:
2643: /*
2644: Decode the command line arguments
2645: */
2646: public void configure(String[] argv) throws InvalidInputException {
2647:
2648: if ((argv == null) || (argv.length == 0)) {
2649: printUsage();
2650: return;
2651: }
2652:
2653: final int INSIDE_CLASSPATH_start = 1;
2654: final int INSIDE_DESTINATION_PATH = 3;
2655: final int INSIDE_TARGET = 4;
2656: final int INSIDE_LOG = 5;
2657: final int INSIDE_REPETITION = 6;
2658: final int INSIDE_SOURCE = 7;
2659: final int INSIDE_DEFAULT_ENCODING = 8;
2660: final int INSIDE_BOOTCLASSPATH_start = 9;
2661: final int INSIDE_MAX_PROBLEMS = 11;
2662: final int INSIDE_EXT_DIRS = 12;
2663: final int INSIDE_SOURCE_PATH_start = 13;
2664: final int INSIDE_ENDORSED_DIRS = 15;
2665: final int INSIDE_SOURCE_DIRECTORY_DESTINATION_PATH = 16;
2666: final int INSIDE_PROCESSOR_PATH_start = 17;
2667: final int INSIDE_PROCESSOR_start = 18;
2668: final int INSIDE_S_start = 19;
2669: final int INSIDE_CLASS_NAMES = 20;
2670:
2671: final int DEFAULT = 0;
2672: ArrayList bootclasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
2673: String sourcepathClasspathArg = null;
2674: ArrayList sourcepathClasspaths = new ArrayList(
2675: DEFAULT_SIZE_CLASSPATH);
2676: ArrayList classpaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
2677: ArrayList extdirsClasspaths = null;
2678: ArrayList endorsedDirClasspaths = null;
2679:
2680: int index = -1;
2681: int filesCount = 0;
2682: int classCount = 0;
2683: int argCount = argv.length;
2684: int mode = DEFAULT;
2685: this .repetitions = 0;
2686: boolean printUsageRequired = false;
2687: String usageSection = null;
2688: boolean printVersionRequired = false;
2689:
2690: boolean didSpecifyDefaultEncoding = false;
2691: boolean didSpecifyDeprecation = false;
2692: boolean didSpecifyWarnings = false;
2693: boolean useEnableJavadoc = false;
2694: boolean didSpecifyCompliance = false;
2695: boolean didSpecifyDisabledAnnotationProcessing = false;
2696:
2697: String customEncoding = null;
2698: String customDestinationPath = null;
2699: String currentSourceDirectory = null;
2700: String currentArg = Util.EMPTY_STRING;
2701:
2702: // expand the command line if necessary
2703: boolean needExpansion = false;
2704: loop: for (int i = 0; i < argCount; i++) {
2705: if (argv[i].startsWith("@")) { //$NON-NLS-1$
2706: needExpansion = true;
2707: break loop;
2708: }
2709: }
2710:
2711: String[] newCommandLineArgs = null;
2712: if (needExpansion) {
2713: newCommandLineArgs = new String[argCount];
2714: index = 0;
2715: for (int i = 0; i < argCount; i++) {
2716: String[] newArgs = null;
2717: String arg = argv[i].trim();
2718: if (arg.startsWith("@")) { //$NON-NLS-1$
2719: try {
2720: LineNumberReader reader = new LineNumberReader(
2721: new StringReader(new String(
2722: Util.getFileCharContent(
2723: new File(arg
2724: .substring(1)),
2725: null))));
2726: StringBuffer buffer = new StringBuffer();
2727: String line;
2728: while ((line = reader.readLine()) != null) {
2729: line = line.trim();
2730: if (!line.startsWith("#")) { //$NON-NLS-1$
2731: buffer.append(line).append(" "); //$NON-NLS-1$
2732: }
2733: }
2734: newArgs = tokenize(buffer.toString());
2735: } catch (IOException e) {
2736: throw new InvalidInputException(
2737: this
2738: .bind(
2739: "configure.invalidexpansionargumentname", arg)); //$NON-NLS-1$
2740: }
2741: }
2742: if (newArgs != null) {
2743: int newCommandLineArgsLength = newCommandLineArgs.length;
2744: int newArgsLength = newArgs.length;
2745: System
2746: .arraycopy(
2747: newCommandLineArgs,
2748: 0,
2749: (newCommandLineArgs = new String[newCommandLineArgsLength
2750: + newArgsLength - 1]), 0,
2751: index);
2752: System.arraycopy(newArgs, 0, newCommandLineArgs,
2753: index, newArgsLength);
2754: index += newArgsLength;
2755: } else {
2756: newCommandLineArgs[index++] = arg;
2757: }
2758: }
2759: index = -1;
2760: } else {
2761: newCommandLineArgs = argv;
2762: for (int i = 0; i < argCount; i++) {
2763: newCommandLineArgs[i] = newCommandLineArgs[i].trim();
2764: }
2765: }
2766: argCount = newCommandLineArgs.length;
2767: this .expandedCommandLine = newCommandLineArgs;
2768: while (++index < argCount) {
2769:
2770: if (customEncoding != null) {
2771: throw new InvalidInputException(
2772: this
2773: .bind(
2774: "configure.unexpectedCustomEncoding", currentArg, customEncoding)); //$NON-NLS-1$
2775: }
2776:
2777: currentArg = newCommandLineArgs[index];
2778:
2779: switch (mode) {
2780: case DEFAULT:
2781: if (currentArg.startsWith("[")) { //$NON-NLS-1$
2782: throw new InvalidInputException(this .bind(
2783: "configure.unexpectedBracket", //$NON-NLS-1$
2784: currentArg));
2785: }
2786:
2787: if (currentArg.endsWith("]")) { //$NON-NLS-1$
2788: // look for encoding specification
2789: int encodingStart = currentArg.indexOf('[') + 1;
2790: if (encodingStart <= 1) {
2791: throw new InvalidInputException(
2792: this
2793: .bind(
2794: "configure.unexpectedBracket", currentArg)); //$NON-NLS-1$
2795: }
2796: int encodingEnd = currentArg.length() - 1;
2797: if (encodingStart >= 1) {
2798: if (encodingStart < encodingEnd) {
2799: customEncoding = currentArg.substring(
2800: encodingStart, encodingEnd);
2801: try { // ensure encoding is supported
2802: new InputStreamReader(
2803: new ByteArrayInputStream(
2804: new byte[0]),
2805: customEncoding);
2806: } catch (UnsupportedEncodingException e) {
2807: throw new InvalidInputException(
2808: this
2809: .bind(
2810: "configure.unsupportedEncoding", customEncoding)); //$NON-NLS-1$
2811: }
2812: }
2813: currentArg = currentArg.substring(0,
2814: encodingStart - 1);
2815: }
2816: }
2817:
2818: if (currentArg
2819: .endsWith(SuffixConstants.SUFFIX_STRING_java)) {
2820: if (this .filenames == null) {
2821: this .filenames = new String[argCount - index];
2822: this .encodings = new String[argCount - index];
2823: this .destinationPaths = new String[argCount
2824: - index];
2825: } else if (filesCount == this .filenames.length) {
2826: int length = this .filenames.length;
2827: System
2828: .arraycopy(
2829: this .filenames,
2830: 0,
2831: (this .filenames = new String[length
2832: + argCount - index]),
2833: 0, length);
2834: System
2835: .arraycopy(
2836: this .encodings,
2837: 0,
2838: (this .encodings = new String[length
2839: + argCount - index]),
2840: 0, length);
2841: System
2842: .arraycopy(
2843: this .destinationPaths,
2844: 0,
2845: (this .destinationPaths = new String[length
2846: + argCount - index]),
2847: 0, length);
2848: }
2849: this .filenames[filesCount] = currentArg;
2850: this .encodings[filesCount++] = customEncoding;
2851: // destination path cannot be specified upon an individual file
2852: customEncoding = null;
2853: mode = DEFAULT;
2854: continue;
2855: }
2856: if (currentArg.equals("-log")) { //$NON-NLS-1$
2857: if (this .log != null)
2858: throw new InvalidInputException(this .bind(
2859: "configure.duplicateLog", currentArg)); //$NON-NLS-1$
2860: mode = INSIDE_LOG;
2861: continue;
2862: }
2863: if (currentArg.equals("-repeat")) { //$NON-NLS-1$
2864: if (this .repetitions > 0)
2865: throw new InvalidInputException(
2866: this
2867: .bind(
2868: "configure.duplicateRepeat", currentArg)); //$NON-NLS-1$
2869: mode = INSIDE_REPETITION;
2870: continue;
2871: }
2872: if (currentArg.equals("-maxProblems")) { //$NON-NLS-1$
2873: if (this .maxProblems > 0)
2874: throw new InvalidInputException(
2875: this
2876: .bind(
2877: "configure.duplicateMaxProblems", currentArg)); //$NON-NLS-1$
2878: mode = INSIDE_MAX_PROBLEMS;
2879: continue;
2880: }
2881: if (currentArg.equals("-source")) { //$NON-NLS-1$
2882: mode = INSIDE_SOURCE;
2883: continue;
2884: }
2885: if (currentArg.equals("-encoding")) { //$NON-NLS-1$
2886: mode = INSIDE_DEFAULT_ENCODING;
2887: continue;
2888: }
2889: if (currentArg.equals("-1.3")) { //$NON-NLS-1$
2890: if (didSpecifyCompliance) {
2891: throw new InvalidInputException(
2892: this
2893: .bind(
2894: "configure.duplicateCompliance", currentArg));//$NON-NLS-1$
2895: }
2896: didSpecifyCompliance = true;
2897: this .options.put(CompilerOptions.OPTION_Compliance,
2898: CompilerOptions.VERSION_1_3);
2899: mode = DEFAULT;
2900: continue;
2901: }
2902: if (currentArg.equals("-1.4")) { //$NON-NLS-1$
2903: if (didSpecifyCompliance) {
2904: throw new InvalidInputException(
2905: this
2906: .bind(
2907: "configure.duplicateCompliance", currentArg)); //$NON-NLS-1$
2908: }
2909: didSpecifyCompliance = true;
2910: this .options.put(CompilerOptions.OPTION_Compliance,
2911: CompilerOptions.VERSION_1_4);
2912: mode = DEFAULT;
2913: continue;
2914: }
2915: if (currentArg.equals("-1.5") || currentArg.equals("-5") || currentArg.equals("-5.0")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
2916: if (didSpecifyCompliance) {
2917: throw new InvalidInputException(
2918: this
2919: .bind(
2920: "configure.duplicateCompliance", currentArg)); //$NON-NLS-1$
2921: }
2922: didSpecifyCompliance = true;
2923: this .options.put(CompilerOptions.OPTION_Compliance,
2924: CompilerOptions.VERSION_1_5);
2925: mode = DEFAULT;
2926: continue;
2927: }
2928: if (currentArg.equals("-1.6") || currentArg.equals("-6") || currentArg.equals("-6.0")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
2929: if (didSpecifyCompliance) {
2930: throw new InvalidInputException(
2931: this
2932: .bind(
2933: "configure.duplicateCompliance", currentArg)); //$NON-NLS-1$
2934: }
2935: didSpecifyCompliance = true;
2936: this .options.put(CompilerOptions.OPTION_Compliance,
2937: CompilerOptions.VERSION_1_6);
2938: mode = DEFAULT;
2939: continue;
2940: }
2941: if (currentArg.equals("-1.7") || currentArg.equals("-7") || currentArg.equals("-7.0")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
2942: if (didSpecifyCompliance) {
2943: throw new InvalidInputException(
2944: this
2945: .bind(
2946: "configure.duplicateCompliance", currentArg)); //$NON-NLS-1$
2947: }
2948: didSpecifyCompliance = true;
2949: this .options.put(CompilerOptions.OPTION_Compliance,
2950: CompilerOptions.VERSION_1_7);
2951: mode = DEFAULT;
2952: continue;
2953: }
2954: if (currentArg.equals("-d")) { //$NON-NLS-1$
2955: if (this .destinationPath != null) {
2956: StringBuffer errorMessage = new StringBuffer();
2957: errorMessage.append(currentArg);
2958: if ((index + 1) < argCount) {
2959: errorMessage.append(' ');
2960: errorMessage
2961: .append(newCommandLineArgs[index + 1]);
2962: }
2963: throw new InvalidInputException(
2964: this
2965: .bind(
2966: "configure.duplicateOutputPath", errorMessage.toString())); //$NON-NLS-1$
2967: }
2968: mode = INSIDE_DESTINATION_PATH;
2969: continue;
2970: }
2971: if (currentArg.equals("-classpath") //$NON-NLS-1$
2972: || currentArg.equals("-cp")) { //$NON-NLS-1$
2973: mode = INSIDE_CLASSPATH_start;
2974: continue;
2975: }
2976: if (currentArg.equals("-bootclasspath")) {//$NON-NLS-1$
2977: if (bootclasspaths.size() > 0) {
2978: StringBuffer errorMessage = new StringBuffer();
2979: errorMessage.append(currentArg);
2980: if ((index + 1) < argCount) {
2981: errorMessage.append(' ');
2982: errorMessage
2983: .append(newCommandLineArgs[index + 1]);
2984: }
2985: throw new InvalidInputException(
2986: this
2987: .bind(
2988: "configure.duplicateBootClasspath", errorMessage.toString())); //$NON-NLS-1$
2989: }
2990: mode = INSIDE_BOOTCLASSPATH_start;
2991: continue;
2992: }
2993: if (currentArg.equals("-sourcepath")) {//$NON-NLS-1$
2994: if (sourcepathClasspathArg != null) {
2995: StringBuffer errorMessage = new StringBuffer();
2996: errorMessage.append(currentArg);
2997: if ((index + 1) < argCount) {
2998: errorMessage.append(' ');
2999: errorMessage
3000: .append(newCommandLineArgs[index + 1]);
3001: }
3002: throw new InvalidInputException(
3003: this
3004: .bind(
3005: "configure.duplicateSourcepath", errorMessage.toString())); //$NON-NLS-1$
3006: }
3007: mode = INSIDE_SOURCE_PATH_start;
3008: continue;
3009: }
3010: if (currentArg.equals("-extdirs")) {//$NON-NLS-1$
3011: if (extdirsClasspaths != null) {
3012: StringBuffer errorMessage = new StringBuffer();
3013: errorMessage.append(currentArg);
3014: if ((index + 1) < argCount) {
3015: errorMessage.append(' ');
3016: errorMessage
3017: .append(newCommandLineArgs[index + 1]);
3018: }
3019: throw new InvalidInputException(
3020: this
3021: .bind(
3022: "configure.duplicateExtDirs", errorMessage.toString())); //$NON-NLS-1$
3023: }
3024: mode = INSIDE_EXT_DIRS;
3025: continue;
3026: }
3027: if (currentArg.equals("-endorseddirs")) { //$NON-NLS-1$
3028: if (endorsedDirClasspaths != null) {
3029: StringBuffer errorMessage = new StringBuffer();
3030: errorMessage.append(currentArg);
3031: if ((index + 1) < argCount) {
3032: errorMessage.append(' ');
3033: errorMessage
3034: .append(newCommandLineArgs[index + 1]);
3035: }
3036: throw new InvalidInputException(
3037: this
3038: .bind(
3039: "configure.duplicateEndorsedDirs", errorMessage.toString())); //$NON-NLS-1$
3040: }
3041: mode = INSIDE_ENDORSED_DIRS;
3042: continue;
3043: }
3044: if (currentArg.equals("-progress")) { //$NON-NLS-1$
3045: mode = DEFAULT;
3046: this .showProgress = true;
3047: continue;
3048: }
3049: if (currentArg.equals("-proceedOnError")) { //$NON-NLS-1$
3050: mode = DEFAULT;
3051: this .proceedOnError = true;
3052: continue;
3053: }
3054: if (currentArg.equals("-time")) { //$NON-NLS-1$
3055: mode = DEFAULT;
3056: this .timing = true;
3057: continue;
3058: }
3059: if (currentArg.equals("-version") //$NON-NLS-1$
3060: || currentArg.equals("-v")) { //$NON-NLS-1$
3061: this .logger.logVersion(true);
3062: this .proceed = false;
3063: return;
3064: }
3065: if (currentArg.equals("-showversion")) { //$NON-NLS-1$
3066: printVersionRequired = true;
3067: mode = DEFAULT;
3068: continue;
3069: }
3070: if ("-deprecation".equals(currentArg)) { //$NON-NLS-1$
3071: didSpecifyDeprecation = true;
3072: this .options.put(
3073: CompilerOptions.OPTION_ReportDeprecation,
3074: CompilerOptions.WARNING);
3075: mode = DEFAULT;
3076: continue;
3077: }
3078: if (currentArg.equals("-help") || currentArg.equals("-?")) { //$NON-NLS-1$ //$NON-NLS-2$
3079: printUsageRequired = true;
3080: mode = DEFAULT;
3081: continue;
3082: }
3083: if (currentArg.equals("-help:warn") || //$NON-NLS-1$
3084: currentArg.equals("-?:warn")) { //$NON-NLS-1$
3085: printUsageRequired = true;
3086: usageSection = "misc.usage.warn"; //$NON-NLS-1$
3087: continue;
3088: }
3089: if (currentArg.equals("-noExit")) { //$NON-NLS-1$
3090: this .systemExitWhenFinished = false;
3091: mode = DEFAULT;
3092: continue;
3093: }
3094: if (currentArg.equals("-verbose")) { //$NON-NLS-1$
3095: this .verbose = true;
3096: mode = DEFAULT;
3097: continue;
3098: }
3099: if (currentArg.equals("-referenceInfo")) { //$NON-NLS-1$
3100: this .produceRefInfo = true;
3101: mode = DEFAULT;
3102: continue;
3103: }
3104: if (currentArg.equals("-inlineJSR")) { //$NON-NLS-1$
3105: mode = DEFAULT;
3106: this .options.put(CompilerOptions.OPTION_InlineJsr,
3107: CompilerOptions.ENABLED);
3108: continue;
3109: }
3110: if (currentArg.startsWith("-g")) { //$NON-NLS-1$
3111: mode = DEFAULT;
3112: String debugOption = currentArg;
3113: int length = currentArg.length();
3114: if (length == 2) {
3115: this .options
3116: .put(
3117: CompilerOptions.OPTION_LocalVariableAttribute,
3118: CompilerOptions.GENERATE);
3119: this .options
3120: .put(
3121: CompilerOptions.OPTION_LineNumberAttribute,
3122: CompilerOptions.GENERATE);
3123: this .options
3124: .put(
3125: CompilerOptions.OPTION_SourceFileAttribute,
3126: CompilerOptions.GENERATE);
3127: continue;
3128: }
3129: if (length > 3) {
3130: this .options
3131: .put(
3132: CompilerOptions.OPTION_LocalVariableAttribute,
3133: CompilerOptions.DO_NOT_GENERATE);
3134: this .options
3135: .put(
3136: CompilerOptions.OPTION_LineNumberAttribute,
3137: CompilerOptions.DO_NOT_GENERATE);
3138: this .options
3139: .put(
3140: CompilerOptions.OPTION_SourceFileAttribute,
3141: CompilerOptions.DO_NOT_GENERATE);
3142: if (length == 7
3143: && debugOption.equals("-g:" + NONE)) //$NON-NLS-1$
3144: continue;
3145: StringTokenizer tokenizer = new StringTokenizer(
3146: debugOption.substring(3, debugOption
3147: .length()), ","); //$NON-NLS-1$
3148: while (tokenizer.hasMoreTokens()) {
3149: String token = tokenizer.nextToken();
3150: if (token.equals("vars")) { //$NON-NLS-1$
3151: this .options
3152: .put(
3153: CompilerOptions.OPTION_LocalVariableAttribute,
3154: CompilerOptions.GENERATE);
3155: } else if (token.equals("lines")) { //$NON-NLS-1$
3156: this .options
3157: .put(
3158: CompilerOptions.OPTION_LineNumberAttribute,
3159: CompilerOptions.GENERATE);
3160: } else if (token.equals("source")) { //$NON-NLS-1$
3161: this .options
3162: .put(
3163: CompilerOptions.OPTION_SourceFileAttribute,
3164: CompilerOptions.GENERATE);
3165: } else {
3166: throw new InvalidInputException(
3167: this
3168: .bind(
3169: "configure.invalidDebugOption", debugOption)); //$NON-NLS-1$
3170: }
3171: }
3172: continue;
3173: }
3174: throw new InvalidInputException(
3175: this
3176: .bind(
3177: "configure.invalidDebugOption", debugOption)); //$NON-NLS-1$
3178: }
3179: if (currentArg.startsWith("-nowarn")) { //$NON-NLS-1$
3180: disableWarnings();
3181: mode = DEFAULT;
3182: continue;
3183: }
3184: if (currentArg.startsWith("-warn")) { //$NON-NLS-1$
3185: mode = DEFAULT;
3186: String warningOption = currentArg;
3187: int length = currentArg.length();
3188: if (length == 10
3189: && warningOption.equals("-warn:" + NONE)) { //$NON-NLS-1$
3190: disableWarnings();
3191: continue;
3192: }
3193: if (length <= 6) {
3194: throw new InvalidInputException(
3195: this
3196: .bind(
3197: "configure.invalidWarningConfiguration", warningOption)); //$NON-NLS-1$
3198: }
3199: int warnTokenStart;
3200: boolean isEnabling;
3201: switch (warningOption.charAt(6)) {
3202: case '+':
3203: warnTokenStart = 7;
3204: isEnabling = true;
3205: break;
3206: case '-':
3207: warnTokenStart = 7;
3208: isEnabling = false; // mentionned warnings are disabled
3209: break;
3210: default:
3211: warnTokenStart = 6;
3212: // clear default warning level
3213: // but allow multiple warning option on the command line
3214: if (!didSpecifyWarnings)
3215: disableWarnings();
3216: isEnabling = true;
3217: }
3218:
3219: StringTokenizer tokenizer = new StringTokenizer(
3220: warningOption.substring(warnTokenStart,
3221: warningOption.length()), ","); //$NON-NLS-1$
3222: int tokenCounter = 0;
3223:
3224: if (didSpecifyDeprecation) { // deprecation could have also been set through -deprecation option
3225: this .options
3226: .put(
3227: CompilerOptions.OPTION_ReportDeprecation,
3228: CompilerOptions.WARNING);
3229: }
3230:
3231: while (tokenizer.hasMoreTokens()) {
3232: String token = tokenizer.nextToken();
3233: tokenCounter++;
3234: handleWarningToken(token, isEnabling,
3235: useEnableJavadoc);
3236: }
3237: if (tokenCounter == 0)
3238: throw new InvalidInputException(
3239: this
3240: .bind(
3241: "configure.invalidWarningOption", currentArg)); //$NON-NLS-1$
3242: didSpecifyWarnings = true;
3243: continue;
3244: }
3245: if (currentArg.equals("-target")) { //$NON-NLS-1$
3246: mode = INSIDE_TARGET;
3247: continue;
3248: }
3249: if (currentArg.equals("-preserveAllLocals")) { //$NON-NLS-1$
3250: this .options.put(
3251: CompilerOptions.OPTION_PreserveUnusedLocal,
3252: CompilerOptions.PRESERVE);
3253: mode = DEFAULT;
3254: continue;
3255: }
3256: if (currentArg.equals("-enableJavadoc")) {//$NON-NLS-1$
3257: mode = DEFAULT;
3258: this .options.put(
3259: CompilerOptions.OPTION_DocCommentSupport,
3260: CompilerOptions.ENABLED);
3261: useEnableJavadoc = true;
3262: continue;
3263: }
3264: if (currentArg.equals("-Xemacs")) { //$NON-NLS-1$
3265: mode = DEFAULT;
3266: this .logger.setEmacs();
3267: continue;
3268: }
3269: // annotation processing
3270: if (currentArg.startsWith("-A")) { //$NON-NLS-1$
3271: mode = DEFAULT;
3272: continue;
3273: }
3274: if (currentArg.equals("-processorpath")) { //$NON-NLS-1$
3275: mode = INSIDE_PROCESSOR_PATH_start;
3276: continue;
3277: }
3278: if (currentArg.equals("-processor")) { //$NON-NLS-1$
3279: mode = INSIDE_PROCESSOR_start;
3280: continue;
3281: }
3282: if (currentArg.equals("-proc:only")) { //$NON-NLS-1$
3283: this .options.put(
3284: CompilerOptions.OPTION_GenerateClassFiles,
3285: CompilerOptions.DISABLED);
3286: mode = DEFAULT;
3287: continue;
3288: }
3289: if (currentArg.equals("-proc:none")) { //$NON-NLS-1$
3290: didSpecifyDisabledAnnotationProcessing = true;
3291: this .options.put(
3292: CompilerOptions.OPTION_Process_Annotations,
3293: CompilerOptions.DISABLED);
3294: mode = DEFAULT;
3295: continue;
3296: }
3297: if (currentArg.equals("-s")) { //$NON-NLS-1$
3298: mode = INSIDE_S_start;
3299: continue;
3300: }
3301: if (currentArg.equals("-XprintProcessorInfo") //$NON-NLS-1$
3302: || currentArg.equals("-XprintRounds")) { //$NON-NLS-1$
3303: mode = DEFAULT;
3304: continue;
3305: }
3306: // tolerated javac options - quietly filtered out
3307: if (currentArg.startsWith("-X")) { //$NON-NLS-1$
3308: mode = DEFAULT;
3309: continue;
3310: }
3311: if (currentArg.startsWith("-J")) { //$NON-NLS-1$
3312: mode = DEFAULT;
3313: continue;
3314: }
3315: if (currentArg.equals("-O")) { //$NON-NLS-1$
3316: mode = DEFAULT;
3317: continue;
3318: }
3319: if (currentArg.equals("-classNames")) { //$NON-NLS-1$
3320: mode = INSIDE_CLASS_NAMES;
3321: continue;
3322: }
3323: break;
3324: case INSIDE_TARGET:
3325: if (this .didSpecifyTarget) {
3326: throw new InvalidInputException(this .bind(
3327: "configure.duplicateTarget", currentArg));//$NON-NLS-1$
3328: }
3329: this .didSpecifyTarget = true;
3330: if (currentArg.equals("1.1")) { //$NON-NLS-1$
3331: this .options.put(
3332: CompilerOptions.OPTION_TargetPlatform,
3333: CompilerOptions.VERSION_1_1);
3334: } else if (currentArg.equals("1.2")) { //$NON-NLS-1$
3335: this .options.put(
3336: CompilerOptions.OPTION_TargetPlatform,
3337: CompilerOptions.VERSION_1_2);
3338: } else if (currentArg.equals("1.3")) { //$NON-NLS-1$
3339: this .options.put(
3340: CompilerOptions.OPTION_TargetPlatform,
3341: CompilerOptions.VERSION_1_3);
3342: } else if (currentArg.equals("1.4")) { //$NON-NLS-1$
3343: this .options.put(
3344: CompilerOptions.OPTION_TargetPlatform,
3345: CompilerOptions.VERSION_1_4);
3346: } else if (currentArg.equals("1.5") || currentArg.equals("5") || currentArg.equals("5.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
3347: this .options.put(
3348: CompilerOptions.OPTION_TargetPlatform,
3349: CompilerOptions.VERSION_1_5);
3350: } else if (currentArg.equals("1.6") || currentArg.equals("6") || currentArg.equals("6.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
3351: this .options.put(
3352: CompilerOptions.OPTION_TargetPlatform,
3353: CompilerOptions.VERSION_1_6);
3354: } else if (currentArg.equals("1.7") || currentArg.equals("7") || currentArg.equals("7.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
3355: this .options.put(
3356: CompilerOptions.OPTION_TargetPlatform,
3357: CompilerOptions.VERSION_1_7);
3358: } else if (currentArg.equals("jsr14")) { //$NON-NLS-1$
3359: this .options.put(
3360: CompilerOptions.OPTION_TargetPlatform,
3361: CompilerOptions.VERSION_JSR14);
3362: } else if (currentArg.equals("cldc1.1")) { //$NON-NLS-1$
3363: this .options.put(
3364: CompilerOptions.OPTION_TargetPlatform,
3365: CompilerOptions.VERSION_CLDC1_1);
3366: this .options.put(CompilerOptions.OPTION_InlineJsr,
3367: CompilerOptions.ENABLED);
3368: } else {
3369: throw new InvalidInputException(this .bind(
3370: "configure.targetJDK", currentArg)); //$NON-NLS-1$
3371: }
3372: mode = DEFAULT;
3373: continue;
3374: case INSIDE_LOG:
3375: this .log = currentArg;
3376: mode = DEFAULT;
3377: continue;
3378: case INSIDE_REPETITION:
3379: try {
3380: this .repetitions = Integer.parseInt(currentArg);
3381: if (this .repetitions <= 0) {
3382: throw new InvalidInputException(this .bind(
3383: "configure.repetition", currentArg)); //$NON-NLS-1$
3384: }
3385: } catch (NumberFormatException e) {
3386: throw new InvalidInputException(this .bind(
3387: "configure.repetition", currentArg)); //$NON-NLS-1$
3388: }
3389: mode = DEFAULT;
3390: continue;
3391: case INSIDE_MAX_PROBLEMS:
3392: try {
3393: this .maxProblems = Integer.parseInt(currentArg);
3394: if (this .maxProblems <= 0) {
3395: throw new InvalidInputException(this .bind(
3396: "configure.maxProblems", currentArg)); //$NON-NLS-1$
3397: }
3398: this .options.put(
3399: CompilerOptions.OPTION_MaxProblemPerUnit,
3400: currentArg);
3401: } catch (NumberFormatException e) {
3402: throw new InvalidInputException(this .bind(
3403: "configure.maxProblems", currentArg)); //$NON-NLS-1$
3404: }
3405: mode = DEFAULT;
3406: continue;
3407: case INSIDE_SOURCE:
3408: if (this .didSpecifySource) {
3409: throw new InvalidInputException(this .bind(
3410: "configure.duplicateSource", currentArg));//$NON-NLS-1$
3411: }
3412: this .didSpecifySource = true;
3413: if (currentArg.equals("1.3")) { //$NON-NLS-1$
3414: this .options.put(CompilerOptions.OPTION_Source,
3415: CompilerOptions.VERSION_1_3);
3416: } else if (currentArg.equals("1.4")) { //$NON-NLS-1$
3417: this .options.put(CompilerOptions.OPTION_Source,
3418: CompilerOptions.VERSION_1_4);
3419: } else if (currentArg.equals("1.5") || currentArg.equals("5") || currentArg.equals("5.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
3420: this .options.put(CompilerOptions.OPTION_Source,
3421: CompilerOptions.VERSION_1_5);
3422: } else if (currentArg.equals("1.6") || currentArg.equals("6") || currentArg.equals("6.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
3423: this .options.put(CompilerOptions.OPTION_Source,
3424: CompilerOptions.VERSION_1_6);
3425: } else if (currentArg.equals("1.7") || currentArg.equals("7") || currentArg.equals("7.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
3426: this .options.put(CompilerOptions.OPTION_Source,
3427: CompilerOptions.VERSION_1_7);
3428: } else {
3429: throw new InvalidInputException(this .bind(
3430: "configure.source", currentArg)); //$NON-NLS-1$
3431: }
3432: mode = DEFAULT;
3433: continue;
3434: case INSIDE_DEFAULT_ENCODING:
3435: if (didSpecifyDefaultEncoding) {
3436: throw new InvalidInputException(
3437: this
3438: .bind(
3439: "configure.duplicateDefaultEncoding", currentArg)); //$NON-NLS-1$
3440: }
3441: try { // ensure encoding is supported
3442: new InputStreamReader(new ByteArrayInputStream(
3443: new byte[0]), currentArg);
3444: } catch (UnsupportedEncodingException e) {
3445: throw new InvalidInputException(
3446: this
3447: .bind(
3448: "configure.unsupportedEncoding", currentArg)); //$NON-NLS-1$
3449: }
3450: this .options.put(CompilerOptions.OPTION_Encoding,
3451: currentArg);
3452: didSpecifyDefaultEncoding = true;
3453: mode = DEFAULT;
3454: continue;
3455: case INSIDE_DESTINATION_PATH:
3456: this .setDestinationPath(currentArg.equals(NONE) ? NONE
3457: : currentArg);
3458: mode = DEFAULT;
3459: continue;
3460: case INSIDE_CLASSPATH_start:
3461: mode = DEFAULT;
3462: index += processPaths(newCommandLineArgs, index,
3463: currentArg, classpaths);
3464: continue;
3465: case INSIDE_BOOTCLASSPATH_start:
3466: mode = DEFAULT;
3467: index += processPaths(newCommandLineArgs, index,
3468: currentArg, bootclasspaths);
3469: continue;
3470: case INSIDE_SOURCE_PATH_start:
3471: mode = DEFAULT;
3472: String[] sourcePaths = new String[1];
3473: index += processPaths(newCommandLineArgs, index,
3474: currentArg, sourcePaths);
3475: sourcepathClasspathArg = sourcePaths[0];
3476: continue;
3477: case INSIDE_EXT_DIRS:
3478: if (currentArg.indexOf("[-d") != -1) { //$NON-NLS-1$
3479: throw new InvalidInputException(this .bind(
3480: "configure.unexpectedDestinationPathEntry", //$NON-NLS-1$
3481: "-extdir")); //$NON-NLS-1$
3482: }
3483: StringTokenizer tokenizer = new StringTokenizer(
3484: currentArg, File.pathSeparator, false);
3485: extdirsClasspaths = new ArrayList(
3486: DEFAULT_SIZE_CLASSPATH);
3487: while (tokenizer.hasMoreTokens())
3488: extdirsClasspaths.add(tokenizer.nextToken());
3489: mode = DEFAULT;
3490: continue;
3491: case INSIDE_ENDORSED_DIRS:
3492: if (currentArg.indexOf("[-d") != -1) { //$NON-NLS-1$
3493: throw new InvalidInputException(this .bind(
3494: "configure.unexpectedDestinationPathEntry", //$NON-NLS-1$
3495: "-endorseddirs")); //$NON-NLS-1$
3496: }
3497: tokenizer = new StringTokenizer(currentArg,
3498: File.pathSeparator, false);
3499: endorsedDirClasspaths = new ArrayList(
3500: DEFAULT_SIZE_CLASSPATH);
3501: while (tokenizer.hasMoreTokens())
3502: endorsedDirClasspaths.add(tokenizer.nextToken());
3503: mode = DEFAULT;
3504: continue;
3505: case INSIDE_SOURCE_DIRECTORY_DESTINATION_PATH:
3506: if (currentArg.endsWith("]")) { //$NON-NLS-1$
3507: customDestinationPath = currentArg.substring(0,
3508: currentArg.length() - 1);
3509: } else {
3510: throw new InvalidInputException(this .bind(
3511: "configure.incorrectDestinationPathEntry", //$NON-NLS-1$
3512: "[-d " + currentArg)); //$NON-NLS-1$
3513: }
3514: break;
3515: case INSIDE_PROCESSOR_PATH_start:
3516: // nothing to do here. This is consumed again by the AnnotationProcessorManager
3517: mode = DEFAULT;
3518: continue;
3519: case INSIDE_PROCESSOR_start:
3520: // nothing to do here. This is consumed again by the AnnotationProcessorManager
3521: mode = DEFAULT;
3522: continue;
3523: case INSIDE_S_start:
3524: // nothing to do here. This is consumed again by the AnnotationProcessorManager
3525: mode = DEFAULT;
3526: continue;
3527: case INSIDE_CLASS_NAMES:
3528: tokenizer = new StringTokenizer(currentArg, ","); //$NON-NLS-1$
3529: if (this .classNames == null) {
3530: this .classNames = new String[DEFAULT_SIZE_CLASSPATH];
3531: }
3532: while (tokenizer.hasMoreTokens()) {
3533: if (this .classNames.length == classCount) {
3534: // resize
3535: System
3536: .arraycopy(
3537: this .classNames,
3538: 0,
3539: (this .classNames = new String[classCount * 2]),
3540: 0, classCount);
3541: }
3542: this .classNames[classCount++] = tokenizer
3543: .nextToken();
3544: }
3545: mode = DEFAULT;
3546: continue;
3547: }
3548:
3549: // default is input directory, if no custom destination path exists
3550: if (customDestinationPath == null) {
3551: if (File.separatorChar != '/') {
3552: currentArg = currentArg.replace('/',
3553: File.separatorChar);
3554: }
3555: if (currentArg.endsWith("[-d")) { //$NON-NLS-1$
3556: currentSourceDirectory = currentArg.substring(0,
3557: currentArg.length() - 3);
3558: mode = INSIDE_SOURCE_DIRECTORY_DESTINATION_PATH;
3559: continue;
3560: } else {
3561: currentSourceDirectory = currentArg;
3562: }
3563: }
3564: File dir = new File(currentSourceDirectory);
3565: if (!dir.isDirectory()) {
3566: throw new InvalidInputException(
3567: this
3568: .bind(
3569: "configure.unrecognizedOption", currentSourceDirectory)); //$NON-NLS-1$
3570: }
3571: String[] result = FileFinder.find(dir,
3572: SuffixConstants.SUFFIX_STRING_JAVA);
3573: if (NONE.equals(customDestinationPath)) {
3574: customDestinationPath = NONE; // ensure == comparison
3575: }
3576: if (this .filenames != null) {
3577: // some source files were specified explicitly
3578: int length = result.length;
3579: System.arraycopy(this .filenames, 0,
3580: (this .filenames = new String[length
3581: + filesCount]), 0, filesCount);
3582: System.arraycopy(this .encodings, 0,
3583: (this .encodings = new String[length
3584: + filesCount]), 0, filesCount);
3585: System.arraycopy(this .destinationPaths, 0,
3586: (this .destinationPaths = new String[length
3587: + filesCount]), 0, filesCount);
3588: System.arraycopy(result, 0, this .filenames, filesCount,
3589: length);
3590: for (int i = 0; i < length; i++) {
3591: this .encodings[filesCount + i] = customEncoding;
3592: this .destinationPaths[filesCount + i] = customDestinationPath;
3593: }
3594: filesCount += length;
3595: customEncoding = null;
3596: customDestinationPath = null;
3597: currentSourceDirectory = null;
3598: } else {
3599: this .filenames = result;
3600: filesCount = this .filenames.length;
3601: this .encodings = new String[filesCount];
3602: this .destinationPaths = new String[filesCount];
3603: for (int i = 0; i < filesCount; i++) {
3604: this .encodings[i] = customEncoding;
3605: this .destinationPaths[i] = customDestinationPath;
3606: }
3607: customEncoding = null;
3608: customDestinationPath = null;
3609: currentSourceDirectory = null;
3610: }
3611: mode = DEFAULT;
3612: continue;
3613: }
3614:
3615: if (printUsageRequired || (filesCount == 0 && classCount == 0)) {
3616: if (usageSection == null) {
3617: printUsage(); // default
3618: } else {
3619: printUsage(usageSection);
3620: }
3621: this .proceed = false;
3622: return;
3623: }
3624:
3625: if (this .log != null) {
3626: this .logger.setLog(this .log);
3627: } else {
3628: this .showProgress = false;
3629: }
3630: this .logger.logVersion(printVersionRequired);
3631:
3632: validateOptions(didSpecifyCompliance);
3633:
3634: // Enable annotation processing by default in batch mode when compliance is at least 1.6
3635: // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=185768
3636: if (!didSpecifyDisabledAnnotationProcessing
3637: && CompilerOptions.versionToJdkLevel(this .options
3638: .get(CompilerOptions.OPTION_Compliance)) >= ClassFileConstants.JDK1_6) {
3639: this .options.put(
3640: CompilerOptions.OPTION_Process_Annotations,
3641: CompilerOptions.ENABLED);
3642: }
3643:
3644: this .logger.logCommandLineArguments(newCommandLineArgs);
3645: this .logger.logOptions(this .options);
3646: if (this .repetitions == 0) {
3647: this .repetitions = 1;
3648: }
3649: if (this .repetitions >= 3 && this .timing) {
3650: this .times = new long[this .repetitions];
3651: this .timesCounter = 0;
3652: }
3653:
3654: if (filesCount != 0) {
3655: System.arraycopy(this .filenames, 0,
3656: (this .filenames = new String[filesCount]), 0,
3657: filesCount);
3658: }
3659:
3660: if (classCount != 0) {
3661: System.arraycopy(this .classNames, 0,
3662: (this .classNames = new String[classCount]), 0,
3663: classCount);
3664: }
3665:
3666: setPaths(bootclasspaths, sourcepathClasspathArg,
3667: sourcepathClasspaths, classpaths, extdirsClasspaths,
3668: endorsedDirClasspaths, customEncoding);
3669: }
3670:
3671: protected void disableWarnings() {
3672: Object[] entries = this .options.entrySet().toArray();
3673: for (int i = 0, max = entries.length; i < max; i++) {
3674: Map.Entry entry = (Map.Entry) entries[i];
3675: if (!(entry.getKey() instanceof String))
3676: continue;
3677: if (!(entry.getValue() instanceof String))
3678: continue;
3679: if (((String) entry.getValue())
3680: .equals(CompilerOptions.WARNING)) {
3681: this .options
3682: .put(entry.getKey(), CompilerOptions.IGNORE);
3683: }
3684: }
3685: this .options.put(CompilerOptions.OPTION_TaskTags,
3686: Util.EMPTY_STRING);
3687: }
3688:
3689: public String extractDestinationPathFromSourceFile(
3690: CompilationResult result) {
3691: ICompilationUnit compilationUnit = result.compilationUnit;
3692: if (compilationUnit != null) {
3693: char[] fileName = compilationUnit.getFileName();
3694: int lastIndex = CharOperation.lastIndexOf(
3695: java.io.File.separatorChar, fileName);
3696: if (lastIndex != -1) {
3697: final String outputPathName = new String(fileName, 0,
3698: lastIndex);
3699: final File output = new File(outputPathName);
3700: if (output.exists() && output.isDirectory()) {
3701: return outputPathName;
3702: }
3703: }
3704: }
3705: return System.getProperty("user.dir"); //$NON-NLS-1$
3706: }
3707:
3708: /*
3709: * Answer the component to which will be handed back compilation results from the compiler
3710: */
3711: public ICompilerRequestor getBatchRequestor() {
3712: return new ICompilerRequestor() {
3713: int lineDelta = 0;
3714:
3715: public void acceptResult(CompilationResult compilationResult) {
3716: if (compilationResult.lineSeparatorPositions != null) {
3717: int unitLineCount = compilationResult.lineSeparatorPositions.length;
3718: Main.this .lineCount += unitLineCount;
3719: this .lineDelta += unitLineCount;
3720: if (Main.this .showProgress && this .lineDelta > 2000) {
3721: // in -log mode, dump a dot every 2000 lines compiled
3722: Main.this .logger.logProgress();
3723: this .lineDelta = 0;
3724: }
3725: }
3726: Main.this .logger.startLoggingSource(compilationResult);
3727: if (compilationResult.hasProblems()
3728: || compilationResult.hasTasks()) {
3729: int localErrorCount = Main.this .logger.logProblems(
3730: compilationResult.getAllProblems(),
3731: compilationResult.compilationUnit
3732: .getContents(), Main.this );
3733: // exit?
3734: if (Main.this .systemExitWhenFinished
3735: && !Main.this .proceedOnError
3736: && (localErrorCount > 0)) {
3737: // ensure dumping problems for enqueued units as well, since may contain primary errors (123476)
3738: CompilationUnitDeclaration[] queuedUnits = Main.this .batchCompiler.unitsToProcess;
3739: for (int i = 0, length = Main.this .batchCompiler.totalUnits; i < length; i++) {
3740: CompilationUnitDeclaration queuedUnit = queuedUnits[i];
3741: if (queuedUnit == null)
3742: continue;
3743: CompilationResult result = queuedUnit.compilationResult;
3744: if (result.hasProblems()
3745: && !result.hasBeenAccepted) {
3746: Main.this .logger.logProblems(result
3747: .getAllProblems(),
3748: result.compilationUnit
3749: .getContents(),
3750: Main.this );
3751: }
3752: }
3753: Main.this .logger.endLoggingSource();
3754: Main.this .logger.endLoggingSources();
3755: Main.this .logger.printStats();
3756: Main.this .logger.flush();
3757: Main.this .logger.close();
3758: System.exit(-1);
3759: }
3760: }
3761: outputClassFiles(compilationResult);
3762: Main.this .logger.endLoggingSource();
3763: }
3764: };
3765: }
3766:
3767: /*
3768: * Build the set of compilation source units
3769: */
3770: public CompilationUnit[] getCompilationUnits()
3771: throws InvalidInputException {
3772: int fileCount = this .filenames.length;
3773: CompilationUnit[] units = new CompilationUnit[fileCount];
3774: HashtableOfObject knownFileNames = new HashtableOfObject(
3775: fileCount);
3776:
3777: String defaultEncoding = (String) this .options
3778: .get(CompilerOptions.OPTION_Encoding);
3779: if (Util.EMPTY_STRING.equals(defaultEncoding))
3780: defaultEncoding = null;
3781:
3782: for (int i = 0; i < fileCount; i++) {
3783: char[] charName = this .filenames[i].toCharArray();
3784: if (knownFileNames.get(charName) != null)
3785: throw new InvalidInputException(this .bind(
3786: "unit.more", this .filenames[i])); //$NON-NLS-1$
3787: knownFileNames.put(charName, charName);
3788: File file = new File(this .filenames[i]);
3789: if (!file.exists())
3790: throw new InvalidInputException(this .bind(
3791: "unit.missing", this .filenames[i])); //$NON-NLS-1$
3792: String encoding = this .encodings[i];
3793: if (encoding == null)
3794: encoding = defaultEncoding;
3795: units[i] = new CompilationUnit(null, this .filenames[i],
3796: encoding, this .destinationPaths[i]);
3797: }
3798: return units;
3799: }
3800:
3801: /*
3802: * Low-level API performing the actual compilation
3803: */
3804: public IErrorHandlingPolicy getHandlingPolicy() {
3805:
3806: // passes the initial set of files to the batch oracle (to avoid finding more than once the same units when case insensitive match)
3807: return new IErrorHandlingPolicy() {
3808: public boolean proceedOnErrors() {
3809: return Main.this .proceedOnError; // stop if there are some errors
3810: }
3811:
3812: public boolean stopOnFirstError() {
3813: return false;
3814: }
3815: };
3816: }
3817:
3818: /*
3819: * External API
3820: */
3821: public File getJavaHome() {
3822: if (!javaHomeChecked) {
3823: javaHomeChecked = true;
3824: String javaHome = System.getProperty("java.home");//$NON-NLS-1$
3825: if (javaHome != null) {
3826: this .javaHomeCache = new File(javaHome);
3827: if (!this .javaHomeCache.exists())
3828: this .javaHomeCache = null;
3829: }
3830: }
3831: return this .javaHomeCache;
3832: }
3833:
3834: public FileSystem getLibraryAccess() {
3835: return new FileSystem(this .checkedClasspaths, this .filenames);
3836: }
3837:
3838: /*
3839: * Low-level API performing the actual compilation
3840: */
3841: public IProblemFactory getProblemFactory() {
3842: return new DefaultProblemFactory(this .compilerLocale);
3843: }
3844:
3845: /*
3846: * External API
3847: */
3848: protected void initialize(PrintWriter outWriter,
3849: PrintWriter errWriter, boolean systemExit) {
3850: this .initialize(outWriter, errWriter, systemExit, null);
3851: }
3852:
3853: protected void initialize(PrintWriter outWriter,
3854: PrintWriter errWriter, boolean systemExit,
3855: Map customDefaultOptions) {
3856: this .logger = new Logger(this , outWriter, errWriter);
3857: this .proceed = true;
3858: this .out = outWriter;
3859: this .err = errWriter;
3860: this .systemExitWhenFinished = systemExit;
3861: this .options = new CompilerOptions().getMap();
3862: if (customDefaultOptions != null) {
3863: this .didSpecifySource = customDefaultOptions
3864: .get(CompilerOptions.OPTION_Source) != null;
3865: this .didSpecifyTarget = customDefaultOptions
3866: .get(CompilerOptions.OPTION_TargetPlatform) != null;
3867: for (Iterator iter = customDefaultOptions.entrySet()
3868: .iterator(); iter.hasNext();) {
3869: Map.Entry entry = (Map.Entry) iter.next();
3870: this .options.put(entry.getKey(), entry.getValue());
3871: }
3872: } else {
3873: this .didSpecifySource = false;
3874: this .didSpecifyTarget = false;
3875: }
3876: this .classNames = null;
3877: }
3878:
3879: // Dump classfiles onto disk for all compilation units that where successful
3880: // and do not carry a -d none spec, either directly or inherited from Main.
3881: public void outputClassFiles(CompilationResult unitResult) {
3882: if (!((unitResult == null) || (unitResult.hasErrors() && !this .proceedOnError))) {
3883: ClassFile[] classFiles = unitResult.getClassFiles();
3884: String currentDestinationPath = null;
3885: boolean generateClasspathStructure = false;
3886: CompilationUnit compilationUnit = (CompilationUnit) unitResult.compilationUnit;
3887: if (compilationUnit.destinationPath == null) {
3888: if (this .destinationPath == null) {
3889: currentDestinationPath = extractDestinationPathFromSourceFile(unitResult);
3890: } else if (this .destinationPath != NONE) {
3891: currentDestinationPath = this .destinationPath;
3892: generateClasspathStructure = true;
3893: } // else leave currentDestinationPath null
3894: } else if (compilationUnit.destinationPath != NONE) {
3895: currentDestinationPath = compilationUnit.destinationPath;
3896: generateClasspathStructure = true;
3897: } // else leave currentDestinationPath null
3898: if (currentDestinationPath != null) {
3899: for (int i = 0, fileCount = classFiles.length; i < fileCount; i++) {
3900: // retrieve the key and the corresponding classfile
3901: ClassFile classFile = classFiles[i];
3902: char[] filename = classFile.fileName();
3903: int length = filename.length;
3904: char[] relativeName = new char[length + 6];
3905: System.arraycopy(filename, 0, relativeName, 0,
3906: length);
3907: System.arraycopy(SuffixConstants.SUFFIX_class, 0,
3908: relativeName, length, 6);
3909: CharOperation.replace(relativeName, '/',
3910: File.separatorChar);
3911: String relativeStringName = new String(relativeName);
3912: try {
3913: if (this .compilerOptions.verbose)
3914: this .out
3915: .println(Messages
3916: .bind(
3917: Messages.compilation_write,
3918: new String[] {
3919: String
3920: .valueOf(this .exportedClassFilesCounter + 1),
3921: relativeStringName }));
3922: ClassFile.writeToDisk(
3923: generateClasspathStructure,
3924: currentDestinationPath,
3925: relativeStringName, classFile);
3926: LookupEnvironment env = this .batchCompiler.lookupEnvironment;
3927: if (classFile.isShared)
3928: env.classFilePool.release(classFile);
3929: this .logger.logClassFile(
3930: generateClasspathStructure,
3931: currentDestinationPath,
3932: relativeStringName);
3933: this .exportedClassFilesCounter++;
3934: } catch (IOException e) {
3935: this .logger.logNoClassFileCreated(
3936: currentDestinationPath,
3937: relativeStringName, e);
3938: }
3939: }
3940: }
3941: }
3942: }
3943:
3944: /*
3945: * Low-level API performing the actual compilation
3946: */
3947: public void performCompilation() throws InvalidInputException {
3948:
3949: this .startTime = System.currentTimeMillis();
3950:
3951: FileSystem environment = getLibraryAccess();
3952: this .compilerOptions = new CompilerOptions(this .options);
3953: this .compilerOptions.performMethodsFullRecovery = false;
3954: this .compilerOptions.performStatementsRecovery = false;
3955: this .batchCompiler = new Compiler(environment,
3956: getHandlingPolicy(), this .compilerOptions,
3957: getBatchRequestor(), getProblemFactory(), this .out);
3958:
3959: if (this .compilerOptions.complianceLevel >= ClassFileConstants.JDK1_6
3960: && this .compilerOptions.processAnnotations) {
3961: if (checkVMVersion(ClassFileConstants.JDK1_6)) {
3962: initializeAnnotationProcessorManager();
3963: if (this .classNames != null) {
3964: this .batchCompiler
3965: .setBinaryTypes(processClassNames(this .batchCompiler.lookupEnvironment));
3966: }
3967: } else {
3968: // report a warning
3969: this .logger
3970: .logIncorrectVMVersionForAnnotationProcessing();
3971: }
3972: }
3973:
3974: // set the non-externally configurable options.
3975: this .compilerOptions.verbose = this .verbose;
3976: this .compilerOptions.produceReferenceInfo = this .produceRefInfo;
3977: try {
3978: this .logger.startLoggingSources();
3979: this .batchCompiler.compile(getCompilationUnits());
3980: } finally {
3981: this .logger.endLoggingSources();
3982: }
3983:
3984: if (this .extraProblems != null) {
3985: this .logger.loggingExtraProblems(this );
3986: this .extraProblems = null;
3987: }
3988: this .logger.printStats();
3989:
3990: // cleanup
3991: environment.cleanup();
3992: }
3993:
3994: private ReferenceBinding[] processClassNames(
3995: LookupEnvironment environment) throws InvalidInputException {
3996: // check for .class file presence in case of apt processing
3997: int length = this .classNames.length;
3998: ReferenceBinding[] referenceBindings = new ReferenceBinding[length];
3999: for (int i = 0; i < length; i++) {
4000: String currentName = this .classNames[i];
4001: char[][] compoundName = null;
4002: if (currentName.indexOf('.') != -1) {
4003: // consider names with '.' as fully qualified names
4004: char[] typeName = currentName.toCharArray();
4005: compoundName = CharOperation.splitOn('.', typeName);
4006: } else {
4007: compoundName = new char[][] { currentName.toCharArray() };
4008: }
4009: ReferenceBinding type = environment.getType(compoundName);
4010: if (type != null && type.isValidBinding()) {
4011: if (type.isBinaryBinding()) {
4012: referenceBindings[i] = type;
4013: }
4014: } else {
4015: throw new InvalidInputException(this .bind(
4016: "configure.invalidClassName", currentName));//$NON-NLS-1$
4017: }
4018: }
4019: return referenceBindings;
4020: }
4021:
4022: protected void initializeAnnotationProcessorManager() {
4023: try {
4024: Class c = Class
4025: .forName("org.eclipse.jdt.internal.compiler.apt.dispatch.BatchAnnotationProcessorManager"); //$NON-NLS-1$
4026: AbstractAnnotationProcessorManager annotationManager = (AbstractAnnotationProcessorManager) c
4027: .newInstance();
4028: annotationManager.configure(this , this .expandedCommandLine);
4029: annotationManager.setErr(this .err);
4030: annotationManager.setOut(this .out);
4031: this .batchCompiler.annotationProcessorManager = annotationManager;
4032: } catch (ClassNotFoundException e) {
4033: // ignore
4034: } catch (InstantiationException e) {
4035: // should not happen
4036: throw new org.eclipse.jdt.internal.compiler.problem.AbortCompilation();
4037: } catch (IllegalAccessException e) {
4038: // should not happen
4039: throw new org.eclipse.jdt.internal.compiler.problem.AbortCompilation();
4040: } catch (UnsupportedClassVersionError e) {
4041: // report a warning
4042: this .logger.logIncorrectVMVersionForAnnotationProcessing();
4043: }
4044: }
4045:
4046: public void printUsage() {
4047: printUsage("misc.usage"); //$NON-NLS-1$
4048: }
4049:
4050: private void printUsage(String sectionID) {
4051: this .logger.logUsage(this .bind(sectionID, new String[] {
4052: System.getProperty("path.separator"), //$NON-NLS-1$
4053: this .bind("compiler.name"), //$NON-NLS-1$
4054: this .bind("compiler.version"), //$NON-NLS-1$
4055: this .bind("compiler.copyright") //$NON-NLS-1$
4056: }));
4057: this .logger.flush();
4058: }
4059:
4060: /*
4061: * External API
4062: */
4063: public void processPathEntries(final int defaultSize,
4064: final ArrayList paths, final String currentPath,
4065: String customEncoding, boolean isSourceOnly,
4066: boolean rejectDestinationPathOnJars)
4067: throws InvalidInputException {
4068: String currentClasspathName = null;
4069: String currentDestinationPath = null;
4070: ArrayList currentRuleSpecs = new ArrayList(defaultSize);
4071: StringTokenizer tokenizer = new StringTokenizer(currentPath,
4072: File.pathSeparator + "[]", true); //$NON-NLS-1$
4073: ArrayList tokens = new ArrayList();
4074: while (tokenizer.hasMoreTokens()) {
4075: tokens.add(tokenizer.nextToken());
4076: }
4077: // state machine
4078: final int start = 0;
4079: final int readyToClose = 1;
4080: // 'path' 'path1[rule];path2'
4081: final int readyToCloseEndingWithRules = 2;
4082: // 'path[rule]' 'path1;path2[rule]'
4083: final int readyToCloseOrOtherEntry = 3;
4084: // 'path[rule];' 'path;' 'path1;path2;'
4085: final int rulesNeedAnotherRule = 4;
4086: // 'path[rule1;'
4087: final int rulesStart = 5;
4088: // 'path[' 'path1;path2['
4089: final int rulesReadyToClose = 6;
4090: // 'path[rule' 'path[rule1;rule2'
4091: final int destinationPathReadyToClose = 7;
4092: // 'path[-d bin'
4093: final int readyToCloseEndingWithDestinationPath = 8;
4094: // 'path[-d bin]' 'path[rule][-d bin]'
4095: final int destinationPathStart = 9;
4096: // 'path[rule]['
4097: final int bracketOpened = 10;
4098: // '.*[.*'
4099: final int bracketClosed = 11;
4100: // '.*([.*])+'
4101:
4102: final int error = 99;
4103: int state = start;
4104: String token = null;
4105: int cursor = 0, tokensNb = tokens.size(), bracket = -1;
4106: while (cursor < tokensNb && state != error) {
4107: token = (String) tokens.get(cursor++);
4108: if (token.equals(File.pathSeparator)) {
4109: switch (state) {
4110: case start:
4111: case readyToCloseOrOtherEntry:
4112: case bracketOpened:
4113: break;
4114: case readyToClose:
4115: case readyToCloseEndingWithRules:
4116: case readyToCloseEndingWithDestinationPath:
4117: state = readyToCloseOrOtherEntry;
4118: addNewEntry(paths, currentClasspathName,
4119: currentRuleSpecs, customEncoding,
4120: currentDestinationPath, isSourceOnly,
4121: rejectDestinationPathOnJars);
4122: currentRuleSpecs.clear();
4123: break;
4124: case rulesReadyToClose:
4125: state = rulesNeedAnotherRule;
4126: break;
4127: case destinationPathReadyToClose:
4128: throw new InvalidInputException(this .bind(
4129: "configure.incorrectDestinationPathEntry", //$NON-NLS-1$
4130: currentPath));
4131: case bracketClosed:
4132: cursor = bracket + 1;
4133: state = rulesStart;
4134: break;
4135: default:
4136: state = error;
4137: }
4138: } else if (token.equals("[")) { //$NON-NLS-1$
4139: switch (state) {
4140: case start:
4141: currentClasspathName = ""; //$NON-NLS-1$
4142: case readyToClose:
4143: bracket = cursor - 1;
4144: case bracketClosed:
4145: state = bracketOpened;
4146: break;
4147: case readyToCloseEndingWithRules:
4148: state = destinationPathStart;
4149: break;
4150: case readyToCloseEndingWithDestinationPath:
4151: state = rulesStart;
4152: break;
4153: case bracketOpened:
4154: default:
4155: state = error;
4156: }
4157: } else if (token.equals("]")) { //$NON-NLS-1$
4158: switch (state) {
4159: case rulesReadyToClose:
4160: state = readyToCloseEndingWithRules;
4161: break;
4162: case destinationPathReadyToClose:
4163: state = readyToCloseEndingWithDestinationPath;
4164: break;
4165: case bracketOpened:
4166: state = bracketClosed;
4167: break;
4168: case bracketClosed:
4169: default:
4170: state = error;
4171: }
4172: } else {
4173: // regular word
4174: switch (state) {
4175: case start:
4176: case readyToCloseOrOtherEntry:
4177: state = readyToClose;
4178: currentClasspathName = token;
4179: break;
4180: case rulesStart:
4181: if (token.startsWith("-d ")) { //$NON-NLS-1$
4182: if (currentDestinationPath != null) {
4183: throw new InvalidInputException(
4184: this
4185: .bind(
4186: "configure.duplicateDestinationPathEntry", //$NON-NLS-1$
4187: currentPath));
4188: }
4189: currentDestinationPath = token.substring(3)
4190: .trim();
4191: state = destinationPathReadyToClose;
4192: break;
4193: } // else we proceed with a rule
4194: case rulesNeedAnotherRule:
4195: if (currentDestinationPath != null) {
4196: throw new InvalidInputException(
4197: this
4198: .bind(
4199: "configure.accessRuleAfterDestinationPath", //$NON-NLS-1$
4200: currentPath));
4201: }
4202: state = rulesReadyToClose;
4203: currentRuleSpecs.add(token);
4204: break;
4205: case destinationPathStart:
4206: if (!token.startsWith("-d ")) { //$NON-NLS-1$
4207: state = error;
4208: } else {
4209: currentDestinationPath = token.substring(3)
4210: .trim();
4211: state = destinationPathReadyToClose;
4212: }
4213: break;
4214: case bracketClosed:
4215: for (int i = bracket; i < cursor; i++) {
4216: currentClasspathName += (String) tokens.get(i);
4217: }
4218: state = readyToClose;
4219: break;
4220: case bracketOpened:
4221: break;
4222: default:
4223: state = error;
4224: }
4225: }
4226: if (state == bracketClosed && cursor == tokensNb) {
4227: cursor = bracket + 1;
4228: state = rulesStart;
4229: }
4230: }
4231: switch (state) {
4232: case readyToCloseOrOtherEntry:
4233: break;
4234: case readyToClose:
4235: case readyToCloseEndingWithRules:
4236: case readyToCloseEndingWithDestinationPath:
4237: addNewEntry(paths, currentClasspathName, currentRuleSpecs,
4238: customEncoding, currentDestinationPath,
4239: isSourceOnly, rejectDestinationPathOnJars);
4240: break;
4241: case bracketOpened:
4242: case bracketClosed:
4243: default:
4244: // we go on anyway
4245: if (currentPath.length() != 0) {
4246: this .logger.logIncorrectClasspath(currentPath);
4247: }
4248: }
4249: }
4250:
4251: private int processPaths(String[] args, int index,
4252: String currentArg, ArrayList paths)
4253: throws InvalidInputException {
4254: int localIndex = index;
4255: int count = 0;
4256: for (int i = 0, max = currentArg.length(); i < max; i++) {
4257: switch (currentArg.charAt(i)) {
4258: case '[':
4259: count++;
4260: break;
4261: case ']':
4262: count--;
4263: break;
4264: }
4265: }
4266: if (count == 0) {
4267: paths.add(currentArg);
4268: } else if (count > 1) {
4269: throw new InvalidInputException(this .bind(
4270: "configure.unexpectedBracket", //$NON-NLS-1$
4271: currentArg));
4272: } else {
4273: StringBuffer currentPath = new StringBuffer(currentArg);
4274: while (true) {
4275: if (localIndex >= args.length) {
4276: throw new InvalidInputException(this .bind(
4277: "configure.unexpectedBracket", //$NON-NLS-1$
4278: currentArg));
4279: }
4280: localIndex++;
4281: String nextArg = args[localIndex];
4282: for (int i = 0, max = nextArg.length(); i < max; i++) {
4283: switch (nextArg.charAt(i)) {
4284: case '[':
4285: if (count > 1) {
4286: throw new InvalidInputException(this .bind(
4287: "configure.unexpectedBracket", //$NON-NLS-1$
4288: nextArg));
4289: }
4290: count++;
4291: break;
4292: case ']':
4293: count--;
4294: break;
4295: }
4296: }
4297: if (count == 0) {
4298: currentPath.append(' ');
4299: currentPath.append(nextArg);
4300: paths.add(currentPath.toString());
4301: return localIndex - index;
4302: } else if (count < 0) {
4303: throw new InvalidInputException(this .bind(
4304: "configure.unexpectedBracket", //$NON-NLS-1$
4305: nextArg));
4306: } else {
4307: currentPath.append(' ');
4308: currentPath.append(nextArg);
4309: }
4310: }
4311:
4312: }
4313: return localIndex - index;
4314: }
4315:
4316: private int processPaths(String[] args, int index,
4317: String currentArg, String[] paths)
4318: throws InvalidInputException {
4319: int localIndex = index;
4320: int count = 0;
4321: for (int i = 0, max = currentArg.length(); i < max; i++) {
4322: switch (currentArg.charAt(i)) {
4323: case '[':
4324: count++;
4325: break;
4326: case ']':
4327: count--;
4328: break;
4329: }
4330: }
4331: if (count == 0) {
4332: paths[0] = currentArg;
4333: } else {
4334: StringBuffer currentPath = new StringBuffer(currentArg);
4335: while (true) {
4336: localIndex++;
4337: if (localIndex >= args.length) {
4338: throw new InvalidInputException(this .bind(
4339: "configure.unexpectedBracket", //$NON-NLS-1$
4340: currentArg));
4341: }
4342: String nextArg = args[localIndex];
4343: for (int i = 0, max = nextArg.length(); i < max; i++) {
4344: switch (nextArg.charAt(i)) {
4345: case '[':
4346: if (count > 1) {
4347: throw new InvalidInputException(this .bind(
4348: "configure.unexpectedBracket", //$NON-NLS-1$
4349: currentArg));
4350: }
4351: count++;
4352: break;
4353: case ']':
4354: count--;
4355: break;
4356: }
4357: }
4358: if (count == 0) {
4359: currentPath.append(' ');
4360: currentPath.append(nextArg);
4361: paths[0] = currentPath.toString();
4362: return localIndex - index;
4363: } else if (count < 0) {
4364: throw new InvalidInputException(this .bind(
4365: "configure.unexpectedBracket", //$NON-NLS-1$
4366: currentArg));
4367: } else {
4368: currentPath.append(' ');
4369: currentPath.append(nextArg);
4370: }
4371: }
4372:
4373: }
4374: return localIndex - index;
4375: }
4376:
4377: /**
4378: * Creates a NLS catalog for the given locale.
4379: */
4380: public void relocalize() {
4381: relocalize(Locale.getDefault());
4382: }
4383:
4384: private void relocalize(Locale locale) {
4385: this .compilerLocale = locale;
4386: try {
4387: this .bundle = ResourceBundleFactory.getBundle(locale);
4388: } catch (MissingResourceException e) {
4389: System.out
4390: .println("Missing resource : " + Main.bundleName.replace('.', '/') + ".properties for locale " + locale); //$NON-NLS-1$//$NON-NLS-2$
4391: throw e;
4392: }
4393: }
4394:
4395: /*
4396: * External API
4397: */
4398: public void setLocale(Locale locale) {
4399: relocalize(locale);
4400: }
4401:
4402: /*
4403: * External API
4404: */
4405: public void setDestinationPath(String dest) {
4406: this .destinationPath = dest;
4407: }
4408:
4409: /*
4410: * External API
4411: */
4412: protected void setPaths(ArrayList bootclasspaths,
4413: String sourcepathClasspathArg,
4414: ArrayList sourcepathClasspaths, ArrayList classpaths,
4415: ArrayList extdirsClasspaths,
4416: ArrayList endorsedDirClasspaths, String customEncoding)
4417: throws InvalidInputException {
4418:
4419: // process bootclasspath, classpath and sourcepaths
4420: bootclasspaths = handleBootclasspath(bootclasspaths,
4421: customEncoding);
4422:
4423: classpaths = handleClasspath(classpaths, customEncoding);
4424:
4425: if (sourcepathClasspathArg != null) {
4426: processPathEntries(DEFAULT_SIZE_CLASSPATH,
4427: sourcepathClasspaths, sourcepathClasspathArg,
4428: customEncoding, true, false);
4429: }
4430:
4431: /*
4432: * Feed endorsedDirClasspath according to:
4433: * - -extdirs first if present;
4434: * - else java.ext.dirs if defined;
4435: * - else default extensions directory for the platform.
4436: */
4437: extdirsClasspaths = handleExtdirs(extdirsClasspaths);
4438:
4439: endorsedDirClasspaths = handleEndorseddirs(endorsedDirClasspaths);
4440:
4441: /*
4442: * Concatenate classpath entries
4443: * We put the bootclasspath at the beginning of the classpath
4444: * entries, followed by the extension libraries, followed by
4445: * the sourcepath followed by the classpath. All classpath
4446: * entries are searched for both sources and binaries except
4447: * the sourcepath entries which are searched for sources only.
4448: */
4449: bootclasspaths.addAll(endorsedDirClasspaths);
4450: bootclasspaths.addAll(extdirsClasspaths);
4451: bootclasspaths.addAll(sourcepathClasspaths);
4452: bootclasspaths.addAll(classpaths);
4453: classpaths = bootclasspaths;
4454: classpaths = FileSystem.ClasspathNormalizer
4455: .normalize(classpaths);
4456: this .checkedClasspaths = new FileSystem.Classpath[classpaths
4457: .size()];
4458: classpaths.toArray(this .checkedClasspaths);
4459: this .logger.logClasspath(this .checkedClasspaths);
4460: }
4461:
4462: protected void validateOptions(boolean didSpecifyCompliance)
4463: throws InvalidInputException {
4464: if (didSpecifyCompliance) {
4465: Object version = this .options
4466: .get(CompilerOptions.OPTION_Compliance);
4467: if (CompilerOptions.VERSION_1_3.equals(version)) {
4468: if (!this .didSpecifySource)
4469: this .options.put(CompilerOptions.OPTION_Source,
4470: CompilerOptions.VERSION_1_3);
4471: if (!this .didSpecifyTarget)
4472: this .options.put(
4473: CompilerOptions.OPTION_TargetPlatform,
4474: CompilerOptions.VERSION_1_1);
4475: } else if (CompilerOptions.VERSION_1_4.equals(version)) {
4476: if (this .didSpecifySource) {
4477: Object source = this .options
4478: .get(CompilerOptions.OPTION_Source);
4479: if (CompilerOptions.VERSION_1_3.equals(source)) {
4480: if (!this .didSpecifyTarget)
4481: this .options
4482: .put(
4483: CompilerOptions.OPTION_TargetPlatform,
4484: CompilerOptions.VERSION_1_2);
4485: } else if (CompilerOptions.VERSION_1_4
4486: .equals(source)) {
4487: if (!this .didSpecifyTarget)
4488: this .options
4489: .put(
4490: CompilerOptions.OPTION_TargetPlatform,
4491: CompilerOptions.VERSION_1_4);
4492: }
4493: } else {
4494: this .options.put(CompilerOptions.OPTION_Source,
4495: CompilerOptions.VERSION_1_3);
4496: if (!this .didSpecifyTarget)
4497: this .options.put(
4498: CompilerOptions.OPTION_TargetPlatform,
4499: CompilerOptions.VERSION_1_2);
4500: }
4501: } else if (CompilerOptions.VERSION_1_5.equals(version)) {
4502: if (this .didSpecifySource) {
4503: Object source = this .options
4504: .get(CompilerOptions.OPTION_Source);
4505: if (CompilerOptions.VERSION_1_3.equals(source)
4506: || CompilerOptions.VERSION_1_4
4507: .equals(source)) {
4508: if (!this .didSpecifyTarget)
4509: this .options
4510: .put(
4511: CompilerOptions.OPTION_TargetPlatform,
4512: CompilerOptions.VERSION_1_4);
4513: } else if (CompilerOptions.VERSION_1_5
4514: .equals(source)) {
4515: if (!this .didSpecifyTarget)
4516: this .options
4517: .put(
4518: CompilerOptions.OPTION_TargetPlatform,
4519: CompilerOptions.VERSION_1_5);
4520: }
4521: } else {
4522: this .options.put(CompilerOptions.OPTION_Source,
4523: CompilerOptions.VERSION_1_5);
4524: if (!this .didSpecifyTarget)
4525: this .options.put(
4526: CompilerOptions.OPTION_TargetPlatform,
4527: CompilerOptions.VERSION_1_5);
4528: }
4529: } else if (CompilerOptions.VERSION_1_6.equals(version)) {
4530: if (this .didSpecifySource) {
4531: Object source = this .options
4532: .get(CompilerOptions.OPTION_Source);
4533: if (CompilerOptions.VERSION_1_3.equals(source)
4534: || CompilerOptions.VERSION_1_4
4535: .equals(source)) {
4536: if (!this .didSpecifyTarget)
4537: this .options
4538: .put(
4539: CompilerOptions.OPTION_TargetPlatform,
4540: CompilerOptions.VERSION_1_4);
4541: } else if (CompilerOptions.VERSION_1_5
4542: .equals(source)
4543: || CompilerOptions.VERSION_1_6
4544: .equals(source)) {
4545: if (!this .didSpecifyTarget)
4546: this .options
4547: .put(
4548: CompilerOptions.OPTION_TargetPlatform,
4549: CompilerOptions.VERSION_1_6);
4550: }
4551: } else {
4552: this .options.put(CompilerOptions.OPTION_Source,
4553: CompilerOptions.VERSION_1_6);
4554: if (!this .didSpecifyTarget)
4555: this .options.put(
4556: CompilerOptions.OPTION_TargetPlatform,
4557: CompilerOptions.VERSION_1_6);
4558: }
4559: } else if (CompilerOptions.VERSION_1_7.equals(version)) {
4560: if (this .didSpecifySource) {
4561: Object source = this .options
4562: .get(CompilerOptions.OPTION_Source);
4563: if (CompilerOptions.VERSION_1_3.equals(source)
4564: || CompilerOptions.VERSION_1_4
4565: .equals(source)) {
4566: if (!this .didSpecifyTarget)
4567: this .options
4568: .put(
4569: CompilerOptions.OPTION_TargetPlatform,
4570: CompilerOptions.VERSION_1_4);
4571: } else if (CompilerOptions.VERSION_1_5
4572: .equals(source)
4573: || CompilerOptions.VERSION_1_6
4574: .equals(source)) {
4575: if (!this .didSpecifyTarget)
4576: this .options
4577: .put(
4578: CompilerOptions.OPTION_TargetPlatform,
4579: CompilerOptions.VERSION_1_6);
4580: } else if (CompilerOptions.VERSION_1_7
4581: .equals(source)) {
4582: if (!this .didSpecifyTarget)
4583: this .options
4584: .put(
4585: CompilerOptions.OPTION_TargetPlatform,
4586: CompilerOptions.VERSION_1_7);
4587: }
4588: } else {
4589: this .options.put(CompilerOptions.OPTION_Source,
4590: CompilerOptions.VERSION_1_7);
4591: if (!this .didSpecifyTarget)
4592: this .options.put(
4593: CompilerOptions.OPTION_TargetPlatform,
4594: CompilerOptions.VERSION_1_7);
4595: }
4596: }
4597: } else if (this .didSpecifySource) {
4598: Object version = this .options
4599: .get(CompilerOptions.OPTION_Source);
4600: // default is source 1.3 target 1.2 and compliance 1.4
4601: if (CompilerOptions.VERSION_1_4.equals(version)) {
4602: if (!didSpecifyCompliance)
4603: this .options.put(CompilerOptions.OPTION_Compliance,
4604: CompilerOptions.VERSION_1_4);
4605: if (!this .didSpecifyTarget)
4606: this .options.put(
4607: CompilerOptions.OPTION_TargetPlatform,
4608: CompilerOptions.VERSION_1_4);
4609: } else if (CompilerOptions.VERSION_1_5.equals(version)) {
4610: if (!didSpecifyCompliance)
4611: this .options.put(CompilerOptions.OPTION_Compliance,
4612: CompilerOptions.VERSION_1_5);
4613: if (!this .didSpecifyTarget)
4614: this .options.put(
4615: CompilerOptions.OPTION_TargetPlatform,
4616: CompilerOptions.VERSION_1_5);
4617: } else if (CompilerOptions.VERSION_1_6.equals(version)) {
4618: if (!didSpecifyCompliance)
4619: this .options.put(CompilerOptions.OPTION_Compliance,
4620: CompilerOptions.VERSION_1_6);
4621: if (!this .didSpecifyTarget)
4622: this .options.put(
4623: CompilerOptions.OPTION_TargetPlatform,
4624: CompilerOptions.VERSION_1_6);
4625: } else if (CompilerOptions.VERSION_1_7.equals(version)) {
4626: if (!didSpecifyCompliance)
4627: this .options.put(CompilerOptions.OPTION_Compliance,
4628: CompilerOptions.VERSION_1_7);
4629: if (!this .didSpecifyTarget)
4630: this .options.put(
4631: CompilerOptions.OPTION_TargetPlatform,
4632: CompilerOptions.VERSION_1_7);
4633: }
4634: }
4635:
4636: final Object sourceVersion = this .options
4637: .get(CompilerOptions.OPTION_Source);
4638: final Object compliance = this .options
4639: .get(CompilerOptions.OPTION_Compliance);
4640: if (sourceVersion.equals(CompilerOptions.VERSION_1_7)
4641: && CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK1_7) {
4642: // compliance must be 1.7 if source is 1.7
4643: throw new InvalidInputException(
4644: this
4645: .bind(
4646: "configure.incompatibleComplianceForSource", (String) this .options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_7)); //$NON-NLS-1$
4647: } else if (sourceVersion.equals(CompilerOptions.VERSION_1_6)
4648: && CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK1_6) {
4649: // compliance must be 1.6 if source is 1.6
4650: throw new InvalidInputException(
4651: this
4652: .bind(
4653: "configure.incompatibleComplianceForSource", (String) this .options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_6)); //$NON-NLS-1$
4654: } else if (sourceVersion.equals(CompilerOptions.VERSION_1_5)
4655: && CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK1_5) {
4656: // compliance must be 1.5 if source is 1.5
4657: throw new InvalidInputException(
4658: this
4659: .bind(
4660: "configure.incompatibleComplianceForSource", (String) this .options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_5)); //$NON-NLS-1$
4661: } else if (sourceVersion.equals(CompilerOptions.VERSION_1_4)
4662: && CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK1_4) {
4663: // compliance must be 1.4 if source is 1.4
4664: throw new InvalidInputException(
4665: this
4666: .bind(
4667: "configure.incompatibleComplianceForSource", (String) this .options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_4)); //$NON-NLS-1$
4668: }
4669:
4670: // check and set compliance/source/target compatibilities
4671: if (this .didSpecifyTarget) {
4672: final Object targetVersion = this .options
4673: .get(CompilerOptions.OPTION_TargetPlatform);
4674: // tolerate jsr14 target
4675: if (CompilerOptions.VERSION_JSR14.equals(targetVersion)) {
4676: // expecting source >= 1.5
4677: if (CompilerOptions.versionToJdkLevel(sourceVersion) < ClassFileConstants.JDK1_5) {
4678: throw new InvalidInputException(
4679: this
4680: .bind(
4681: "configure.incompatibleTargetForGenericSource", (String) targetVersion, (String) sourceVersion)); //$NON-NLS-1$
4682: }
4683: } else if (CompilerOptions.VERSION_CLDC1_1
4684: .equals(targetVersion)) {
4685: if (this .didSpecifySource
4686: && CompilerOptions
4687: .versionToJdkLevel(sourceVersion) >= ClassFileConstants.JDK1_4) {
4688: throw new InvalidInputException(
4689: this
4690: .bind(
4691: "configure.incompatibleSourceForCldcTarget", (String) targetVersion, (String) sourceVersion)); //$NON-NLS-1$
4692: }
4693: if (CompilerOptions.versionToJdkLevel(compliance) >= ClassFileConstants.JDK1_5) {
4694: throw new InvalidInputException(
4695: this
4696: .bind(
4697: "configure.incompatibleComplianceForCldcTarget", (String) targetVersion, (String) sourceVersion)); //$NON-NLS-1$
4698: }
4699: } else {
4700: // target must be 1.7 if source is 1.7
4701: if (CompilerOptions.versionToJdkLevel(sourceVersion) >= ClassFileConstants.JDK1_7
4702: && CompilerOptions
4703: .versionToJdkLevel(targetVersion) < ClassFileConstants.JDK1_7) {
4704: throw new InvalidInputException(
4705: this
4706: .bind(
4707: "configure.incompatibleTargetForSource", (String) targetVersion, CompilerOptions.VERSION_1_7)); //$NON-NLS-1$
4708: }
4709: // target must be 1.6 if source is 1.6
4710: if (CompilerOptions.versionToJdkLevel(sourceVersion) >= ClassFileConstants.JDK1_6
4711: && CompilerOptions
4712: .versionToJdkLevel(targetVersion) < ClassFileConstants.JDK1_6) {
4713: throw new InvalidInputException(
4714: this
4715: .bind(
4716: "configure.incompatibleTargetForSource", (String) targetVersion, CompilerOptions.VERSION_1_6)); //$NON-NLS-1$
4717: }
4718: // target must be 1.5 if source is 1.5
4719: if (CompilerOptions.versionToJdkLevel(sourceVersion) >= ClassFileConstants.JDK1_5
4720: && CompilerOptions
4721: .versionToJdkLevel(targetVersion) < ClassFileConstants.JDK1_5) {
4722: throw new InvalidInputException(
4723: this
4724: .bind(
4725: "configure.incompatibleTargetForSource", (String) targetVersion, CompilerOptions.VERSION_1_5)); //$NON-NLS-1$
4726: }
4727: // target must be 1.4 if source is 1.4
4728: if (CompilerOptions.versionToJdkLevel(sourceVersion) >= ClassFileConstants.JDK1_4
4729: && CompilerOptions
4730: .versionToJdkLevel(targetVersion) < ClassFileConstants.JDK1_4) {
4731: throw new InvalidInputException(
4732: this
4733: .bind(
4734: "configure.incompatibleTargetForSource", (String) targetVersion, CompilerOptions.VERSION_1_4)); //$NON-NLS-1$
4735: }
4736: // target cannot be greater than compliance level
4737: if (CompilerOptions.versionToJdkLevel(compliance) < CompilerOptions
4738: .versionToJdkLevel(targetVersion)) {
4739: throw new InvalidInputException(
4740: this
4741: .bind(
4742: "configure.incompatibleComplianceForTarget", (String) this .options.get(CompilerOptions.OPTION_Compliance), (String) targetVersion)); //$NON-NLS-1$
4743: }
4744: }
4745: }
4746: }
4747: }
|