123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996 |
- /* *******************************************************************
- * 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 Common Public License v1.0
- * which accompanies this distribution and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- * PARC initial implementation
- * ******************************************************************/
-
-
- package org.aspectj.ajdt.internal.core.builder;
-
- import java.io.*;
- import java.util.*;
- import java.util.jar.*;
- import java.util.zip.ZipEntry;
-
- import org.aspectj.ajdt.internal.compiler.AjCompilerAdapter;
- import org.aspectj.ajdt.internal.compiler.IBinarySourceProvider;
- 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.*;
- import org.aspectj.ajdt.internal.compiler.problem.AjProblemReporter;
- import org.aspectj.asm.*;
- //import org.aspectj.asm.internal.*;
- import org.aspectj.asm.internal.ProgramElement;
- import org.aspectj.bridge.*;
- import org.aspectj.util.FileUtil;
- import org.aspectj.weaver.Dump;
- import org.aspectj.weaver.World;
- import org.aspectj.weaver.bcel.*;
- import org.eclipse.core.runtime.OperationCanceledException;
- import org.eclipse.jdt.core.compiler.*;
- import org.eclipse.jdt.internal.compiler.*;
- import org.eclipse.jdt.internal.compiler.batch.*;
- import org.eclipse.jdt.internal.compiler.batch.FileSystem;
- import org.eclipse.jdt.internal.compiler.env.*;
- import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
- import org.eclipse.jdt.internal.compiler.parser.Parser;
- import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
- import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
- //import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
-
- public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourceProvider,ICompilerAdapterFactory {
- private static final String CANT_WRITE_RESULT = "unable to write compilation result";
- private static final String MANIFEST_NAME = "META-INF/MANIFEST.MF";
- static final boolean COPY_INPATH_DIR_RESOURCES = false;
- static final boolean FAIL_IF_RUNTIME_NOT_FOUND = false;
-
- private static final FileFilter binarySourceFilter =
- new FileFilter() {
- 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.
- */
- private static AsmHierarchyBuilder asmHierarchyBuilder = new AsmHierarchyBuilder();
-
- private IProgressListener progressListener = null;
-
- private int compiledCount;
- private int sourceFileCount;
-
- private JarOutputStream zos;
- private boolean batchCompile = true;
- private INameEnvironment environment;
-
- private Map /* String -> List<UCF>*/ binarySourcesForTheNextCompile = new HashMap();
-
- private IHierarchy structureModel;
- public AjBuildConfig buildConfig;
-
- AjState state = new AjState(this);
-
- BcelWeaver bcelWeaver;
- public BcelWorld bcelWorld;
-
- public CountingMessageHandler handler;
-
- public AjBuildManager(IMessageHandler holder) {
- super();
- this.handler = CountingMessageHandler.makeCountingMessageHandler(holder);
- }
-
- /** @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 doBuild(buildConfig, baseHandler, true);
- }
-
- public boolean incrementalBuild(
- AjBuildConfig buildConfig,
- IMessageHandler baseHandler)
- throws IOException, AbortException {
- return doBuild(buildConfig, baseHandler, false);
- }
-
-
- /** @throws AbortException if check for runtime fails */
- protected boolean doBuild(
- AjBuildConfig buildConfig,
- IMessageHandler baseHandler,
- boolean batch) throws IOException, AbortException {
- boolean ret = true;
- batchCompile = batch;
-
- try {
- if (batch) {
- this.state = new AjState(this);
- }
-
- boolean canIncremental = state.prepareForNextBuild(buildConfig);
- if (!canIncremental && !batch) { // retry as batch?
- return doBuild(buildConfig, baseHandler, true);
- }
- this.handler =
- CountingMessageHandler.makeCountingMessageHandler(baseHandler);
- // XXX duplicate, no? remove?
- String check = checkRtJar(buildConfig);
- if (check != null) {
- if (FAIL_IF_RUNTIME_NOT_FOUND) {
- MessageUtil.error(handler, check);
- return false;
- } else {
- MessageUtil.warn(handler, check);
- }
- }
- // if (batch) {
- setBuildConfig(buildConfig);
- //}
- if (batch || !AsmManager.attemptIncrementalModelRepairs) {
- // if (buildConfig.isEmacsSymMode() || buildConfig.isGenerateModelMode()) {
- setupModel(buildConfig);
- // }
- }
- if (batch) {
- initBcelWorld(handler);
- }
- if (handler.hasErrors()) {
- return false;
- }
-
- if (buildConfig.getOutputJar() != null) {
- if (!openOutputStream(buildConfig.getOutputJar())) return false;
- }
-
- if (batch) {
- // System.err.println("XXXX batch: " + buildConfig.getFiles());
- if (buildConfig.isEmacsSymMode() || buildConfig.isGenerateModelMode()) {
- bcelWorld.setModel(AsmManager.getDefault().getHierarchy());
- // in incremental build, only get updated model?
- }
- binarySourcesForTheNextCompile = state.getBinaryFilesToCompile(true);
- performCompilation(buildConfig.getFiles());
- if (handler.hasErrors()) {
- return false;
- }
-
- if (AsmManager.isReporting())
- AsmManager.getDefault().reportModelInfo("After a batch build");
-
- } else {
- // done already?
- // if (buildConfig.isEmacsSymMode() || buildConfig.isGenerateModelMode()) {
- // bcelWorld.setModel(StructureModelManager.INSTANCE.getStructureModel());
- // }
- // System.err.println("XXXX start inc ");
- binarySourcesForTheNextCompile = state.getBinaryFilesToCompile(true);
- List files = state.getFilesToCompile(true);
- if (buildConfig.isEmacsSymMode() || buildConfig.isGenerateModelMode())
- if (AsmManager.attemptIncrementalModelRepairs)
- AsmManager.getDefault().processDelta(files,state.addedFiles,state.deletedFiles);
- boolean hereWeGoAgain = !(files.isEmpty() && binarySourcesForTheNextCompile.isEmpty());
- for (int i = 0; (i < 5) && hereWeGoAgain; i++) {
- // System.err.println("XXXX inc: " + files);
-
- performCompilation(files);
- if (handler.hasErrors() || (progressListener!=null && progressListener.isCancelledRequested())) {
- return false;
- }
- 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)
- AsmManager.getDefault().processDelta(files,state.addedFiles,state.deletedFiles);
- }
- if (!files.isEmpty()) {
- return batchBuild(buildConfig, baseHandler);
- } else {
- if (AsmManager.isReporting())
- AsmManager.getDefault().reportModelInfo("After an incremental build");
- }
- }
-
- // XXX not in Mik's incremental
- if (buildConfig.isEmacsSymMode()) {
- new org.aspectj.ajdt.internal.core.builder.EmacsStructureModelManager().externalizeModel();
- }
- // have to tell state we succeeded or next is not incremental
- state.successfulCompile(buildConfig);
-
- copyResourcesToDestination();
- /*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()) {
- AsmManager.getDefault().fireModelUpdated();
- }
- } finally {
- if (zos != null) {
- closeOutputStream(buildConfig.getOutputJar());
- }
- ret = !handler.hasErrors();
- // bug 59895, don't release reference to handler as may be needed by a nested call
- //handler = null;
- }
- return ret;
- }
-
-
- private boolean openOutputStream(File outJar) {
- try {
- OutputStream os = FileUtil.makeOutputStream(buildConfig.getOutputJar());
- zos = new JarOutputStream(os,bcelWeaver.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();
- zos = null;
-
- /* Ensure we don't write an incomplete JAR bug-71339 */
- if (handler.hasErrors()) {
- outJar.delete();
- }
- } 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 (Iterator i = buildConfig.getInJars().iterator(); i.hasNext(); ) {
- File inJar = (File)i.next();
- copyResourcesFromJarFile(inJar);
- }
-
- for (Iterator i = buildConfig.getInpath().iterator(); i.hasNext(); ) {
- File inPathElement = (File)i.next();
- if (inPathElement.isDirectory()) {
- copyResourcesFromDirectory(inPathElement);
- } else {
- copyResourcesFromJarFile(inPathElement);
- }
- }
-
- if (buildConfig.getSourcePathResources() != null) {
- for (Iterator i = buildConfig.getSourcePathResources().keySet().iterator(); i.hasNext(); ) {
- String resource = (String)i.next();
- File from = (File)buildConfig.getSourcePathResources().get(resource);
- copyResourcesFromFile(from,resource,from);
- }
- }
-
- writeManifest();
- }
-
- private void copyResourcesFromJarFile(File jarFile) throws IOException {
- JarInputStream inStream = null;
- try {
- 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() && acceptResource(filename)) {
- byte[] bytes = FileUtil.readAsByteArray(inStream);
- writeResource(filename,bytes,jarFile);
- }
-
- inStream.closeEntry();
- }
- } finally {
- if (inStream != null) inStream.close();
- }
- }
-
- 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() {
- 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 (int i = 0; i < files.length; i++) {
- // ASSERT: files[i].getAbsolutePath().startsWith(inFile.getAbsolutePath()
- // or we are in trouble...
- String filename = files[i].getAbsolutePath().substring(
- dir.getAbsolutePath().length()+1);
- copyResourcesFromFile(files[i],filename,dir);
- }
- }
-
- private void copyResourcesFromFile(File f,String filename,File src) throws IOException {
- if (!acceptResource(filename)) return;
- FileInputStream fis = null;
- try {
- fis = new FileInputStream(f);
- byte[] bytes = FileUtil.readAsByteArray(fis);
- // String relativePath = files[i].getPath();
-
- writeResource(filename,bytes,src);
- } finally {
- if (fis != null) fis.close();
- }
- }
-
- private void writeResource(String filename, byte[] content, File srcLocation) throws IOException {
- if (state.resources.contains(filename)) {
- IMessage msg = new Message("duplicate resource: '" + filename + "'",
- IMessage.WARNING,
- null,
- new SourceLocation(srcLocation,0));
- handler.handleMessage(msg);
- return;
- }
- if (zos != null) {
- ZipEntry newEntry = new ZipEntry(filename); //??? get compression scheme right
-
- zos.putNextEntry(newEntry);
- zos.write(content);
- zos.closeEntry();
- } else {
- OutputStream fos =
- FileUtil.makeOutputStream(new File(buildConfig.getOutputDir(),filename));
- fos.write(content);
- fos.close();
- }
- state.resources.add(filename);
- }
-
- /*
- * 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 = bcelWeaver.getManifest(false);
- if (manifest != null && zos == null) {
- OutputStream fos =
- FileUtil.makeOutputStream(new File(buildConfig.getOutputDir(),MANIFEST_NAME));
- manifest.write(fos);
- fos.close();
- }
- }
-
- private boolean acceptResource(String resourceName) {
- if (
- (resourceName.startsWith("CVS/")) ||
- (resourceName.indexOf("/CVS/") != -1) ||
- (resourceName.endsWith("/CVS")) ||
- (resourceName.endsWith(".class")) ||
- (resourceName.toUpperCase().equals(MANIFEST_NAME))
- )
- {
- return false;
- } else {
- return true;
- }
- }
-
-
- // 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.
- *
- * TODO: implement incremental policy.
- */
- private void setupModel(AjBuildConfig config) {
- IHierarchy model = AsmManager.getDefault().getHierarchy();
- String rootLabel = "<root>";
-
- AsmManager.getDefault().getRelationshipMap().clear();
-
- 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(rootLabel, kind, new ArrayList()));
-
- model.setFileMap(new HashMap());
- setStructureModel(model);
- }
-
- //
- // private void dumplist(List l) {
- // System.err.println("---- "+l.size());
- // for (int i =0 ;i<l.size();i++) System.err.println(i+"\t "+l.get(i));
- // }
- // private void accumulateFileNodes(IProgramElement ipe,List store) {
- // if (ipe.getKind()==IProgramElement.Kind.FILE_JAVA ||
- // ipe.getKind()==IProgramElement.Kind.FILE_ASPECTJ) {
- // if (!ipe.getName().equals("<root>")) {
- // store.add(ipe);
- // return;
- // }
- // }
- // for (Iterator i = ipe.getChildren().iterator();i.hasNext();) {
- // accumulateFileNodes((IProgramElement)i.next(),store);
- // }
- // }
-
- /** init only on initial batch compile? no file-specific options */
- private void initBcelWorld(IMessageHandler handler) throws IOException {
- bcelWorld = new BcelWorld(buildConfig.getClasspath(), handler, null);
- bcelWorld.setXnoInline(buildConfig.isXnoInline());
- bcelWorld.setXlazyTjp(buildConfig.isXlazyTjp());
- bcelWeaver = new BcelWeaver(bcelWorld);
- state.binarySourceFiles = new HashMap();
-
- for (Iterator i = buildConfig.getAspectpath().iterator(); i.hasNext();) {
- File f = (File) i.next();
- bcelWeaver.addLibraryJarFile(f);
- }
-
- // String lintMode = buildConfig.getLintMode();
-
- if (buildConfig.getLintMode().equals(AjBuildConfig.AJLINT_DEFAULT)) {
- bcelWorld.getLint().loadDefaultProperties();
- } else {
- bcelWorld.getLint().setAll(buildConfig.getLintMode());
- }
-
- if (buildConfig.getLintSpecFile() != null) {
- bcelWorld.getLint().setFromProperties(buildConfig.getLintSpecFile());
- }
-
- //??? incremental issues
- for (Iterator i = buildConfig.getInJars().iterator(); i.hasNext(); ) {
- File inJar = (File)i.next();
- List unwovenClasses = bcelWeaver.addJarFile(inJar, buildConfig.getOutputDir(),false);
- state.binarySourceFiles.put(inJar.getPath(), unwovenClasses);
- }
-
- for (Iterator i = buildConfig.getInpath().iterator(); i.hasNext(); ) {
- File inPathElement = (File)i.next();
- 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,buildConfig.getOutputDir(),true);
- state.binarySourceFiles.put(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 (int j = 0; j < binSrcs.length; j++) {
- UnwovenClassFile ucf =
- bcelWeaver.addClassFile(binSrcs[j], inPathElement, buildConfig.getOutputDir());
- List ucfl = new ArrayList();
- ucfl.add(ucf);
- state.binarySourceFiles.put(binSrcs[j].getPath(),ucfl);
- }
- }
- }
-
-
- bcelWeaver.setReweavableMode(buildConfig.isXreweavable(),buildConfig.getXreweavableCompressClasses());
-
- //check for org.aspectj.runtime.JoinPoint
- bcelWorld.resolve("org.aspectj.lang.JoinPoint");
- }
-
- public World getWorld() {
- return bcelWorld;
- }
-
- void addAspectClassFilesToWeaver(List addedClassFiles) throws IOException {
- for (Iterator i = addedClassFiles.iterator(); i.hasNext(); ) {
- UnwovenClassFile classFile = (UnwovenClassFile) i.next();
- bcelWeaver.addClassFile(classFile);
- }
- }
-
- // public boolean weaveAndGenerateClassFiles() throws IOException {
- // handler.handleMessage(MessageUtil.info("weaving"));
- // if (progressListener != null) progressListener.setText("weaving aspects");
- // bcelWeaver.setProgressListener(progressListener, 0.5, 0.5/state.addedClassFiles.size());
- // //!!! doesn't provide intermediate progress during weaving
- // // XXX add all aspects even during incremental builds?
- // addAspectClassFilesToWeaver(state.addedClassFiles);
- // if (buildConfig.isNoWeave()) {
- // if (buildConfig.getOutputJar() != null) {
- // bcelWeaver.dumpUnwoven(buildConfig.getOutputJar());
- // } else {
- // bcelWeaver.dumpUnwoven();
- // bcelWeaver.dumpResourcesToOutPath();
- // }
- // } else {
- // if (buildConfig.getOutputJar() != null) {
- // bcelWeaver.weave(buildConfig.getOutputJar());
- // } else {
- // bcelWeaver.weave();
- // bcelWeaver.dumpResourcesToOutPath();
- // }
- // }
- // if (progressListener != null) progressListener.setProgress(1.0);
- // return true;
- // //return messageAdapter.getErrorCount() == 0; //!javaBuilder.notifier.anyErrors();
- // }
-
- public FileSystem getLibraryAccess(String[] classpaths, String[] filenames) {
- String defaultEncoding = buildConfig.getOptions().defaultEncoding;
- if ("".equals(defaultEncoding)) //$NON-NLS-1$
- defaultEncoding = null; //$NON-NLS-1$
- // 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<classpaths.length;i++) classpathModes[i]=ClasspathDirectory.BINARY;
- return new FileSystem(classpaths, filenames, defaultEncoding,classpathModes);
- }
-
- public IProblemFactory getProblemFactory() {
- return new DefaultProblemFactory(Locale.getDefault());
- }
-
- /*
- * Build the set of compilation source units
- */
- public CompilationUnit[] getCompilationUnits(String[] filenames, String[] encodings) {
- int fileCount = filenames.length;
- CompilationUnit[] units = new CompilationUnit[fileCount];
- // HashtableOfObject knownFileNames = new HashtableOfObject(fileCount);
-
- String defaultEncoding = buildConfig.getOptions().defaultEncoding;
- if ("".equals(defaultEncoding)) //$NON-NLS-1$
- defaultEncoding = null; //$NON-NLS-1$
-
- for (int i = 0; i < fileCount; i++) {
- String encoding = encodings[i];
- if (encoding == null)
- encoding = defaultEncoding;
- units[i] = new CompilationUnit(null, filenames[i], encoding);
- }
- return units;
- }
-
- public String extractDestinationPathFromSourceFile(CompilationResult result) {
- ICompilationUnit compilationUnit = result.compilationUnit;
- if (compilationUnit != null) {
- char[] fileName = compilationUnit.getFileName();
- int lastIndex = CharOperation.lastIndexOf(java.io.File.separatorChar, fileName);
- if (lastIndex == -1) {
- return System.getProperty("user.dir"); //$NON-NLS-1$
- }
- return new String(CharOperation.subarray(fileName, 0, lastIndex));
- }
- return System.getProperty("user.dir"); //$NON-NLS-1$
- }
-
-
- public void performCompilation(List files) {
- if (progressListener != null) {
- compiledCount = 0;
- sourceFileCount = files.size();
- progressListener.setText("compiling source files");
- }
- //System.err.println("got files: " + files);
- String[] filenames = new String[files.size()];
- String[] encodings = new String[files.size()];
- //System.err.println("filename: " + this.filenames);
- for (int i=0; i < files.size(); i++) {
- filenames[i] = ((File)files.get(i)).getPath();
- }
-
- List cps = buildConfig.getFullClasspath();
- Dump.saveFullClasspath(cps);
- String[] classpaths = new String[cps.size()];
- for (int i=0; i < cps.size(); i++) {
- classpaths[i] = (String)cps.get(i);
- }
-
- //System.out.println("compiling");
- environment = getLibraryAccess(classpaths, filenames);
-
- if (!state.classesFromName.isEmpty()) {
- environment = new StatefulNameEnvironment(environment, state.classesFromName);
- }
-
- org.eclipse.jdt.internal.compiler.Compiler.setCompilerAdapterFactory(this);
- org.eclipse.jdt.internal.compiler.Compiler compiler =
- new org.eclipse.jdt.internal.compiler.Compiler(environment,
- DefaultErrorHandlingPolicies.proceedWithAllProblems(),
- buildConfig.getOptions().getMap(),
- getBatchRequestor(),
- getProblemFactory());
-
- CompilerOptions options = compiler.options;
-
- options.produceReferenceInfo = true; //TODO turn off when not needed
-
- try {
- compiler.compile(getCompilationUnits(filenames, encodings));
- } catch (OperationCanceledException oce) {
- handler.handleMessage(new Message("build cancelled:"+oce.getMessage(),IMessage.WARNING,null,null));
- }
- // cleanup
- environment.cleanup();
- environment = null;
- }
-
- /*
- * Answer the component to which will be handed back compilation results from the compiler
- */
- public IIntermediateResultsRequestor getInterimResultRequestor() {
- return new IIntermediateResultsRequestor() {
- int lineDelta = 0;
- 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() {
-
- 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
- if (!(unitResult.hasErrors() && !proceedOnError())) {
- 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";
- try {
- if (buildConfig.getOutputJar() == null) {
- writeDirectoryEntry(unitResult, classFile,filename);
- } else {
- writeZipEntry(classFile,filename);
- }
- } catch (IOException ex) {
- IMessage message = EclipseAdapterUtils.makeErrorMessage(
- new String(unitResult.fileName),
- CANT_WRITE_RESULT,
- ex);
- handler.handleMessage(message);
- }
-
- }
- }
-
- if (unitResult.hasProblems() || unitResult.hasTasks()) {
- IProblem[] problems = unitResult.getAllProblems();
- for (int i=0; i < problems.length; i++) {
- IMessage message =
- EclipseAdapterUtils.makeMessage(unitResult.compilationUnit, problems[i]);
- handler.handleMessage(message);
- }
- }
-
- }
-
- private void writeDirectoryEntry(
- CompilationResult unitResult,
- ClassFile classFile,
- String filename)
- throws IOException {
- File destinationPath = buildConfig.getOutputDir();
- String outFile;
- if (destinationPath == null) {
- outFile = new File(filename).getName();
- outFile = new File(extractDestinationPathFromSourceFile(unitResult), outFile).getPath();
- } else {
- outFile = new File(destinationPath, filename).getPath();
- }
- BufferedOutputStream os =
- FileUtil.makeOutputStream(new File(outFile));
- os.write(classFile.getBytes());
- os.close();
- }
-
- 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();
- }
- };
- }
-
- protected boolean proceedOnError() {
- return true; //???
- }
-
- // 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;
- handler.reset();
- }
-
- String makeClasspathString() {
- if (buildConfig == null || buildConfig.getClasspath() == null) return "";
- StringBuffer buf = new StringBuffer();
- boolean first = true;
- for (Iterator it = buildConfig.getClasspath().iterator(); it.hasNext(); ) {
- if (first) { first = false; }
- else { buf.append(File.pathSeparator); }
- buf.append(it.next().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.
- */
- public String checkRtJar(AjBuildConfig buildConfig) {
- // omitting dev info
- if (Version.text.equals(Version.DEVELOPMENT)) {
- // 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.getClasspath() == null) return "no classpath specified";
- for (Iterator it = buildConfig.getClasspath().iterator(); it.hasNext(); ) {
- File p = new File( (String)it.next() );
- if (p.isFile() && p.getName().equals("aspectjrt.jar")) {
-
- try {
- String version = null;
- Manifest manifest = new JarFile(p).getManifest();
- if (manifest == null) {
- return "no manifest found in " + p.getAbsolutePath() +
- ", expected " + Version.text;
- }
- 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.DEVELOPMENT.equals(version)) {
- // MessageUtil.info(holder,
- // "running with development version of aspectjrt.jar in " +
- // p.getAbsolutePath());
- return null;
- } else if (!Version.text.equals(version)) {
- return "bad version number found in " + p.getAbsolutePath() +
- " expected " + Version.text + " found " + version;
- }
- } catch (IOException ioe) {
- return "bad jar file found in " + p.getAbsolutePath() + " error: " + ioe;
- }
- return null;
- } else {
- // might want to catch other classpath errors
- }
- }
-
- return "couldn't find aspectjrt.jar on classpath, checked: " + makeClasspathString();
- }
-
-
- public String toString() {
- StringBuffer buf = new StringBuffer();
- 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 IHierarchy getStructureModel() {
- return structureModel;
- }
-
- 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[])
- */
- public String getOutputClassFileName(char[] eclipseClassFileName, CompilationResult result) {
- String filename = new String(eclipseClassFileName);
- filename = filename.replace('/', File.separatorChar) + ".class";
- File destinationPath = buildConfig.getOutputDir();
- 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)
- */
- public ICompilerAdapter getAdapter(org.eclipse.jdt.internal.compiler.Compiler forCompiler) {
- // complete compiler config and return a suitable adapter...
- 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);
-
- return new AjCompilerAdapter(forCompiler,batchCompile,bcelWorld,bcelWeaver,
- factory,
- getInterimResultRequestor(),
- progressListener,
- this, // IOutputFilenameProvider
- this, // IBinarySourceProvider
- state.binarySourceFiles,
- state.resultsFromFile.values(),
- buildConfig.isNoWeave());
- }
-
- /* (non-Javadoc)
- * @see org.aspectj.ajdt.internal.compiler.IBinarySourceProvider#getBinarySourcesForThisWeave()
- */
- 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;
- }
- } // class AjBuildManager
|