]> source.dussan.org Git - aspectj.git/commitdiff
245566: incremental magic
authoraclement <aclement>
Fri, 29 Aug 2008 00:00:02 +0000 (00:00 +0000)
committeraclement <aclement>
Fri, 29 Aug 2008 00:00:02 +0000 (00:00 +0000)
ajde.core/src/org/aspectj/ajde/core/ICompilerConfiguration.java
ajde.core/src/org/aspectj/ajde/core/internal/AjdeCoreBuildManager.java

index 10562cca02f4530c8869c6314fffe26ae82ad2ba..5b3d8c8d99eca98140243cc09ed73c21227edb9a 100644 (file)
@@ -14,92 +14,96 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.aspectj.ajdt.internal.core.builder.CompilerConfigurationChangeFlags;
+
 /**
- * Interface that contains all the configuration required for the 
- * compiler to be able to perform a build
+ * Interface that contains all the configuration required for the compiler to be able to perform a build
  */
-public interface ICompilerConfiguration {
-       
+public interface ICompilerConfiguration extends CompilerConfigurationChangeFlags {
+
        /**
-        * Returns the table of the current custom java options. 
+        * Returns the table of the current custom java options.
         * <p>
-        * For a complete description of the configurable options, see 
-        * {@link org.aspectj.ajde.core.JavaOptions#getDefaultJavaOptions}
+        * For a complete description of the configurable options, see {@link org.aspectj.ajde.core.JavaOptions#getDefaultJavaOptions}
         * or {@link org.aspectj.org.eclipse.jdt.core.IJavaProject#getOptions(boolean)}
         * </p>
         * 
-        * @return table of current settings of all options 
-        *   (key type: <code>String</code>; value type: <code>String</code>)
+        * @return table of current settings of all options (key type: <code>String</code>; value type: <code>String</code>)
         * @see org.aspectj.ajde.core.JavaOptions#getDefaultJavaOptions or
-        * org.aspectj.org.eclipse.jdt.core.IJavaProject#getOptions(boolean)
+        *      org.aspectj.org.eclipse.jdt.core.IJavaProject#getOptions(boolean)
         */
-       public Map /*String --> String */getJavaOptionsMap();
-       
+       public Map /* String --> String */getJavaOptionsMap();
+
        /**
-        * The non-standard options, typically prefaced with -X when used 
-        * with a command line compiler. The default is no non-standard 
-        * options. Options should be separated by a space, for example 
-        * "-showWeaveInfo -XnoInline"
+        * The non-standard options, typically prefaced with -X when used with a command line compiler. The default is no non-standard
+        * options. Options should be separated by a space, for example "-showWeaveInfo -XnoInline"
         */
        public String getNonStandardOptions();
-       
+
        /**
         * @return a list of those files to include in the build
         */
-    public List /*String*/ getProjectSourceFiles();
-
-    /**
-     * Return a subset of those files we'd get on getProjectSourceFiles() - the subset that have changed since
-     * the last build.  If someone else has already worked out what needs rebuilding, we don't need to do it again
-     * by checking all of the projectSourceFiles(). Returning an empty list means nothing has changed, returning null
-     * means you have no idea what changed and the compiler should work it out.
-     * 
-     * @return a subset of those files that would be returned on getProjectSourceFiles() that have actually *changed*
-     */
-    public List /*String*/ getProjectSourceFilesChanged();
-    
-    /**
-     * @return the classpath to use
-     */
-    public String getClasspath();
-
-    /**
-     * @return the IOutputLocationManager associated with this 
-     * compiler configuration
-     */
-    public IOutputLocationManager getOutputLocationManager();
+       public List /* String */getProjectSourceFiles();
+
+       /**
+        * Return a subset of those files we'd get on getProjectSourceFiles() - the subset that have changed since the last build. If
+        * someone else has already worked out what needs rebuilding, we don't need to do it again by checking all of the
+        * projectSourceFiles(). Returning an empty list means nothing has changed, returning null means you have no idea what changed
+        * and the compiler should work it out.
+        * 
+        * @return a subset of those files that would be returned on getProjectSourceFiles() that have actually *changed*
+        */
+       public List /* File */getProjectSourceFilesChanged();
+
+       /**
+        * @return the classpath to use
+        */
+       public String getClasspath();
+
+       /**
+        * @return the IOutputLocationManager associated with this compiler configuration
+        */
+       public IOutputLocationManager getOutputLocationManager();
+
+       /**
+        * @return the set of input path elements for this compilation. Set members should be of the type java.io.File. An empty set or
+        *         null is acceptable for this option. From -inpath
+        */
+       public Set /* java.io.File */getInpath();
 
        /**
-        * @return the set of input path elements for this compilation.
-        * Set members should be of the type java.io.File.
-        * An empty set or null is acceptable for this option.
-        * From -inpath
+        * @return the output jar file for the compilation results. Return null to leave classfiles unjar'd in output directory From
+        *         -outjar
         */
-    public Set /*java.io.File*/ getInpath();
-    
+       public String getOutJar();
+
        /**
-        * @return the output jar file for the compilation results.
-        * Return null to leave classfiles unjar'd in output directory
-        * From -outjar
+        * @return the set of aspect jar files to be used for the compilation. Returning null or an empty set disables this option. Set
+        *         members should be of type java.io.File. From -aspectpath
         */
-    public String getOutJar();
+       public Set /* java.io.File */getAspectPath();
 
        /**
-        * @return the set of aspect jar files to be used for the compilation.
-        * Returning null or an empty set disables this option. Set members
-        * should be of type java.io.File.
-        * From -aspectpath
+        * Get the set of non-Java resources for this compilation. Set members should be of type java.io.File. An empty set or null is
+        * acceptable for this option.
+        * 
+        * @return map from unique resource name to absolute path to source resource (String to File)
         */
-    public Set /*java.io.File*/ getAspectPath();
-    
+       public Map /* String --> java.io.File */getSourcePathResources();
+
        /**
-        * Get the set of non-Java resources for this compilation.
-        * Set members should be of type java.io.File.
-        * An empty set or null is acceptable for this option.
+        * Returns a set of bit flags indicating what has changed in the configuration since it was previously read. This allows the
+        * compiler to avoid repeating computation for values that are the same as before.
         * 
-        * @return map from unique resource name to absolute path to source 
-        * resource (String to File)
+        * @return set of bit flags, see the constants in @link {@link CompilerConfigurationChangeFlags}. If unsure return EVERYTHING
+        */
+       public int getConfigurationChanges();
+
+       /**
+        * Called by AspectJ once it has processed the configuration object and is ready to do a build. The configuration object may or
+        * may not be interested in this event. It probably will be if it is correctly tracking changes and answering
+        * getConfigurationChanges() with something other than EVERYTHING.
         */
-    public Map /*String --> java.io.File */getSourcePathResources();
-       
+       public void configurationRead();
+
 }
index c1075c64d3681391ffa92c94f1438a2197ee7fc0..850fde2e77146703af9c969ae81b693aa442f916 100644 (file)
@@ -41,175 +41,189 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.aspectj.util.LangUtil;
 
 /**
- * Build Manager which drives the build for a given AjCompiler.
- * Tools call build on the AjCompiler which drives this.
+ * Build Manager which drives the build for a given AjCompiler. Tools call build on the AjCompiler which drives this.
  */
 public class AjdeCoreBuildManager {
 
        private AjCompiler compiler;
-       
-    private AjdeCoreBuildNotifierAdapter currNotifier = null;
+
+       private AjdeCoreBuildNotifierAdapter currNotifier = null;
        private AjBuildManager ajBuildManager;
        private IMessageHandler msgHandlerAdapter;
-       
+
        public AjdeCoreBuildManager(AjCompiler compiler) {
                this.compiler = compiler;
                msgHandlerAdapter = new AjdeCoreMessageHandlerAdapter(compiler.getMessageHandler());
                ajBuildManager = new AjBuildManager(msgHandlerAdapter);
                ajBuildManager.environmentSupportsIncrementalCompilation(true);
-               // this static information needs to be set to ensure 
+               // this static information needs to be set to ensure
                // incremental compilation works correctly
-               IncrementalStateManager.recordIncrementalStates=true;
-               IncrementalStateManager.debugIncrementalStates=false;
+               IncrementalStateManager.recordIncrementalStates = true;
+               IncrementalStateManager.debugIncrementalStates = false;
                AsmManager.attemptIncrementalModelRepairs = true;
        }
-       
+
        // XXX hideous, should not be Object
        public void setCustomMungerFactory(Object o) {
                ajBuildManager.setCustomMungerFactory(o);
        }
-       
+
        public Object getCustomMungerFactory() {
                return ajBuildManager.getCustomMungerFactory();
        }
-       
+
        /**
         * @param buildFresh - true if want to force a full build, false otherwise
         */
        public void doBuild(boolean buildFresh) {
-               if (!buildFresh) {
-                       buildFresh = updateAsmManagerInformation();
-               }
-        try {
-               startNotifiers();
-               
-               // record the options passed to the compiler
-                       handleMessage(new Message(getFormattedOptionsString(),IMessage.INFO,null,null));
+               if (!buildFresh) {
+                       buildFresh = updateAsmManagerInformation();
+               }
+               try {
+                       startNotifiers();
+
+                       // record the options passed to the compiler
+                       if (!compiler.getMessageHandler().isIgnoring(IMessage.INFO)) {
+                               handleMessage(new Message(getFormattedOptionsString(), IMessage.INFO, null, null));
+                       }
 
                        CompilationAndWeavingContext.reset();
 
-                       AjBuildConfig buildConfig = genAjBuildConfig();
-                       if (buildConfig == null) return;
-
-            if (buildFresh) {
-               ajBuildManager.batchBuild(buildConfig,msgHandlerAdapter); 
-            } else {
-                               ajBuildManager.incrementalBuild(buildConfig,msgHandlerAdapter);                         
-            }
-/*                     
-            if (buildFresh) {
-                       AjBuildConfig buildConfig = genAjBuildConfig();
-                       if (buildConfig == null) return;
-               ajBuildManager.batchBuild(buildConfig,msgHandlerAdapter); 
-            } else {
-               AjBuildConfig buildConfig = ajBuildManager.getState().getBuildConfig();
-               
-                               ajBuildManager.incrementalBuild(buildConfig,msgHandlerAdapter);                         
-            }
-*/
-                       IncrementalStateManager.recordSuccessfulBuild(compiler.getId(),ajBuildManager.getState());
-            
-        } catch (ConfigParser.ParseException pe) {
-               handleMessage(new Message("Config file entry invalid, file: " + pe.getFile().getPath() 
-                       + ", line number: " + pe.getLine(),IMessage.WARNING,null,null));
+                       if (buildFresh) {
+                               AjBuildConfig buildConfig = genAjBuildConfig();
+                               if (buildConfig == null) {
+                                       return;
+                               }
+                               ajBuildManager.batchBuild(buildConfig, msgHandlerAdapter);
+                       } else {
+                               // Only rebuild the config object if the configuration has changed
+                               AjBuildConfig buildConfig = null;
+                               ICompilerConfiguration compilerConfig = compiler.getCompilerConfiguration();
+                               int changes = compilerConfig.getConfigurationChanges();
+                               if (changes != ICompilerConfiguration.NO_CHANGES) {
+                                       buildConfig = genAjBuildConfig();
+                                       if (buildConfig == null) {
+                                               return;
+                                       }
+                               } else {
+                                       buildConfig = ajBuildManager.getState().getBuildConfig();
+                                       buildConfig.setChanged(changes); // pass it through for the state to use it when making decisions
+                                       buildConfig.setModifiedFiles(compilerConfig.getProjectSourceFilesChanged());
+                                       compilerConfig.configurationRead();
+                               }
+                               ajBuildManager.incrementalBuild(buildConfig, msgHandlerAdapter);
+                       }
+                       /*
+                        * if (buildFresh) { AjBuildConfig buildConfig = genAjBuildConfig(); if (buildConfig == null) return;
+                        * ajBuildManager.batchBuild(buildConfig,msgHandlerAdapter); } else { AjBuildConfig buildConfig =
+                        * ajBuildManager.getState().getBuildConfig();
+                        * 
+                        * ajBuildManager.incrementalBuild(buildConfig,msgHandlerAdapter); }
+                        */
+                       IncrementalStateManager.recordSuccessfulBuild(compiler.getId(), ajBuildManager.getState());
+
+               } catch (ConfigParser.ParseException pe) {
+                       handleMessage(new Message("Config file entry invalid, file: " + pe.getFile().getPath() + ", line number: "
+                                       + pe.getLine(), IMessage.WARNING, null, null));
                } catch (AbortException e) {
-            final IMessage message = e.getIMessage();
-            if (message == null) {
-                handleMessage(new Message(LangUtil.unqualifiedClassName(e) + " thrown: " 
-                               + e.getMessage(),IMessage.ERROR,e,null));
-            } else {
-               handleMessage(new Message(message.getMessage() + "\n" 
-                               + CompilationAndWeavingContext.getCurrentContext(),IMessage.ERROR,e,null));
-            }
+                       final IMessage message = e.getIMessage();
+                       if (message == null) {
+                               handleMessage(new Message(LangUtil.unqualifiedClassName(e) + " thrown: " + e.getMessage(), IMessage.ERROR, e, null));
+                       } else {
+                               handleMessage(new Message(message.getMessage() + "\n" + CompilationAndWeavingContext.getCurrentContext(),
+                                               IMessage.ERROR, e, null));
+                       }
                } catch (Throwable t) {
-            handleMessage(new Message("Compile error: " + LangUtil.unqualifiedClassName(t) + " thrown: " +
-                       "" + t.getMessage(),IMessage.ABORT,t,null));
-        } finally {
-               compiler.getBuildProgressMonitor().finish(ajBuildManager.wasFullBuild());
-        }
+                       handleMessage(new Message("Compile error: " + LangUtil.unqualifiedClassName(t) + " thrown: " + "" + t.getMessage(),
+                                       IMessage.ABORT, t, null));
+               } finally {
+                       compiler.getBuildProgressMonitor().finish(ajBuildManager.wasFullBuild());
+               }
        }
-       
+
        /**
         * Starts the various notifiers which are interested in the build progress
         */
        private void startNotifiers() {
-       compiler.getBuildProgressMonitor().begin();
-               currNotifier = new AjdeCoreBuildNotifierAdapter(compiler.getBuildProgressMonitor());            
-               ajBuildManager.setProgressListener(currNotifier);               
+               compiler.getBuildProgressMonitor().begin();
+               currNotifier = new AjdeCoreBuildNotifierAdapter(compiler.getBuildProgressMonitor());
+               ajBuildManager.setProgressListener(currNotifier);
        }
-       
+
        /**
-        * Switches the relationshipMap and hierarchy used by AsmManager to be
-        * the one for the current compiler - this will not be necessary once
-        * the static nature is removed from the asm.
+        * Switches the relationshipMap and hierarchy used by AsmManager to be the one for the current compiler - this will not be
+        * necessary once the static nature is removed from the asm.
         */
        private boolean updateAsmManagerInformation() {
-               AjState updatedState = IncrementalStateManager.retrieveStateFor(compiler.getId());
-               if (updatedState == null) {
-                       return true;
-               } else {
-                       AsmManager.getDefault().setRelationshipMap(updatedState.getRelationshipMap());
-                       AsmManager.getDefault().setHierarchy(updatedState.getStructureModel());
-               }
+               AjState updatedState = IncrementalStateManager.retrieveStateFor(compiler.getId());
+               if (updatedState == null) {
+                       return true;
+               } else {
+                       AsmManager.getDefault().setRelationshipMap(updatedState.getRelationshipMap());
+                       AsmManager.getDefault().setHierarchy(updatedState.getStructureModel());
+               }
                return false;
        }
-    
-       // AMC - updated for AspectJ 1.1 options
+
        private String getFormattedOptionsString() {
                ICompilerConfiguration compilerConfig = compiler.getCompilerConfiguration();
-               return "Building with settings: "
-                       + "\n-> output paths: " + formatCollection(compilerConfig.getOutputLocationManager()
-                                       .getAllOutputLocations())
-                       + "\n-> classpath: " + compilerConfig.getClasspath()
-                       + "\n-> -inpath " + formatCollection(compilerConfig.getInpath())
-                       + "\n-> -outjar " + formatOptionalString(compilerConfig.getOutJar())
-                       + "\n-> -aspectpath " + formatCollection(compilerConfig.getAspectPath())
-                       + "\n-> -sourcePathResources " + formatMap(compilerConfig.getSourcePathResources())
-                       + "\n-> non-standard options: " + compilerConfig.getNonStandardOptions()
-                       + "\n-> javaoptions:" + formatMap(compilerConfig.getJavaOptionsMap());
+               return "Building with settings: " + "\n-> output paths: "
+                               + formatCollection(compilerConfig.getOutputLocationManager().getAllOutputLocations()) + "\n-> classpath: "
+                               + compilerConfig.getClasspath() + "\n-> -inpath " + formatCollection(compilerConfig.getInpath()) + "\n-> -outjar "
+                               + formatOptionalString(compilerConfig.getOutJar()) + "\n-> -aspectpath "
+                               + formatCollection(compilerConfig.getAspectPath()) + "\n-> -sourcePathResources "
+                               + formatMap(compilerConfig.getSourcePathResources()) + "\n-> non-standard options: "
+                               + compilerConfig.getNonStandardOptions() + "\n-> javaoptions:" + formatMap(compilerConfig.getJavaOptionsMap());
        }
-       
-       private String formatCollection( Collection options ) {
-               if ( options == null ) return "<default>";
-               if ( options.isEmpty() ) return "none";
-               
+
+       private String formatCollection(Collection options) {
+               if (options == null)
+                       return "<default>";
+               if (options.isEmpty())
+                       return "none";
+
                StringBuffer formattedOptions = new StringBuffer();
                Iterator it = options.iterator();
                while (it.hasNext()) {
                        String o = it.next().toString();
-                       if (formattedOptions.length() > 0) formattedOptions.append(", ");
-                       formattedOptions.append( o );
+                       if (formattedOptions.length() > 0)
+                               formattedOptions.append(", ");
+                       formattedOptions.append(o);
                }
                return formattedOptions.toString();
        }
-       
-       private String formatMap( Map options) {
-               if (options == null) return "<default>";
-               if (options.isEmpty()) return "none";
-               
+
+       private String formatMap(Map options) {
+               if (options == null)
+                       return "<default>";
+               if (options.isEmpty())
+                       return "none";
+
                return options.toString();
        }
-       
-       private String formatOptionalString( String s ) {
-               if ( s == null ) { return ""    ; }
-               else { return s; }
+
+       private String formatOptionalString(String s) {
+               if (s == null) {
+                       return "";
+               } else {
+                       return s;
+               }
        }
-       
-    /**
-     * Generate a new AjBuildConfig from the compiler configuration
-     * associated with this AjdeCoreBuildManager
-     * 
-     * @return null if invalid configuration, corresponding 
-     * AjBuildConfig otherwise
-     */
+
+       /**
+        * Generate a new AjBuildConfig from the compiler configuration associated with this AjdeCoreBuildManager
+        * 
+        * @return null if invalid configuration, corresponding AjBuildConfig otherwise
+        */
        public AjBuildConfig genAjBuildConfig() {
-           File configFile = new File(compiler.getId());
-           String[] args = null;
-           if (configFile.exists() && configFile.isFile()) {
+               File configFile = new File(compiler.getId());
+               String[] args = null;
+               if (configFile.exists() && configFile.isFile()) {
                        args = new String[] { "@" + configFile.getAbsolutePath() };
                } else {
                        List l = compiler.getCompilerConfiguration().getProjectSourceFiles();
-                       if (l == null) return null;
+                       if (l == null)
+                               return null;
                        args = new String[l.size()];
                        int counter = 0;
                        for (Iterator iter = l.iterator(); iter.hasNext();) {
@@ -218,163 +232,159 @@ public class AjdeCoreBuildManager {
                                counter++;
                        }
                }
-        CountingMessageHandler handler = CountingMessageHandler.makeCountingMessageHandler(
-                       msgHandlerAdapter);
+               CountingMessageHandler handler = CountingMessageHandler.makeCountingMessageHandler(msgHandlerAdapter);
                BuildArgParser parser = new BuildArgParser(handler);
-               
+
                AjBuildConfig config = new AjBuildConfig();
-        parser.populateBuildConfig(config, args, false, configFile); 
-        configureCompilerOptions(config);
+               parser.populateBuildConfig(config, args, false, configFile);
+               configureCompilerOptions(config);
+               compiler.getCompilerConfiguration().configurationRead();
 
                ISourceLocation location = null;
                if (config.getConfigFile() != null) {
-                       location = new SourceLocation(config.getConfigFile(), 0); 
+                       location = new SourceLocation(config.getConfigFile(), 0);
                }
-        
+
                String message = parser.getOtherMessages(true);
-               if (null != message) {  
-                       IMessage m = new Message(message, IMessage.ERROR, null, location);            
+               if (null != message) {
+                       IMessage m = new Message(message, IMessage.ERROR, null, location);
                        handler.handleMessage(m);
                }
-        
-        // always force model generation in AJDE
-        config.setGenerateModelMode(true);      
-        // always be in incremental mode in AJDE
-        config.setIncrementalMode(true);
-        // always force proceedOnError in AJDE
-        config.setProceedOnError(true);
+
+               // always force model generation in AJDE
+               config.setGenerateModelMode(true);
+               // always be in incremental mode in AJDE
+               config.setIncrementalMode(true);
+               // always force proceedOnError in AJDE
+               config.setProceedOnError(true);
                return config;
        }
-       
+
        /**
-        * Configure the given AjBuildConfig with the options found in the
-        * ICompilerConfiguration implementation associated with the AjCompiler
-        * for this AjdeCoreBuildManager
+        * Configure the given AjBuildConfig with the options found in the ICompilerConfiguration implementation associated with the
+        * AjCompiler for this AjdeCoreBuildManager
         * 
         * @param config
         */
        private void configureCompilerOptions(AjBuildConfig config) {
-               
-        String propcp = compiler.getCompilerConfiguration().getClasspath();
-        if (!LangUtil.isEmpty(propcp)) {
-            StringTokenizer st = new StringTokenizer(propcp, File.pathSeparator);
-            List configClasspath = config.getClasspath();
-            ArrayList toAdd = new ArrayList();
-            while (st.hasMoreTokens()) {
-                String entry = st.nextToken();
-                if (!configClasspath.contains(entry)) {
-                    toAdd.add(entry);
-                }
-            }
-            if (0 < toAdd.size()) {
-                ArrayList both = new ArrayList(configClasspath.size() + toAdd.size());
-                both.addAll(configClasspath);
-                both.addAll(toAdd);
-                config.setClasspath(both);
-            }
-        }
-        
-        // set the outputjar
-        if (config.getOutputJar() == null) {
-            String outJar = compiler.getCompilerConfiguration().getOutJar();
-            if (!LangUtil.isEmpty(outJar)) {
-                config.setOutputJar(new File( outJar ) );  
-            }
-        }
-        
-        // set compilation result destination manager 
-        IOutputLocationManager outputLocationManager = compiler.getCompilerConfiguration().getOutputLocationManager();
-        if (config.getCompilationResultDestinationManager() == null && outputLocationManager != null) {
-               config.setCompilationResultDestinationManager(new OutputLocationAdapter(outputLocationManager));
-        }
-
-        join(config.getInpath(),compiler.getCompilerConfiguration().getInpath());
-        // bug 168840 - calling 'setInPath(..)' creates BinarySourceFiles which
-        // are used to see if there have been changes in classes on the inpath
-        if (config.getInpath() != null) config.setInPath(config.getInpath());
+
+               String propcp = compiler.getCompilerConfiguration().getClasspath();
+               if (!LangUtil.isEmpty(propcp)) {
+                       StringTokenizer st = new StringTokenizer(propcp, File.pathSeparator);
+                       List configClasspath = config.getClasspath();
+                       ArrayList toAdd = new ArrayList();
+                       while (st.hasMoreTokens()) {
+                               String entry = st.nextToken();
+                               if (!configClasspath.contains(entry)) {
+                                       toAdd.add(entry);
+                               }
+                       }
+                       if (0 < toAdd.size()) {
+                               ArrayList both = new ArrayList(configClasspath.size() + toAdd.size());
+                               both.addAll(configClasspath);
+                               both.addAll(toAdd);
+                               config.setClasspath(both);
+                       }
+               }
+
+               // set the outputjar
+               if (config.getOutputJar() == null) {
+                       String outJar = compiler.getCompilerConfiguration().getOutJar();
+                       if (!LangUtil.isEmpty(outJar)) {
+                               config.setOutputJar(new File(outJar));
+                       }
+               }
+
+               // set compilation result destination manager
+               IOutputLocationManager outputLocationManager = compiler.getCompilerConfiguration().getOutputLocationManager();
+               if (config.getCompilationResultDestinationManager() == null && outputLocationManager != null) {
+                       config.setCompilationResultDestinationManager(new OutputLocationAdapter(outputLocationManager));
+               }
+
+               join(config.getInpath(), compiler.getCompilerConfiguration().getInpath());
+               // bug 168840 - calling 'setInPath(..)' creates BinarySourceFiles which
+               // are used to see if there have been changes in classes on the inpath
+               if (config.getInpath() != null)
+                       config.setInPath(config.getInpath());
                config.setSourcePathResources(compiler.getCompilerConfiguration().getSourcePathResources());
-        join(config.getAspectpath(), compiler.getCompilerConfiguration().getAspectPath());
-        
+               join(config.getAspectpath(), compiler.getCompilerConfiguration().getAspectPath());
+
                Map jom = compiler.getCompilerConfiguration().getJavaOptionsMap();
-               if (jom!=null) {
-                       String version = (String)jom.get(CompilerOptions.OPTION_Compliance);
-                       if (version!=null && ( version.equals(CompilerOptions.VERSION_1_5) || version.equals(CompilerOptions.VERSION_1_6))) {
+               if (jom != null) {
+                       String version = (String) jom.get(CompilerOptions.OPTION_Compliance);
+                       if (version != null && (version.equals(CompilerOptions.VERSION_1_5) || version.equals(CompilerOptions.VERSION_1_6))) {
                                config.setBehaveInJava5Way(true);
                        }
                        config.getOptions().set(jom);
                }
-               
-               configureNonStandardOptions(config);    
+
+               configureNonStandardOptions(config);
        }
-       
-    private void join(Collection target, Collection source) { 
-        if ((null == target) || (null == source)) {
-            return;
-        }
-        for (Iterator iter = source.iterator(); iter.hasNext();) {
-            Object next = iter.next();
-            if (! target.contains(next)) {
-                target.add(next);
-            }
-        }
-    }
-    
+
+       private void join(Collection target, Collection source) {
+               if ((null == target) || (null == source)) {
+                       return;
+               }
+               for (Iterator iter = source.iterator(); iter.hasNext();) {
+                       Object next = iter.next();
+                       if (!target.contains(next)) {
+                               target.add(next);
+                       }
+               }
+       }
+
        /**
-        * Helper method for configure build options. This reads all command-line 
-        * options specified in the non-standard options text entry and sets any 
-        * corresponding unset values in config.
+        * Helper method for configure build options. This reads all command-line options specified in the non-standard options text
+        * entry and sets any corresponding unset values in config.
         */
        private void configureNonStandardOptions(AjBuildConfig config) {
 
                String nonStdOptions = compiler.getCompilerConfiguration().getNonStandardOptions();
-        if (LangUtil.isEmpty(nonStdOptions)) {
-            return;
-        }
-               
+               if (LangUtil.isEmpty(nonStdOptions)) {
+                       return;
+               }
+
                // Break a string into a string array of non-standard options.
-               // Allows for one option to include a ' '.   i.e. assuming it has been quoted, it
+               // Allows for one option to include a ' '. i.e. assuming it has been quoted, it
                // won't accidentally get treated as a pair of options (can be needed for xlint props file option)
                List tokens = new ArrayList();
                int ind = nonStdOptions.indexOf('\"');
-               int ind2 = nonStdOptions.indexOf('\"',ind+1);
+               int ind2 = nonStdOptions.indexOf('\"', ind + 1);
                if ((ind > -1) && (ind2 > -1)) { // dont tokenize within double quotes
-                       String pre = nonStdOptions.substring(0,ind);
-                       String quoted = nonStdOptions.substring(ind+1,ind2);
-                       String post = nonStdOptions.substring(ind2+1,nonStdOptions.length());
+                       String pre = nonStdOptions.substring(0, ind);
+                       String quoted = nonStdOptions.substring(ind + 1, ind2);
+                       String post = nonStdOptions.substring(ind2 + 1, nonStdOptions.length());
                        tokens.addAll(tokenizeString(pre));
                        tokens.add(quoted);
                        tokens.addAll(tokenizeString(post));
                } else {
                        tokens.addAll(tokenizeString(nonStdOptions));
                }
-               String[] args = (String[])tokens.toArray(new String[]{});
-               
-               
+               String[] args = (String[]) tokens.toArray(new String[] {});
+
                // set the non-standard options in an alternate build config
                // (we don't want to lose the settings we already have)
-        CountingMessageHandler counter 
-            = CountingMessageHandler.makeCountingMessageHandler(msgHandlerAdapter);
+               CountingMessageHandler counter = CountingMessageHandler.makeCountingMessageHandler(msgHandlerAdapter);
                AjBuildConfig altConfig = AjdtCommand.genBuildConfig(args, counter);
                if (counter.hasErrors()) {
-            return;
-        }
-        // copy globals where local is not set
-        config.installGlobals(altConfig);
-    }
-       
+                       return;
+               }
+               // copy globals where local is not set
+               config.installGlobals(altConfig);
+       }
+
        /** Local helper method for splitting option strings */
        private List tokenizeString(String str) {
                List tokens = new ArrayList();
                StringTokenizer tok = new StringTokenizer(str);
-               while ( tok.hasMoreTokens() ) {
-                       tokens.add(tok.nextToken());    
+               while (tok.hasMoreTokens()) {
+                       tokens.add(tok.nextToken());
                }
                return tokens;
        }
-       
+
        /**
-        * Helper method to ask the messagehandler to handle the 
-        * given message
+        * Helper method to ask the messagehandler to handle the given message
         */
        private void handleMessage(Message msg) {
                compiler.getMessageHandler().handleMessage(msg);