/* ******************************************************************* * 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.internal.core.builder; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.jar.Attributes; import java.util.jar.JarFile; import java.util.jar.JarInputStream; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; import java.util.zip.ZipEntry; import org.aspectj.ajdt.ajc.BuildArgParser; import org.aspectj.ajdt.internal.compiler.AjCompilerAdapter; import org.aspectj.ajdt.internal.compiler.AjPipeliningCompilerAdapter; import org.aspectj.ajdt.internal.compiler.CompilationResultDestinationManager; import org.aspectj.ajdt.internal.compiler.IBinarySourceProvider; import org.aspectj.ajdt.internal.compiler.ICompilerAdapter; import org.aspectj.ajdt.internal.compiler.ICompilerAdapterFactory; import org.aspectj.ajdt.internal.compiler.IIntermediateResultsRequestor; import org.aspectj.ajdt.internal.compiler.IOutputClassFileNameProvider; import org.aspectj.ajdt.internal.compiler.InterimCompilationResult; import org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment; import org.aspectj.ajdt.internal.compiler.lookup.AnonymousClassPublisher; import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory; import org.aspectj.ajdt.internal.compiler.problem.AjProblemReporter; import org.aspectj.asm.AsmManager; import org.aspectj.asm.IHierarchy; import org.aspectj.asm.IProgramElement; import org.aspectj.asm.internal.ProgramElement; import org.aspectj.bridge.AbortException; import org.aspectj.bridge.CountingMessageHandler; import org.aspectj.bridge.ILifecycleAware; import org.aspectj.bridge.IMessage; import org.aspectj.bridge.IMessageHandler; import org.aspectj.bridge.IProgressListener; 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.bridge.context.CompilationAndWeavingContext; import org.aspectj.bridge.context.ContextFormatter; import org.aspectj.bridge.context.ContextToken; import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation; import org.aspectj.org.eclipse.jdt.core.compiler.IProblem; import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile; import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult; import org.aspectj.org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies; import org.aspectj.org.eclipse.jdt.internal.compiler.ICompilerRequestor; import org.aspectj.org.eclipse.jdt.internal.compiler.IProblemFactory; import org.aspectj.org.eclipse.jdt.internal.compiler.batch.ClasspathLocation; import org.aspectj.org.eclipse.jdt.internal.compiler.batch.CompilationUnit; import org.aspectj.org.eclipse.jdt.internal.compiler.batch.FileSystem; import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.aspectj.org.eclipse.jdt.internal.compiler.env.ICompilationUnit; import org.aspectj.org.eclipse.jdt.internal.compiler.env.IModule; import org.aspectj.org.eclipse.jdt.internal.compiler.env.INameEnvironment; 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.AbortCompilation; import org.aspectj.org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; import org.aspectj.tools.ajc.Main; import org.aspectj.util.FileUtil; import org.aspectj.weaver.CustomMungerFactory; import org.aspectj.weaver.Dump; import org.aspectj.weaver.ResolvedType; import org.aspectj.weaver.World; import org.aspectj.weaver.bcel.BcelWeaver; import org.aspectj.weaver.bcel.BcelWorld; import org.aspectj.weaver.bcel.UnwovenClassFile; import org.eclipse.core.runtime.OperationCanceledException; public class AjBuildManager implements IOutputClassFileNameProvider, IBinarySourceProvider, ICompilerAdapterFactory { private static final String CROSSREFS_FILE_NAME = "build.lst"; private static final String CANT_WRITE_RESULT = "unable to write compilation result"; private static final String MANIFEST_NAME = "META-INF/MANIFEST.MF"; public static boolean COPY_INPATH_DIR_RESOURCES = false; // AJDT doesn't want this check, so Main enables it. private static boolean DO_RUNTIME_VERSION_CHECK = false; // If runtime version check fails, warn or fail? (unset?) static final boolean FAIL_IF_RUNTIME_NOT_FOUND = false; private static final FileFilter binarySourceFilter = new FileFilter() { @Override public boolean accept(File f) { return f.getName().endsWith(".class"); } }; /** * This builder is static so that it can be subclassed and reset. However, note that there is only one builder present, so if * two extendsion reset it, only the latter will get used. */ public static AsmHierarchyBuilder asmHierarchyBuilder = new AsmHierarchyBuilder(); static { // CompilationAndWeavingContext.setMultiThreaded(false); CompilationAndWeavingContext.registerFormatter(CompilationAndWeavingContext.BATCH_BUILD, new AjBuildContexFormatter()); CompilationAndWeavingContext .registerFormatter(CompilationAndWeavingContext.INCREMENTAL_BUILD, new AjBuildContexFormatter()); } private IProgressListener progressListener = null; private boolean environmentSupportsIncrementalCompilation = false; private int compiledCount; private int sourceFileCount; private JarOutputStream zos; private boolean batchCompile = true; private INameEnvironment environment; private Map> /* String -> List */binarySourcesForTheNextCompile = new HashMap<>(); // FIXME asc should this really be in here? // private AsmManager structureModel; public AjBuildConfig buildConfig; private boolean ignoreOutxml; private boolean wasFullBuild = true; // true if last build was a full build rather than an incremental build AjState state = new AjState(this); /** * Enable check for runtime version, used only by Ant/command-line Main. * * @param caller Main unused except to limit to non-null clients. */ public static void enableRuntimeVersionCheck(Main caller) { DO_RUNTIME_VERSION_CHECK = null != caller; } public BcelWeaver getWeaver() { return state.getWeaver(); } public BcelWorld getBcelWorld() { return state.getBcelWorld(); } public CountingMessageHandler handler; private CustomMungerFactory customMungerFactory; public AjBuildManager(IMessageHandler holder) { super(); this.handler = CountingMessageHandler.makeCountingMessageHandler(holder); } public void environmentSupportsIncrementalCompilation(boolean itDoes) { this.environmentSupportsIncrementalCompilation = itDoes; if (itDoes) { org.aspectj.weaver.loadtime.definition.DocumentParser.deactivateCaching(); } } /** @return true if we should generate a model as a side-effect */ public boolean doGenerateModel() { return buildConfig.isGenerateModelMode(); } public boolean batchBuild(AjBuildConfig buildConfig, IMessageHandler baseHandler) throws IOException, AbortException { return performBuild(buildConfig, baseHandler, true); } public boolean incrementalBuild(AjBuildConfig buildConfig, IMessageHandler baseHandler) throws IOException, AbortException { return performBuild(buildConfig, baseHandler, false); } /** * Perform a build. * * @return true if the build was successful (ie. no errors) */ private boolean performBuild(AjBuildConfig buildConfig, IMessageHandler baseHandler, boolean isFullBuild) throws IOException, AbortException { boolean ret = true; batchCompile = isFullBuild; wasFullBuild = isFullBuild; if (baseHandler instanceof ILifecycleAware) { ((ILifecycleAware) baseHandler).buildStarting(!isFullBuild); } CompilationAndWeavingContext.reset(); final int phase = isFullBuild ? CompilationAndWeavingContext.BATCH_BUILD : CompilationAndWeavingContext.INCREMENTAL_BUILD; final ContextToken ct = CompilationAndWeavingContext.enteringPhase(phase, buildConfig); try { if (isFullBuild) { this.state = new AjState(this); } this.state.setCouldBeSubsequentIncrementalBuild(this.environmentSupportsIncrementalCompilation); final boolean canIncremental = state.prepareForNextBuild(buildConfig); if (!canIncremental && !isFullBuild) { // retry as batch? CompilationAndWeavingContext.leavingPhase(ct); if (state.listenerDefined()) { state.getListener().recordDecision("Falling back to batch compilation"); } return performBuild(buildConfig, baseHandler, true); } this.handler = CountingMessageHandler.makeCountingMessageHandler(baseHandler); if (buildConfig == null || buildConfig.isCheckRuntimeVersion()) { if (DO_RUNTIME_VERSION_CHECK) { final String check = checkRtJar(buildConfig); if (check != null) { if (FAIL_IF_RUNTIME_NOT_FOUND) { MessageUtil.error(handler, check); CompilationAndWeavingContext.leavingPhase(ct); return false; } else { MessageUtil.warn(handler, check); } } } } // if (batch) { setBuildConfig(buildConfig); // } if (isFullBuild || !AsmManager.attemptIncrementalModelRepairs) { // if (buildConfig.isEmacsSymMode() || buildConfig.isGenerateModelMode()) { setupModel(buildConfig); // } } if (isFullBuild) { initBcelWorld(handler); } if (handler.hasErrors()) { CompilationAndWeavingContext.leavingPhase(ct); return false; } if (buildConfig.getOutputJar() != null) { if (!openOutputStream(buildConfig.getOutputJar())) { CompilationAndWeavingContext.leavingPhase(ct); return false; } } if (isFullBuild) { // System.err.println("XXXX batch: " + buildConfig.getFiles()); if (buildConfig.isEmacsSymMode() || buildConfig.isGenerateModelMode()) { AsmManager.setLastActiveStructureModel(state.getStructureModel()); getWorld().setModel(state.getStructureModel()); // in incremental build, only get updated model? } binarySourcesForTheNextCompile = state.getBinaryFilesToCompile(true); performCompilation(buildConfig.getFiles()); state.clearBinarySourceFiles(); // we don't want these hanging around... if (!proceedOnError() && handler.hasErrors()) { CompilationAndWeavingContext.leavingPhase(ct); if (AsmManager.isReporting()) { state.getStructureModel().reportModelInfo("After a batch build"); } return false; } if (AsmManager.isReporting()) { state.getStructureModel().reportModelInfo("After a batch build"); } } else { // done already? // if (buildConfig.isEmacsSymMode() || buildConfig.isGenerateModelMode()) { // bcelWorld.setModel(StructureModelManager.INSTANCE.getStructureModel()); // } // System.err.println("XXXX start inc "); AsmManager.setLastActiveStructureModel(state.getStructureModel()); binarySourcesForTheNextCompile = state.getBinaryFilesToCompile(true); Set files = state.getFilesToCompile(true); if (buildConfig.isEmacsSymMode() || buildConfig.isGenerateModelMode()) { if (AsmManager.attemptIncrementalModelRepairs) { state.getStructureModel().resetDeltaProcessing(); state.getStructureModel().processDelta(files, state.getAddedFiles(), state.getDeletedFiles()); } } boolean hereWeGoAgain = !(files.isEmpty() && binarySourcesForTheNextCompile.isEmpty()); for (int i = 0; (i < 5) && hereWeGoAgain; i++) { if (state.listenerDefined()) { state.getListener() .recordInformation("Starting incremental compilation loop " + (i + 1) + " of possibly 5"); // System.err.println("XXXX inc: " + files); } performCompilation(files); if ((!proceedOnError() && handler.hasErrors()) || (progressListener != null && progressListener.isCancelledRequested())) { CompilationAndWeavingContext.leavingPhase(ct); return false; } if (state.requiresFullBatchBuild()) { if (state.listenerDefined()) { state.getListener().recordInformation(" Dropping back to full build"); } return batchBuild(buildConfig, baseHandler); } binarySourcesForTheNextCompile = state.getBinaryFilesToCompile(false); files = state.getFilesToCompile(false); hereWeGoAgain = !(files.isEmpty() && binarySourcesForTheNextCompile.isEmpty()); // TODO Andy - Needs some thought here... // I think here we might want to pass empty addedFiles/deletedFiles as they were // dealt with on the first call to processDelta - we are going through this loop // again because in compiling something we found something else we needed to // rebuild. But what case causes this? if (hereWeGoAgain) { if (buildConfig.isEmacsSymMode() || buildConfig.isGenerateModelMode()) { if (AsmManager.attemptIncrementalModelRepairs) { state.getStructureModel().processDelta(files, state.getAddedFiles(), state.getDeletedFiles()); } } } } if (!files.isEmpty()) { CompilationAndWeavingContext.leavingPhase(ct); return batchBuild(buildConfig, baseHandler); } else { if (AsmManager.isReporting()) { state.getStructureModel().reportModelInfo("After an incremental build"); } } } // XXX not in Mik's incremental if (buildConfig.isEmacsSymMode()) { new org.aspectj.ajdt.internal.core.builder.EmacsStructureModelManager().externalizeModel(state.getStructureModel()); } // for bug 113554: support ajsym file generation for command line builds if (buildConfig.isGenerateCrossRefsMode()) { final File configFileProxy = new File(buildConfig.getOutputDir(), CROSSREFS_FILE_NAME); state.getStructureModel().writeStructureModel(configFileProxy.getAbsolutePath()); } // have to tell state we succeeded or next is not incremental state.successfulCompile(buildConfig, isFullBuild); // For a full compile, copy resources to the destination // - they should not get deleted on incremental and AJDT // will handle changes to them that require a recopying if (isFullBuild) { copyResourcesToDestination(); } if (buildConfig.getOutxmlName() != null) { writeOutxmlFile(); } /* boolean weaved = */// weaveAndGenerateClassFiles(); // if not weaved, then no-op build, no model changes // but always returns true // XXX weaved not in Mik's incremental if (buildConfig.isGenerateModelMode()) { state.getStructureModel().fireModelUpdated(); } CompilationAndWeavingContext.leavingPhase(ct); } finally { if (baseHandler instanceof ILifecycleAware) { ((ILifecycleAware) baseHandler).buildFinished(!isFullBuild); } if (zos != null) { closeOutputStream(buildConfig.getOutputJar()); } ret = !handler.hasErrors(); if (getBcelWorld() != null) { final BcelWorld bcelWorld = getBcelWorld(); bcelWorld.reportTimers(); bcelWorld.tidyUp(); } if (getWeaver() != null) { getWeaver().tidyUp(); // bug 59895, don't release reference to handler as may be needed by a nested call // handler = null; } } return ret; } /** * Open an output jar file in which to write the compiler output. * * @param outJar the jar file to open * @return true if successful */ private boolean openOutputStream(File outJar) { try { OutputStream os = FileUtil.makeOutputStream(buildConfig.getOutputJar()); zos = new JarOutputStream(os, getWeaver().getManifest(true)); } catch (IOException ex) { IMessage message = new Message("Unable to open outjar " + outJar.getPath() + "(" + ex.getMessage() + ")", new SourceLocation(outJar, 0), true); handler.handleMessage(message); return false; } return true; } private void closeOutputStream(File outJar) { try { if (zos != null) { zos.close(); if (buildConfig.getCompilationResultDestinationManager() != null) { buildConfig.getCompilationResultDestinationManager().reportFileWrite(outJar.getPath(), CompilationResultDestinationManager.FILETYPE_OUTJAR); } } zos = null; /* Ensure we don't write an incomplete JAR bug-71339 */ if (handler.hasErrors()) { outJar.delete(); if (buildConfig.getCompilationResultDestinationManager() != null) { buildConfig.getCompilationResultDestinationManager().reportFileRemove(outJar.getPath(), CompilationResultDestinationManager.FILETYPE_OUTJAR); } } } catch (IOException ex) { IMessage message = new Message("Unable to write outjar " + outJar.getPath() + "(" + ex.getMessage() + ")", new SourceLocation(outJar, 0), true); handler.handleMessage(message); } } private void copyResourcesToDestination() throws IOException { // resources that we need to copy are contained in the injars and inpath only for (File inJar : buildConfig.getInJars()) { copyResourcesFromJarFile(inJar); } for (File inPathElement : buildConfig.getInpath()) { if (inPathElement.isDirectory()) { copyResourcesFromDirectory(inPathElement); } else { copyResourcesFromJarFile(inPathElement); } } if (buildConfig.getSourcePathResources() != null) { for (String resource : buildConfig.getSourcePathResources().keySet()) { File from = buildConfig.getSourcePathResources().get(resource); copyResourcesFromFile(from, resource, from); } } writeManifest(); } private void copyResourcesFromJarFile(File jarFile) throws IOException { try (JarInputStream inStream = new JarInputStream(new FileInputStream(jarFile))) { while (true) { ZipEntry entry = inStream.getNextEntry(); if (entry == null) { break; } String filename = entry.getName(); // System.out.println("? copyResourcesFromJarFile() filename='" + filename +"'"); if (entry.isDirectory()) { writeDirectory(filename, jarFile); } else if (acceptResource(filename, false)) { byte[] bytes = FileUtil.readAsByteArray(inStream); writeResource(filename, bytes, jarFile); } inStream.closeEntry(); } } } private void copyResourcesFromDirectory(File dir) throws IOException { if (!COPY_INPATH_DIR_RESOURCES) { return; } // Get a list of all files (i.e. everything that isnt a directory) File[] files = FileUtil.listFiles(dir, new FileFilter() { @Override public boolean accept(File f) { boolean accept = !(f.isDirectory() || f.getName().endsWith(".class")); return accept; } }); // For each file, add it either as a real .class file or as a resource for (File file : files) { // ASSERT: files[i].getAbsolutePath().startsWith(inFile.getAbsolutePath() // or we are in trouble... String filename = file.getAbsolutePath().substring(dir.getAbsolutePath().length() + 1); copyResourcesFromFile(file, filename, dir); } } private void copyResourcesFromFile(File f, String filename, File src) throws IOException { if (!acceptResource(filename, true)) { return; } FileInputStream fis = null; try { fis = new FileInputStream(f); byte[] bytes = FileUtil.readAsByteArray(fis); // String relativePath = files[i].getPath(); writeResource(filename, bytes, src); } catch (FileNotFoundException fnfe) { // pr359332: looks like the file moved (refactoring?) just as this copy was starting // that is OK } finally { if (fis != null) { fis.close(); } } } /** * Add a directory entry to the output zip file. Don't do anything if not writing out to a zip file. A directory entry is one * whose filename ends with '/' * * @param directory the directory path * @param srcloc the src of the directory entry, for use when creating a warning message * @throws IOException if something goes wrong creating the new zip entry */ private void writeDirectory(String directory, File srcloc) throws IOException { if (state.hasResource(directory)) { IMessage msg = new Message("duplicate resource: '" + directory + "'", IMessage.WARNING, null, new SourceLocation( srcloc, 0)); handler.handleMessage(msg); return; } if (zos != null) { ZipEntry newEntry = new ZipEntry(directory); zos.putNextEntry(newEntry); zos.closeEntry(); state.recordResource(directory, srcloc); } // Nothing to do if not writing to a zip file } private void writeResource(String filename, byte[] content, File srcLocation) throws IOException { if (state.hasResource(filename)) { IMessage msg = new Message("duplicate resource: '" + filename + "'", IMessage.WARNING, null, new SourceLocation( srcLocation, 0)); handler.handleMessage(msg); return; } if (filename.equals(buildConfig.getOutxmlName())) { ignoreOutxml = true; IMessage msg = new Message("-outxml/-outxmlfile option ignored because resource already exists: '" + filename + "'", IMessage.WARNING, null, new SourceLocation(srcLocation, 0)); handler.handleMessage(msg); } if (zos != null) { ZipEntry newEntry = new ZipEntry(filename); // ??? get compression scheme right zos.putNextEntry(newEntry); zos.write(content); zos.closeEntry(); } else { File destDir = buildConfig.getOutputDir(); if (buildConfig.getCompilationResultDestinationManager() != null) { destDir = buildConfig.getCompilationResultDestinationManager().getOutputLocationForResource(srcLocation); } try { File outputLocation = new File(destDir, filename); OutputStream fos = FileUtil.makeOutputStream(outputLocation); fos.write(content); fos.close(); if (buildConfig.getCompilationResultDestinationManager() != null) { buildConfig.getCompilationResultDestinationManager().reportFileWrite(outputLocation.getPath(), CompilationResultDestinationManager.FILETYPE_RESOURCE); } } catch (FileNotFoundException fnfe) { IMessage msg = new Message("unable to copy resource to output folder: '" + filename + "' - reason: " + fnfe.getMessage(), IMessage.ERROR, null, new SourceLocation(srcLocation, 0)); handler.handleMessage(msg); } } state.recordResource(filename, srcLocation); } /* * If we are writing to an output directory copy the manifest but only if we already have one */ private void writeManifest() throws IOException { Manifest manifest = getWeaver().getManifest(false); if (manifest != null && zos == null) { File outputDir = buildConfig.getOutputDir(); if (buildConfig.getCompilationResultDestinationManager() != null) { // Manifests are only written if we have a jar on the inpath. Therefore, // we write the manifest to the defaultOutputLocation because this is // where we sent the classes that were on the inpath outputDir = buildConfig.getCompilationResultDestinationManager().getDefaultOutputLocation(); } if (outputDir == null) { return; } File outputLocation = new File(outputDir, MANIFEST_NAME); OutputStream fos = FileUtil.makeOutputStream(outputLocation); manifest.write(fos); fos.close(); if (buildConfig.getCompilationResultDestinationManager() != null) { buildConfig.getCompilationResultDestinationManager().reportFileWrite(outputLocation.getPath(), CompilationResultDestinationManager.FILETYPE_RESOURCE); } } } private boolean acceptResource(String resourceName, boolean fromFile) { if ((resourceName.startsWith("CVS/")) || (resourceName.contains("/CVS/")) || (resourceName.endsWith("/CVS")) || (resourceName.endsWith(".class")) || (resourceName.startsWith(".svn/")) || (resourceName.contains("/.svn/")) || (resourceName.endsWith("/.svn")) || // Do not copy manifests if either they are coming from a jar or we are writing to a jar (resourceName.toUpperCase().equals(MANIFEST_NAME) && (!fromFile || zos != null))) { return false; } else { return true; } } private void writeOutxmlFile() throws IOException { if (ignoreOutxml) { return; } String filename = buildConfig.getOutxmlName(); // System.err.println("? AjBuildManager.writeOutxmlFile() outxml=" + filename); Map> outputDirsAndAspects = findOutputDirsForAspects(); Set>> outputDirs = outputDirsAndAspects.entrySet(); for (Map.Entry> entry : outputDirs) { File outputDir = entry.getKey(); List aspects = entry.getValue(); ByteArrayOutputStream baos = getOutxmlContents(aspects); if (zos != null) { ZipEntry newEntry = new ZipEntry(filename); zos.putNextEntry(newEntry); zos.write(baos.toByteArray()); zos.closeEntry(); } else { File outputFile = new File(outputDir, filename); OutputStream fos = FileUtil.makeOutputStream(outputFile); fos.write(baos.toByteArray()); fos.close(); if (buildConfig.getCompilationResultDestinationManager() != null) { buildConfig.getCompilationResultDestinationManager().reportFileWrite(outputFile.getPath(), CompilationResultDestinationManager.FILETYPE_RESOURCE); } } } } private ByteArrayOutputStream getOutxmlContents(List aspectNames) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(baos); ps.println(""); ps.println(""); if (aspectNames != null) { for (Object aspectName : aspectNames) { String name = (String) aspectName; ps.println(""); } } ps.println(""); ps.println(""); ps.println(); ps.close(); return baos; } /** * Returns a map where the keys are File objects corresponding to all the output directories and the values are a list of * aspects which are sent to that ouptut directory */ private Map> findOutputDirsForAspects() { Map> outputDirsToAspects = new HashMap<>(); Map aspectNamesToFileNames = state.getAspectNamesToFileNameMap(); if (buildConfig.getCompilationResultDestinationManager() == null || buildConfig.getCompilationResultDestinationManager().getAllOutputLocations().size() == 1) { // we only have one output directory...which simplifies things File outputDir = buildConfig.getOutputDir(); if (buildConfig.getCompilationResultDestinationManager() != null) { outputDir = buildConfig.getCompilationResultDestinationManager().getDefaultOutputLocation(); } List aspectNames = new ArrayList<>(); if (aspectNamesToFileNames != null) { Set keys = aspectNamesToFileNames.keySet(); for (String name : keys) { aspectNames.add(name); } } outputDirsToAspects.put(outputDir, aspectNames); } else { List outputDirs = buildConfig.getCompilationResultDestinationManager().getAllOutputLocations(); for (Object dir : outputDirs) { File outputDir = (File) dir; outputDirsToAspects.put(outputDir, new ArrayList<>()); } if (aspectNamesToFileNames != null) { Set> entrySet = aspectNamesToFileNames.entrySet(); for (Map.Entry entry : entrySet) { String aspectName = entry.getKey(); char[] fileName = entry.getValue(); File outputDir = buildConfig.getCompilationResultDestinationManager().getOutputLocationForClass( new File(new String(fileName))); if (!outputDirsToAspects.containsKey(outputDir)) { outputDirsToAspects.put(outputDir, new ArrayList<>()); } ((List) outputDirsToAspects.get(outputDir)).add(aspectName); } } } return outputDirsToAspects; } // public static void dumprels() { // IRelationshipMap irm = AsmManager.getDefault().getRelationshipMap(); // int ctr = 1; // Set entries = irm.getEntries(); // for (Iterator iter = entries.iterator(); iter.hasNext();) { // String hid = (String) iter.next(); // List rels = irm.get(hid); // for (Iterator iterator = rels.iterator(); iterator.hasNext();) { // IRelationship ir = (IRelationship) iterator.next(); // List targets = ir.getTargets(); // for (Iterator iterator2 = targets.iterator(); // iterator2.hasNext(); // ) { // String thid = (String) iterator2.next(); // System.err.println("Hid:"+(ctr++)+":(targets="+targets.size()+") "+hid+" ("+ir.getName()+") "+thid); // } // } // } // } /** * Responsible for managing the ASM model between builds. Contains the policy for maintaining the persistance of elements in the * model. * * This code is driven before each 'fresh' (batch) build to create a new model. */ private void setupModel(AjBuildConfig config) { if (!(config.isEmacsSymMode() || config.isGenerateModelMode())) { return; } // AsmManager.setCreatingModel(config.isEmacsSymMode() || config.isGenerateModelMode()); // if (!AsmManager.isCreatingModel()) // return; CompilationResultDestinationManager crdm = config.getCompilationResultDestinationManager(); AsmManager structureModel = AsmManager.createNewStructureModel(crdm == null ? Collections.EMPTY_MAP : crdm.getInpathMap()); // AsmManager.getDefault().getRelationshipMap().clear(); IHierarchy model = structureModel.getHierarchy(); String rootLabel = ""; IProgramElement.Kind kind = IProgramElement.Kind.FILE_JAVA; if (buildConfig.getConfigFile() != null) { rootLabel = buildConfig.getConfigFile().getName(); model.setConfigFile(buildConfig.getConfigFile().getAbsolutePath()); kind = IProgramElement.Kind.FILE_LST; } model.setRoot(new ProgramElement(structureModel, rootLabel, kind, new ArrayList())); model.setFileMap(new HashMap<>()); // setStructureModel(model); state.setStructureModel(structureModel); // state.setRelationshipMap(AsmManager.getDefault().getRelationshipMap()); } // // private void dumplist(List l) { // System.err.println("---- "+l.size()); // for (int i =0 ;i")) { // store.add(ipe); // return; // } // } // for (Iterator i = ipe.getChildren().iterator();i.hasNext();) { // accumulateFileNodes((IProgramElement)i.next(),store); // } // } // LTODO delegate to BcelWeaver? // XXX hideous, should not be Object public void setCustomMungerFactory(Object o) { customMungerFactory = (CustomMungerFactory) o; } public Object getCustomMungerFactory() { return customMungerFactory; } /** init only on initial batch compile? no file-specific options */ private void initBcelWorld(IMessageHandler handler) throws IOException { List cp = buildConfig.getFullClasspath(); // pr145693 // buildConfig.getBootclasspath(); // cp.addAll(buildConfig.getClasspath()); BcelWorld bcelWorld = new BcelWorld(cp, handler, null); bcelWorld.setBehaveInJava5Way(buildConfig.getBehaveInJava5Way()); bcelWorld.setTiming(buildConfig.isTiming(), false); bcelWorld.setAddSerialVerUID(buildConfig.isAddSerialVerUID()); bcelWorld.setXmlConfigured(buildConfig.isXmlConfigured()); bcelWorld.setXmlFiles(buildConfig.getXmlFiles()); bcelWorld.performExtraConfiguration(buildConfig.getXconfigurationInfo()); bcelWorld.setTargetAspectjRuntimeLevel(buildConfig.getTargetAspectjRuntimeLevel()); bcelWorld.setOptionalJoinpoints(buildConfig.getXJoinpoints()); bcelWorld.setXnoInline(buildConfig.isXnoInline()); bcelWorld.setXlazyTjp(buildConfig.isXlazyTjp()); bcelWorld.setXHasMemberSupportEnabled(buildConfig.isXHasMemberEnabled()); bcelWorld.setPinpointMode(buildConfig.isXdevPinpoint()); bcelWorld.setErrorAndWarningThreshold(buildConfig.getOptions().errorThreshold.isSet(24), buildConfig.getOptions().warningThreshold.isSet(24)); BcelWeaver bcelWeaver = new BcelWeaver(bcelWorld); bcelWeaver.setCustomMungerFactory(customMungerFactory); state.setWorld(bcelWorld); state.setWeaver(bcelWeaver); state.clearBinarySourceFiles(); if (buildConfig.getLintMode().equals(AjBuildConfig.AJLINT_DEFAULT)) { bcelWorld.getLint().loadDefaultProperties(); } else { bcelWorld.getLint().setAll(buildConfig.getLintMode()); } if (buildConfig.getLintOptionsMap() != null) { bcelWorld.getLint().setFromMap(buildConfig.getLintOptionsMap()); } if (buildConfig.getLintSpecFile() != null) { bcelWorld.getLint().setFromProperties(buildConfig.getLintSpecFile()); } for (File f: buildConfig.getAspectpath()) { if (!f.exists()) { IMessage message = new Message("invalid aspectpath entry: " + f.getName(), null, true); handler.handleMessage(message); } else { bcelWeaver.addLibraryJarFile(f); } } // String lintMode = buildConfig.getLintMode(); File outputDir = buildConfig.getOutputDir(); if (outputDir == null && buildConfig.getCompilationResultDestinationManager() != null) { // send all output from injars and inpath to the default output location // (will also later send the manifest there too) outputDir = buildConfig.getCompilationResultDestinationManager().getDefaultOutputLocation(); } // ??? incremental issues for (File inJar : buildConfig.getInJars()) { List unwovenClasses = bcelWeaver.addJarFile(inJar, outputDir, false); state.recordBinarySource(inJar.getPath(), unwovenClasses); } for (File inPathElement : buildConfig.getInpath()) { if (!inPathElement.isDirectory()) { // its a jar file on the inpath // the weaver method can actually handle dirs, but we don't call it, see next block List unwovenClasses = bcelWeaver.addJarFile(inPathElement, outputDir, true); state.recordBinarySource(inPathElement.getPath(), unwovenClasses); } else { // add each class file in an in-dir individually, this gives us the best error reporting // (they are like 'source' files then), and enables a cleaner incremental treatment of // class file changes in indirs. File[] binSrcs = FileUtil.listFiles(inPathElement, binarySourceFilter); for (File binSrc : binSrcs) { UnwovenClassFile ucf = bcelWeaver.addClassFile(binSrc, inPathElement, outputDir); List ucfl = new ArrayList<>(); ucfl.add(ucf); state.recordBinarySource(binSrc.getPath(), ucfl); } } } bcelWeaver.setReweavableMode(buildConfig.isXNotReweavable()); // check for org.aspectj.runtime.JoinPoint ResolvedType joinPoint = bcelWorld.resolve("org.aspectj.lang.JoinPoint"); if (joinPoint.isMissing()) { IMessage message = new Message( "classpath error: unable to find org.aspectj.lang.JoinPoint (check that aspectjrt.jar is in your classpath)", null, true); handler.handleMessage(message); } } public World getWorld() { return getBcelWorld(); } // void addAspectClassFilesToWeaver(List addedClassFiles) throws IOException { // for (Iterator i = addedClassFiles.iterator(); i.hasNext();) { // UnwovenClassFile classFile = (UnwovenClassFile) i.next(); // getWeaver().addClassFile(classFile); // } // } public FileSystem getLibraryAccess(String[] classpaths, String[] filenames) { String defaultEncoding = buildConfig.getOptions().defaultEncoding; if ("".equals(defaultEncoding)) {//$NON-NLS-1$ defaultEncoding = null; } // Bug 46671: We need an array as long as the number of elements in the classpath - *even though* not every // element of the classpath is likely to be a directory. If we ensure every element of the array is set to // only look for BINARY, then we make sure that for any classpath element that is a directory, we won't build // a classpathDirectory object that will attempt to look for source when it can't find binary. // int[] classpathModes = new int[classpaths.length]; // for (int i =0 ;i files) { if (progressListener != null) { compiledCount = 0; sourceFileCount = files.size(); progressListener.setText("compiling source files"); } // Translate from strings to File objects String[] filenames = new String[files.size()]; int idx = 0; for (File f : files) { filenames[idx++] = f.getPath(); } environment = state.getNameEnvironment(); boolean environmentNeedsRebuilding = false; // Might be a bit too cautious, but let us see how it goes if (buildConfig.getChanged() != AjBuildConfig.NO_CHANGES) { environmentNeedsRebuilding = true; } if (environment == null || environmentNeedsRebuilding) { List cps = buildConfig.getFullClasspath(); Dump.saveFullClasspath(cps); String[] classpaths = new String[cps.size()]; for (int i = 0; i < cps.size(); i++) { classpaths[i] = cps.get(i); } FileSystem fileSystem = getLibraryAccess(classpaths, filenames); environment = new StatefulNameEnvironment(fileSystem, state.getClassNameToFileMap(), state); state.setFileSystem(fileSystem); state.setNameEnvironment(environment); } else { ((StatefulNameEnvironment) environment).update(state.getClassNameToFileMap(), state.deltaAddedClasses); state.deltaAddedClasses.clear(); } org.aspectj.ajdt.internal.compiler.CompilerAdapter.setCompilerAdapterFactory(this); final Map settings = buildConfig.getOptions().getMap(); final BuildArgParser bMain = buildConfig.getBuildArgParser(); final org.aspectj.org.eclipse.jdt.internal.compiler.Compiler compiler = new org.aspectj.org.eclipse.jdt.internal.compiler.Compiler( environment, DefaultErrorHandlingPolicies.proceedWithAllProblems(), settings, getBatchRequestor(), getProblemFactory()); bMain.compilerOptions = compiler.options; bMain.batchCompiler = compiler; bMain.initializeAnnotationProcessorManager(); compiler.options.produceReferenceInfo = true; // TODO turn off when not needed if (bMain.compilerOptions.complianceLevel >= ClassFileConstants.JDK1_6 && bMain.compilerOptions.processAnnotations) { // need this too? // if (bMain.checkVMVersion(ClassFileConstants.JDK1_6)) { // initializeAnnotationProcessorManager(); // if (this.classNames != null) { // this.batchCompiler.setBinaryTypes(processClassNames(this.batchCompiler.lookupEnvironment)); // } // } else { // // report a warning // this.logger.logIncorrectVMVersionForAnnotationProcessing(); // } if (bMain.checkVMVersion(ClassFileConstants.JDK9)) { try { bMain.initRootModules(bMain.batchCompiler.lookupEnvironment, state.getFileSystem()); } 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); } } } try { compiler.compile(getCompilationUnits(filenames)); } catch (OperationCanceledException oce) { handler.handleMessage(new Message("build cancelled:" + oce.getMessage(), IMessage.WARNING, null, null)); } // cleanup org.aspectj.ajdt.internal.compiler.CompilerAdapter.setCompilerAdapterFactory(null); AnonymousClassPublisher.aspectOf().setAnonymousClassCreationListener(null); environment.cleanup(); // environment = null; } public void cleanupEnvironment() { if (environment != null) { environment.cleanup(); environment = null; // le = null; } } /* * Answer the component to which will be handed back compilation results from the compiler */ public IIntermediateResultsRequestor getInterimResultRequestor() { return new IIntermediateResultsRequestor() { @Override public void acceptResult(InterimCompilationResult result) { if (progressListener != null) { compiledCount++; progressListener.setProgress((compiledCount / 2.0) / sourceFileCount); progressListener.setText("compiled: " + result.fileName()); } state.noteResult(result); if (progressListener != null && progressListener.isCancelledRequested()) { throw new AbortCompilation(true, new OperationCanceledException("Compilation cancelled as requested")); } } }; } public ICompilerRequestor getBatchRequestor() { return new ICompilerRequestor() { @Override public void acceptResult(CompilationResult unitResult) { // end of compile, must now write the results to the output destination // this is either a jar file or a file in a directory boolean hasErrors = unitResult.hasErrors(); if (!hasErrors || proceedOnError()) { Collection classFiles = unitResult.compiledTypes.values(); boolean shouldAddAspectName = (buildConfig.getOutxmlName() != null); for (ClassFile classFile : classFiles) { String filename = new String(classFile.fileName()); String classname = filename.replace('/', '.'); filename = filename.replace('/', File.separatorChar) + ".class"; try { if (buildConfig.getOutputJar() == null) { String outfile = writeDirectoryEntry(unitResult, classFile, filename); getWorld().classWriteEvent(classFile.getCompoundName()); if (environmentSupportsIncrementalCompilation) { if (!classname.endsWith("$ajcMightHaveAspect")) { ResolvedType type = getBcelWorld().resolve(classname); if (type.isAspect()) { state.recordAspectClassFile(outfile); } } } } else { writeZipEntry(classFile, filename); } if (shouldAddAspectName && !classname.endsWith("$ajcMightHaveAspect")) { addAspectName(classname, unitResult.getFileName()); } } catch (IOException ex) { IMessage message = EclipseAdapterUtils.makeErrorMessage(new String(unitResult.fileName), CANT_WRITE_RESULT, ex); handler.handleMessage(message); } } state.noteNewResult(unitResult); unitResult.compiledTypes.clear(); // free up references to AjClassFile instances } if (unitResult.hasProblems() || unitResult.hasTasks()) { IProblem[] problems = unitResult.getAllProblems(); for (IProblem problem : problems) { IMessage message = EclipseAdapterUtils.makeMessage(unitResult.compilationUnit, problem, getBcelWorld(), progressListener); handler.handleMessage(message); } } } private String writeDirectoryEntry(CompilationResult unitResult, ClassFile classFile, String filename) throws IOException { File destinationPath = buildConfig.getOutputDir(); if (buildConfig.getCompilationResultDestinationManager() != null) { destinationPath = buildConfig.getCompilationResultDestinationManager().getOutputLocationForClass( new File(new String(unitResult.fileName))); } String outFile; if (destinationPath == null) { outFile = new File(filename).getName(); outFile = new File(extractDestinationPathFromSourceFile(unitResult), outFile).getPath(); } else { outFile = new File(destinationPath, filename).getPath(); } try { BufferedOutputStream os = FileUtil.makeOutputStream(new File(outFile)); os.write(classFile.getBytes()); os.close(); } catch (FileNotFoundException fnfe) { IMessage msg = new Message("unable to write out class file: '" + filename + "' - reason: " + fnfe.getMessage(), IMessage.ERROR, null, new SourceLocation(new File(outFile), 0)); handler.handleMessage(msg); } if (buildConfig.getCompilationResultDestinationManager() != null) { buildConfig.getCompilationResultDestinationManager().reportFileWrite(outFile, CompilationResultDestinationManager.FILETYPE_CLASS); } return outFile; } private void writeZipEntry(ClassFile classFile, String name) throws IOException { name = name.replace(File.separatorChar, '/'); ZipEntry newEntry = new ZipEntry(name); // ??? get compression scheme right zos.putNextEntry(newEntry); zos.write(classFile.getBytes()); zos.closeEntry(); } private void addAspectName(String name, char[] fileContainingAspect) { BcelWorld world = getBcelWorld(); ResolvedType type = world.resolve(name); // System.err.println("? writeAspectName() type=" + type); if (type.isAspect()) { if (state.getAspectNamesToFileNameMap() == null) { state.initializeAspectNamesToFileNameMap(); } if (!state.getAspectNamesToFileNameMap().containsKey(name)) { state.getAspectNamesToFileNameMap().put(name, fileContainingAspect); } } } }; } protected boolean proceedOnError() { return buildConfig.getProceedOnError(); } // public void noteClassFiles(AjCompiler.InterimResult result) { // if (result == null) return; // CompilationResult unitResult = result.result; // String sourceFileName = result.fileName(); // if (!(unitResult.hasErrors() && !proceedOnError())) { // List unwovenClassFiles = new ArrayList(); // Enumeration classFiles = unitResult.compiledTypes.elements(); // while (classFiles.hasMoreElements()) { // ClassFile classFile = (ClassFile) classFiles.nextElement(); // String filename = new String(classFile.fileName()); // filename = filename.replace('/', File.separatorChar) + ".class"; // // File destinationPath = buildConfig.getOutputDir(); // if (destinationPath == null) { // filename = new File(filename).getName(); // filename = new File(extractDestinationPathFromSourceFile(unitResult), filename).getPath(); // } else { // filename = new File(destinationPath, filename).getPath(); // } // // //System.out.println("classfile: " + filename); // unwovenClassFiles.add(new UnwovenClassFile(filename, classFile.getBytes())); // } // state.noteClassesFromFile(unitResult, sourceFileName, unwovenClassFiles); // // System.out.println("file: " + sourceFileName); // // for (int i=0; i < unitResult.simpleNameReferences.length; i++) { // // System.out.println("simple: " + new String(unitResult.simpleNameReferences[i])); // // } // // for (int i=0; i < unitResult.qualifiedReferences.length; i++) { // // System.out.println("qualified: " + // // new String(CharOperation.concatWith(unitResult.qualifiedReferences[i], '/'))); // // } // } else { // state.noteClassesFromFile(null, sourceFileName, Collections.EMPTY_LIST); // } // } // private void setBuildConfig(AjBuildConfig buildConfig) { this.buildConfig = buildConfig; if (!this.environmentSupportsIncrementalCompilation) { this.environmentSupportsIncrementalCompilation = (buildConfig.isIncrementalMode() || buildConfig .isIncrementalFileMode()); } handler.reset(); } String makeClasspathString(AjBuildConfig buildConfig) { if (buildConfig == null || buildConfig.getFullClasspath() == null) { return ""; } StringBuilder buf = new StringBuilder(); boolean first = true; for (String s : buildConfig.getFullClasspath()) { if (first) { first = false; } else { buf.append(File.pathSeparator); } buf.append(s.toString()); } return buf.toString(); } /** * This will return null if aspectjrt.jar is present and has the correct version. Otherwise it will return a string message * indicating the problem. */ private String checkRtJar(AjBuildConfig buildConfig) { // omitting dev info if (Version.getText().equals(Version.DEVELOPMENT) || Version.getText().endsWith("BUILD-SNAPSHOT")) { // in the development version we can't do this test usefully // MessageUtil.info(holder, "running development version of aspectj compiler"); return null; } if (buildConfig == null || buildConfig.getFullClasspath() == null) { return "no classpath specified"; } for (String s: buildConfig.getFullClasspath()) { if (s.endsWith("runtime/target/classes") || s.endsWith("runtime\\target\\classes")) { // doing an AspectJ build return null; } } String ret = null; for (String s : buildConfig.getFullClasspath()) { File p = new File(s); // pr112830, allow variations on aspectjrt.jar of the form aspectjrtXXXXXX.jar if (p.isFile() && p.getName().startsWith("aspectjrt") && p.getName().endsWith(".jar")) { try { String version = null; Manifest manifest = new JarFile(p).getManifest(); if (manifest == null) { ret = "no manifest found in " + p.getAbsolutePath() + ", expected " + Version.getText(); continue; } Attributes attr = manifest.getAttributes("org/aspectj/lang/"); if (null != attr) { version = attr.getValue(Attributes.Name.IMPLEMENTATION_VERSION); if (null != version) { version = version.trim(); } } // assume that users of development aspectjrt.jar know what they're doing if (version != null && (Version.DEVELOPMENT.equals(version) || version.endsWith("BUILD-SNAPSHOT"))) { // MessageUtil.info(holder, // "running with development version of aspectjrt.jar in " + // p.getAbsolutePath()); return null; } else if (!Version.getText().equals(version)) { ret = "bad version number found in " + p.getAbsolutePath() + " expected " + Version.getText() + " found " + version; continue; } } catch (IOException ioe) { ret = "bad jar file found in " + p.getAbsolutePath() + " error: " + ioe; } return null; // this is the "OK" return value! } else if (p.isFile() && p.getName().contains("org.aspectj.runtime")) { // likely to be a variant from the springsource bundle repo b272591 return null; } else { // might want to catch other classpath errors } } if (ret != null) { return ret; // last error found in potentially matching jars... } return "couldn't find aspectjrt.jar on classpath, checked: " + makeClasspathString(buildConfig); } @Override public String toString() { StringBuilder buf = new StringBuilder(); buf.append("AjBuildManager("); buf.append(")"); return buf.toString(); } // // public void setStructureModel(IHierarchy structureModel) { // this.structureModel = structureModel; // } /** * Returns null if there is no structure model */ public AsmManager getStructureModel() { return (state == null ? null : state.getStructureModel()); } public IProgressListener getProgressListener() { return progressListener; } public void setProgressListener(IProgressListener progressListener) { this.progressListener = progressListener; } /* * (non-Javadoc) * * @see org.aspectj.ajdt.internal.compiler.AjCompiler.IOutputClassFileNameProvider#getOutputClassFileName(char[]) */ @Override public String getOutputClassFileName(char[] eclipseClassFileName, CompilationResult result) { String filename = new String(eclipseClassFileName); filename = filename.replace('/', File.separatorChar) + ".class"; File destinationPath = buildConfig.getOutputDir(); if (buildConfig.getCompilationResultDestinationManager() != null) { File f = new File(new String(result.getFileName())); destinationPath = buildConfig.getCompilationResultDestinationManager().getOutputLocationForClass(f); } String outFile; if (destinationPath == null) { outFile = new File(filename).getName(); outFile = new File(extractDestinationPathFromSourceFile(result), outFile).getPath(); } else { outFile = new File(destinationPath, filename).getPath(); } return outFile; } /* * (non-Javadoc) * * @see org.eclipse.jdt.internal.compiler.ICompilerAdapterFactory#getAdapter(org.eclipse.jdt.internal.compiler.Compiler) */ @Override public ICompilerAdapter getAdapter(org.aspectj.org.eclipse.jdt.internal.compiler.Compiler forCompiler) { // complete compiler config and return a suitable adapter... populateCompilerOptionsFromLintSettings(forCompiler); AjProblemReporter pr = new AjProblemReporter(DefaultErrorHandlingPolicies.proceedWithAllProblems(), forCompiler.options, getProblemFactory()); forCompiler.problemReporter = pr; AjLookupEnvironment le = new AjLookupEnvironment(forCompiler, forCompiler.options, pr, environment); EclipseFactory factory = new EclipseFactory(le, this); le.factory = factory; pr.factory = factory; forCompiler.lookupEnvironment = le; forCompiler.parser = new Parser(pr, forCompiler.options.parseLiteralExpressionsAsConstants); if (getBcelWorld().shouldPipelineCompilation()) { IMessage message = MessageUtil.info("Pipelining compilation"); handler.handleMessage(message); return new AjPipeliningCompilerAdapter(forCompiler, batchCompile, getBcelWorld(), getWeaver(), factory, getInterimResultRequestor(), progressListener, this, // IOutputFilenameProvider this, // IBinarySourceProvider state.getBinarySourceMap(), buildConfig.isTerminateAfterCompilation(), buildConfig.getProceedOnError(), buildConfig.isNoAtAspectJAnnotationProcessing(), buildConfig.isMakeReflectable(), state); } else { return new AjCompilerAdapter(forCompiler, batchCompile, getBcelWorld(), getWeaver(), factory, getInterimResultRequestor(), progressListener, this, // IOutputFilenameProvider this, // IBinarySourceProvider state.getBinarySourceMap(), buildConfig.isTerminateAfterCompilation(), buildConfig.getProceedOnError(), buildConfig.isNoAtAspectJAnnotationProcessing(), buildConfig.isMakeReflectable(), state); } } /** * Some AspectJ lint options need to be known about in the compiler. This is how we pass them over... * * @param forCompiler */ private void populateCompilerOptionsFromLintSettings(org.aspectj.org.eclipse.jdt.internal.compiler.Compiler forCompiler) { BcelWorld world = this.state.getBcelWorld(); IMessage.Kind swallowedExceptionKind = world.getLint().swallowedExceptionInCatchBlock.getKind(); Map optionsMap = new HashMap(); optionsMap.put(CompilerOptions.OPTION_ReportSwallowedExceptionInCatchBlock, swallowedExceptionKind == null ? "ignore" : swallowedExceptionKind.toString()); forCompiler.options.set(optionsMap); } /* * (non-Javadoc) * * @see org.aspectj.ajdt.internal.compiler.IBinarySourceProvider#getBinarySourcesForThisWeave() */ @Override public Map> getBinarySourcesForThisWeave() { return binarySourcesForTheNextCompile; } public static AsmHierarchyBuilder getAsmHierarchyBuilder() { return asmHierarchyBuilder; } /** * Override the the default hierarchy builder. */ public static void setAsmHierarchyBuilder(AsmHierarchyBuilder newBuilder) { asmHierarchyBuilder = newBuilder; } public AjState getState() { return state; } public void setState(AjState buildState) { state = buildState; } private static class AjBuildContexFormatter implements ContextFormatter { @Override public String formatEntry(int phaseId, Object data) { StringBuilder sb = new StringBuilder(); if (phaseId == CompilationAndWeavingContext.BATCH_BUILD) { sb.append("batch building "); } else { sb.append("incrementally building "); } AjBuildConfig config = (AjBuildConfig) data; List classpath = config.getClasspath(); sb.append("with classpath: "); for (Object o : classpath) { sb.append(o.toString()); sb.append(File.pathSeparator); } return sb.toString(); } } public boolean wasFullBuild() { return wasFullBuild; } }