From a24d15f5e7538985ca9718d9e78635bb53372736 Mon Sep 17 00:00:00 2001 From: Andy Clement Date: Fri, 20 Oct 2017 12:48:41 -0700 Subject: Adjust how classpath entries manipulated for Java9 support Prior to this AspectJ would discard ignore the ClasspathEntry objects built by JDT and just work with the classpath as a string, driving the JDT FileSystem to rebuild classpath entries again at a later date using the string. This is more complex in Java9 because the string representation was losing whether some entries came in via modulepath. ClasspathEntry construction for modulepath entries is non trivial (since the module-info must be processed). The new version will cache some of the ClasspathEntry objects (those built for modulepaths) and do more work on the AspectJ side building classpath entries in general. It now passes these entries to a different FileSystem entry point rather than the entry point that takes a string path. --- .../ajde/core/internal/AjdeCoreBuildManager.java | 26 ++- .../src/org/aspectj/ajdt/ajc/BuildArgParser.java | 122 ++++++++++- .../src/org/aspectj/ajdt/ajc/ConfigParser.java | 19 +- .../compiler/lookup/AjLookupEnvironment.java | 11 + .../ajdt/internal/core/builder/AjBuildConfig.java | 228 +++++++++++++++++++-- .../ajdt/internal/core/builder/AjBuildManager.java | 43 +++- .../core/builder/StatefulNameEnvironment.java | 38 +++- .../internal/core/builder/AjBuildManagerTest.java | 2 +- .../ajdt/internal/core/builder/AjStateTest.java | 24 ++- .../testsrc/org/aspectj/tools/ajc/AjcTestCase.java | 69 +++++-- util/src/org/aspectj/util/SoftHashMap.java | 2 +- 11 files changed, 504 insertions(+), 80 deletions(-) diff --git a/ajde.core/src/org/aspectj/ajde/core/internal/AjdeCoreBuildManager.java b/ajde.core/src/org/aspectj/ajde/core/internal/AjdeCoreBuildManager.java index 4ab05c968..5577a01af 100644 --- a/ajde.core/src/org/aspectj/ajde/core/internal/AjdeCoreBuildManager.java +++ b/ajde.core/src/org/aspectj/ajde/core/internal/AjdeCoreBuildManager.java @@ -37,6 +37,7 @@ import org.aspectj.bridge.ISourceLocation; import org.aspectj.bridge.Message; import org.aspectj.bridge.SourceLocation; import org.aspectj.bridge.context.CompilationAndWeavingContext; +import org.aspectj.org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath; import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.aspectj.util.LangUtil; @@ -277,6 +278,14 @@ public class AjdeCoreBuildManager { both.addAll(configClasspath); both.addAll(toAdd); config.setClasspath(both); + Classpath[] checkedClasspaths = config.getCheckedClasspaths(); + ArrayList cps = parser.handleClasspath(toAdd, compilerConfig.getProjectEncoding()); + Classpath[] newCheckedClasspaths = new Classpath[checkedClasspaths.length+cps.size()]; + System.arraycopy(checkedClasspaths, 0, newCheckedClasspaths, 0, checkedClasspaths.length); + for (int i=0;i jom = compilerConfig.getJavaOptionsMap(); @@ -347,17 +356,6 @@ public class AjdeCoreBuildManager { return config; } - private void mergeInto(Collection target, Collection source) { - if ((null == target) || (null == source)) { - return; - } - for (T next : source) { - if (!target.contains(next)) { - target.add(next); - } - } - } - /** * Helper method for configure build options. This reads all command-line options specified in the non-standard options text * entry and sets any corresponding unset values in config. diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java index fae1aadd3..c061208f0 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java @@ -17,8 +17,10 @@ import org.aspectj.ajdt.internal.core.builder.AjBuildConfig; import org.aspectj.bridge.*; 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.util.FileUtil; import org.aspectj.util.LangUtil; @@ -162,6 +164,11 @@ public class BuildArgParser extends Main { javaArgList.addAll(parser.getUnparsedArgs()); super.configure(javaArgList.toArray(new String[javaArgList.size()])); + if (parser.getModuleInfoArgument() != null) { + IModule moduleDesc = super.getModuleDesc(parser.getModuleInfoArgument()); + buildConfig.setModuleDesc(moduleDesc); + } + if (!proceed) { buildConfig.doNotProceed(); return buildConfig; @@ -181,8 +188,14 @@ public class BuildArgParser extends Main { } if (setClasspath) { + // This computed classpaths will be missing aspectpaths, inpaths, add those first buildConfig.setClasspath(getClasspath(parser)); + 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())) { @@ -214,8 +227,7 @@ public class BuildArgParser extends Main { } /* Search aspectpath */ - for (Iterator i = buildConfig.getAspectpath().iterator(); i.hasNext();) { - File pathElement = (File) i.next(); + for (File pathElement: buildConfig.getAspectpath()) { if (!pathElement.isDirectory() && pathElement.equals(outjar)) { String message = WeaverMessages.format(WeaverMessages.OUTJAR_IN_INPUT_PATH); MessageUtil.error(handler, message); @@ -237,6 +249,28 @@ public class BuildArgParser extends Main { 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; + } + public void printVersion() { final String version = bind("misc.version", //$NON-NLS-1$ new String[] { bind("compiler.name"), //$NON-NLS-1$ @@ -325,7 +359,23 @@ public class BuildArgParser extends Main { } 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; + } + + 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). @@ -380,6 +430,9 @@ public class BuildArgParser extends Main { } 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()); @@ -389,10 +442,13 @@ public class BuildArgParser extends Main { 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; @@ -402,38 +458,48 @@ public class BuildArgParser extends Main { 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. */ - public void parseOption(String arg, LinkedList args) { // XXX use ListIterator.remove() + 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); - List inPath = buildConfig.getInpath(); StringTokenizer st = new StringTokenizer(((ConfigParser.Arg) args.get(nextArgIndex)).getValue(), File.pathSeparator); + boolean inpathChange = false; while (st.hasMoreTokens()) { String filename = st.nextToken(); File file = makeFile(filename); if (FileUtil.isZipFile(file)) { - inPath.add(file); + buildConfig.addToInpath(file); + inpathChange = true; } else { if (file.isDirectory()) { - inPath.add(file); + buildConfig.addToInpath(file); + inpathChange = true; } else { showWarning("skipping missing, empty or corrupt inpath entry: " + filename); } } } - buildConfig.setInPath(inPath); + if (inpathChange) { + buildConfig.processInPath(); + } args.remove(args.get(nextArgIndex)); } } else if (arg.equals("-injars")) { @@ -467,7 +533,8 @@ public class BuildArgParser extends Main { String filename = st.nextToken(); File jarFile = makeFile(filename); if (FileUtil.isZipFile(jarFile) || jarFile.isDirectory()) { - buildConfig.getAspectpath().add(jarFile); +// buildConfig.getAspectpath().add(jarFile); + buildConfig.addToAspectpath(jarFile); } else { showWarning("skipping missing, empty or corrupt aspectpath entry: " + filename); } @@ -659,10 +726,47 @@ public class BuildArgParser extends Main { } } classpath = cp.toString(); - args.remove(args.get(nextArgIndex)); + Arg pathArg = args.get(nextArgIndex); + unparsedArgs.add("-classpath"); + unparsedArgs.add(pathArg.getValue()); + args.remove(pathArg); } else { showError("-classpath requires classpath entries"); } + } else if (arg.equals("--module-path") || arg.equals("-p")) { + if (args.size() > nextArgIndex) { + String mpArg = ((ConfigParser.Arg) args.get(nextArgIndex)).getValue(); + modulepath = mpArg; +// StringBuffer mp = new StringBuffer(); +// StringTokenizer strTok = new StringTokenizer(mpArg, File.pathSeparator); +// while (strTok.hasMoreTokens()) { +// mp.append(makeFile(strTok.nextToken())); +// if (strTok.hasMoreTokens()) { +// mp.append(File.pathSeparator); +// } +// } +// modulepath = mp.toString(); + 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 = ((ConfigParser.Arg) args.get(nextArgIndex)).getValue(); + modulesourcepath = mspArg; +// StringBuffer mp = new StringBuffer(); +// StringTokenizer strTok = new StringTokenizer(mpArg, File.pathSeparator); +// while (strTok.hasMoreTokens()) { +// mp.append(makeFile(strTok.nextToken())); +// if (strTok.hasMoreTokens()) { +// mp.append(File.pathSeparator); +// } +// } +// modulepath = mp.toString(); + args.remove(args.get(nextArgIndex)); + } else { + showError("--module-source-path requires modulepath entries"); + } } else if (arg.equals("-extdirs")) { if (args.size() > nextArgIndex) { String extdirsArg = ((ConfigParser.Arg) args.get(nextArgIndex)).getValue(); diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/ConfigParser.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/ConfigParser.java index afa936db3..b92a4b439 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/ConfigParser.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/ConfigParser.java @@ -176,7 +176,7 @@ public class ConfigParser { } } - protected void parseOption(String arg, LinkedList args) { + protected void parseOption(String arg, LinkedList args) { showWarning("unrecognized option: " + arg); } @@ -191,22 +191,22 @@ public class ConfigParser { throw new ParseException(CONFIG_MSG + message, location); } - void parseArgs(LinkedList args) { + void parseArgs(LinkedList args) { while (args.size() > 0) { parseOneArg(args); } } - protected Arg removeArg(LinkedList args) { + protected Arg removeArg(LinkedList args) { if (args.size() == 0) { showError("value missing"); return null; } else { - return (Arg) args.removeFirst(); + return args.removeFirst(); } } - protected String removeStringArg(LinkedList args) { + protected String removeStringArg(LinkedList args) { Arg arg = removeArg(args); if (arg == null) { return null; @@ -235,7 +235,7 @@ public class ConfigParser { return false; } - void parseOneArg(LinkedList args) { + void parseOneArg(LinkedList args) { Arg arg = removeArg(args); String v = arg.getValue(); location = arg.getLocation(); @@ -245,6 +245,9 @@ public class ConfigParser { parseConfigFileHelper(makeFile(removeArg(args).getValue())); } else if (isSourceFileName(v)) { addFileOrPattern(makeFile(v)); + if (v.endsWith("module-info.java")) { + parseOption(arg.getValue(), args); + } } else if (isXml(v)) { addXmlFile(makeFile(v)); } else { @@ -284,6 +287,10 @@ public class ConfigParser { private Location location; private String value; + public String toString() { + return "Arg[location="+location+" value="+value+"]"; + } + public Arg(String value, Location location) { this.value = value; this.location = location; diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java index 52ad76f5b..935eb3cee 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java @@ -107,6 +107,10 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC INameEnvironment nameEnvironment) { super(typeRequestor, options, problemReporter, nameEnvironment); } + + public AjLookupEnvironment(LookupEnvironment env, ModuleBinding moduleBinding) { + super(env, moduleBinding); + } // ??? duplicates some of super's code public void completeTypeBindings() { @@ -1474,6 +1478,13 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC this.factory.cleanup(); super.reset(); } + + @Override + public LookupEnvironment wrapInModuleEnvironment(ModuleBinding moduleBinding) { + AjLookupEnvironment newAjLookupEnvironment = new AjLookupEnvironment(this, moduleBinding); + newAjLookupEnvironment.factory = this.factory; + return newAjLookupEnvironment; + } } // commented out, supplied as info on how to manipulate annotations in an diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java index 98bd0484e..0587c4462 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java @@ -20,14 +20,29 @@ import java.io.File; import java.io.FileFilter; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.StringTokenizer; import org.aspectj.ajdt.ajc.BuildArgParser; import org.aspectj.ajdt.internal.compiler.CompilationResultDestinationManager; +import org.aspectj.org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy; +import org.aspectj.org.eclipse.jdt.internal.compiler.batch.ClasspathJar; +import org.aspectj.org.eclipse.jdt.internal.compiler.batch.ClasspathJrt; +import org.aspectj.org.eclipse.jdt.internal.compiler.batch.ClasspathLocation; +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.batch.ModuleFinder; +import org.aspectj.org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath; +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.parser.Parser; +import org.aspectj.org.eclipse.jdt.internal.compiler.problem.ProblemReporter; import org.aspectj.util.FileUtil; /** @@ -35,7 +50,9 @@ import org.aspectj.util.FileUtil; * an AjCompilerOptions instance */ public class AjBuildConfig implements CompilerConfigurationChangeFlags { - + + public static final Classpath[] NO_CHECKED_CLASSPATHS = new Classpath[0]; + private boolean shouldProceed = true; public static final String AJLINT_IGNORE = "ignore"; @@ -59,8 +76,16 @@ public class AjBuildConfig implements CompilerConfigurationChangeFlags { private Map sourcePathResources = new HashMap(); private List aspectpath = new ArrayList(); private List classpath = new ArrayList(); + private List modulepath = new ArrayList(); + // Expensive to compute (searching modules, parsing module-info) + private ArrayList modulepathClasspathEntries = null; + private List modulesourcepath = new ArrayList(); + // Expensive to compute (searching modules, parsing module-info) + private ArrayList modulesourcepathClasspathEntries = null; + private Classpath[] checkedClasspaths = null; private List bootclasspath = new ArrayList(); private List cpElementsWithModifiedContents = new ArrayList(); + private IModule moduleDesc; private File configFile; private String lintMode = AJLINT_DEFAULT; @@ -205,6 +230,53 @@ public class AjBuildConfig implements CompilerConfigurationChangeFlags { public void setClasspath(List classpath) { this.classpath = classpath; + checkedClasspaths = null; + } + + public List getModulepath() { + return modulepath; + } + + public List getModulesourcepath() { + return modulesourcepath; + } + + public void setModulepath(List modulepath) { + this.modulepath = modulepath; + checkedClasspaths = null; + } + + public void setModulesourcepath(List modulesourcepath) { + this.modulesourcepath = modulesourcepath; + checkedClasspaths = null; + } + + public void setCheckedClasspaths(Classpath[] checkedClasspaths) { + this.checkedClasspaths = checkedClasspaths; + checkedClasspaths = null; + } + + private List processFilePath(List path, java.lang.String encoding) { + List entries = new ArrayList(); + for (File file: path) { + entries.add(FileSystem.getClasspath(file.getAbsolutePath(), encoding, null, ClasspathLocation.BINARY)); + } + return entries; + } + + private List processStringPath(List path, java.lang.String encoding) { + List entries = new ArrayList(); + for (String file: path) { + entries.add(FileSystem.getClasspath(file, encoding, null, ClasspathLocation.BINARY)); + } + return entries; + } + + public Classpath[] getCheckedClasspaths() { + if (checkedClasspaths == null) { + computeCheckedClasspath(); + } + return checkedClasspaths; } public List getBootclasspath() { @@ -225,7 +297,7 @@ public class AjBuildConfig implements CompilerConfigurationChangeFlags { public List getInpath() { // Elements of the list are either archives (jars/zips) or directories - return inPath; + return Collections.unmodifiableList(inPath); } public List getInJars() { @@ -246,11 +318,10 @@ public class AjBuildConfig implements CompilerConfigurationChangeFlags { public void setInJars(List sourceJars) { this.inJars = sourceJars; + checkedClasspaths = null; } - public void setInPath(List dirsOrJars) { - inPath = dirsOrJars; - + public void processInPath() { // remember all the class files in directories on the inpath binaryFiles = new ArrayList(); FileFilter filter = new FileFilter() { @@ -258,7 +329,7 @@ public class AjBuildConfig implements CompilerConfigurationChangeFlags { return pathname.getPath().endsWith(".class"); } }; - for (Iterator iter = dirsOrJars.iterator(); iter.hasNext();) { + for (Iterator iter = inPath.iterator(); iter.hasNext();) { File inpathElement = iter.next(); if (inpathElement.isDirectory()) { File[] files = FileUtil.listFiles(inpathElement, filter); @@ -269,6 +340,12 @@ public class AjBuildConfig implements CompilerConfigurationChangeFlags { } } + public void setInPath(List dirsOrJars) { + inPath = dirsOrJars; + checkedClasspaths = null; + processInPath(); + } + public List getSourceRoots() { return sourceRoots; } @@ -308,16 +385,18 @@ public class AjBuildConfig implements CompilerConfigurationChangeFlags { public List getFullClasspath() { List full = new ArrayList(); full.addAll(getBootclasspath()); // XXX Is it OK that boot classpath overrides inpath/injars/aspectpath? - for (Iterator i = inJars.iterator(); i.hasNext();) { - full.add((i.next()).getAbsolutePath()); + for (File file: inJars) { + full.add(file.getAbsolutePath()); } - for (Iterator i = inPath.iterator(); i.hasNext();) { - full.add((i.next()).getAbsolutePath()); + for (File file: inPath) { + full.add(file.getAbsolutePath()); } - for (Iterator i = aspectpath.iterator(); i.hasNext();) { - full.add((i.next()).getAbsolutePath()); + for (File file: aspectpath) { + full.add(file.getAbsolutePath()); } full.addAll(getClasspath()); + full.addAll(getModulepath()); + full.addAll(getModulesourcepath()); // if (null != outputDir) { // full.add(outputDir.getAbsolutePath()); // } else if (null != outputJar) { @@ -335,11 +414,22 @@ public class AjBuildConfig implements CompilerConfigurationChangeFlags { } public List getAspectpath() { - return aspectpath; + return Collections.unmodifiableList(aspectpath); } public void setAspectpath(List aspectpath) { this.aspectpath = aspectpath; + checkedClasspaths = null; + } + + public void addToAspectpath(File file) { + this.aspectpath.add(file); + checkedClasspaths = null; + } + + public void addToInjars(File file) { + this.inJars.add(file); + checkedClasspaths = null; } /** @return true if any config file, sourceroots, sourcefiles, injars or inpath */ @@ -765,4 +855,116 @@ public class AjBuildConfig implements CompilerConfigurationChangeFlags { public void setProjectEncoding(String projectEncoding) { options.defaultEncoding = projectEncoding; } + + public String getProjectEncoding() { + return options.defaultEncoding; + } + + public void setModuleDesc(IModule moduleDesc) { + this.moduleDesc = moduleDesc; + } + + public IModule getModuleDesc() { + return moduleDesc; + } + + public void addToInpath(Set newInpathEntries) { + if (newInpathEntries != null && newInpathEntries.size() != 0) { + for (File newInpathEntry: newInpathEntries) { + if (!inPath.contains(newInpathEntry)) { + inPath.add(newInpathEntry); + } + } + checkedClasspaths = null; + } + } + + public void addToInpath(File newInpathEntry) { +// if (!inPath.contains(newInpathEntry)) { + inPath.add(newInpathEntry); +// } + checkedClasspaths = null; + } + + public void addToAspectpath(Set newAspectpathEntries) { + if (newAspectpathEntries != null && newAspectpathEntries.size() != 0) { + for (File newAspectpathEntry: newAspectpathEntries) { + if (!aspectpath.contains(newAspectpathEntry)) { + aspectpath.add(newAspectpathEntry); + } + } + checkedClasspaths = null; + } + } + + public void setModulepathClasspathEntries(ArrayList modulepathClasspathEntries) { + this.modulepathClasspathEntries = modulepathClasspathEntries; + } + + public void setModulesourcepathClasspathEntries(ArrayList modulesourcepathClasspathEntries) { + this.modulesourcepathClasspathEntries = modulesourcepathClasspathEntries; + } + + public File removeAspectPathEntry(int i) { + checkedClasspaths = null; + return aspectpath.remove(i); + } + + public String removeClasspathEntry(int i) { + checkedClasspaths = null; + return classpath.remove(i); + } + + public File removeInpathEntry(int i) { + checkedClasspaths = null; + return inPath.remove(i); + } + + public File removeInjarsEntry(int i) { + checkedClasspaths = null; + return inJars.remove(0); + } + + + // This is similar to the calculation done in Main.setPaths() but it isn't as sophisticated + // as that one (doesn't need to be) and it also considers the additional paths for an + // AspectJ project (aspectpath/inpath/injars) + private void computeCheckedClasspath() { + // Follow what we do in getFullClasspath(): + // bootclasspath, injars, inpath, aspectpath, classpath, modulepath + + String encoding = getProjectEncoding(); + // What to do about bootclasspath on java 9? + + // ArrayList allPaths = handleBootclasspath(bootclasspaths, customEncoding); + ArrayList allPaths = new ArrayList(); + allPaths.addAll(processStringPath(bootclasspath, encoding)); + allPaths.addAll(processFilePath(inJars, encoding)); + allPaths.addAll(processFilePath(inPath, encoding)); + allPaths.addAll(processFilePath(aspectpath, encoding)); + if (modulepathClasspathEntries != null) { + allPaths.addAll(modulepathClasspathEntries); + } + if (modulesourcepathClasspathEntries != null) { + allPaths.addAll(modulesourcepathClasspathEntries); + } + // The classpath is done after modules to give precedence to modules that share the + // same paths as classpath elements (the upcoming normalize will remove later dups) + allPaths.addAll(processStringPath(classpath, encoding)); + for (Iterator iter = allPaths.iterator();iter.hasNext();) { + Classpath next = iter.next(); + if (next == null) { + iter.remove(); + } + } + allPaths = FileSystem.ClasspathNormalizer.normalize(allPaths); + this.checkedClasspaths = new FileSystem.Classpath[allPaths.size()]; + allPaths.toArray(this.checkedClasspaths); + for (int i=0;i classesFromName; private Map inflatedClassFilesCache; private Set packageNames; private AjState state; - private INameEnvironment baseEnvironment; + private IModuleAwareNameEnvironment baseEnvironment; - public StatefulNameEnvironment(INameEnvironment baseEnvironment, Map classesFromName, AjState state) { + public StatefulNameEnvironment(IModuleAwareNameEnvironment baseEnvironment, Map classesFromName, AjState state) { this.classesFromName = classesFromName; this.inflatedClassFilesCache = new HashMap(); this.baseEnvironment = baseEnvironment; @@ -130,4 +130,34 @@ public class StatefulNameEnvironment implements INameEnvironment { this.classesFromName = classNameToFileMap; } + @Override + public NameEnvironmentAnswer findType(char[][] compoundName, char[] moduleName) { + return baseEnvironment.findType(compoundName, moduleName); + } + + @Override + public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, char[] moduleName) { + return baseEnvironment.findType(typeName, packageName, moduleName); + } + + @Override + public char[][] getModulesDeclaringPackage(char[][] parentPackageName, char[] name, char[] moduleName) { + return baseEnvironment.getModulesDeclaringPackage(parentPackageName, name, moduleName); + } + + @Override + public boolean hasCompilationUnit(char[][] qualifiedPackageName, char[] moduleName, boolean checkCUs) { + return baseEnvironment.hasCompilationUnit(qualifiedPackageName, moduleName, checkCUs); + } + + @Override + public IModule getModule(char[] moduleName) { + return baseEnvironment.getModule(moduleName); + } + + @Override + public char[][] getAllAutomaticModules() { + return baseEnvironment.getAllAutomaticModules(); + } + } diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjBuildManagerTest.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjBuildManagerTest.java index 3799b4cda..c4be26936 100644 --- a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjBuildManagerTest.java +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjBuildManagerTest.java @@ -57,10 +57,10 @@ public class AjBuildManagerTest extends TestCase { } public void testSimpleStructure() throws IOException /* , CoreException */{ - AjBuildManager manager = new AjBuildManager(messageWriter); BuildArgParser parser = new BuildArgParser(messageWriter); String javaClassPath = System.getProperty("java.class.path"); + System.out.println(javaClassPath); String sandboxName = Ajc.createEmptySandbox().getAbsolutePath(); AjBuildConfig buildConfig = parser.genBuildConfig(new String[] { "-d", sandboxName, "-classpath", javaClassPath, AjdtAjcTests.TESTDATA_PATH + "/src1/A.java", diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjStateTest.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjStateTest.java index 1693178e3..101fdade1 100644 --- a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjStateTest.java +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjStateTest.java @@ -48,44 +48,48 @@ public class AjStateTest extends TestCase { } public void testAddEntryToAspectpath() { - newConfig.getAspectpath().add(new File("anotherEntry.jar")); + newConfig.addToAspectpath(new File("anotherEntry.jar")); +// newConfig.getAspectpath().add(new File("anotherEntry.jar")); assertFalse("Can do incremental", aRightState.prepareForNextBuild(newConfig)); } public void testRemoveEntryFromAspectpath() { - newConfig.getAspectpath().remove(0); + newConfig.removeAspectPathEntry(0); assertFalse("Can do incremental", aRightState.prepareForNextBuild(newConfig)); } public void testReorderAspectpath() { - String o = newConfig.getClasspath().remove(0); - newConfig.getAspectpath().add(new File(o)); + String o = newConfig.removeClasspathEntry(0); + newConfig.addToAspectpath(new File(o)); +// newConfig.getAspectpath().add(new File(o)); assertFalse("Can do incremental", aRightState.prepareForNextBuild(newConfig)); } public void testAddEntryToInpath() { - newConfig.getInpath().add(new File("anotherEntry")); + newConfig.addToInpath(new File("anotherEntry")); assertFalse("Can do incremental", aRightState.prepareForNextBuild(newConfig)); } public void testRemoveEntryFromInpath() { - newConfig.getInpath().remove(0); + newConfig.removeInpathEntry(0);//getInpath().remove(0); assertFalse("Can do incremental", aRightState.prepareForNextBuild(newConfig)); } public void testReorderInpath() { - String o = newConfig.getClasspath().remove(0); - newConfig.getInpath().add(new File(o)); + String o = newConfig.removeClasspathEntry(0);//getClasspath().remove(0); + newConfig.addToInpath(new File(o));//getInpath().add(new File(o)); assertFalse("Can do incremental", aRightState.prepareForNextBuild(newConfig)); } public void testAddEntryToInjars() { - newConfig.getInJars().add(new File("anotherEntry.jar")); + newConfig.addToInjars(new File("anotherEntry.jar")); +// newConfig.getInJars().add(new File("anotherEntry.jar")); assertFalse("Can do incremental", aRightState.prepareForNextBuild(newConfig)); } public void testRemoveEntryFromInjars() { - newConfig.getInJars().remove(0); + newConfig.removeInjarsEntry(0); +// newConfig.getInJars().remove(0); assertFalse("Can do incremental", aRightState.prepareForNextBuild(newConfig)); } diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/tools/ajc/AjcTestCase.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/tools/ajc/AjcTestCase.java index 12b1e3508..b665afeba 100644 --- a/org.aspectj.ajdt.core/testsrc/org/aspectj/tools/ajc/AjcTestCase.java +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/tools/ajc/AjcTestCase.java @@ -581,7 +581,7 @@ public class AjcTestCase extends TestCase { } public RunResult run(String className, String[] args, String classpath) { - return run(className, args, "", null, false,false); + return run(className, null, args, "", "", null, false,false); } /** @@ -593,7 +593,7 @@ public class AjcTestCase extends TestCase { * be appended to the classpath, as will any jars in the sandbox. * @param runSpec */ - public RunResult run(String className, String[] args, String vmargs, final String classpath, boolean useLTW, boolean useFullLTW) { + public RunResult run(String className, String moduleName, String[] args, String vmargs, final String classpath, String modulepath, boolean useLTW, boolean useFullLTW) { if (args != null) { for (int i = 0; i < args.length; i++) { @@ -607,8 +607,16 @@ public class AjcTestCase extends TestCase { cp.append(substituteSandbox(classpath)); cp.append(File.pathSeparator); } - cp.append(ajc.getSandboxDirectory().getAbsolutePath()); - getAnyJars(ajc.getSandboxDirectory(), cp); + if (moduleName == null) { + // When running modules, we want more control so don't try to be helpful by adding all jars + cp.append(ajc.getSandboxDirectory().getAbsolutePath()); + getAnyJars(ajc.getSandboxDirectory(), cp); + } + StringBuffer mp = new StringBuffer(); + if (modulepath != null) { + mp.append(substituteSandbox(modulepath)); + mp.append(File.pathSeparator); + } URLClassLoader sandboxLoader; ClassLoader parentLoader = getClass().getClassLoader().getParent(); @@ -639,7 +647,6 @@ public class AjcTestCase extends TestCase { String absPath = directory.getAbsolutePath(); String javaagent= absPath+File.separator+".."+File.separator+"aj-build"+File.separator+"dist"+File.separator+"tools"+File.separator+"lib"+File.separator+"aspectjweaver.jar"; try { - String command ="java " +vmargs+ " -classpath " + cp +" -javaagent:"+javaagent + " " + className ; // Command is executed using ProcessBuilder to allow setting CWD for ajc sandbox compliance @@ -654,10 +661,35 @@ public class AjcTestCase extends TestCase { System.out.println("Error executing full LTW test: " + e); e.printStackTrace(); } - return lastRunResult; - - }else{ + } else if (moduleName != null) { + // CODE FOR RUNNING MODULES + if(vmargs == null){ + vmargs =""; + } + try { + if (mp.indexOf("$runtime") != -1) { + mp = mp.replace(mp.indexOf("$runtime"),"$runtime".length(),TestUtil.aspectjrtPath().toString()); + } + if (cp.indexOf("aspectjrt")==-1) { + cp.append(TestUtil.aspectjrtPath().getPath()).append(File.pathSeparator); + } + String command = LangUtil.getJavaExecutable().getAbsolutePath() + " " +vmargs+ (cp.length()==0?"":" -classpath " + cp) + " -p "+mp+" --module "+moduleName ; + System.out.println("Command is "+command); + // Command is executed using ProcessBuilder to allow setting CWD for ajc sandbox compliance + ProcessBuilder pb = new ProcessBuilder(tokenizeCommand(command)); + pb.directory( new File(ajc.getSandboxDirectory().getAbsolutePath())); + exec = pb.start(); + BufferedReader stdInput = new BufferedReader(new InputStreamReader(exec.getInputStream())); + BufferedReader stdError = new BufferedReader(new InputStreamReader(exec.getErrorStream())); + exec.waitFor(); + lastRunResult = createResultFromBufferReaders(command,stdInput, stdError); + } catch (Exception e) { + System.out.println("Error executing module test: " + e); + e.printStackTrace(); + } + return lastRunResult; + } else { cp.append(DEFAULT_CLASSPATH_ENTRIES); URL[] urls = getURLs(cp.toString()); sandboxLoader = new URLClassLoader(urls, parentLoader); @@ -666,7 +698,8 @@ public class AjcTestCase extends TestCase { ByteArrayOutputStream baosErr = new ByteArrayOutputStream(); - StringBuffer command = new StringBuffer("java -classpath "); + StringBuffer command = new StringBuffer(); + command.append("java -classpath "); command.append(cp.toString()); command.append(" "); command.append(className); @@ -834,15 +867,15 @@ public class AjcTestCase extends TestCase { return urls; } - private String substituteSandbox(String classpath) { - // the longhand form of the non 1.3 API: classpath.replace("$sandbox", ajc.getSandboxDirectory().getAbsolutePath()); - while (classpath.indexOf("$sandbox") != -1) { - int pos = classpath.indexOf("$sandbox"); - String firstbit = classpath.substring(0, pos); - String endbit = classpath.substring(pos + 8); - classpath = firstbit + ajc.getSandboxDirectory().getAbsolutePath() + endbit; + private String substituteSandbox(String path) { + // the longhand form of the non 1.3 API: path.replace("$sandbox", ajc.getSandboxDirectory().getAbsolutePath()); + while (path.indexOf("$sandbox") != -1) { + int pos = path.indexOf("$sandbox"); + String firstbit = path.substring(0, pos); + String endbit = path.substring(pos + 8); + path = firstbit + ajc.getSandboxDirectory().getAbsolutePath() + endbit; } - return classpath; + return path; } /** @@ -864,6 +897,8 @@ public class AjcTestCase extends TestCase { args[i + 1] = substituteSandbox(args[i + 1]); String next = args[i + 1]; hasruntime = ((null != next) && (-1 != next.indexOf("aspectjrt.jar"))); + } else if ("-p".equals(args[i]) || "--module-path".equals(args[i])) { + args[i + 1] = substituteSandbox(args[i + 1]); } } if (-1 == cpIndex) { diff --git a/util/src/org/aspectj/util/SoftHashMap.java b/util/src/org/aspectj/util/SoftHashMap.java index f7971bddb..94ae83441 100644 --- a/util/src/org/aspectj/util/SoftHashMap.java +++ b/util/src/org/aspectj/util/SoftHashMap.java @@ -12,7 +12,7 @@ import java.util.*; public class SoftHashMap extends AbstractMap { private Map map; - private ReferenceQueue rq = new ReferenceQueue<>(); + private ReferenceQueue rq = new ReferenceQueue(); public SoftHashMap() { this.map = new HashMap(); -- cgit v1.2.3