| /******************************************************************************* |
| * Copyright (c) 2000, 2004 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Common Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/cpl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.compiler.batch; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.FilenameFilter; |
| import java.io.IOException; |
| import java.io.InputStreamReader; |
| import java.io.LineNumberReader; |
| import java.io.PrintWriter; |
| import java.io.StringReader; |
| import java.io.UnsupportedEncodingException; |
| import java.util.Enumeration; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.MissingResourceException; |
| import java.util.ResourceBundle; |
| import java.util.StringTokenizer; |
| |
| import org.eclipse.jdt.core.compiler.CharOperation; |
| import org.eclipse.jdt.core.compiler.InvalidInputException; |
| import org.eclipse.jdt.core.compiler.IProblem; |
| import org.eclipse.jdt.internal.compiler.ClassFile; |
| import org.eclipse.jdt.internal.compiler.CompilationResult; |
| import org.eclipse.jdt.internal.compiler.Compiler; |
| import org.eclipse.jdt.internal.compiler.ICompilerRequestor; |
| import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy; |
| import org.eclipse.jdt.internal.compiler.IProblemFactory; |
| import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; |
| import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; |
| import org.eclipse.jdt.internal.compiler.env.INameEnvironment; |
| import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; |
| import org.eclipse.jdt.internal.compiler.problem.DefaultProblem; |
| import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; |
| import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; |
| import org.eclipse.jdt.internal.compiler.util.SuffixConstants; |
| import org.eclipse.jdt.internal.compiler.util.HashtableOfObject; |
| import org.eclipse.jdt.internal.compiler.util.Util; |
| |
| public class Main implements ProblemSeverities, SuffixConstants { |
| |
| static { |
| relocalize(); |
| } |
| |
| /* Bundle containing messages */ |
| public static ResourceBundle bundle; |
| public final static String bundleName = |
| "org.eclipse.jdt.internal.compiler.batch.messages"; //$NON-NLS-1$ |
| |
| public final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$ |
| public final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$ |
| public String[] classpaths; |
| public String destinationPath; |
| public String[] encodings; |
| public PrintWriter err; |
| public int exportedClassFilesCounter; |
| public String[] filenames; |
| public boolean generatePackagesStructure; |
| public int globalErrorsCount; |
| public int globalProblemsCount; |
| public int globalWarningsCount; |
| public long lineCount; |
| public String log; |
| |
| public boolean noWarn = false; |
| |
| public Map options; |
| public CompilerOptions compilerOptions; // read-only |
| |
| public PrintWriter out; |
| |
| public boolean proceed = true; |
| public boolean proceedOnError = false; |
| public boolean produceRefInfo = false; |
| public int repetitions; |
| public int maxProblems; |
| public boolean showProgress = false; |
| public boolean systemExitWhenFinished = true; |
| public long startTime; |
| public boolean timing = false; |
| public boolean verbose = false; |
| |
| public Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhenFinished) { |
| |
| this.out = outWriter; |
| this.err = errWriter; |
| this.systemExitWhenFinished = systemExitWhenFinished; |
| this.options = new CompilerOptions().getMap(); |
| } |
| |
| /** |
| * Lookup the message with the given ID in this catalog |
| * @param id |
| * @return |
| */ |
| public static String bind(String id) { |
| return bind(id, (String[]) null); |
| } |
| |
| /** |
| * Lookup the message with the given ID in this catalog and bind its |
| * substitution locations with the given string. |
| * @param id |
| * @param binding |
| * @return |
| */ |
| public static String bind(String id, String binding) { |
| return bind(id, new String[] { binding }); |
| } |
| |
| /** |
| * Lookup the message with the given ID in this catalog and bind its |
| * substitution locations with the given strings. |
| * @param id |
| * @param binding1 |
| * @param binding2 |
| * @return |
| */ |
| public static String bind(String id, String binding1, String binding2) { |
| return bind(id, new String[] { binding1, binding2 }); |
| } |
| |
| /** |
| * Lookup the message with the given ID in this catalog and bind its |
| * substitution locations with the given string values. |
| * @param id |
| * @param bindings |
| * @return |
| */ |
| public static String bind(String id, String[] bindings) { |
| if (id == null) |
| return "No message available"; //$NON-NLS-1$ |
| String message = null; |
| try { |
| message = bundle.getString(id); |
| } catch (MissingResourceException e) { |
| // If we got an exception looking for the message, fail gracefully by just returning |
| // the id we were looking for. In most cases this is semi-informative so is not too bad. |
| return "Missing message: " + id + " in: " + bundleName; //$NON-NLS-2$ //$NON-NLS-1$ |
| } |
| // for compatibility with MessageFormat which eliminates double quotes in original message |
| char[] messageWithNoDoubleQuotes = |
| CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE); |
| message = new String(messageWithNoDoubleQuotes); |
| |
| int length = message.length(); |
| int start = -1; |
| int end = length; |
| StringBuffer output = null; |
| while (true) { |
| if ((end = message.indexOf('{', start)) > -1) { |
| if (output == null) output = new StringBuffer(80); |
| output.append(message.substring(start + 1, end)); |
| if ((start = message.indexOf('}', end)) > -1) { |
| int index = -1; |
| try { |
| index = Integer.parseInt(message.substring(end + 1, start)); |
| output.append(bindings[index]); |
| } catch (NumberFormatException nfe) { // could be nested message ID {compiler.name} |
| String argId = message.substring(end + 1, start); |
| boolean done = false; |
| if (!id.equals(argId)) { |
| String argMessage = null; |
| try { |
| argMessage = bundle.getString(argId); |
| output.append(argMessage); |
| done = true; |
| } catch (MissingResourceException e) { |
| // missing the right resource |
| } |
| } |
| if (!done) output.append(message.substring(end + 1, start + 1)); |
| } catch (ArrayIndexOutOfBoundsException e) { |
| output.append("{missing " + Integer.toString(index) + "}"); //$NON-NLS-2$ //$NON-NLS-1$ |
| } |
| } else { |
| output.append(message.substring(end, length)); |
| break; |
| } |
| } else { |
| if (output == null) return message; |
| output.append(message.substring(start + 1, length)); |
| break; |
| } |
| } |
| return output.toString(); |
| } |
| |
| /* |
| * Internal IDE API |
| */ |
| public static boolean compile(String commandLine) { |
| |
| return compile(commandLine, new PrintWriter(System.out), new PrintWriter(System.err)); |
| } |
| |
| /* |
| * Internal IDE API for test harness purpose |
| */ |
| public static boolean compile(String commandLine, PrintWriter outWriter, PrintWriter errWriter) { |
| |
| return new Main(outWriter, errWriter, false).compile(tokenize(commandLine)); |
| } |
| |
| /* |
| * External API |
| */ |
| |
| public static void main(String[] argv) { |
| new Main(new PrintWriter(System.out), new PrintWriter(System.err), true).compile(argv); |
| } |
| |
| /** |
| * Creates a NLS catalog for the given locale. |
| */ |
| public static void relocalize() { |
| try { |
| bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault()); |
| } catch(MissingResourceException e) { |
| System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$ |
| throw e; |
| } |
| } |
| |
| public static String[] tokenize(String commandLine) { |
| |
| int count = 0; |
| String[] arguments = new String[10]; |
| StringTokenizer tokenizer = new StringTokenizer(commandLine, " \"", true); //$NON-NLS-1$ |
| String token = ""; //$NON-NLS-1$ |
| boolean insideQuotes = false; |
| boolean startNewToken = true; |
| |
| // take care to quotes on the command line |
| // 'xxx "aaa bbb";ccc yyy' ---> {"xxx", "aaa bbb;ccc", "yyy" } |
| // 'xxx "aaa bbb;ccc" yyy' ---> {"xxx", "aaa bbb;ccc", "yyy" } |
| // 'xxx "aaa bbb";"ccc" yyy' ---> {"xxx", "aaa bbb;ccc", "yyy" } |
| // 'xxx/"aaa bbb";"ccc" yyy' ---> {"xxx/aaa bbb;ccc", "yyy" } |
| while (tokenizer.hasMoreTokens()) { |
| token = tokenizer.nextToken(); |
| |
| if (token.equals(" ")) { //$NON-NLS-1$ |
| if (insideQuotes) { |
| arguments[count - 1] += token; |
| startNewToken = false; |
| } else { |
| startNewToken = true; |
| } |
| } else if (token.equals("\"")) { //$NON-NLS-1$ |
| if (!insideQuotes && startNewToken) { //$NON-NLS-1$ |
| if (count == arguments.length) |
| System.arraycopy(arguments, 0, (arguments = new String[count * 2]), 0, count); |
| arguments[count++] = ""; //$NON-NLS-1$ |
| } |
| insideQuotes = !insideQuotes; |
| startNewToken = false; |
| } else { |
| if (insideQuotes) { |
| arguments[count - 1] += token; |
| } else { |
| if (token.length() > 0 && !startNewToken) { |
| arguments[count - 1] += token; |
| } else { |
| if (count == arguments.length) |
| System.arraycopy(arguments, 0, (arguments = new String[count * 2]), 0, count); |
| String trimmedToken = token.trim(); |
| if (trimmedToken.length() != 0) { |
| arguments[count++] = trimmedToken; |
| } |
| } |
| } |
| startNewToken = false; |
| } |
| } |
| System.arraycopy(arguments, 0, arguments = new String[count], 0, count); |
| return arguments; |
| } |
| |
| /* |
| * Low-level API performing the actual compilation |
| */ |
| public boolean compile(String[] argv) { |
| |
| // decode command line arguments |
| try { |
| configure(argv); |
| if (this.proceed) { |
| // if (this.verbose) { |
| // System.out.println(new CompilerOptions(this.options)); |
| // } |
| if (this.showProgress) |
| this.out.println(Main.bind("progress.compiling")); //$NON-NLS-1$ |
| for (int i = 0; i < this.repetitions; i++) { |
| this.globalProblemsCount = 0; |
| this.globalErrorsCount = 0; |
| this.globalWarningsCount = 0; |
| this.lineCount = 0; |
| this.exportedClassFilesCounter = 0; |
| |
| if (this.repetitions > 1) { |
| this.out.flush(); |
| this.out.println( |
| Main.bind( |
| "compile.repetition", //$NON-NLS-1$ |
| String.valueOf(i + 1), |
| String.valueOf(this.repetitions))); |
| } |
| // request compilation |
| performCompilation(); |
| } |
| if (this.showProgress) |
| this.out.println(); |
| } |
| if (this.systemExitWhenFinished) { |
| this.out.flush(); |
| this.err.flush(); |
| System.exit(this.globalErrorsCount > 0 ? -1 : 0); |
| } |
| } catch (InvalidInputException e) { |
| this.err.println(e.getMessage()); |
| this.err.println("------------------------"); //$NON-NLS-1$ |
| printUsage(); |
| if (this.systemExitWhenFinished) { |
| System.exit(-1); |
| } |
| return false; |
| } catch (ThreadDeath e) { // do not stop this one |
| throw e; |
| } catch (Throwable e) { // internal compiler error |
| if (this.systemExitWhenFinished) { |
| this.out.flush(); |
| this.err.flush(); |
| if (this.log != null) { |
| this.err.close(); |
| } |
| System.exit(-1); |
| } |
| return false; |
| //e.printStackTrace(); |
| } finally { |
| this.out.flush(); |
| this.err.flush(); |
| if (this.log != null) { |
| this.err.close(); |
| } |
| } |
| if (this.globalErrorsCount == 0){ |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| /* |
| Decode the command line arguments |
| */ |
| public void configure(String[] argv) throws InvalidInputException { |
| |
| if ((argv == null) || (argv.length == 0)) { |
| printUsage(); |
| return; |
| } |
| final int InsideClasspath = 1; |
| final int InsideDestinationPath = 2; |
| final int TargetSetting = 4; |
| final int InsideLog = 8; |
| final int InsideRepetition = 16; |
| final int InsideSource = 32; |
| final int InsideDefaultEncoding = 64; |
| final int InsideBootClasspath = 128; |
| final int InsideMaxProblems = 256; |
| final int Default = 0; |
| String[] bootclasspaths = null; |
| int DEFAULT_SIZE_CLASSPATH = 4; |
| int pathCount = 0; |
| int bootclasspathCount = 0; |
| int index = -1, filesCount = 0, argCount = argv.length; |
| int mode = Default; |
| this.repetitions = 0; |
| boolean printUsageRequired = false; |
| boolean printVersionRequired = false; |
| |
| boolean didSpecifyCompliance = false; |
| boolean didSpecifyDefaultEncoding = false; |
| boolean didSpecifyTarget = false; |
| boolean didSpecifyDeprecation = false; |
| boolean didSpecifyWarnings = false; |
| |
| String customEncoding = null; |
| String currentArg = ""; //$NON-NLS-1$ |
| |
| // expand the command line if necessary |
| boolean needExpansion = false; |
| loop: for (int i = 0; i < argCount; i++) { |
| if (argv[i].startsWith("@")) { //$NON-NLS-1$ |
| needExpansion = true; |
| break loop; |
| } |
| } |
| |
| String[] newCommandLineArgs = null; |
| if (needExpansion) { |
| newCommandLineArgs = new String[argCount]; |
| index = 0; |
| for (int i = 0; i < argCount; i++) { |
| String[] newArgs = null; |
| String arg = argv[i].trim(); |
| if (arg.startsWith("@")) { //$NON-NLS-1$ |
| try { |
| LineNumberReader reader = new LineNumberReader(new StringReader(new String(Util.getFileCharContent(new File(arg.substring(1)), null)))); |
| StringBuffer buffer = new StringBuffer(); |
| String line; |
| while((line = reader.readLine()) != null) { |
| buffer.append(line).append(" "); //$NON-NLS-1$ |
| } |
| newArgs = tokenize(buffer.toString()); |
| } catch(IOException e) { |
| throw new InvalidInputException( |
| Main.bind("configure.invalidexpansionargumentname", arg)); //$NON-NLS-1$ |
| } |
| } |
| if (newArgs != null) { |
| int newCommandLineArgsLength = newCommandLineArgs.length; |
| int newArgsLength = newArgs.length; |
| System.arraycopy(newCommandLineArgs, 0, (newCommandLineArgs = new String[newCommandLineArgsLength + newArgsLength - 1]), 0, index); |
| System.arraycopy(newArgs, 0, newCommandLineArgs, index, newArgsLength); |
| index += newArgsLength; |
| } else { |
| newCommandLineArgs[index++] = arg; |
| } |
| } |
| index = -1; |
| } else { |
| newCommandLineArgs = argv; |
| for (int i = 0; i < argCount; i++) { |
| newCommandLineArgs[i] = newCommandLineArgs[i].trim(); |
| } |
| } |
| argCount = newCommandLineArgs.length; |
| while (++index < argCount) { |
| |
| if (customEncoding != null) { |
| throw new InvalidInputException( |
| Main.bind("configure.unexpectedCustomEncoding", currentArg, customEncoding)); //$NON-NLS-1$ |
| } |
| |
| currentArg = newCommandLineArgs[index]; |
| |
| customEncoding = null; |
| if (currentArg.endsWith("]")) { //$NON-NLS-1$ |
| // look for encoding specification |
| int encodingStart = currentArg.indexOf('[') + 1; |
| int encodingEnd = currentArg.length() - 1; |
| if (encodingStart >= 1) { |
| if (encodingStart < encodingEnd) { |
| customEncoding = currentArg.substring(encodingStart, encodingEnd); |
| try { // ensure encoding is supported |
| new InputStreamReader(new ByteArrayInputStream(new byte[0]), customEncoding); |
| } catch (UnsupportedEncodingException e) { |
| throw new InvalidInputException( |
| Main.bind("configure.unsupportedEncoding", customEncoding)); //$NON-NLS-1$ |
| } |
| } |
| currentArg = currentArg.substring(0, encodingStart - 1); |
| } |
| } |
| |
| if (currentArg.endsWith(SUFFIX_STRING_java)) { |
| if (this.filenames == null) { |
| this.filenames = new String[argCount - index]; |
| this.encodings = new String[argCount - index]; |
| } else if (filesCount == this.filenames.length) { |
| int length = this.filenames.length; |
| System.arraycopy( |
| this.filenames, |
| 0, |
| (this.filenames = new String[length + argCount - index]), |
| 0, |
| length); |
| System.arraycopy( |
| this.encodings, |
| 0, |
| (this.encodings = new String[length + argCount - index]), |
| 0, |
| length); |
| } |
| this.filenames[filesCount] = currentArg; |
| this.encodings[filesCount++] = customEncoding; |
| customEncoding = null; |
| mode = Default; |
| continue; |
| } |
| if (currentArg.equals("-log")) { //$NON-NLS-1$ |
| if (this.log != null) |
| throw new InvalidInputException( |
| Main.bind("configure.duplicateLog", currentArg)); //$NON-NLS-1$ |
| mode = InsideLog; |
| continue; |
| } |
| if (currentArg.equals("-repeat")) { //$NON-NLS-1$ |
| if (this.repetitions > 0) |
| throw new InvalidInputException( |
| Main.bind("configure.duplicateRepeat", currentArg)); //$NON-NLS-1$ |
| mode = InsideRepetition; |
| continue; |
| } |
| if (currentArg.equals("-maxProblems")) { //$NON-NLS-1$ |
| if (this.maxProblems > 0) |
| throw new InvalidInputException( |
| Main.bind("configure.duplicateMaxProblems", currentArg)); //$NON-NLS-1$ |
| mode = InsideMaxProblems; |
| continue; |
| } |
| if (currentArg.equals("-source")) { //$NON-NLS-1$ |
| mode = InsideSource; |
| continue; |
| } |
| if (currentArg.equals("-encoding")) { //$NON-NLS-1$ |
| mode = InsideDefaultEncoding; |
| continue; |
| } |
| if (currentArg.equals("-1.3")) { //$NON-NLS-1$ |
| if (didSpecifyCompliance) { |
| throw new InvalidInputException( |
| Main.bind("configure.duplicateCompliance", currentArg));//$NON-NLS-1$ |
| } |
| didSpecifyCompliance = true; |
| this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_3); |
| mode = Default; |
| continue; |
| } |
| if (currentArg.equals("-1.4")) { //$NON-NLS-1$ |
| if (didSpecifyCompliance) { |
| throw new InvalidInputException( |
| Main.bind("configure.duplicateCompliance", currentArg)); //$NON-NLS-1$ |
| } |
| didSpecifyCompliance = true; |
| this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4); |
| mode = Default; |
| continue; |
| } |
| if (currentArg.equals("-d")) { //$NON-NLS-1$ |
| if (this.destinationPath != null) |
| throw new InvalidInputException( |
| Main.bind("configure.duplicateOutputPath", currentArg)); //$NON-NLS-1$ |
| mode = InsideDestinationPath; |
| this.generatePackagesStructure = true; |
| continue; |
| } |
| if (currentArg.equals("-classpath") //$NON-NLS-1$ |
| || currentArg.equals("-cp")) { //$NON-NLS-1$ //$NON-NLS-2$ |
| if (pathCount == 0) { |
| this.classpaths = new String[DEFAULT_SIZE_CLASSPATH]; |
| } |
| mode = InsideClasspath; |
| continue; |
| } |
| if (currentArg.equals("-bootclasspath")) {//$NON-NLS-1$ |
| if (bootclasspathCount > 0) |
| throw new InvalidInputException( |
| Main.bind("configure.duplicateBootClasspath", currentArg)); //$NON-NLS-1$ |
| bootclasspaths = new String[DEFAULT_SIZE_CLASSPATH]; |
| mode = InsideBootClasspath; |
| continue; |
| } |
| if (currentArg.equals("-progress")) { //$NON-NLS-1$ |
| mode = Default; |
| this.showProgress = true; |
| continue; |
| } |
| if (currentArg.equals("-proceedOnError")) { //$NON-NLS-1$ |
| mode = Default; |
| this.proceedOnError = true; |
| continue; |
| } |
| if (currentArg.equals("-time")) { //$NON-NLS-1$ |
| mode = Default; |
| this.timing = true; |
| continue; |
| } |
| if (currentArg.equals("-version") //$NON-NLS-1$ |
| || currentArg.equals("-v")) { //$NON-NLS-1$ |
| printVersion(); |
| this.proceed = false; |
| return; |
| } |
| if (currentArg.equals("-showversion")) { //$NON-NLS-1$ |
| printVersionRequired = true; |
| continue; |
| } |
| if ("-deprecation".equals(currentArg)) { //$NON-NLS-1$ |
| didSpecifyDeprecation = true; |
| this.options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING); |
| continue; |
| } |
| if (currentArg.equals("-help") || currentArg.equals("-?")) { //$NON-NLS-1$ //$NON-NLS-2$ |
| printUsageRequired = true; |
| continue; |
| } |
| if (currentArg.equals("-noExit")) { //$NON-NLS-1$ |
| mode = Default; |
| this.systemExitWhenFinished = false; |
| continue; |
| } |
| if (currentArg.equals("-verbose")) { //$NON-NLS-1$ |
| mode = Default; |
| this.verbose = true; |
| continue; |
| } |
| if (currentArg.equals("-referenceInfo")) { //$NON-NLS-1$ |
| mode = Default; |
| this.produceRefInfo = true; |
| continue; |
| } |
| if (currentArg.equals("-inlineJSR")) { //$NON-NLS-1$ |
| mode = Default; |
| this.options.put( |
| CompilerOptions.OPTION_InlineJsr, |
| CompilerOptions.ENABLED); |
| continue; |
| } |
| if (currentArg.startsWith("-g")) { //$NON-NLS-1$ |
| mode = Default; |
| String debugOption = currentArg; |
| int length = currentArg.length(); |
| if (length == 2) { |
| this.options.put( |
| CompilerOptions.OPTION_LocalVariableAttribute, |
| CompilerOptions.GENERATE); |
| this.options.put( |
| CompilerOptions.OPTION_LineNumberAttribute, |
| CompilerOptions.GENERATE); |
| this.options.put( |
| CompilerOptions.OPTION_SourceFileAttribute, |
| CompilerOptions.GENERATE); |
| continue; |
| } |
| if (length > 3) { |
| this.options.put( |
| CompilerOptions.OPTION_LocalVariableAttribute, |
| CompilerOptions.DO_NOT_GENERATE); |
| this.options.put( |
| CompilerOptions.OPTION_LineNumberAttribute, |
| CompilerOptions.DO_NOT_GENERATE); |
| this.options.put( |
| CompilerOptions.OPTION_SourceFileAttribute, |
| CompilerOptions.DO_NOT_GENERATE); |
| if (length == 7 && debugOption.equals("-g:none")) //$NON-NLS-1$ |
| continue; |
| StringTokenizer tokenizer = |
| new StringTokenizer(debugOption.substring(3, debugOption.length()), ","); //$NON-NLS-1$ |
| while (tokenizer.hasMoreTokens()) { |
| String token = tokenizer.nextToken(); |
| if (token.equals("vars")) { //$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_LocalVariableAttribute, |
| CompilerOptions.GENERATE); |
| } else if (token.equals("lines")) { //$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_LineNumberAttribute, |
| CompilerOptions.GENERATE); |
| } else if (token.equals("source")) { //$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_SourceFileAttribute, |
| CompilerOptions.GENERATE); |
| } else { |
| throw new InvalidInputException( |
| Main.bind("configure.invalidDebugOption", debugOption)); //$NON-NLS-1$ |
| } |
| } |
| continue; |
| } |
| throw new InvalidInputException( |
| Main.bind("configure.invalidDebugOption", debugOption)); //$NON-NLS-1$ |
| } |
| if (currentArg.startsWith("-nowarn")) { //$NON-NLS-1$ |
| disableWarnings(); |
| mode = Default; |
| continue; |
| } |
| if (currentArg.startsWith("-warn")) { //$NON-NLS-1$ |
| mode = Default; |
| String warningOption = currentArg; |
| int length = currentArg.length(); |
| if (length == 10 && warningOption.equals("-warn:none")) { //$NON-NLS-1$ |
| disableWarnings(); |
| continue; |
| } |
| if (length < 6) |
| throw new InvalidInputException( |
| Main.bind("configure.invalidWarningConfiguration", warningOption)); //$NON-NLS-1$ |
| int warnTokenStart; |
| boolean isEnabling; |
| switch (warningOption.charAt(6)) { |
| case '+' : |
| warnTokenStart = 7; |
| isEnabling = true; |
| break; |
| case '-' : |
| warnTokenStart = 7; |
| isEnabling = false; // mentionned warnings are disabled |
| break; |
| default: |
| warnTokenStart = 6; |
| // clear default warning level |
| // but allow multiple warning option on the command line |
| if (!didSpecifyWarnings) disableWarnings(); |
| isEnabling = true; |
| } |
| |
| StringTokenizer tokenizer = |
| new StringTokenizer(warningOption.substring(warnTokenStart, warningOption.length()), ","); //$NON-NLS-1$ |
| int tokenCounter = 0; |
| |
| if (didSpecifyDeprecation) { // deprecation could have also been set through -deprecation option |
| this.options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING); |
| } |
| |
| while (tokenizer.hasMoreTokens()) { |
| String token = tokenizer.nextToken(); |
| tokenCounter++; |
| if (token.equals("constructorName")) { //$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportMethodWithConstructorName, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| } else if (token.equals("pkgDefaultMethod") || token.equals("packageDefaultMethod")/*backward compatible*/ ) { //$NON-NLS-1$ //$NON-NLS-2$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportOverridingPackageDefaultMethod, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| } else if (token.equals("maskedCatchBlock") || token.equals("maskedCatchBlocks")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportHiddenCatchBlock, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| } else if (token.equals("deprecation")) { //$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportDeprecation, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| this.options.put( |
| CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode, |
| CompilerOptions.DISABLED); |
| } else if (token.equals("allDeprecation")) { //$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportDeprecation, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| this.options.put( |
| CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode, |
| isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED); |
| this.options.put( |
| CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod, |
| isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED); |
| } else if (token.equals("unusedLocal") || token.equals("unusedLocals")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportUnusedLocal, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| } else if (token.equals("unusedArgument") || token.equals("unusedArguments")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportUnusedParameter, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| } else if (token.equals("unusedImport") || token.equals("unusedImports")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportUnusedImport, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| } else if (token.equals("unusedPrivate")) { //$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportUnusedPrivateMember, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| } else if (token.equals("localHiding")) { //$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportLocalVariableHiding, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| } else if (token.equals("fieldHiding")) { //$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportFieldHiding, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| } else if (token.equals("specialParamHiding")) { //$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportSpecialParameterHidingField, |
| isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED); |
| } else if (token.equals("conditionAssign")) { //$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportPossibleAccidentalBooleanAssignment, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| } else if (token.equals("syntheticAccess")) { //$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportSyntheticAccessEmulation, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| } else if (token.equals("nls")) { //$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportNonExternalizedStringLiteral, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| } else if (token.equals("staticReceiver")) { //$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportNonStaticAccessToStatic, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| } else if (token.equals("indirectStatic")) { //$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportIndirectStaticAccess, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| } else if (token.equals("noEffectAssign")) { //$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportNoEffectAssignment, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| } else if (token.equals("intfNonInherited") || token.equals("interfaceNonInherited")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportIncompatibleNonInheritedInterfaceMethod, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| } else if (token.equals("charConcat") || token.equals("noImplicitStringConversion")/*backward compatible*/) {//$NON-NLS-1$ //$NON-NLS-2$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportNoImplicitStringConversion, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| } else if (token.equals("semicolon")) {//$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportSuperfluousSemicolon, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| } else if (token.equals("emptyBlock")) {//$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportUndocumentedEmptyBlock, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| } else if (token.equals("uselessTypeCheck")) {//$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| } else if (token.equals("javadoc")) {//$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_DocCommentSupport, |
| isEnabling ? CompilerOptions.ENABLED: CompilerOptions.DISABLED); |
| // if disabling then it's not necessary to set other javadoc options |
| if (isEnabling) { |
| this.options.put( |
| CompilerOptions.OPTION_ReportInvalidJavadoc, |
| CompilerOptions.WARNING); |
| this.options.put( |
| CompilerOptions.OPTION_ReportInvalidJavadocTags, |
| CompilerOptions.ENABLED); |
| this.options.put( |
| CompilerOptions.OPTION_ReportInvalidJavadocTagsVisibility, |
| CompilerOptions.PRIVATE); |
| this.options.put( |
| CompilerOptions.OPTION_ReportMissingJavadocTags, |
| CompilerOptions.WARNING); |
| this.options.put( |
| CompilerOptions.OPTION_ReportMissingJavadocTagsVisibility, |
| CompilerOptions.PRIVATE); |
| } |
| } else if (token.equals("allJavadoc")) { //$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_DocCommentSupport, |
| isEnabling ? CompilerOptions.ENABLED: CompilerOptions.DISABLED); |
| // if disabling then it's not necessary to set other javadoc options |
| if (isEnabling) { |
| this.options.put( |
| CompilerOptions.OPTION_ReportInvalidJavadoc, |
| CompilerOptions.WARNING); |
| this.options.put( |
| CompilerOptions.OPTION_ReportInvalidJavadocTags, |
| CompilerOptions.ENABLED); |
| this.options.put( |
| CompilerOptions.OPTION_ReportInvalidJavadocTagsVisibility, |
| CompilerOptions.PRIVATE); |
| this.options.put( |
| CompilerOptions.OPTION_ReportMissingJavadocTags, |
| CompilerOptions.WARNING); |
| this.options.put( |
| CompilerOptions.OPTION_ReportMissingJavadocTagsVisibility, |
| CompilerOptions.PRIVATE); |
| this.options.put( |
| CompilerOptions.OPTION_ReportMissingJavadocComments, |
| CompilerOptions.WARNING); |
| } |
| } else if (token.startsWith("tasks")) { //$NON-NLS-1$ |
| String taskTags = ""; //$NON-NLS-1$ |
| int start = token.indexOf('('); |
| int end = token.indexOf(')'); |
| if (start >= 0 && end >= 0 && start < end){ |
| taskTags = token.substring(start+1, end).trim(); |
| taskTags = taskTags.replace('|',','); |
| } |
| if (taskTags.length() == 0){ |
| throw new InvalidInputException(Main.bind("configure.invalidTaskTag", token)); //$NON-NLS-1$ |
| } |
| this.options.put( |
| CompilerOptions.OPTION_TaskTags, |
| isEnabling ? taskTags : ""); //$NON-NLS-1$ |
| } else if (token.equals("assertIdentifier")) { //$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportAssertIdentifier, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| } else if (token.equals("finally")) { //$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportFinallyBlockNotCompletingNormally, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| } else if (token.equals("unusedThrown")) { //$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportUnusedDeclaredThrownException, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| } else if (token.equals("unqualifiedField")) { //$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_ReportUnqualifiedFieldAccess, |
| isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); |
| } else { |
| throw new InvalidInputException(Main.bind("configure.invalidWarning", token)); //$NON-NLS-1$ |
| } |
| } |
| if (tokenCounter == 0) |
| throw new InvalidInputException( |
| Main.bind("configure.invalidWarningOption", currentArg)); //$NON-NLS-1$ |
| didSpecifyWarnings = true; |
| continue; |
| } |
| if (currentArg.equals("-target")) { //$NON-NLS-1$ |
| mode = TargetSetting; |
| continue; |
| } |
| if (currentArg.equals("-preserveAllLocals")) { //$NON-NLS-1$ |
| this.options.put( |
| CompilerOptions.OPTION_PreserveUnusedLocal, |
| CompilerOptions.PRESERVE); |
| continue; |
| } |
| if (mode == TargetSetting) { |
| didSpecifyTarget = true; |
| if (currentArg.equals("1.1")) { //$NON-NLS-1$ |
| this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_1); |
| } else if (currentArg.equals("1.2")) { //$NON-NLS-1$ |
| this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2); |
| } else if (currentArg.equals("1.3")) { //$NON-NLS-1$ |
| this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_3); |
| } else if (currentArg.equals("1.4")) { //$NON-NLS-1$ |
| this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4); |
| if (didSpecifyCompliance && CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Compliance)) <= ClassFileConstants.JDK1_3) { |
| throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForTarget14", (String)this.options.get(CompilerOptions.OPTION_Compliance))); //$NON-NLS-1$ |
| } |
| this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4); |
| } else { |
| throw new InvalidInputException(Main.bind("configure.targetJDK", currentArg)); //$NON-NLS-1$ |
| } |
| mode = Default; |
| continue; |
| } |
| if (mode == InsideLog) { |
| this.log = currentArg; |
| mode = Default; |
| continue; |
| } |
| if (mode == InsideRepetition) { |
| try { |
| this.repetitions = Integer.parseInt(currentArg); |
| if (this.repetitions <= 0) { |
| throw new InvalidInputException(Main.bind("configure.repetition", currentArg)); //$NON-NLS-1$ |
| } |
| } catch (NumberFormatException e) { |
| throw new InvalidInputException(Main.bind("configure.repetition", currentArg)); //$NON-NLS-1$ |
| } |
| mode = Default; |
| continue; |
| } |
| if (mode == InsideMaxProblems) { |
| try { |
| this.maxProblems = Integer.parseInt(currentArg); |
| if (this.maxProblems <= 0) { |
| throw new InvalidInputException(Main.bind("configure.maxProblems", currentArg)); //$NON-NLS-1$ |
| } |
| this.options.put(CompilerOptions.OPTION_MaxProblemPerUnit, currentArg); |
| } catch (NumberFormatException e) { |
| throw new InvalidInputException(Main.bind("configure.maxProblems", currentArg)); //$NON-NLS-1$ |
| } |
| mode = Default; |
| continue; |
| } |
| if (mode == InsideSource) { |
| if (currentArg.equals("1.3")) { //$NON-NLS-1$ |
| this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3); |
| } else if (currentArg.equals("1.4")) { //$NON-NLS-1$ |
| this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_4); |
| } else { |
| throw new InvalidInputException(Main.bind("configure.source", currentArg)); //$NON-NLS-1$ |
| } |
| mode = Default; |
| continue; |
| } |
| if (mode == InsideDefaultEncoding) { |
| if (didSpecifyDefaultEncoding) { |
| throw new InvalidInputException( |
| Main.bind("configure.duplicateDefaultEncoding", currentArg)); //$NON-NLS-1$ |
| } |
| try { // ensure encoding is supported |
| new InputStreamReader(new ByteArrayInputStream(new byte[0]), currentArg); |
| } catch (UnsupportedEncodingException e) { |
| throw new InvalidInputException( |
| Main.bind("configure.unsupportedEncoding", currentArg)); //$NON-NLS-1$ |
| } |
| this.options.put(CompilerOptions.OPTION_Encoding, currentArg); |
| didSpecifyDefaultEncoding = true; |
| mode = Default; |
| continue; |
| } |
| if (mode == InsideDestinationPath) { |
| this.destinationPath = currentArg; |
| mode = Default; |
| continue; |
| } |
| if (mode == InsideClasspath) { |
| StringTokenizer tokenizer = new StringTokenizer(currentArg, File.pathSeparator); |
| while (tokenizer.hasMoreTokens()) { |
| int length; |
| if ((length = this.classpaths.length) <= pathCount) { |
| System.arraycopy( |
| this.classpaths, |
| 0, |
| (this.classpaths = new String[length * 2]), |
| 0, |
| length); |
| } |
| this.classpaths[pathCount++] = tokenizer.nextToken(); |
| } |
| mode = Default; |
| continue; |
| } |
| if (mode == InsideBootClasspath) { |
| StringTokenizer tokenizer = new StringTokenizer(currentArg, File.pathSeparator); |
| while (tokenizer.hasMoreTokens()) { |
| int length; |
| if ((length = bootclasspaths.length) <= bootclasspathCount) { |
| System.arraycopy( |
| bootclasspaths, |
| 0, |
| (bootclasspaths = new String[length * 2]), |
| 0, |
| length); |
| } |
| bootclasspaths[bootclasspathCount++] = tokenizer.nextToken(); |
| } |
| mode = Default; |
| continue; |
| } |
| //default is input directory |
| currentArg = currentArg.replace('/', File.separatorChar); |
| if (currentArg.endsWith(File.separator)) |
| currentArg = |
| currentArg.substring(0, currentArg.length() - File.separator.length()); |
| File dir = new File(currentArg); |
| if (!dir.isDirectory()) |
| throw new InvalidInputException( |
| Main.bind("configure.directoryNotExist", currentArg)); //$NON-NLS-1$ |
| FileFinder finder = new FileFinder(); |
| try { |
| finder.find(dir, SUFFIX_STRING_JAVA, this.verbose); //$NON-NLS-1$ |
| } catch (Exception e) { |
| throw new InvalidInputException(Main.bind("configure.IOError", currentArg)); //$NON-NLS-1$ |
| } |
| if (this.filenames != null) { |
| // some source files were specified explicitly |
| String results[] = finder.resultFiles; |
| int length = results.length; |
| System.arraycopy( |
| this.filenames, |
| 0, |
| (this.filenames = new String[length + filesCount]), |
| 0, |
| filesCount); |
| System.arraycopy( |
| this.encodings, |
| 0, |
| (this.encodings = new String[length + filesCount]), |
| 0, |
| filesCount); |
| System.arraycopy(results, 0, this.filenames, filesCount, length); |
| for (int i = 0; i < length; i++) { |
| this.encodings[filesCount + i] = customEncoding; |
| } |
| filesCount += length; |
| customEncoding = null; |
| } else { |
| this.filenames = finder.resultFiles; |
| filesCount = this.filenames.length; |
| this.encodings = new String[filesCount]; |
| for (int i = 0; i < filesCount; i++) { |
| this.encodings[i] = customEncoding; |
| } |
| customEncoding = null; |
| } |
| mode = Default; |
| continue; |
| } |
| if (printUsageRequired || filesCount == 0) { |
| printUsage(); |
| this.proceed = false; |
| return; |
| } else { |
| if (printVersionRequired) { |
| printVersion(); |
| } |
| } |
| |
| if (filesCount != 0) |
| System.arraycopy( |
| this.filenames, |
| 0, |
| (this.filenames = new String[filesCount]), |
| 0, |
| filesCount); |
| if (pathCount == 0) { |
| // no user classpath specified. |
| String classProp = System.getProperty("java.class.path"); //$NON-NLS-1$ |
| if ((classProp == null) || (classProp.length() == 0)) { |
| this.err.println(Main.bind("configure.noClasspath")); //$NON-NLS-1$ |
| classProp = System.getProperty("user.dir"); //$NON-NLS-1$ |
| } |
| StringTokenizer tokenizer = new StringTokenizer(classProp, File.pathSeparator); |
| this.classpaths = new String[tokenizer.countTokens() + 1]; |
| while (tokenizer.hasMoreTokens()) { |
| this.classpaths[pathCount++] = tokenizer.nextToken(); |
| } |
| this.classpaths[pathCount++] = System.getProperty("user.dir");//$NON-NLS-1$ |
| } |
| |
| if (bootclasspathCount == 0) { |
| /* no bootclasspath specified |
| * we can try to retrieve the default librairies of the VM used to run |
| * the batch compiler |
| */ |
| String javaversion = System.getProperty("java.version");//$NON-NLS-1$ |
| if (javaversion != null && javaversion.equalsIgnoreCase("1.1.8")) { //$NON-NLS-1$ |
| this.err.println(Main.bind("configure.requiresJDK1.2orAbove")); //$NON-NLS-1$ |
| this.proceed = false; |
| return; |
| } else { |
| String javaVMName = System.getProperty("java.vm.name");//$NON-NLS-1$ |
| if (javaVMName != null && javaVMName.equalsIgnoreCase("J9")) {//$NON-NLS-1$ |
| /* |
| * Handle J9 VM settings: Retrieve jclMax by default |
| */ |
| String javaHome = System.getProperty("java.home");//$NON-NLS-1$ |
| if (javaHome != null) { |
| File javaHomeFile = new File(javaHome); |
| if (javaHomeFile.exists()) { |
| try { |
| javaHomeFile = new File(javaHomeFile.getCanonicalPath()); |
| File defaultLibrary = new File(javaHomeFile, "lib" + File.separator + "jclMax" + File.separator + "classes.zip"); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ |
| File locales = new File(javaHomeFile, "lib" + File.separator + "jclMax" + File.separator + "locale.zip"); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ |
| File charconv = new File(javaHomeFile, "lib" + File.separator + "charconv.zip"); //$NON-NLS-1$//$NON-NLS-2$ |
| /* we don't need to check if defaultLibrary exists. This is done later when the user |
| * classpath and the bootclasspath are merged. |
| */ |
| bootclasspaths = new String[] { |
| defaultLibrary.getAbsolutePath(), |
| locales.getAbsolutePath(), |
| charconv.getAbsolutePath()}; |
| bootclasspathCount = 3; |
| } catch (IOException e) { |
| // cannot retrieve libraries |
| } |
| } |
| } |
| } else { |
| /* |
| * Handle >= JDK 1.2.2 settings: retrieve rt.jar |
| */ |
| String javaHome = System.getProperty("java.home");//$NON-NLS-1$ |
| if (javaHome != null) { |
| File javaHomeFile = new File(javaHome); |
| if (javaHomeFile.exists()) { |
| try { |
| javaHomeFile = new File(javaHomeFile.getCanonicalPath()); |
| // add all jars in the lib subdirectory |
| File[] systemLibrariesJars = getFilesFrom(new File(javaHomeFile, "lib"), SUFFIX_STRING_jar);//$NON-NLS-1$ |
| int length = systemLibrariesJars.length; |
| bootclasspaths = new String[length]; |
| for (int i = 0; i < length; i++) { |
| /* we don't need to check if this file exists. This is done later when the user |
| * classpath and the bootclasspath are merged. |
| */ |
| bootclasspaths[bootclasspathCount++] = systemLibrariesJars[i].getAbsolutePath(); |
| } |
| } catch (IOException e) { |
| // cannot retrieve libraries |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| if (this.log != null) { |
| try { |
| this.err = new PrintWriter(new FileOutputStream(this.log, false)); |
| } catch (IOException e) { |
| throw new InvalidInputException(Main.bind("configure.cannotOpenLog")); //$NON-NLS-1$ |
| } |
| } else { |
| this.showProgress = false; |
| } |
| |
| if (this.classpaths == null) { |
| this.classpaths = new String[0]; |
| } |
| /* |
| * We put the bootclasspath at the beginning of the classpath entries |
| */ |
| String[] newclasspaths = null; |
| if ((pathCount + bootclasspathCount) != this.classpaths.length) { |
| newclasspaths = new String[pathCount + bootclasspathCount]; |
| } else { |
| newclasspaths = this.classpaths; |
| } |
| System.arraycopy( |
| this.classpaths, |
| 0, |
| newclasspaths, |
| bootclasspathCount, |
| pathCount); |
| |
| if (bootclasspathCount != 0) { |
| System.arraycopy( |
| bootclasspaths, |
| 0, |
| newclasspaths, |
| 0, |
| bootclasspathCount); |
| } |
| this.classpaths = newclasspaths; |
| for (int i = 0, max = this.classpaths.length; i < max; i++) { |
| File file = new File(this.classpaths[i]); |
| if (!file.exists()) { // signal missing classpath entry file |
| this.out.println(Main.bind("configure.incorrectClasspath", this.classpaths[i])); //$NON-NLS-1$ |
| } |
| } |
| if (this.destinationPath == null) { |
| this.generatePackagesStructure = false; |
| } else if ("none".equals(this.destinationPath)) { //$NON-NLS-1$ |
| this.destinationPath = null; |
| } |
| |
| // target must be 1.4 if source is 1.4 |
| if (CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Source)) >= ClassFileConstants.JDK1_4 |
| && CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_TargetPlatform)) < ClassFileConstants.JDK1_4 |
| && didSpecifyTarget){ |
| throw new InvalidInputException(Main.bind("configure.incompatibleTargetForSource14", (String)this.options.get(CompilerOptions.OPTION_TargetPlatform))); //$NON-NLS-1$ |
| } |
| |
| // target cannot be 1.4 if compliance is 1.3 |
| if (CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Compliance)) < ClassFileConstants.JDK1_4 |
| && CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_TargetPlatform)) >= ClassFileConstants.JDK1_4 |
| && didSpecifyTarget){ |
| throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForTarget14", (String)this.options.get(CompilerOptions.OPTION_Compliance))); //$NON-NLS-1$ |
| } |
| |
| // check and set compliance/source/target compatibilities |
| if (this.options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_4)){ |
| if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4); |
| if (!didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4); |
| } |
| // compliance must be 1.4 if source is 1.4 |
| if (this.options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_4) |
| && !this.options.get(CompilerOptions.OPTION_Compliance).equals(CompilerOptions.VERSION_1_4)){ |
| throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForSource14", (String)this.options.get(CompilerOptions.OPTION_Compliance))); //$NON-NLS-1$ |
| } |
| |
| // set default target according to compliance & sourcelevel. |
| if (!didSpecifyTarget) { |
| if (this.options.get(CompilerOptions.OPTION_Compliance).equals(CompilerOptions.VERSION_1_3)) { |
| this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_1); |
| } else if (this.options.get(CompilerOptions.OPTION_Compliance).equals(CompilerOptions.VERSION_1_4)) { |
| if (this.options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_3)) { |
| this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2); |
| } else if (this.options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_4)) { |
| this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4); |
| } |
| } |
| } |
| |
| if (this.repetitions == 0) { |
| this.repetitions = 1; |
| } |
| } |
| |
| private void disableWarnings() { |
| Object[] entries = this.options.entrySet().toArray(); |
| for (int i = 0, max = entries.length; i < max; i++) { |
| Map.Entry entry = (Map.Entry) entries[i]; |
| if (!(entry.getKey() instanceof String)) |
| continue; |
| if (!(entry.getValue() instanceof String)) |
| continue; |
| if (((String) entry.getValue()).equals(CompilerOptions.WARNING)) { |
| this.options.put(entry.getKey(), CompilerOptions.IGNORE); |
| } |
| } |
| this.options.put(CompilerOptions.OPTION_TaskTags, ""); //$NON-NLS-1$ |
| } |
| |
| public String extractDestinationPathFromSourceFile(CompilationResult result) { |
| ICompilationUnit compilationUnit = result.compilationUnit; |
| if (compilationUnit != null) { |
| char[] fileName = compilationUnit.getFileName(); |
| int lastIndex = CharOperation.lastIndexOf(java.io.File.separatorChar, fileName); |
| if (lastIndex == -1) { |
| return System.getProperty("user.dir"); //$NON-NLS-1$ |
| } |
| return new String(CharOperation.subarray(fileName, 0, lastIndex)); |
| } |
| return System.getProperty("user.dir"); //$NON-NLS-1$ |
| } |
| /* |
| * Answer the component to which will be handed back compilation results from the compiler |
| */ |
| public ICompilerRequestor getBatchRequestor() { |
| return new ICompilerRequestor() { |
| int lineDelta = 0; |
| public void acceptResult(CompilationResult compilationResult) { |
| if (compilationResult.lineSeparatorPositions != null) { |
| int unitLineCount = compilationResult.lineSeparatorPositions.length; |
| Main.this.lineCount += unitLineCount; |
| this.lineDelta += unitLineCount; |
| if (Main.this.showProgress |
| && this.lineDelta > 2000) { // in -log mode, dump a dot every 2000 lines compiled |
| Main.this.out.print('.'); |
| this.lineDelta = 0; |
| } |
| } |
| if (compilationResult.hasProblems() || compilationResult.hasTasks()) { |
| IProblem[] problems = compilationResult.getAllProblems(); |
| int count = problems.length; |
| int localErrorCount = 0; |
| char[] unitSource = compilationResult.compilationUnit.getContents(); |
| for (int i = 0; i < count; i++) { |
| if (problems[i] != null) { |
| Main.this.globalProblemsCount++; |
| if (localErrorCount == 0) |
| Main.this.err.println("----------"); //$NON-NLS-1$ |
| Main.this.err.print( |
| Main.this.globalProblemsCount |
| + ". " //$NON-NLS-1$ |
| + (problems[i].isError() |
| ? Main.bind("requestor.error") //$NON-NLS-1$ |
| : Main.bind("requestor.warning"))); //$NON-NLS-1$ |
| if (problems[i].isError()) { |
| Main.this.globalErrorsCount++; |
| } else { |
| Main.this.globalWarningsCount++; |
| } |
| Main.this.err.print(" "); //$NON-NLS-1$ |
| Main.this.err.print( |
| Main.bind("requestor.in", new String(problems[i].getOriginatingFileName()))); //$NON-NLS-1$ |
| try { |
| Main.this.err.println( |
| ((DefaultProblem) problems[i]).errorReportSource(unitSource)); |
| Main.this.err.println(problems[i].getMessage()); |
| } catch (Exception e) { |
| Main.this.err.println( |
| Main.bind("requestor.notRetrieveErrorMessage", problems[i].toString())); //$NON-NLS-1$ |
| } |
| Main.this.err.println("----------"); //$NON-NLS-1$ |
| if (problems[i].isError()) |
| localErrorCount++; |
| } |
| } |
| // exit? |
| if (Main.this.systemExitWhenFinished && !Main.this.proceedOnError && (localErrorCount > 0)) { |
| Main.this.printStats(); |
| Main.this.err.flush(); |
| Main.this.out.flush(); |
| System.exit(-1); |
| } |
| } |
| outputClassFiles(compilationResult); |
| } |
| }; |
| } |
| /* |
| * Build the set of compilation source units |
| */ |
| public CompilationUnit[] getCompilationUnits() |
| throws InvalidInputException { |
| int fileCount = this.filenames.length; |
| CompilationUnit[] units = new CompilationUnit[fileCount]; |
| HashtableOfObject knownFileNames = new HashtableOfObject(fileCount); |
| |
| String defaultEncoding = (String) this.options.get(CompilerOptions.OPTION_Encoding); |
| if ("".equals(defaultEncoding)) //$NON-NLS-1$ |
| defaultEncoding = null; //$NON-NLS-1$ |
| |
| for (int i = 0; i < fileCount; i++) { |
| char[] charName = this.filenames[i].toCharArray(); |
| if (knownFileNames.get(charName) != null) { |
| throw new InvalidInputException(Main.bind("unit.more", this.filenames[i])); //$NON-NLS-1$ |
| } else { |
| knownFileNames.put(charName, charName); |
| } |
| File file = new File(this.filenames[i]); |
| if (!file.exists()) |
| throw new InvalidInputException(Main.bind("unit.missing", this.filenames[i])); //$NON-NLS-1$ |
| String encoding = this.encodings[i]; |
| if (encoding == null) |
| encoding = defaultEncoding; |
| units[i] = new CompilationUnit(null, this.filenames[i], encoding); |
| } |
| return units; |
| } |
| |
| private File[] getFilesFrom(File f, final String extension) { |
| return f.listFiles(new FilenameFilter() { |
| public boolean accept(File dir, String name) { |
| if (name.toLowerCase().endsWith(extension)) { |
| return true; |
| } |
| return false; |
| } |
| }); |
| } |
| /* |
| * Low-level API performing the actual compilation |
| */ |
| public IErrorHandlingPolicy getHandlingPolicy() { |
| |
| // passes the initial set of files to the batch oracle (to avoid finding more than once the same units when case insensitive match) |
| return new IErrorHandlingPolicy() { |
| public boolean proceedOnErrors() { |
| return Main.this.proceedOnError; // stop if there are some errors |
| } |
| public boolean stopOnFirstError() { |
| return false; |
| } |
| }; |
| } |
| public FileSystem getLibraryAccess() { |
| |
| String defaultEncoding = (String) this.options.get(CompilerOptions.OPTION_Encoding); |
| if ("".equals(defaultEncoding)) //$NON-NLS-1$ |
| defaultEncoding = null; //$NON-NLS-1$ |
| return new FileSystem(this.classpaths, this.filenames, defaultEncoding); |
| } |
| /* |
| * Low-level API performing the actual compilation |
| */ |
| public IProblemFactory getProblemFactory() { |
| return new DefaultProblemFactory(Locale.getDefault()); |
| } |
| // Dump classfiles onto disk for all compilation units that where successfull. |
| |
| public void outputClassFiles(CompilationResult unitResult) { |
| |
| if (!((unitResult == null) || (unitResult.hasErrors() && !this.proceedOnError))) { |
| Enumeration classFiles = unitResult.compiledTypes.elements(); |
| if (!this.generatePackagesStructure) { |
| while (classFiles.hasMoreElements()) { |
| this.destinationPath = extractDestinationPathFromSourceFile(unitResult); |
| // retrieve the key and the corresponding classfile |
| ClassFile classFile = (ClassFile) classFiles.nextElement(); |
| char[] filename = classFile.fileName(); |
| int length = filename.length; |
| char[] relativeName = new char[length + 6]; |
| System.arraycopy(filename, 0, relativeName, 0, length); |
| System.arraycopy(SUFFIX_class, 0, relativeName, length, 6); |
| CharOperation.replace(relativeName, '/', File.separatorChar); |
| try { |
| if (this.compilerOptions.verbose) |
| System.out.println(Util.bind("compilation.write", //$NON-NLS-1$ |
| new String[] { |
| String.valueOf(this.exportedClassFilesCounter+1), |
| new String(relativeName) })); |
| ClassFile.writeToDisk( |
| this.generatePackagesStructure, |
| this.destinationPath, |
| new String(relativeName), |
| classFile.getBytes()); |
| } catch (IOException e) { |
| String fileName = this.destinationPath + new String(relativeName); |
| e.printStackTrace(); |
| this.err.println(Main.bind("output.noClassFileCreated", fileName)); //$NON-NLS-1$ |
| } |
| this.exportedClassFilesCounter++; |
| } |
| } else if (this.destinationPath != null) { |
| while (classFiles.hasMoreElements()) { |
| // retrieve the key and the corresponding classfile |
| ClassFile classFile = (ClassFile) classFiles.nextElement(); |
| char[] filename = classFile.fileName(); |
| int length = filename.length; |
| char[] relativeName = new char[length + 6]; |
| System.arraycopy(filename, 0, relativeName, 0, length); |
| System.arraycopy(SUFFIX_class, 0, relativeName, length, 6); |
| CharOperation.replace(relativeName, '/', File.separatorChar); |
| try { |
| if (this.compilerOptions.verbose) |
| System.out.println(Util.bind("compilation.write", //$NON-NLS-1$ |
| new String[] { |
| String.valueOf(this.exportedClassFilesCounter+1), |
| new String(relativeName) })); |
| ClassFile.writeToDisk( |
| this.generatePackagesStructure, |
| this.destinationPath, |
| new String(relativeName), |
| classFile.getBytes()); |
| } catch (IOException e) { |
| String fileName = this.destinationPath + new String(relativeName); |
| e.printStackTrace(); |
| this.err.println(Main.bind("output.noClassFileCreated", fileName)); //$NON-NLS-1$ |
| } |
| this.exportedClassFilesCounter++; |
| } |
| } |
| } |
| } |
| /* |
| * Low-level API performing the actual compilation |
| */ |
| public void performCompilation() throws InvalidInputException { |
| |
| this.startTime = System.currentTimeMillis(); |
| |
| INameEnvironment environment = getLibraryAccess(); |
| Compiler batchCompiler = |
| new Compiler( |
| environment, |
| getHandlingPolicy(), |
| this.options, |
| getBatchRequestor(), |
| getProblemFactory()); |
| this.compilerOptions = batchCompiler.options; |
| |
| // set the non-externally configurable options. |
| this.compilerOptions.verbose = this.verbose; |
| this.compilerOptions.produceReferenceInfo = this.produceRefInfo; |
| batchCompiler.compile(getCompilationUnits()); |
| |
| printStats(); |
| |
| // cleanup |
| environment.cleanup(); |
| } |
| |
| public void printStats() { |
| if (this.timing) { |
| |
| long time = System.currentTimeMillis() - this.startTime; |
| if (this.lineCount != 0) { |
| this.out.println( |
| Main.bind( |
| "compile.instantTime", //$NON-NLS-1$ |
| new String[] { |
| String.valueOf(this.lineCount), |
| String.valueOf(time), |
| String.valueOf(((int)(this.lineCount * 10000.0 / time)) / 10.0)})); |
| } else { |
| this.out.println(Main.bind("compile.totalTime", String.valueOf(time))); //$NON-NLS-1$ |
| } |
| } |
| if (this.globalProblemsCount > 0) { |
| if (this.globalProblemsCount == 1) { |
| this.err.print(Main.bind("compile.oneProblem")); //$NON-NLS-1$ |
| } else { |
| this.err.print( |
| Main.bind("compile.severalProblems", String.valueOf(this.globalProblemsCount))); //$NON-NLS-1$ |
| } |
| this.err.print(" ("); //$NON-NLS-1$ |
| if (this.globalErrorsCount > 0) { |
| if (this.globalErrorsCount == 1) { |
| this.err.print(Main.bind("compile.oneError")); //$NON-NLS-1$ |
| } else { |
| this.err.print( |
| Main.bind("compile.severalErrors", String.valueOf(this.globalErrorsCount))); //$NON-NLS-1$ |
| } |
| } |
| if (this.globalWarningsCount > 0) { |
| if (this.globalErrorsCount > 0) { |
| this.err.print(", "); //$NON-NLS-1$ |
| } |
| if (this.globalWarningsCount == 1) { |
| this.err.print(Main.bind("compile.oneWarning")); //$NON-NLS-1$ |
| } else { |
| this.err.print( |
| Main.bind("compile.severalWarnings", String.valueOf(this.globalWarningsCount))); //$NON-NLS-1$ |
| } |
| } |
| this.err.println(")"); //$NON-NLS-1$ |
| } |
| if (this.exportedClassFilesCounter != 0 |
| && (this.showProgress || this.timing || this.verbose)) { |
| if (this.exportedClassFilesCounter == 1) { |
| this.out.println(Main.bind("compile.oneClassFileGenerated")); //$NON-NLS-1$ |
| } else { |
| this.out.println( |
| Main.bind( |
| "compile.severalClassFilesGenerated", //$NON-NLS-1$ |
| String.valueOf(this.exportedClassFilesCounter))); |
| } |
| } |
| } |
| public void printUsage() { |
| this.out.println(Main.bind("misc.usage")); //$NON-NLS-1$ |
| this.out.flush(); |
| this.err.flush(); |
| } |
| public void printVersion() { |
| this.out.println(Main.bind("misc.version")); //$NON-NLS-1$ |
| this.out.flush(); |
| this.err.flush(); |
| } |
| } |