]> source.dussan.org Git - aspectj.git/commitdiff
test and fix for 166580: multiple output locations and incremental compilation
authoraclement <aclement>
Tue, 9 Jan 2007 09:37:29 +0000 (09:37 +0000)
committeraclement <aclement>
Tue, 9 Jan 2007 09:37:29 +0000 (09:37 +0000)
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/CompilationResultDestinationManager.java
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjState.java
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/IncrementalStateManager.java

index 5c7c30d4ad9405aa894247af124b783bff28760c..5173dbe23a16fec2d386033efa69d315b9cd627d 100644 (file)
@@ -12,6 +12,7 @@
 package org.aspectj.ajdt.internal.compiler;
 
 import java.io.File;
+import java.util.List;
 
 /**
  * acts as a bridge from ajde's OutputLocationManager interface to the compiler internals
@@ -43,4 +44,15 @@ public interface CompilationResultDestinationManager {
         */
        File getOutputLocationForResource(File resource);
        
+       /**
+        * Return a list of all output locations handled by this OutputLocationManager
+        */
+       List /*File*/ getAllOutputLocations();
+       
+       /**
+        * Return the default output location (for example, <my_project>/bin). This is
+        * where classes which are on the inpath will be placed.
+        */
+       File getDefaultOutputLocation();
+       
 }
index c8e670028553031a8907cfffe859aeaad5f8c558..4d71345d8261b72925691e6058605ef99c04928e 100644 (file)
@@ -29,6 +29,7 @@ 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;
@@ -95,8 +96,8 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc
        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";
-       static final boolean COPY_INPATH_DIR_RESOURCES = false;
-    // AJDT doesn't want this check, so Main enables it.
+       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;
@@ -554,9 +555,16 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc
        private void writeManifest () throws IOException {
                Manifest manifest = getWeaver().getManifest(false);
                if (manifest != null && zos == null) {
-                       OutputStream fos = 
-                               FileUtil.makeOutputStream(new File(buildConfig.getOutputDir(),MANIFEST_NAME));
-                       manifest.write(fos);    
+                       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;
+                       OutputStream fos = FileUtil.makeOutputStream(new File(outputDir,MANIFEST_NAME));
+                       manifest.write(fos);
                        fos.close();
                }
        }
@@ -583,36 +591,91 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc
                if (ignoreOutxml) return;
                
                String filename = buildConfig.getOutxmlName();
