Logo Search packages:      
Sourcecode: aspectj version File versions  Download package

AjBuildManager.java

/* *******************************************************************
 * 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 v1.0 
 * which accompanies this distribution and is available at 
 * http://www.eclipse.org/legal/epl-v10.html 
 *  
 * 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.Iterator;
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.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.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.env.ICompilationUnit;
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.lookup.LookupEnvironment;
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() {
            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<UCF> */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 main 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;
      }

      /** @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();
            int phase = isFullBuild ? CompilationAndWeavingContext.BATCH_BUILD : CompilationAndWeavingContext.INCREMENTAL_BUILD;
            ContextToken ct = CompilationAndWeavingContext.enteringPhase(phase, buildConfig);
            try {
                  if (isFullBuild) {
                        this.state = new AjState(this);
                  }

                  this.state.setCouldBeSubsequentIncrementalBuild(this.environmentSupportsIncrementalCompilation);

                  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) {
                              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()) {
                        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)
                        getBcelWorld().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 (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()) {
                              writeDirectory(filename, jarFile);
                        } else if (acceptResource(filename, false)) {
                              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, true))
                  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();
            }
      }

      /**
       * 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.indexOf("/CVS/") != -1) || (resourceName.endsWith("/CVS"))
                        || (resourceName.endsWith(".class")) || (resourceName.startsWith(".svn/"))
                        || (resourceName.indexOf("/.svn/") != -1) || (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 (Iterator iterator = outputDirs.iterator(); iterator.hasNext();) {
                  Map.Entry entry = (Map.Entry) iterator.next();
                  File outputDir = (File) entry.getKey();
                  List aspects = (List) 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("<aspectj>");
            ps.println("<aspects>");
            if (aspectNames != null) {
                  for (Iterator i = aspectNames.iterator(); i.hasNext();) {
                        String name = (String) i.next();
                        ps.println("<aspect name=\"" + name + "\"/>");
                  }
            }
            ps.println("</aspects>");
            ps.println("</aspectj>");
            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 /* File --> List (String) */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 (Iterator iterator = keys.iterator(); iterator.hasNext();) {
                              String name = (String) iterator.next();
                              aspectNames.add(name);
                        }
                  }
                  outputDirsToAspects.put(outputDir, aspectNames);
            } else {
                  List outputDirs = buildConfig.getCompilationResultDestinationManager().getAllOutputLocations();
                  for (Iterator iterator = outputDirs.iterator(); iterator.hasNext();) {
                        File outputDir = (File) iterator.next();
                        outputDirsToAspects.put(outputDir, new ArrayList());
                  }
                  Set entrySet = aspectNamesToFileNames.entrySet();
                  for (Iterator iterator = entrySet.iterator(); iterator.hasNext();) {
                        Map.Entry entry = (Map.Entry) iterator.next();
                        String aspectName = (String) entry.getKey();
                        char[] fileName = (char[]) 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 = "<root>";

            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<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);
      // }
      // }

      // 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.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, buildConfig.getOptions().warningThreshold);
            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.getLintSpecFile() != null) {
                  bcelWorld.getLint().setFromProperties(buildConfig.getLintSpecFile());
            }

            for (Iterator i = buildConfig.getAspectpath().iterator(); i.hasNext();) {
                  File f = (File) i.next();
                  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 (Iterator i = buildConfig.getInJars().iterator(); i.hasNext();) {
                  File inJar = (File) i.next();
                  List unwovenClasses = bcelWeaver.addJarFile(inJar, outputDir, false);
                  state.recordBinarySource(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, 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 (int j = 0; j < binSrcs.length; j++) {
                              UnwovenClassFile ucf = bcelWeaver.addClassFile(binSrcs[j], inPathElement, outputDir);
                              List ucfl = new ArrayList();
                              ucfl.add(ucf);
                              state.recordBinarySource(binSrcs[j].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<classpaths.length;i++) classpathModes[i]=ClasspathDirectory.BINARY;
            return new FileSystem(classpaths, filenames, defaultEncoding, ClasspathLocation.BINARY);
      }

      public IProblemFactory getProblemFactory() {
            return new DefaultProblemFactory(Locale.getDefault());
      }

      /*
       * Build the set of compilation source units
       */
      public CompilationUnit[] getCompilationUnits(String[] filenames) {
            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;
            }

            for (int i = 0; i < fileCount; i++) {
                  units[i] = new CompilationUnit(null, filenames[i], defaultEncoding);
            }
            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(Collection 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 (Iterator fIterator = files.iterator(); fIterator.hasNext();) {
                  File f = (File) fIterator.next();
                  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] = (String) cps.get(i);
                  }
                  environment = new StatefulNameEnvironment(getLibraryAccess(classpaths, filenames), state.getClassNameToFileMap(), state);
                  state.setNameEnvironment(environment);
            } else {
                  ((StatefulNameEnvironment) environment).update(state.getClassNameToFileMap(), state.deltaAddedClasses);
                  state.deltaAddedClasses.clear();
            }

            org.aspectj.ajdt.internal.compiler.CompilerAdapter.setCompilerAdapterFactory(this);
            org.aspectj.org.eclipse.jdt.internal.compiler.Compiler compiler = new org.aspectj.org.eclipse.jdt.internal.compiler.Compiler(
                        environment, DefaultErrorHandlingPolicies.proceedWithAllProblems(), buildConfig.getOptions().getMap(),
                        getBatchRequestor(), getProblemFactory());

            compiler.options.produceReferenceInfo = true; // TODO turn off when not needed

            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() {
                  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
                        boolean hasErrors = unitResult.hasErrors();
                        if (!hasErrors || proceedOnError()) {
                              Collection classFiles = unitResult.compiledTypes.values();
                              boolean shouldAddAspectName = (buildConfig.getOutxmlName() != null);
                              for (Iterator iter = classFiles.iterator(); iter.hasNext();) {
                                    ClassFile classFile = (ClassFile) iter.next();
                                    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);
                                                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 (int i = 0; i < problems.length; i++) {
                                    IMessage message = EclipseAdapterUtils.makeMessage(unitResult.compilationUnit, problems[i], 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 "";
            StringBuffer buf = new StringBuffer();
            boolean first = true;
            for (Iterator it = buildConfig.getFullClasspath().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.
       */
      private 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.getFullClasspath() == null)
                  return "no classpath specified";

            String ret = null;
            for (Iterator it = buildConfig.getFullClasspath().iterator(); it.hasNext();) {
                  File p = new File((String) it.next());
                  // 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.text;
                                    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.DEVELOPMENT.equals(version)) {
                                    // MessageUtil.info(holder,
                                    // "running with development version of aspectjrt.jar in " +
                                    // p.getAbsolutePath());
                                    return null;
                              } else if (!Version.text.equals(version)) {
                                    ret = "bad version number found in " + p.getAbsolutePath() + " expected " + Version.text + " 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().indexOf("org.aspectj.runtime") != -1) {
                        // 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);
      }

      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 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[])
       */
      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)
       */
      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(), state);
            } else {
                  return new AjCompilerAdapter(forCompiler, batchCompile, getBcelWorld(), getWeaver(), factory,
                              getInterimResultRequestor(), progressListener,
                              this, // IOutputFilenameProvider
                              this, // IBinarySourceProvider
                              state.getBinarySourceMap(), buildConfig.isTerminateAfterCompilation(), buildConfig.getProceedOnError(),
                              buildConfig.isNoAtAspectJAnnotationProcessing(), 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()
       */
      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 {

            public String formatEntry(int phaseId, Object data) {
                  StringBuffer sb = new StringBuffer();
                  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 (Iterator iter = classpath.iterator(); iter.hasNext();) {
                        sb.append(iter.next().toString());
                        sb.append(File.pathSeparator);
                  }
                  return sb.toString();
            }

      }

      public boolean wasFullBuild() {
            return wasFullBuild;
      }
}

Generated by  Doxygen 1.6.0   Back to index