org.aspectj.ajdt.ajc.BuildArgParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aspectjtools Show documentation
Show all versions of aspectjtools Show documentation
Tools from the AspectJ project
/* *******************************************************************
* Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v 2.0
* which accompanies this distribution and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
*
* Contributors:
* PARC initial implementation
* ******************************************************************/
package org.aspectj.ajdt.ajc;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;
import org.aspectj.ajdt.internal.compiler.lookup.EclipseSourceLocation;
import org.aspectj.ajdt.internal.core.builder.AjBuildConfig;
import org.aspectj.bridge.CountingMessageHandler;
import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.IMessageHandler;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.Message;
import org.aspectj.bridge.MessageUtil;
import org.aspectj.bridge.SourceLocation;
import org.aspectj.bridge.Version;
import org.aspectj.org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.aspectj.org.eclipse.jdt.internal.compiler.apt.dispatch.AptProblem;
import org.aspectj.org.eclipse.jdt.internal.compiler.batch.FileSystem;
import org.aspectj.org.eclipse.jdt.internal.compiler.batch.Main;
import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.aspectj.org.eclipse.jdt.internal.compiler.env.IModule;
import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.aspectj.util.FileUtil;
import org.aspectj.util.LangUtil;
import org.aspectj.weaver.Constants;
import org.aspectj.weaver.Dump;
import org.aspectj.weaver.WeaverMessages;
@SuppressWarnings("unchecked")
public class BuildArgParser extends Main {
/** to initialize super's PrintWriter but refer to underlying StringWriter */
private static class StringPrintWriter extends PrintWriter {
public final StringWriter stringWriter;
StringPrintWriter(StringWriter sw) {
super(sw);
this.stringWriter = sw;
}
}
/** @return multi-line String usage for the compiler */
public static String getUsage() {
return _bind("misc.usage", new String[] { _bind("compiler.name", (String[]) null) });
}
public static String getXOptionUsage() {
return _bind("xoption.usage", new String[] { _bind("compiler.name", (String[]) null) });
}
/**
* StringWriter sink for some errors. This only captures errors not handled by any IMessageHandler parameter and only when no
* PrintWriter is set in the constructor. XXX This relies on (Sun's) implementation of StringWriter, which returns the actual
* (not copy) internal StringBuffer.
*/
private final StringBuffer errorSink;
private IMessageHandler handler;
/**
* Overrides super's bundle.
*/
public BuildArgParser(PrintWriter writer, IMessageHandler handler) {
super(writer, writer, false, null, null);
if (writer instanceof StringPrintWriter) {
errorSink = ((StringPrintWriter) writer).stringWriter.getBuffer();
} else {
errorSink = null;
}
this.handler = handler;
}
/** Set up to capture messages using getOtherMessages(boolean) */
public BuildArgParser(IMessageHandler handler) {
this(new StringPrintWriter(new StringWriter()), handler);
}
/**
* Generate build configuration for the input args, passing to handler any error messages.
*
* @param args the String[] arguments for the build configuration
* @return AjBuildConfig per args, which will be invalid unless there are no handler errors.
*/
public AjBuildConfig genBuildConfig(String[] args) {
final AjBuildConfig config = new AjBuildConfig(this);
populateBuildConfig(config, args, true, null);
return config;
}
/**
* Generate build configuration for the input arguments, passing to handler any error messages.
*
* @param args the String[] arguments for the build configuration
* @param setClasspath determines if the classpath should be parsed and set on the build configuration
* @param configFile can be null
* @return AjBuildConfig per arguments, which will be invalid unless there are no handler errors.
*/
public AjBuildConfig populateBuildConfig(AjBuildConfig buildConfig, String[] args, boolean setClasspath, File configFile) {
Dump.saveCommandLine(args);
buildConfig.setConfigFile(configFile);
try {
// sets filenames to be non-null in order to make sure that file parameters are ignored
super.filenames = new String[] { "" };
AjcConfigParser parser = new AjcConfigParser(buildConfig, handler);
parser.parseCommandLine(args);
boolean swi = buildConfig.getShowWeavingInformation();
// Now jump through firey hoops to turn them on/off
if (handler instanceof CountingMessageHandler) {
IMessageHandler delegate = ((CountingMessageHandler) handler).delegate;
if (swi) {
delegate.dontIgnore(IMessage.WEAVEINFO);
} else {
delegate.ignore(IMessage.WEAVEINFO);
}
}
boolean incrementalMode = buildConfig.isIncrementalMode() || buildConfig.isIncrementalFileMode();
List xmlfileList = new ArrayList<>(parser.getXmlFiles());
List fileList = new ArrayList<>();
List files = parser.getFiles();
if (!LangUtil.isEmpty(files)) {
if (incrementalMode) {
MessageUtil.error(handler, "incremental mode only handles source files using -sourceroots");
} else {
fileList.addAll(files);
}
}
List javaArgList = new ArrayList<>();
// disable all special eclipse warnings by default - why???
// ??? might want to instead override getDefaultOptions()
javaArgList.add("-warn:none");
// these next four lines are some nonsense to fool the eclipse batch compiler
// without these it will go searching for reasonable values from properties
// TODO fix org.eclipse.jdt.internal.compiler.batch.Main so this hack isn't needed
javaArgList.add("-classpath");
javaArgList.add(parser.classpath == null ? System.getProperty("user.dir") : parser.classpath);
// javaArgList.add("-bootclasspath");
// javaArgList.add(parser.bootclasspath == null ? System.getProperty("user.dir") : parser.bootclasspath);
javaArgList.addAll(parser.getUnparsedArgs());
super.configure(javaArgList.toArray(new String[0]));
if (parser.getModuleInfoArgument() != null) {
IModule moduleDesc = super.getModuleDesc(parser.getModuleInfoArgument());
buildConfig.setModuleDesc(moduleDesc);
}
if (!proceed) {
buildConfig.doNotProceed();
return buildConfig;
}
if (buildConfig.getSourceRoots() != null) {
for (File file : buildConfig.getSourceRoots()) {
fileList.addAll(collectSourceRootFiles(file));
}
}
buildConfig.setXmlFiles(xmlfileList);
buildConfig.setFiles(fileList);
if (destinationPath != null) { // XXX ?? unparsed but set?
buildConfig.setOutputDir(new File(destinationPath));
}
if (setClasspath) {
// This computed classpaths will be missing aspectpaths, inpaths, add those first
buildConfig.setClasspath(getClasspath(parser));
// Implicit inclusion of jmods on module path
if (checkVMVersion(ClassFileConstants.JDK9)) {
// Add the default jmods path? javac seems to do this
File jmods = new File(getJavaHome(),"jmods");
parser.modulepath = (parser.modulepath == null)?jmods.getAbsolutePath():parser.modulepath+File.pathSeparator+jmods.getAbsolutePath();
}
buildConfig.setModulepath(getModulepath(parser));
buildConfig.setModulepathClasspathEntries(handleModulepath(parser.modulepath));
buildConfig.setModulesourcepath(getModulesourcepath(parser));
buildConfig.setModulesourcepathClasspathEntries(handleModuleSourcepath(parser.modulesourcepath));
buildConfig.setBootclasspath(getBootclasspath(parser));
// TODO other paths (module/module source)
}
if (incrementalMode && (0 == buildConfig.getSourceRoots().size())) {
MessageUtil.error(handler, "specify a source root when in incremental mode");
}
/*
* Ensure we don't overwrite injars, inpath or aspectpath with outjar bug-71339
*/
File outjar = buildConfig.getOutputJar();
if (outjar != null) {
for (File injar: buildConfig.getInJars()) {
if (injar.equals(outjar)) {
String message = WeaverMessages.format(WeaverMessages.OUTJAR_IN_INPUT_PATH);
MessageUtil.error(handler, message);
}
}
for (File inPathElement: buildConfig.getInpath()) {
if (!inPathElement.isDirectory() && inPathElement.equals(outjar)) {
String message = WeaverMessages.format(WeaverMessages.OUTJAR_IN_INPUT_PATH);
MessageUtil.error(handler, message);
}
}
for (File aspectPathElement: buildConfig.getAspectpath()) {
if (!aspectPathElement.isDirectory() && aspectPathElement.equals(outjar)) {
String message = WeaverMessages.format(WeaverMessages.OUTJAR_IN_INPUT_PATH);
MessageUtil.error(handler, message);
}
}
}
setDebugOptions();
buildConfig.getOptions().set(options);
} catch (IllegalArgumentException iae) {
ISourceLocation location = null;
if (buildConfig.getConfigFile() != null) {
location = new SourceLocation(buildConfig.getConfigFile(), 0);
}
IMessage m = new Message(iae.getMessage(), IMessage.ERROR, null, location);
handler.handleMessage(m);
}
return buildConfig;
}
private void augmentCheckedClasspaths(List extraPathEntries, String encoding) {
if (extraPathEntries.size() == 0) {
return;
}
ArrayList asList = toArrayList(extraPathEntries);
List newClasspathEntries = handleClasspath(asList, encoding);
FileSystem.Classpath[] newCheckedClasspaths = new FileSystem.Classpath[checkedClasspaths.length + newClasspathEntries.size()];
System.arraycopy(checkedClasspaths, 0, newCheckedClasspaths, 0, checkedClasspaths.length);
for (int i = 0; i < newClasspathEntries.size();i++) {
newCheckedClasspaths[i + checkedClasspaths.length] = newClasspathEntries.get(i);
}
checkedClasspaths = newCheckedClasspaths;
}
private ArrayList toArrayList(java.util.List files) {
ArrayList arrayList = new ArrayList<>();
for (File file: files) {
arrayList.add(file.getAbsolutePath());
}
return arrayList;
}
@Override
public void printVersion() {
final String version = bind(
"misc.version", //$NON-NLS-1$
new String[] {
bind("compiler.name"), //$NON-NLS-1$
Version.getText() + " - Built: " + Version.getTimeText(),
bind("compiler.version"), //$NON-NLS-1$
bind("compiler.copyright") //$NON-NLS-1$
}
);
System.out.println(version);
}
@Override
public void addExtraProblems(CategorizedProblem problem) {
super.addExtraProblems(problem);
if (problem instanceof AptProblem) {
handler.handleMessage(newAptMessage((AptProblem)problem));
}
}
private IMessage newAptMessage(AptProblem problem) {
String message = problem.getMessage();
boolean isError = problem.isError();
if (problem._referenceContext != null) {
return new Message(message,
new EclipseSourceLocation(problem._referenceContext.compilationResult(), problem.getSourceStart(), problem.getSourceEnd()),
isError);
} else {
return new Message(message, null, isError);
}
}
@Override
public void initializeAnnotationProcessorManager() {
if (this.compilerOptions.complianceLevel < ClassFileConstants.JDK1_6 || !this.compilerOptions.processAnnotations)
return;
super.initializeAnnotationProcessorManager();
}
/**
* Get messages not dumped to handler or any PrintWriter.
*
* @param flush if true, empty errors
* @return null if none, String otherwise
* @see #BuildArgParser(IMessageHandler)
*/
public String getOtherMessages(boolean flush) {
if (null == errorSink) {
return null;
}
String result = errorSink.toString().trim();
if (0 == result.length()) {
result = null;
}
if (flush) {
errorSink.setLength(0);
}
return result;
}
private void setDebugOptions() {
options.put(CompilerOptions.OPTION_LocalVariableAttribute, CompilerOptions.GENERATE);
options.put(CompilerOptions.OPTION_LineNumberAttribute, CompilerOptions.GENERATE);
options.put(CompilerOptions.OPTION_SourceFileAttribute, CompilerOptions.GENERATE);
}
private Collection collectSourceRootFiles(File dir) {
return Arrays.asList(FileUtil.listFiles(dir, FileUtil.aspectjSourceFileFilter));
}
public List getBootclasspath(AjcConfigParser parser) {
List ret = new ArrayList<>();
if (parser.bootclasspath == null) {
if (LangUtil.is9VMOrGreater()) {
addClasspath(LangUtil.getJrtFsFilePath(),ret);
} else {
addClasspath(System.getProperty("sun.boot.class.path", ""), ret);
}
} else {
addClasspath(parser.bootclasspath, ret);
}
return ret;
}
public List getModulepath(AjcConfigParser parser) {
List ret = new ArrayList<>();
addClasspath(parser.modulepath, ret);
return ret;
}
public List getModulesourcepath(AjcConfigParser parser) {
List ret = new ArrayList<>();
addClasspath(parser.modulesourcepath, ret);
return ret;
}
@Override
public ArrayList handleClasspath(ArrayList classpaths, String customEncoding) {
return super.handleClasspath(classpaths, customEncoding);
}
/**
* If the classpath is not set, we use the environment's java.class.path, but remove the aspectjtools.jar entry from that list
* in order to prevent wierd bootstrap issues (refer to bug#39959).
*/
public List getClasspath(AjcConfigParser parser) {
List ret = new ArrayList<>();
// if (parser.bootclasspath == null) {
// addClasspath(System.getProperty("sun.boot.class.path", ""), ret);
// } else {
// addClasspath(parser.bootclasspath, ret);
// }
String extdirs = parser.extdirs;
if (extdirs == null) {
extdirs = System.getProperty("java.ext.dirs", "");
}
addExtDirs(extdirs, ret);
if (parser.classpath == null) {
addClasspath(System.getProperty("java.class.path", ""), ret);
List fixedList = new ArrayList<>();
for (String entry : ret) {
if (!entry.endsWith("aspectjtools.jar")) {
fixedList.add(entry);
}
}
ret = fixedList;
} else {
addClasspath(parser.classpath, ret);
}
// ??? eclipse seems to put outdir on the classpath
// ??? we're brave and believe we don't need it
return ret;
}
public FileSystem.Classpath[] getCheckedClasspaths() {
return checkedClasspaths;
}
private void addExtDirs(String extdirs, List classpathCollector) {
StringTokenizer tokenizer = new StringTokenizer(extdirs, File.pathSeparator);
while (tokenizer.hasMoreTokens()) {
// classpathCollector.add(tokenizer.nextToken());
File dirFile = new File(tokenizer.nextToken());
if (dirFile.canRead() && dirFile.isDirectory()) {
File[] files = dirFile.listFiles(FileUtil.ZIP_FILTER);
for (File file : files) {
classpathCollector.add(file.getAbsolutePath());
}
} else {
// XXX alert on invalid -extdirs entries
}
}
}
private void addClasspath(String classpath, List classpathCollector) {
if (classpath == null) {
return;
}
StringTokenizer tokenizer = new StringTokenizer(classpath, File.pathSeparator);
while (tokenizer.hasMoreTokens()) {
classpathCollector.add(tokenizer.nextToken());
}
}
private class AjcConfigParser extends ConfigParser {
private String bootclasspath = null;
private String classpath = null;
private String modulepath = null;
private String modulesourcepath = null;
private String extdirs = null;
private List unparsedArgs = new ArrayList<>();
private AjBuildConfig buildConfig;
private IMessageHandler handler;
private String moduleInfoArgument;
public AjcConfigParser(AjBuildConfig buildConfig, IMessageHandler handler) {
this.buildConfig = buildConfig;
this.handler = handler;
}
public List getUnparsedArgs() {
return unparsedArgs;
}
public String getModuleInfoArgument() {
return this.moduleInfoArgument;
}
/**
* Extract AspectJ-specific options (except for argfiles). Caller should warn when sourceroots is empty but in incremental
* mode. Signals warnings or errors through handler set in constructor.
*/
@Override
public void parseOption(String arg, LinkedList args) { // XXX use ListIterator.remove()
int nextArgIndex = args.indexOf(arg) + 1; // XXX assumes unique
// trim arg?
buildConfig.setXlazyTjp(true); // now default - MINOR could be pushed down and made default at a lower level
if (LangUtil.isEmpty(arg)) {
showWarning("empty arg found");
} else if (arg.endsWith("module-info.java")) {
moduleInfoArgument = arg;
} else if (arg.equals("-inpath")) {
if (args.size() > nextArgIndex) {
// buildConfig.getAjOptions().put(AjCompilerOptions.OPTION_Inpath, CompilerOptions.PRESERVE);
StringTokenizer st = new StringTokenizer(args.get(nextArgIndex).getValue(),
File.pathSeparator);
boolean inpathChange = false;
while (st.hasMoreTokens()) {
String filename = st.nextToken();
File file = makeFile(filename);
if (FileUtil.isZipFile(file)) {
buildConfig.addToInpath(file);
inpathChange = true;
} else {
if (file.isDirectory()) {
buildConfig.addToInpath(file);
inpathChange = true;
} else {
showWarning("skipping missing, empty or corrupt inpath entry: " + filename);
}
}
}
if (inpathChange) {
buildConfig.processInPath();
}
args.remove(args.get(nextArgIndex));
}
} else if (arg.equals("-injars")) {
if (args.size() > nextArgIndex) {
// buildConfig.getAjOptions().put(AjCompilerOptions.OPTION_InJARs, CompilerOptions.PRESERVE);
StringTokenizer st = new StringTokenizer(args.get(nextArgIndex).getValue(),
File.pathSeparator);
while (st.hasMoreTokens()) {
String filename = st.nextToken();
File jarFile = makeFile(filename);
if (FileUtil.isZipFile(jarFile)) {
buildConfig.getInJars().add(jarFile);
} else {
File dirFile = makeFile(filename);
if (dirFile.isDirectory()) {
buildConfig.getInJars().add(dirFile);
} else {
showWarning("skipping missing, empty or corrupt injar: " + filename);
}
}
}
args.remove(args.get(nextArgIndex));
}
} else if (arg.equals("-aspectpath")) {
if (args.size() > nextArgIndex) {
StringTokenizer st = new StringTokenizer(args.get(nextArgIndex).getValue(),
File.pathSeparator);
while (st.hasMoreTokens()) {
String filename = st.nextToken();
File jarFile = makeFile(filename);
if (FileUtil.isZipFile(jarFile) || jarFile.isDirectory()) {
// buildConfig.getAspectpath().add(jarFile);
buildConfig.addToAspectpath(jarFile);
} else {
showWarning("skipping missing, empty or corrupt aspectpath entry: " + filename);
}
}
args.remove(args.get(nextArgIndex));
}
} else if (arg.equals("-makeAjReflectable")) {
buildConfig.setMakeReflectable(true);
} else if (arg.equals("-sourceroots")) {
if (args.size() > nextArgIndex) {
List sourceRoots = new ArrayList<>();
StringTokenizer st = new StringTokenizer(args.get(nextArgIndex).getValue(),
File.pathSeparator);
while (st.hasMoreTokens()) {
File f = makeFile(st.nextToken());
if (f.isDirectory() && f.canRead()) {
sourceRoots.add(f);
} else {
showError("bad sourceroot: " + f);
}
}
if (0 < sourceRoots.size()) {
buildConfig.setSourceRoots(sourceRoots);
}
args.remove(args.get(nextArgIndex));
} else {
showError("-sourceroots requires list of directories");
}
} else if (arg.equals("-outjar")) {
if (args.size() > nextArgIndex) {
// buildConfig.getAjOptions().put(AjCompilerOptions.OPTION_OutJAR, CompilerOptions.GENERATE);
File jarFile = makeFile(args.get(nextArgIndex).getValue());
if (!jarFile.isDirectory()) {
try {
if (!jarFile.exists()) {
jarFile.createNewFile();
}
buildConfig.setOutputJar(jarFile);
} catch (IOException ioe) {
showError("unable to create outjar file: " + jarFile);
}
} else {
showError("invalid -outjar file: " + jarFile);
}
args.remove(args.get(nextArgIndex));
} else {
showError("-outjar requires jar path argument");
}
} else if (arg.equals("-outxml")) {
buildConfig.setOutxmlName(org.aspectj.bridge.Constants.AOP_AJC_XML);
} else if (arg.equals("-outxmlfile")) {
if (args.size() > nextArgIndex) {
String name = args.get(nextArgIndex).getValue();
buildConfig.setOutxmlName(name);
args.remove(args.get(nextArgIndex));
} else {
showError("-outxmlfile requires file name argument");
}
} else if (arg.equals("-log")) {
// remove it as it's already been handled in org.aspectj.tools.ajc.Main
args.remove(args.get(nextArgIndex));
} else if (arg.equals("-messageHolder")) {
// remove it as it's already been handled in org.aspectj.tools.ajc.Main
args.remove(args.get(nextArgIndex));
} else if (arg.equals("-incremental")) {
buildConfig.setIncrementalMode(true);
} else if (arg.equals("-XincrementalFile")) {
if (args.size() > nextArgIndex) {
File file = makeFile(args.get(nextArgIndex).getValue());
buildConfig.setIncrementalFile(file);
if (!file.canRead()) {
showError("bad -XincrementalFile : " + file);
// if not created before recompile test, stop after first compile
}
args.remove(args.get(nextArgIndex));
} else {
showError("-XincrementalFile requires file argument");
}
} else if (arg.equals("-crossrefs")) {
buildConfig.setGenerateCrossRefsMode(true);
buildConfig.setGenerateModelMode(true);
} else if (arg.startsWith("-checkRuntimeVersion:")) {
String lcArg = arg.toLowerCase();
if (lcArg.endsWith(":false")) {
buildConfig.setCheckRuntimeVersion(false);
} else if (lcArg.endsWith(":true")) {
buildConfig.setCheckRuntimeVersion(true);
} else {
showError("bad value for -checkRuntimeVersion option, must be true or false");
}
} else if (arg.equals("-emacssym")) {
buildConfig.setEmacsSymMode(true);
buildConfig.setGenerateModelMode(true);
} else if (arg.equals("-XjavadocsInModel")) {
buildConfig.setGenerateModelMode(true);
buildConfig.setGenerateJavadocsInModelMode(true);
} else if (arg.equals("-Xdev:NoAtAspectJProcessing")) {
buildConfig.setNoAtAspectJAnnotationProcessing(true);
} else if (arg.equals("-XaddSerialVersionUID")) {
buildConfig.setAddSerialVerUID(true);
} else if (arg.equals("-xmlConfigured")) {
buildConfig.setXmlConfigured(true);
} else if (arg.equals("-Xdev:Pinpoint")) {
buildConfig.setXdevPinpointMode(true);
} else if (arg.startsWith("-Xjoinpoints:")) {
buildConfig.setXJoinpoints(arg.substring(13));
} else if (arg.equals("-noWeave") || arg.equals("-XnoWeave")) {
showWarning("the noweave option is no longer required and is being ignored");
} else if (arg.equals("-XterminateAfterCompilation")) {
buildConfig.setTerminateAfterCompilation(true);
} else if (arg.equals("-XserializableAspects")) {
buildConfig.setXserializableAspects(true);
} else if (arg.equals("-XlazyTjp")) {
// do nothing as this is now on by default
showWarning("-XlazyTjp should no longer be used, build tjps lazily is now the default");
} else if (arg.startsWith("-Xreweavable")) {
showWarning("-Xreweavable is on by default");
if (arg.endsWith(":compress")) {
showWarning("-Xreweavable:compress is no longer available - reweavable is now default");
}
} else if (arg.startsWith("-Xset:")) {
buildConfig.setXconfigurationInfo(arg.substring(6));
} else if (arg.startsWith("-aspectj.pushin=")) {
// a little dirty but this should never be used in the IDE
try {
System.setProperty("aspectj.pushin", arg.substring(16));
} catch (Exception e) {
e.printStackTrace();
}
} else if (arg.startsWith("-XnotReweavable")) {
buildConfig.setXnotReweavable(true);
} else if (arg.equals("-XnoInline")) {
buildConfig.setXnoInline(true);
} else if (arg.equals("-XhasMember")) {
buildConfig.setXHasMemberSupport(true);
} else if (arg.startsWith("-showWeaveInfo")) {
buildConfig.setShowWeavingInformation(true);
} else if (arg.equals("-Xlintfile")) {
if (args.size() > nextArgIndex) {
File lintSpecFile = makeFile(args.get(nextArgIndex).getValue());
// XXX relax restriction on props file suffix?
if (lintSpecFile.canRead() && lintSpecFile.getName().endsWith(".properties")) {
buildConfig.setLintSpecFile(lintSpecFile);
} else {
showError("bad -Xlintfile file: " + lintSpecFile);
buildConfig.setLintSpecFile(null);
}
args.remove(args.get(nextArgIndex));
} else {
showError("-Xlintfile requires .properties file argument");
}
} else if (arg.equals("-Xlint")) {
// buildConfig.getAjOptions().put(
// AjCompilerOptions.OPTION_Xlint,
// CompilerOptions.GENERATE);
buildConfig.setLintMode(AjBuildConfig.AJLINT_DEFAULT);
} else if (arg.startsWith("-Xlint:")) {
if (7 < arg.length()) {
buildConfig.setLintMode(arg.substring(7));
} else {
showError("invalid lint option " + arg);
}
} else if (arg.equals("-bootclasspath")) {
if (args.size() > nextArgIndex) {
String bcpArg = args.get(nextArgIndex).getValue();
StringBuilder bcp = new StringBuilder();
StringTokenizer strTok = new StringTokenizer(bcpArg, File.pathSeparator);
while (strTok.hasMoreTokens()) {
bcp.append(makeFile(strTok.nextToken()));
if (strTok.hasMoreTokens()) {
bcp.append(File.pathSeparator);
}
}
bootclasspath = bcp.toString();
args.remove(args.get(nextArgIndex));
} else {
showError("-bootclasspath requires classpath entries");
}
} else if (arg.equals("-classpath") || arg.equals("-cp")) {
if (args.size() > nextArgIndex) {
String cpArg = args.get(nextArgIndex).getValue();
StringBuilder cp = new StringBuilder();
StringTokenizer strTok = new StringTokenizer(cpArg, File.pathSeparator);
while (strTok.hasMoreTokens()) {
cp.append(makeFile(strTok.nextToken()));
if (strTok.hasMoreTokens()) {
cp.append(File.pathSeparator);
}
}
classpath = cp.toString();
args.remove(args.get(nextArgIndex));
} else {
showError("-classpath requires classpath entries");
}
} else if (arg.equals("--module-path") || arg.equals("-p")) {
if (args.size() > nextArgIndex) {
String mpArg = args.get(nextArgIndex).getValue();
modulepath = mpArg;
args.remove(args.get(nextArgIndex));
} else {
showError("--module-path requires modulepath entries");
}
} else if (arg.equals("--module-source-path") || arg.equals("-p")) {
if (args.size() > nextArgIndex) {
String mspArg = args.get(nextArgIndex).getValue();
modulesourcepath = mspArg;
args.remove(args.get(nextArgIndex));
} else {
showError("--module-source-path requires modulepath entries");
}
} else if (arg.equals("-extdirs")) {
if (args.size() > nextArgIndex) {
String extdirsArg = args.get(nextArgIndex).getValue();
StringBuilder ed = new StringBuilder();
StringTokenizer strTok = new StringTokenizer(extdirsArg, File.pathSeparator);
while (strTok.hasMoreTokens()) {
ed.append(makeFile(strTok.nextToken()));
if (strTok.hasMoreTokens()) {
ed.append(File.pathSeparator);
}
}
extdirs = ed.toString();
args.remove(args.get(nextArgIndex));
} else {
showError("-extdirs requires list of external directories");
}
// error on directory unless -d, -{boot}classpath, or -extdirs
} else if (arg.equals("-d")) {
dirLookahead(arg, args, nextArgIndex);
// } else if (arg.equals("-classpath")) {
// dirLookahead(arg, args, nextArgIndex);
// } else if (arg.equals("-bootclasspath")) {
// dirLookahead(arg, args, nextArgIndex);
// } else if (arg.equals("-extdirs")) {
// dirLookahead(arg, args, nextArgIndex);
} else if (arg.equals("-proceedOnError")) {
buildConfig.setProceedOnError(true);
} else if (arg.equals("-processorpath")) { // -processorpath
addPairToUnparsed(args, arg, nextArgIndex, "-processor requires list of processors' classes");
} else if (arg.equals("-s")) { // -s destination directory for generated source files
addPairToUnparsed(args, arg, nextArgIndex, "-s requires directory");
} else if (arg.equals("-classNames")) { // -classNames
addPairToUnparsed(args, arg, nextArgIndex, "-classNames requires list of classes");
} else if (new File(arg).isDirectory()) {
showError("dir arg not permitted: " + arg);
} else if (arg.startsWith("-Xajruntimetarget")) {
if (arg.endsWith(":1.2")) {
buildConfig.setTargetAspectjRuntimeLevel(Constants.RUNTIME_LEVEL_12);
} else if (arg.endsWith(":1.5")) {
buildConfig.setTargetAspectjRuntimeLevel(Constants.RUNTIME_LEVEL_15);
} else if (arg.endsWith(":1.9")) {
buildConfig.setTargetAspectjRuntimeLevel(Constants.RUNTIME_LEVEL_19);
} else {
showError("-Xajruntimetarget: supports a target level of 1.2, 1.5, 1.9");
}
} else if (arg.equals("-timers")) {
buildConfig.setTiming(true);
// swallow - it is dealt with in Main.runMain()
} else if (arg.equals("-1.3")) {
buildConfig.setBehaveInJava5Way(false);
unparsedArgs.add("-1.3");
} else if (arg.equals("-1.4")) {
buildConfig.setBehaveInJava5Way(false);
unparsedArgs.add("-1.4");
} else if (arg.equals("-source")) {
if (args.size() > nextArgIndex) {
String level = args.get(nextArgIndex).getValue();
if (level.equals("1.3") || level.equals("1.4")) {
buildConfig.setBehaveInJava5Way(false);
}
unparsedArgs.add("-source");
unparsedArgs.add(level);
args.remove(args.get(nextArgIndex));
}
} else {
// argfile, @file parsed by superclass
// no eclipse options parsed:
// -d args, -help (handled),
// -classpath, -target, -1.3, -1.4, -source [1.3|1.4]
// -nowarn, -warn:[...], -deprecation, -noImportError,
// -g:[...], -preserveAllLocals,
// -referenceInfo, -encoding, -verbose, -log, -time
// -noExit, -repeat
// (Actually, -noExit grabbed by Main)
unparsedArgs.add(arg);
}
}
protected void dirLookahead(String arg, LinkedList argList, int nextArgIndex) {
unparsedArgs.add(arg);
ConfigParser.Arg next = (ConfigParser.Arg) argList.get(nextArgIndex);
String value = next.getValue();
if (!LangUtil.isEmpty(value)) {
if (new File(value).isDirectory()) {
unparsedArgs.add(value);
argList.remove(next);
return;
}
}
}
@Override
public void showError(String message) {
ISourceLocation location = null;
if (buildConfig.getConfigFile() != null) {
location = new SourceLocation(buildConfig.getConfigFile(), 0);
}
IMessage errorMessage = new Message(CONFIG_MSG + message, IMessage.ERROR, null, location);
handler.handleMessage(errorMessage);
// MessageUtil.error(handler, CONFIG_MSG + message);
}
@Override
protected void showWarning(String message) {
ISourceLocation location = null;
if (buildConfig.getConfigFile() != null) {
location = new SourceLocation(buildConfig.getConfigFile(), 0);
}
IMessage errorMessage = new Message(CONFIG_MSG + message, IMessage.WARNING, null, location);
handler.handleMessage(errorMessage);
// MessageUtil.warn(handler, message);
}
protected File makeFile(File dir, String name) {
name = name.replace('/', File.separatorChar);
File ret = new File(name);
if (dir == null || ret.isAbsolute()) {
return ret;
}
try {
dir = dir.getCanonicalFile();
} catch (IOException ioe) {
}
return new File(dir, name);
}
private void addPairToUnparsed(LinkedList args, String arg, int nextArgIndex, String errorMessage) {
if (args.size() <= nextArgIndex) {
showError(errorMessage);
return;
}
final Arg nextArg = args.get(nextArgIndex);
args.remove(nextArg);
unparsedArgs.add(arg);
unparsedArgs.add(nextArg.getValue());
}
private int indexOf(Iterable args, String arg) {
int index = 0;
for (Arg argument : args) {
if (arg.equals(argument.getValue())) {
return index;
}
index++;
}
return -1;
}
}
@Override
public boolean checkVMVersion(long minimalSupportedVersion) {
return super.checkVMVersion(minimalSupportedVersion);
}
@Override
public void initRootModules(LookupEnvironment environment, FileSystem fileSystem) {
super.initRootModules(environment, fileSystem);
}
}