-//             System.err.println("? AjBuildManager.writeOutxmlFile() outxml=" + filename);
-//             System.err.println("? AjBuildManager.writeOutxmlFile() outputDir=" + buildConfig.getOutputDir());
-               
+               // 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 {
+                               OutputStream fos = FileUtil.makeOutputStream(new File(outputDir, filename));
+                               fos.write(baos.toByteArray());
+                               fos.close();
+                       }
+               }
+       }
+
+       private ByteArrayOutputStream getOutxmlContents(List aspectNames) {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                PrintStream ps = new PrintStream(baos);
                ps.println("<aspectj>");
                ps.println("<aspects>");
-               if (state.getAspectNames() != null) {
-                       for (Iterator i = state.getAspectNames().iterator(); i.hasNext();) {
-                               String name = (String)i.next();
+               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;
+       }
 
-               if (zos != null) {
-                       ZipEntry newEntry = new ZipEntry(filename);
-                       
-                       zos.putNextEntry(newEntry);
-                       zos.write(baos.toByteArray());
-                       zos.closeEntry();
+       /**
+        * 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 {
-                       OutputStream fos = 
-                               FileUtil.makeOutputStream(new File(buildConfig.getOutputDir(),filename));
-                       fos.write(baos.toByteArray());
-                       fos.close();
+                       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() {
@@ -725,15 +788,20 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc
                                bcelWeaver.addLibraryJarFile(f);
                        }
                }
-               
-//             String lintMode = buildConfig.getLintMode();
-               
-               
-               
-               //??? incremental issues
-               for (Iterator i = buildConfig.getInJars().iterator(); i.hasNext(); ) {
-                       File inJar = (File)i.next();
-                       List unwovenClasses = bcelWeaver.addJarFile(inJar, buildConfig.getOutputDir(),false);
+
+               // 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);
                }
                
@@ -742,7 +810,7 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc
                        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);
+                               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
@@ -750,8 +818,7 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc
                                // 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());
+                                       UnwovenClassFile ucf = bcelWeaver.addClassFile(binSrcs[j], inPathElement, outputDir);
                                        List ucfl = new ArrayList();
                                        ucfl.add(ucf);
                                        state.recordBinarySource(binSrcs[j].getPath(),ucfl);
@@ -955,7 +1022,7 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc
                                                        } else {
                                                                writeZipEntry(classFile,filename);
                                                        }
-                                                       if (shouldAddAspectName) addAspectName(classname);
+                                                       if (shouldAddAspectName) addAspectName(classname, unitResult.getFileName());
                                                } catch (IOException ex) {
                                                        IMessage message = EclipseAdapterUtils.makeErrorMessage(
                                                                        new String(unitResult.fileName),
@@ -1012,16 +1079,17 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc
                                zos.closeEntry();
                        }
                        
-                       private void addAspectName (String name) {
+                       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.getAspectNames() == null) {
-                                               state.initializeAspectNamesList();
+                                       if (state.getAspectNamesToFileNameMap() == null) {
+                                               state.initializeAspectNamesToFileNameMap();
                                        }
-                                       if (!state.getAspectNames().contains(name)) {
-                                               state.getAspectNames().add(name);
+                                       if (!state.getAspectNamesToFileNameMap().containsKey(name)) {
+                                               state.getAspectNamesToFileNameMap().put(name,
+                                                               fileContainingAspect);
                                        }
                                }
                        }
@@ -1188,6 +1256,10 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc
                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();
index 24baedad539101f131f147810c9927a86718e7cd..103a3b89957ae8424b7967003fa6b325079ee673 100644 (file)
@@ -156,10 +156,17 @@ public class AjState {
         */
        private Map/*<String, File>*/ classesFromName = new HashMap();
        
+       /**
+        * Populated by AjBuildManager to record the aspects with the file name in which they're
+        * contained. This is later used when writing the outxml file in AjBuildManager. Need
+        * to record the file name because want to write an outxml file for each of the output
+        * directories and in order to ask the OutputLocationManager for the output location
+        * for a given aspect we need the file in which it is contained.
+        */
+       private Map /*<String, char[]>*/ aspectsFromFileNames;
        
        private List/*File*/ compiledSourceFiles = new ArrayList();
        private List/*String*/ resources = new ArrayList();
-       private List/*String*/ aspectNames;
        
        // these are references created on a particular compile run - when looping round in 
        // addAffectedSourceFiles(), if some have been created then we look at which source files
@@ -193,7 +200,7 @@ public class AjState {
        /**
         * Returns false if a batch build is needed.
         */
-       boolean prepareForNextBuild(AjBuildConfig newBuildConfig) {
+       public boolean prepareForNextBuild(AjBuildConfig newBuildConfig) {
                currentBuildTime = System.currentTimeMillis();
 
                if (!maybeIncremental()) {
@@ -384,30 +391,50 @@ public class AjState {
 
        private boolean pathChange(AjBuildConfig oldConfig, AjBuildConfig newConfig) {
                boolean changed = false;
+               
+               List oldOutputLocs = getOutputLocations(oldConfig);
+               
                List oldClasspath = oldConfig.getClasspath();
                List newClasspath = newConfig.getClasspath();
                if (stateListener!=null) stateListener.aboutToCompareClasspaths(oldClasspath,newClasspath);
-               if (changed(oldClasspath,newClasspath,true,oldConfig.getOutputDir())) return true;
+               if (changed(oldClasspath,newClasspath,true,oldOutputLocs)) return true;
                List oldAspectpath = oldConfig.getAspectpath();
                List newAspectpath = newConfig.getAspectpath();
-               if (changed(oldAspectpath,newAspectpath,true,oldConfig.getOutputDir())) return true;
+               if (changed(oldAspectpath,newAspectpath,true,oldOutputLocs)) return true;
                List oldInJars = oldConfig.getInJars();
                List newInJars = newConfig.getInJars();
-               if (changed(oldInJars,newInJars,false,oldConfig.getOutputDir())) return true;
+               if (changed(oldInJars,newInJars,false,oldOutputLocs)) return true;
                List oldInPath = oldConfig.getInpath();
                List newInPath = newConfig.getInpath();
-               if (changed(oldInPath, newInPath,false,oldConfig.getOutputDir())) return true;
+               if (changed(oldInPath, newInPath,false,oldOutputLocs)) return true;
                return changed;
        }
        
-       private boolean changed(List oldPath, List newPath, boolean checkClassFiles, File oldOutputLocation) {
+       private List /*File*/ getOutputLocations(AjBuildConfig config) {
+               List outputLocs = new ArrayList();
+               if (config.getOutputDir() != null) {
+                       try {
+                               outputLocs.add(config.getOutputDir().getCanonicalFile());
+                       } catch (IOException e) {}
+               }
+               if (config.getCompilationResultDestinationManager() != null) {
+                       List dirs = config.getCompilationResultDestinationManager().getAllOutputLocations();
+                       for (Iterator iterator = dirs.iterator(); iterator.hasNext();) {
+                               File f = (File) iterator.next();
+                               try {
+                                       if (!outputLocs.contains(f.getCanonicalFile())) {
+                                               outputLocs.add(f.getCanonicalFile());
+                                       }
+                                       
+                               } catch (IOException e) {}
+                       }
+               }
+               return outputLocs;
+       }
+       
+       private boolean changed(List oldPath, List newPath, boolean checkClassFiles, List outputLocs) { 
                if (oldPath == null) oldPath = new ArrayList();
                if (newPath == null) newPath = new ArrayList();
-               try {
-                       if (oldOutputLocation != null) {
-                               oldOutputLocation = oldOutputLocation.getCanonicalFile();
-                       }
-               } catch(IOException ex) { /* we did our best...*/ }
                if (oldPath.size() != newPath.size()) {
                        return true;
                }
@@ -425,10 +452,20 @@ public class AjState {
                        if (f.exists() && !f.isDirectory() && (f.lastModified() >= lastSuccessfulBuildTime)) {
                                return true;
                        }
-                       if (f.exists() && f.isDirectory() && checkClassFiles && !(f.equals(oldOutputLocation))) {
-                               boolean b= classFileChangedInDirSinceLastBuild(f);
-                               if (b && stateListener!=null) stateListener.detectedClassChangeInThisDir(f);
-                               if (b) return true;
+                       if (f.exists() && f.isDirectory() && checkClassFiles) {
+                               boolean foundMatch = false;
+                               for (Iterator iterator = outputLocs.iterator(); iterator
+                                               .hasNext();) {
+                                       File dir = (File) iterator.next();
+                                       if (f.equals(dir)) {
+                                               foundMatch = true;
+                                       }
+                               }
+                               if (!foundMatch) {
+                                       boolean b= classFileChangedInDirSinceLastBuild(f);
+                                       if (b && stateListener!=null) stateListener.detectedClassChangeInThisDir(f);
+                                       if (b) return true;                                     
+                               }
                        }
                }
                return false;
@@ -447,7 +484,9 @@ public class AjState {
        //                      addDependentsOf(file);
        //              }
                        
-                       thisTime.addAll(addedFiles);    
+                       if(addedFiles != null) {
+                               thisTime.addAll(addedFiles);                                    
+                       }
                        
                        deleteClassFiles();
                        deleteResources();
@@ -514,11 +553,19 @@ public class AjState {
         }
            for (Iterator iter = resources.iterator(); iter.hasNext();) {
             String resource = (String) iter.next();
-            new File(buildConfig.getOutputDir(),resource).delete();            
+                       List outputDirs = getOutputLocations(buildConfig);
+                       for (Iterator iterator = outputDirs.iterator(); iterator.hasNext();) {
+                               File dir = (File) iterator.next();
+                               File f = new File(dir,resource);
+                               if (f.exists()) {
+                                       f.delete();
+                               }                               
+                       }
         }
        }
        
        private void deleteClassFiles() {
+               if (deletedFiles == null) return;
                for (Iterator i = deletedFiles.iterator(); i.hasNext(); ) {
                        File deletedFile = (File)i.next();
                        addDependentsOf(deletedFile);
@@ -571,21 +618,29 @@ public class AjState {
                // oldResources need to be deleted...
                for (Iterator iter = oldResources.iterator(); iter.hasNext();) {
                        String victim = (String) iter.next();
-                       File f = new File(buildConfig.getOutputDir(),victim);
-                       if (f.exists()) {
-                               f.delete();
-                       }                       
-                       resources.remove(victim);
+                       List outputDirs = getOutputLocations(buildConfig);
+                       for (Iterator iterator = outputDirs.iterator(); iterator.hasNext();) {
+                               File dir = (File) iterator.next();
+                               File f = new File(dir,victim);
+                               if (f.exists()) {
+                                       f.delete();
+                               }                       
+                               resources.remove(victim);                               
+                       }
                }
        }
        
        private void maybeDeleteResource(String resName, List oldResources) {
                if (resources.contains(resName)) {
                        oldResources.remove(resName);
-                       File source = new File(buildConfig.getOutputDir(),resName);
-                       if ((source != null) && (source.exists()) &&
-                           (source.lastModified() >= lastSuccessfulBuildTime)) {
-                               resources.remove(resName); // will ensure it is re-copied
+                       List outputDirs = getOutputLocations(buildConfig);
+                       for (Iterator iterator = outputDirs.iterator(); iterator.hasNext();) {
+                               File dir = (File) iterator.next();
+                               File source = new File(dir,resName);
+                               if ((source != null) && (source.exists()) &&
+                                               (source.lastModified() >= lastSuccessfulBuildTime)) {
+                                       resources.remove(resName); // will ensure it is re-copied
+                               }
                        }
                }               
        }
@@ -617,7 +672,14 @@ public class AjState {
        private UnwovenClassFile createUnwovenClassFile(AjBuildConfig.BinarySourceFile bsf) {
                UnwovenClassFile ucf = null;
                try {
-                       ucf = weaver.addClassFile(bsf.binSrc, bsf.fromInPathDirectory, buildConfig.getOutputDir());
+                       File outputDir = buildConfig.getOutputDir();
+                       if (buildConfig.getCompilationResultDestinationManager() != null) {
+                               // createUnwovenClassFile is called only for classes that are on the inpath,
+                               // all inpath classes are put in the defaultOutputLocation, therefore,
+                               // this is the output dir
+                               outputDir = buildConfig.getCompilationResultDestinationManager().getDefaultOutputLocation();
+                       }
+                       ucf = weaver.addClassFile(bsf.binSrc, bsf.fromInPathDirectory, outputDir);
                } catch(IOException ex) {
                        IMessage msg = new Message("can't read class file " + bsf.binSrc.getPath(),
                                                                           new SourceLocation(bsf.binSrc,0),false);
@@ -1031,7 +1093,8 @@ public class AjState {
     }
        
        protected void addAffectedSourceFiles(List addTo, List lastTimeSources) {
-               if (qualifiedStrings.isEmpty() && simpleStrings.isEmpty()) return;
+               if (qualifiedStrings == null || simpleStrings == null ||
+                               (qualifiedStrings.isEmpty() && simpleStrings.isEmpty())) return;
                if (listenerDefined()) getListener().recordDecision("Examining whether any other files now need compilation based just compiling: '"+stringifyList(lastTimeSources)+"'");
                // the qualifiedStrings are of the form 'p1/p2' & the simpleStrings are just 'X'
                char[][][] qualifiedNames = ReferenceCollection.internQualifiedNames(makeStringSet(qualifiedStrings));
@@ -1247,12 +1310,12 @@ public class AjState {
                buildManager.setStructureModel(null);
        }
        
-       public List getAspectNames() {
-               return aspectNames;
+       public Map getAspectNamesToFileNameMap() {
+               return aspectsFromFileNames;
        }
-       
-       public void initializeAspectNamesList() {
-               this.aspectNames = new LinkedList();
+
+       public void initializeAspectNamesToFileNameMap() {
+               this.aspectsFromFileNames = new HashMap();
        }
        
        // Will allow us to record decisions made during incremental processing, hopefully aid in debugging
@@ -1267,4 +1330,8 @@ public class AjState {
        public IBinaryType checkPreviousBuild(String name) {
                return (IBinaryType)resolvedTypeStructuresFromLastBuild.get(name);
        }
+       
+       public AjBuildManager getAjBuildManager() {
+               return buildManager;
+       }
 }
index b9f2c966243b8aa11046430fd0fa1bef8a8b3078..19f481eabbe0930c5d801b1758ad171889a59976 100644 (file)
@@ -15,8 +15,10 @@ import java.io.File;
 import java.util.Collection;
 import java.util.Hashtable;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Set;
 
+import org.aspectj.ajdt.internal.compiler.CompilationResultDestinationManager;
 import org.aspectj.asm.AsmManager;
 
 
@@ -77,15 +79,28 @@ public class IncrementalStateManager {
                                continue;
                        }
                        File outputDir = ajbc.getOutputDir();
-                       if (outputDir == null) {
+                       if (outputDir != null && outputDir.equals(location)) {
+                               if (debugIncrementalStates) System.err.println("< findStateManagingOutputLocation("+location+") returning "+element);
+                               return element;                         
+                       } 
+                       CompilationResultDestinationManager outputManager = ajbc.getCompilationResultDestinationManager();
+                       if (outputManager != null) {
+                               List outputDirs = outputManager.getAllOutputLocations();
+                               for (Iterator iterator = outputDirs.iterator(); iterator
+                                               .hasNext();) {
+                                       File dir = (File) iterator.next();
+                                       if (dir.equals(location)) {
+                                               if (debugIncrementalStates) System.err.println("< findStateManagingOutputLocation("+location+") returning "+element);
+                                               return element;                         
+                                       }
+                               }
+                       }
+                       if (outputDir == null && outputManager == null) {
                                // FIXME why can it ever be null? due to using outjar?
-                               if (debugIncrementalStates) System.err.println("  output directory for "+ajbc+" is null");
+                               if (debugIncrementalStates) System.err.println("  output directory and output location manager for "+ajbc+" are null");
                                continue;
                        }
-                       if (outputDir.equals(location)) {
-                               if (debugIncrementalStates) System.err.println("< findStateManagingOutputLocation("+location+") returning "+element);
-                               return element;
-                       }
+
                }
                if (debugIncrementalStates) System.err.println("< findStateManagingOutputLocation("+location+") returning null");
                return null;