blob: 2ea9025ee83a45957b3495ef4e77d9321c48853a [file] [log] [blame]
package org.eclipse.jdt.internal.compiler.batch;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.Hashtable;
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.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.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.CharOperation;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
public class Main implements ProblemSeverities {
private boolean noWarn = false;
PrintWriter out;
boolean systemExitWhenFinished = true;
boolean proceedOnError = false;
boolean verbose = false;
boolean produceRefInfo = false;
boolean timer = false;
boolean showProgress = false;
public long time = 0;
long lineCount;
private boolean generatePackagesStructure;
Hashtable options;
String[] filenames;
String[] encodings;
String[] classpaths;
String destinationPath;
String log;
int repetitions;
int globalProblemsCount;
int globalErrorsCount;
int globalWarningsCount;
int exportedClassFilesCounter;
private static final char[] CLASS_FILE_EXTENSION = ".class".toCharArray(); //$NON-NLS-1$
private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
/* Bundle containing messages */
protected static ResourceBundle bundle;
private final static String bundleName =
"org.eclipse.jdt.internal.compiler.batch.messages"; //$NON-NLS-1$
static {
relocalize();
}
private boolean proceed = true;
public Main(PrintWriter writer, boolean systemExitWhenFinished) {
this.out = writer;
this.systemExitWhenFinished = systemExitWhenFinished;
exportedClassFilesCounter = 0;
options = new Hashtable();
options.put(
CompilerOptions.OPTION_LocalVariableAttribute,
CompilerOptions.DO_NOT_GENERATE);
options.put(
CompilerOptions.OPTION_LineNumberAttribute,
CompilerOptions.DO_NOT_GENERATE);
options.put(
CompilerOptions.OPTION_SourceFileAttribute,
CompilerOptions.DO_NOT_GENERATE);
options.put(
CompilerOptions.OPTION_PreserveUnusedLocal,
CompilerOptions.OPTIMIZE_OUT);
options.put(
CompilerOptions.OPTION_ReportUnreachableCode,
CompilerOptions.ERROR);
options.put(CompilerOptions.OPTION_ReportInvalidImport, CompilerOptions.ERROR);
options.put(
CompilerOptions.OPTION_ReportOverridingPackageDefaultMethod,
CompilerOptions.WARNING);
options.put(
CompilerOptions.OPTION_ReportMethodWithConstructorName,
CompilerOptions.WARNING);
options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
options.put(
CompilerOptions.OPTION_ReportHiddenCatchBlock,
CompilerOptions.WARNING);
options.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.IGNORE);
options.put(
CompilerOptions.OPTION_ReportUnusedParameter,
CompilerOptions.IGNORE);
options.put(
CompilerOptions.OPTION_ReportSyntheticAccessEmulation,
CompilerOptions.IGNORE);
options.put(
CompilerOptions.OPTION_ReportNonExternalizedStringLiteral,
CompilerOptions.IGNORE);
options.put(
CompilerOptions.OPTION_ReportAssertIdentifier,
CompilerOptions.IGNORE);
options.put(
CompilerOptions.OPTION_Compliance,
CompilerOptions.VERSION_1_3);
options.put(
CompilerOptions.OPTION_Source,
CompilerOptions.VERSION_1_3);
options.put(
CompilerOptions.OPTION_TargetPlatform,
CompilerOptions.VERSION_1_1);
}
/*
* Low-level API performing the actual compilation
*/
public boolean compile(String[] argv) {
// decode command line arguments
try {
configure(argv);
if (proceed) {
if (showProgress)
out.print(Main.bind("progress.compiling")); //$NON-NLS-1$
for (int i = 0; i < repetitions; i++) {
globalProblemsCount = 0;
globalErrorsCount = 0;
globalWarningsCount = 0;
lineCount = 0;
if (repetitions > 1) {
out.flush();
out.println(
Main.bind(
"compile.repetition", //$NON-NLS-1$
String.valueOf(i + 1),
String.valueOf(repetitions)));
}
long startTime = System.currentTimeMillis();
// request compilation
performCompilation();
if (timer) {
time = System.currentTimeMillis() - startTime;
if (lineCount != 0) {
out.println(
Main.bind(
"compile.instantTime", //$NON-NLS-1$
new String[] {
String.valueOf(lineCount),
String.valueOf(time),
String.valueOf((((int) ((lineCount * 10000.0) / time)) / 10.0))}));
} else {
out.println(Main.bind("compile.totalTime", String.valueOf(time))); //$NON-NLS-1$
}
}
if (globalProblemsCount > 0) {
if (globalProblemsCount == 1) {
out.print(Main.bind("compile.oneProblem")); //$NON-NLS-1$
} else {
out.print(
Main.bind("compile.severalProblems", String.valueOf(globalProblemsCount))); //$NON-NLS-1$
}
out.print(" ("); //$NON-NLS-1$
if (globalErrorsCount > 0) {
if (globalErrorsCount == 1) {
out.print(Main.bind("compile.oneError")); //$NON-NLS-1$
} else {
out.print(
Main.bind("compile.severalErrors", String.valueOf(globalErrorsCount))); //$NON-NLS-1$
}
}
if (globalWarningsCount > 0) {
if (globalErrorsCount > 0) {
out.print(", "); //$NON-NLS-1$
}
if (globalWarningsCount == 1) {
out.print(Main.bind("compile.oneWarning")); //$NON-NLS-1$
} else {
out.print(
Main.bind("compile.severalWarnings", String.valueOf(globalWarningsCount))); //$NON-NLS-1$
}
}
out.println(")"); //$NON-NLS-1$
}
if (exportedClassFilesCounter != 0
&& (this.showProgress || this.timer || this.verbose)) {
if (exportedClassFilesCounter == 1) {
out.print(Main.bind("compile.oneClassFileGenerated")); //$NON-NLS-1$
} else {
out.print(
Main.bind(
"compile.severalClassFilesGenerated", //$NON-NLS-1$
String.valueOf(exportedClassFilesCounter)));
}
}
}
if (showProgress)
System.out.println();
}
if (systemExitWhenFinished) {
out.flush();
System.exit(globalErrorsCount > 0 ? -1 : 0);
}
} catch (InvalidInputException e) {
out.println(e.getMessage());
out.println("------------------------"); //$NON-NLS-1$
printUsage();
if (systemExitWhenFinished) {
System.exit(-1);
}
} catch (ThreadDeath e) { // do not stop this one
throw e;
} catch (Throwable e) { // internal compiler error
if (systemExitWhenFinished) {
out.flush();
if (this.log != null) {
out.close();
}
System.exit(-1);
}
//e.printStackTrace();
} finally {
out.flush();
if (this.log != null) {
out.close();
}
}
if (globalErrorsCount == 0){
return true;
} else {
return false;
}
}
/*
* Internal IDE API
*/
public static boolean compile(String commandLine) {
return compile(commandLine, new PrintWriter(System.out));
}
/*
* Internal IDE API for test harness purpose
*/
public static boolean compile(String commandLine, PrintWriter writer) {
return new Main(writer, false).compile(tokenize(commandLine));
}
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 = "", lastToken; //$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()) {
lastToken = token;
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);
arguments[count++] = token;
}
}
startNewToken = false;
}
}
System.arraycopy(arguments, 0, arguments = new String[count], 0, count);
return arguments;
}
/*
Decode the command line arguments
*/
private void configure(String[] argv) throws InvalidInputException {
if ((argv == null) || (argv.length == 0))
throw new InvalidInputException(Main.bind("configure.noSourceFile")); //$NON-NLS-1$
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 Default = 0;
int DEFAULT_SIZE_CLASSPATH = 4;
boolean warnOptionInUse = false;
boolean noWarnOptionInUse = false;
int pathCount = 0;
int index = -1, filesCount = 0, argCount = argv.length;
int mode = Default;
repetitions = 0;
boolean versionIDRequired = false;
boolean printUsageRequired = false;
boolean didSpecifyCompliance = false;
boolean didSpecifySourceLevel = false;
boolean didSpecifyDefaultEncoding = false;
boolean didSpecifyTarget = false;
String customEncoding = null;
String currentArg = ""; //$NON-NLS-1$
while (++index < argCount) {
if (customEncoding != null) {
throw new InvalidInputException(
Main.bind("configure.unexpectedCustomEncoding", currentArg, customEncoding)); //$NON-NLS-1$
}
currentArg = argv[index].trim();
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(".java")) { //$NON-NLS-1$
if (filenames == null) {
filenames = new String[argCount - index];
encodings = new String[argCount - index];
} else if (filesCount == filenames.length) {
int length = filenames.length;
System.arraycopy(
filenames,
0,
(filenames = new String[length + argCount - index]),
0,
length);
System.arraycopy(
encodings,
0,
(encodings = new String[length + argCount - index]),
0,
length);
}
filenames[filesCount] = currentArg;
encodings[filesCount++] = customEncoding;
customEncoding = null;
mode = Default;
continue;
}
if (currentArg.equals("-log")) { //$NON-NLS-1$
if (log != null)
throw new InvalidInputException(
Main.bind("configure.duplicateLog", currentArg)); //$NON-NLS-1$
mode = InsideLog;
continue;
}
if (currentArg.equals("-repeat")) { //$NON-NLS-1$
if (repetitions > 0)
throw new InvalidInputException(
Main.bind("configure.duplicateRepeat", currentArg)); //$NON-NLS-1$
mode = InsideRepetition;
continue;
}
if (currentArg.equals("-source")) { //$NON-NLS-1$
mode = InsideSource;
didSpecifySourceLevel = true;
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;
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;
options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
mode = Default;
continue;
}
if (currentArg.equals("-d")) { //$NON-NLS-1$
if (destinationPath != null)
throw new InvalidInputException(
Main.bind("configure.duplicateOutputPath", currentArg)); //$NON-NLS-1$
mode = InsideDestinationPath;
generatePackagesStructure = true;
continue;
}
if (currentArg.equals("-classpath") //$NON-NLS-1$
|| currentArg.equals("-cp")) { //$NON-NLS-1$ //$NON-NLS-2$
if (pathCount > 0)
throw new InvalidInputException(
Main.bind("configure.duplicateClasspath", currentArg)); //$NON-NLS-1$
classpaths = new String[DEFAULT_SIZE_CLASSPATH];
mode = InsideClasspath;
continue;
}
if (currentArg.equals("-progress")) { //$NON-NLS-1$
mode = Default;
showProgress = true;
continue;
}
if (currentArg.equals("-proceedOnError")) { //$NON-NLS-1$
mode = Default;
proceedOnError = true;
continue;
}
if (currentArg.equals("-time")) { //$NON-NLS-1$
mode = Default;
timer = true;
continue;
}
if (currentArg.equals("-version") //$NON-NLS-1$
|| currentArg.equals("-v")) { //$NON-NLS-1$ //$NON-NLS-2$
versionIDRequired = true;
continue;
}
if ("-deprecation".equals(currentArg)) { //$NON-NLS-1$
warnOptionInUse = true;
if (noWarnOptionInUse)
throw new InvalidInputException(
Main.bind("configure.duplicateWarningConfiguration")); //$NON-NLS-1$
options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
continue;
}
if (currentArg.equals("-help")) { //$NON-NLS-1$
printUsageRequired = true;
continue;
}
if (currentArg.equals("-noImportError")) { //$NON-NLS-1$
mode = Default;
options.put(
CompilerOptions.OPTION_ReportInvalidImport,
CompilerOptions.WARNING);
continue;
}
if (currentArg.equals("-noExit")) { //$NON-NLS-1$
mode = Default;
systemExitWhenFinished = false;
continue;
}
if (currentArg.equals("-verbose")) { //$NON-NLS-1$
mode = Default;
verbose = true;
continue;
}
if (currentArg.equals("-referenceInfo")) { //$NON-NLS-1$
mode = Default;
produceRefInfo = true;
continue;
}
if (currentArg.startsWith("-g")) { //$NON-NLS-1$
mode = Default;
String debugOption = currentArg;
int length = currentArg.length();
if (length == 2) {
options.put(
CompilerOptions.OPTION_LocalVariableAttribute,
CompilerOptions.GENERATE);
options.put(
CompilerOptions.OPTION_LineNumberAttribute,
CompilerOptions.GENERATE);
options.put(
CompilerOptions.OPTION_SourceFileAttribute,
CompilerOptions.GENERATE);
continue;
}
if (length > 3) {
options.put(
CompilerOptions.OPTION_LocalVariableAttribute,
CompilerOptions.DO_NOT_GENERATE);
options.put(
CompilerOptions.OPTION_LineNumberAttribute,
CompilerOptions.DO_NOT_GENERATE);
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$
options.put(
CompilerOptions.OPTION_LocalVariableAttribute,
CompilerOptions.GENERATE);
} else if (token.equals("lines")) { //$NON-NLS-1$
options.put(
CompilerOptions.OPTION_LineNumberAttribute,
CompilerOptions.GENERATE);
} else if (token.equals("source")) { //$NON-NLS-1$
options.put(
CompilerOptions.OPTION_SourceFileAttribute,
CompilerOptions.GENERATE);
} else {
throw new InvalidInputException(
Main.bind("configure.invalidDebugOption", debugOption)); //$NON-NLS-1$
//$NON-NLS-1$
}
}
continue;
}
throw new InvalidInputException(
Main.bind("configure.invalidDebugOption", debugOption)); //$NON-NLS-1$
}
if (currentArg.startsWith("-nowarn")) { //$NON-NLS-1$
noWarnOptionInUse = true;
noWarn = true;
if (warnOptionInUse)
throw new InvalidInputException(
Main.bind("configure.duplicateWarningConfiguration")); //$NON-NLS-1$
mode = Default;
continue;
}
if (currentArg.startsWith("-warn")) { //$NON-NLS-1$
warnOptionInUse = true;
if (noWarnOptionInUse)
throw new InvalidInputException(
Main.bind("configure.duplicateWarningConfiguration")); //$NON-NLS-1$
mode = Default;
String warningOption = currentArg;
int length = currentArg.length();
if (length == 10 && warningOption.equals("-warn:none")) { //$NON-NLS-1$
noWarn = true;
continue;
}
if (length < 6)
throw new InvalidInputException(
Main.bind("configure.invalidWarningConfiguration", warningOption)); //$NON-NLS-1$
StringTokenizer tokenizer =
new StringTokenizer(warningOption.substring(6, warningOption.length()), ","); //$NON-NLS-1$
int tokenCounter = 0;
options.put(
CompilerOptions.OPTION_ReportOverridingPackageDefaultMethod,
CompilerOptions.IGNORE);
options.put(
CompilerOptions.OPTION_ReportMethodWithConstructorName,
CompilerOptions.IGNORE);
options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.IGNORE);
options.put(
CompilerOptions.OPTION_ReportHiddenCatchBlock,
CompilerOptions.IGNORE);
options.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.IGNORE);
options.put(
CompilerOptions.OPTION_ReportUnusedParameter,
CompilerOptions.IGNORE);
options.put(
CompilerOptions.OPTION_ReportSyntheticAccessEmulation,
CompilerOptions.IGNORE);
options.put(
CompilerOptions.OPTION_ReportNonExternalizedStringLiteral,
CompilerOptions.IGNORE);
options.put(
CompilerOptions.OPTION_ReportAssertIdentifier,
CompilerOptions.IGNORE);
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
tokenCounter++;
if (token.equals("constructorName")) { //$NON-NLS-1$
options.put(
CompilerOptions.OPTION_ReportMethodWithConstructorName,
CompilerOptions.WARNING);
} else if (token.equals("packageDefaultMethod")) { //$NON-NLS-1$
options.put(
CompilerOptions.OPTION_ReportOverridingPackageDefaultMethod,
CompilerOptions.WARNING);
} else if (token.equals("maskedCatchBlocks")) { //$NON-NLS-1$
options.put(
CompilerOptions.OPTION_ReportHiddenCatchBlock,
CompilerOptions.WARNING);
} else if (token.equals("deprecation")) { //$NON-NLS-1$
options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
} else if (token.equals("unusedLocals")) { //$NON-NLS-1$
options.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.WARNING);
} else if (token.equals("unusedArguments")) { //$NON-NLS-1$
options.put(
CompilerOptions.OPTION_ReportUnusedParameter,
CompilerOptions.WARNING);
} else if (token.equals("syntheticAccess")) { //$NON-NLS-1$
options.put(
CompilerOptions.OPTION_ReportSyntheticAccessEmulation,
CompilerOptions.WARNING);
} else if (token.equals("nls")) { //$NON-NLS-1$
options.put(
CompilerOptions.OPTION_ReportNonExternalizedStringLiteral,
CompilerOptions.WARNING);
} else if (token.equals("assertIdentifier")) { //$NON-NLS-1$
options.put(
CompilerOptions.OPTION_ReportAssertIdentifier,
CompilerOptions.WARNING);
} 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$
continue;
}
if (currentArg.equals("-target")) { //$NON-NLS-1$
didSpecifyTarget = true;
mode = TargetSetting;
continue;
}
if (currentArg.equals("-preserveAllLocals")) { //$NON-NLS-1$
options.put(
CompilerOptions.OPTION_PreserveUnusedLocal,
CompilerOptions.PRESERVE);
continue;
}
if (mode == TargetSetting) {
if (currentArg.equals("1.1")) { //$NON-NLS-1$
options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_1);
} else if (currentArg.equals("1.2")) { //$NON-NLS-1$
options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2);
} else if (currentArg.equals("1.3")) { //$NON-NLS-1$
options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_3);
} else if (currentArg.equals("1.4")) { //$NON-NLS-1$
options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
} else {
throw new InvalidInputException(Main.bind("configure.targetJDK", currentArg)); //$NON-NLS-1$
}
mode = Default;
continue;
}
if (mode == InsideLog) {
log = currentArg;
mode = Default;
continue;
}
if (mode == InsideRepetition) {
try {
repetitions = Integer.parseInt(currentArg);
if (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 == InsideSource) {
if (currentArg.equals("1.3")) { //$NON-NLS-1$
options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
} else if (currentArg.equals("1.4")) { //$NON-NLS-1$
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$
}
options.put(CompilerOptions.OPTION_Encoding, currentArg);
didSpecifyDefaultEncoding = true;
mode = Default;
continue;
}
if (mode == InsideDestinationPath) {
destinationPath = currentArg;
mode = Default;
continue;
}
if (mode == InsideClasspath) {
StringTokenizer tokenizer = new StringTokenizer(currentArg, File.pathSeparator);
while (tokenizer.hasMoreTokens()) {
int length;
if ((length = classpaths.length) <= pathCount) {
System.arraycopy(
classpaths,
0,
(classpaths = new String[length * 2]),
0,
length);
}
classpaths[pathCount++] = 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, ".JAVA", verbose); //$NON-NLS-1$
} catch (Exception e) {
throw new InvalidInputException(Main.bind("configure.IOError", currentArg)); //$NON-NLS-1$
}
if (filenames != null) {
// some source files were specified explicitly
String results[] = finder.resultFiles;
int length = results.length;
System.arraycopy(
filenames,
0,
(filenames = new String[length + filesCount]),
0,
filesCount);
System.arraycopy(
encodings,
0,
(encodings = new String[length + filesCount]),
0,
filesCount);
System.arraycopy(results, 0, filenames, filesCount, length);
for (int i = 0; i < length; i++) {
encodings[filesCount + i] = customEncoding;
}
filesCount += length;
customEncoding = null;
} else {
filenames = finder.resultFiles;
filesCount = filenames.length;
encodings = new String[filesCount];
for (int i = 0; i < filesCount; i++) {
encodings[i] = customEncoding;
}
customEncoding = null;
}
mode = Default;
continue;
}
if (noWarn) {
// filter options which are related to the assist component
Object[] entries = 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)) {
options.put((String) entry.getKey(), CompilerOptions.IGNORE);
}
}
}
/*
* Standalone options
*/
if (versionIDRequired) {
out.println(Main.bind("configure.version", Main.bind("compiler.version"))); //$NON-NLS-1$ //$NON-NLS-2$
out.println();
proceed = false;
return;
}
if (printUsageRequired) {
printUsage();
proceed = false;
return;
}
if (filesCount != 0)
System.arraycopy(
filenames,
0,
(filenames = new String[filesCount]),
0,
filesCount);
if (pathCount == 0) {
String classProp = System.getProperty("DEFAULT_CLASSPATH"); //$NON-NLS-1$
if ((classProp == null) || (classProp.length() == 0)) {
out.println(Main.bind("configure.noClasspath")); //$NON-NLS-1$
classProp = "."; //$NON-NLS-1$
}
StringTokenizer tokenizer = new StringTokenizer(classProp, File.pathSeparator);
classpaths = new String[tokenizer.countTokens()];
while (tokenizer.hasMoreTokens()) {
classpaths[pathCount++] = tokenizer.nextToken();
}
}
if (classpaths == null)
classpaths = new String[0];
System.arraycopy(
classpaths,
0,
(classpaths = new String[pathCount]),
0,
pathCount);
for (int i = 0, max = classpaths.length; i < max; i++) {
File file = new File(classpaths[i]);
if (!file.exists()) // signal missing classpath entry file
out.println(Main.bind("configure.incorrectClasspath", classpaths[i])); //$NON-NLS-1$
}
if (destinationPath == null) {
generatePackagesStructure = false;
} else if ("none".equals(destinationPath)) { //$NON-NLS-1$
destinationPath = null;
}
if (filenames == null)
throw new InvalidInputException(Main.bind("configure.noSource")); //$NON-NLS-1$
// check and set compliance/source/target compatibilities
if (!didSpecifyCompliance){
if (options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_4)){
options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
} else {
options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_3);
}
}
String compliance = (String)options.get(CompilerOptions.OPTION_Compliance);
if (CompilerOptions.VERSION_1_4.equals(compliance)){
// default 1.4 settings
if (!didSpecifySourceLevel){
options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_4);
}
if (!didSpecifyTarget){
options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
}
} else if (CompilerOptions.VERSION_1_3.equals(compliance)){
// default 1.4 settings
if (!didSpecifySourceLevel){
options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
}
if (!didSpecifyTarget){
options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_1);
}
}
// compliance must be 1.4 if source is 1.4
if (options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_4)
&& !options.get(CompilerOptions.OPTION_Compliance).equals(CompilerOptions.VERSION_1_4)){
throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForSource14", (String)options.get(CompilerOptions.OPTION_Compliance))); //$NON-NLS-1$
}
// target must be 1.4 if source is 1.4
if (options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_4)
&& !options.get(CompilerOptions.OPTION_TargetPlatform).equals(CompilerOptions.VERSION_1_4)){
throw new InvalidInputException(Main.bind("configure.incompatibleTargetForSource14", (String)options.get(CompilerOptions.OPTION_TargetPlatform))); //$NON-NLS-1$
}
// target cannot be 1.4 if compliance is 1.3
if (options.get(CompilerOptions.OPTION_TargetPlatform).equals(CompilerOptions.VERSION_1_4)
&& !options.get(CompilerOptions.OPTION_Compliance).equals(CompilerOptions.VERSION_1_4)){
throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForTarget14", (String)options.get(CompilerOptions.OPTION_Compliance))); //$NON-NLS-1$
}
if (log != null) {
try {
out = new PrintWriter(new FileOutputStream(log, false));
} catch (IOException e) {
throw new InvalidInputException(Main.bind("configure.cannotOpenLog")); //$NON-NLS-1$
}
} else {
showProgress = false;
}
if (repetitions == 0) {
repetitions = 1;
}
}
protected Map getOptions() {
return this.options;
}
/*
* Answer the component to which will be handed back compilation results from the compiler
*/
protected ICompilerRequestor getBatchRequestor() {
return new ICompilerRequestor() {
int lineDelta = 0;
public void acceptResult(CompilationResult compilationResult) {
if (compilationResult.lineSeparatorPositions != null) {
int unitLineCount = compilationResult.lineSeparatorPositions.length;
lineCount += unitLineCount;
lineDelta += unitLineCount;
if (showProgress
&& lineDelta > 2000) { // in -log mode, dump a dot every 2000 lines compiled
System.out.print('.');
lineDelta = 0;
}
}
if (compilationResult.hasProblems()) {
IProblem[] problems = compilationResult.getProblems();
int count = problems.length;
int localErrorCount = 0;
for (int i = 0; i < count; i++) {
if (problems[i] != null) {
globalProblemsCount++;
if (localErrorCount == 0)
out.println("----------"); //$NON-NLS-1$
out.print(
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()) {
globalErrorsCount++;
} else {
globalWarningsCount++;
}
out.print(" "); //$NON-NLS-1$
out.print(
Main.bind("requestor.in", new String(problems[i].getOriginatingFileName()))); //$NON-NLS-1$
try {
out.println(
((DefaultProblem) problems[i]).errorReportSource(
compilationResult.compilationUnit));
out.println(problems[i].getMessage());
} catch (Exception e) {
out.println(
Main.bind("requestor.notRetrieveErrorMessage", problems[i].toString())); //$NON-NLS-1$
}
out.println("----------"); //$NON-NLS-1$
if (problems[i].isError())
localErrorCount++;
}
};
// exit?
if (systemExitWhenFinished && !proceedOnError && (localErrorCount > 0)) {
out.flush();
System.exit(-1);
}
}
outputClassFiles(compilationResult);
}
};
}
/*
* Build the set of compilation source units
*/
protected CompilationUnit[] getCompilationUnits()
throws InvalidInputException {
int fileCount = filenames.length;
CompilationUnit[] units = new CompilationUnit[fileCount];
HashtableOfObject knownFileNames = new HashtableOfObject(fileCount);
String defaultEncoding = (String) 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 = filenames[i].toCharArray();
if (knownFileNames.get(charName) != null) {
throw new InvalidInputException(Main.bind("unit.more", filenames[i])); //$NON-NLS-1$
} else {
knownFileNames.put(charName, charName);
}
File file = new File(filenames[i]);
if (!file.exists())
throw new InvalidInputException(Main.bind("unit.missing", filenames[i])); //$NON-NLS-1$
String encoding = encodings[i];
if (encoding == null)
encoding = defaultEncoding;
units[i] = new CompilationUnit(null, filenames[i], encoding);
}
return units;
}
/*
* Low-level API performing the actual compilation
*/
protected 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 stopOnFirstError() {
return false;
}
public boolean proceedOnErrors() {
return proceedOnError; // stop if there are some errors
}
};
}
/*
* Low-level API performing the actual compilation
*/
protected FileSystem getLibraryAccess() {
String defaultEncoding = (String) options.get(CompilerOptions.OPTION_Encoding);
if ("".equals(defaultEncoding)) //$NON-NLS-1$
defaultEncoding = null; //$NON-NLS-1$
return new FileSystem(classpaths, filenames, defaultEncoding);
}
/*
* Low-level API performing the actual compilation
*/
protected IProblemFactory getProblemFactory() {
return new DefaultProblemFactory(Locale.getDefault());
}
/*
* External API
*/
public static void main(String[] argv) {
new Main(new PrintWriter(System.out), true).compile(argv);
}
// Dump classfiles onto disk for all compilation units that where successfull.
protected void outputClassFiles(CompilationResult unitResult) {
if (!((unitResult == null) || (unitResult.hasErrors() && !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(CLASS_FILE_EXTENSION, 0, relativeName, length, 6);
CharOperation.replace(relativeName, '/', File.separatorChar);
try {
ClassFile.writeToDisk(
generatePackagesStructure,
destinationPath,
new String(relativeName),
classFile.getBytes());
} catch (IOException e) {
String fileName = destinationPath + new String(relativeName);
e.printStackTrace();
System.out.println(Main.bind("output.noClassFileCreated", fileName)); //$NON-NLS-1$
}
exportedClassFilesCounter++;
}
} else if (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(CLASS_FILE_EXTENSION, 0, relativeName, length, 6);
CharOperation.replace(relativeName, '/', File.separatorChar);
try {
ClassFile.writeToDisk(
generatePackagesStructure,
destinationPath,
new String(relativeName),
classFile.getBytes());
} catch (IOException e) {
String fileName = destinationPath + new String(relativeName);
e.printStackTrace();
System.out.println(Main.bind("output.noClassFileCreated", fileName)); //$NON-NLS-1$
}
exportedClassFilesCounter++;
}
}
}
}
/*
* Low-level API performing the actual compilation
*/
protected void performCompilation() throws InvalidInputException {
INameEnvironment environment = getLibraryAccess();
Compiler batchCompiler =
new Compiler(
environment,
getHandlingPolicy(),
getOptions(),
getBatchRequestor(),
getProblemFactory());
CompilerOptions options = batchCompiler.options;
// set the non-externally configurable options.
options.setVerboseMode(verbose);
options.produceReferenceInfo(produceRefInfo);
batchCompiler.compile(getCompilationUnits());
// cleanup
environment.cleanup();
}
private void printUsage() {
out.println(Main.bind("misc.usage", Main.bind("compiler.version"))); //$NON-NLS-1$ //$NON-NLS-2$
out.flush();
}
/**
* Creates a NLS catalog for the given locale.
*/
public static void relocalize() {
bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault());
}
/**
* Lookup the message with the given ID in this catalog
*/
public static String bind(String id) {
return bind(id, (String[]) null);
}
/**
* Lookup the message with the given ID in this catalog and bind its
* substitution locations with the given string values.
*/
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);
if (bindings == null)
return message;
int length = message.length();
int start = -1;
int end = length;
StringBuffer output = new StringBuffer(80);
while (true) {
if ((end = message.indexOf('{', start)) > -1) {
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) {
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 {
output.append(message.substring(start + 1, length));
break;
}
}
return output.toString();
}
/**
* Lookup the message with the given ID in this catalog and bind its
* substitution locations with the given string.
*/
public static String bind(String id, String binding) {
return bind(id, new String[] { binding });
}
/**
* Lookup the message with the given ID in this catalog and bind its
* substitution locations with the given strings.
*/
public static String bind(String id, String binding1, String binding2) {
return bind(id, new String[] { binding1, binding2 });
}
private 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$
}
}