if (args.size() > nextArgIndex) {
buildConfig.getAjOptions().put(AjCompilerOptions.OPTION_Inpath, CompilerOptions.PRESERVE);
+ List inPath = buildConfig.getInpath();
StringTokenizer st = new StringTokenizer(
((ConfigParser.Arg)args.get(nextArgIndex)).getValue(),
File.pathSeparator);
String filename = st.nextToken();
File file = makeFile(filename);
if (file.exists() && FileUtil.hasZipSuffix(filename)) {
- buildConfig.getInpath().add(file);
+ inPath.add(file);
} else {
if (file.isDirectory()) {
- buildConfig.getInpath().add(file);
+ inPath.add(file);
} else
showError("bad inpath component: " + filename);
}
}
-
+ buildConfig.setInPath(inPath);
args.remove(args.get(nextArgIndex));
}
} else if (arg.equals("-injars")) {;
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.Map;
private IIntermediateResultsRequestor intermediateResultsRequestor;
private IProgressListener progressListener;
private IOutputClassFileNameProvider outputFileNameProvider;
+ private IBinarySourceProvider binarySourceProvider;
private WeaverMessageHandler weaverMessageHandler;
- private List /* InterimCompilationResult */ binarySources = new ArrayList();
+ private Map /* fileName |-> List<UnwovenClassFile> */ binarySourceSetForFullWeave = new HashMap();
private Collection /*InterimCompilationResult*/ resultSetForFullWeave = Collections.EMPTY_LIST;
IIntermediateResultsRequestor intRequestor,
IProgressListener progressListener,
IOutputClassFileNameProvider outputFileNameProvider,
- Map binarySourceEntries, /* fileName |-> List<UnwovenClassFile> */
+ IBinarySourceProvider binarySourceProvider,
+ Map fullBinarySourceEntries, /* fileName |-> List<UnwovenClassFile> */
Collection /* InterimCompilationResult */ resultSetForFullWeave,
boolean isXNoWeave) {
this.compiler = compiler;
this.intermediateResultsRequestor = intRequestor;
this.progressListener = progressListener;
this.outputFileNameProvider = outputFileNameProvider;
+ this.binarySourceProvider = binarySourceProvider;
this.isXNoWeave = isXNoWeave;
+ this.binarySourceSetForFullWeave = fullBinarySourceEntries;
this.resultSetForFullWeave = resultSetForFullWeave;
this.eWorld = eFactory;
IMessageHandler msgHandler = world.getMessageHandler();
weaverMessageHandler = new WeaverMessageHandler(msgHandler, compiler);
world.setMessageHandler(weaverMessageHandler);
-
- addBinarySource(binarySourceEntries);
}
public void beforeCompiling(ICompilationUnit[] sourceUnits) {
} else {
resultsPendingWeave.add(intRes);
}
-
}
public void beforeResolving(CompilationUnitDeclaration unit, ICompilationUnit sourceUnit, boolean verifyMethods, boolean analyzeCode, boolean generateCode) {
}
}
- private void addBinarySource(Map binarySourceEntries) {
+ private List getBinarySourcesFrom(Map binarySourceEntries) {
// Map is fileName |-> List<UnwovenClassFile>
+ List ret = new ArrayList();
for (Iterator binIter = binarySourceEntries.keySet().iterator(); binIter.hasNext();) {
String sourceFileName = (String) binIter.next();
List unwovenClassFiles = (List) binarySourceEntries.get(sourceFileName);
result.noSourceAvailable();
InterimCompilationResult binarySource =
new InterimCompilationResult(result,unwovenClassFiles);
- binarySources.add(binarySource);
+ ret.add(binarySource);
}
+ return ret;
}
private void notifyRequestor() {
}
weaver.prepareForWeave();
-
- if (isBatchCompile) {
- resultsPendingWeave.addAll(binarySources);
- // passed into the compiler, the set of classes in injars and inpath...
- } else if (weaver.needToReweaveWorld()) {
- addAllKnownClassesToWeaveList();
+ if (weaver.needToReweaveWorld()) {
+ if (!isBatchCompile) addAllKnownClassesToWeaveList(); // if it's batch, they're already on the list...
+ resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourceSetForFullWeave));
+ } else {
+ Map binarySourcesToAdd = binarySourceProvider.getBinarySourcesForThisWeave();
+ resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourcesToAdd));
}
+// if (isBatchCompile) {
+// resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourceSetForFullWeave));
+// // passed into the compiler, the set of classes in injars and inpath...
+// } else if (weaver.needToReweaveWorld()) {
+// addAllKnownClassesToWeaveList();
+// resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourceSetForFullWeave));
+// }
+
weaver.weave(new WeaverAdapter(this,weaverMessageHandler,progressListener));
}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.aspectj.ajdt.internal.compiler;
+
+import java.util.Map;
+
+/**
+ * @author colyer
+ *
+ * Implementors of this interface are called by the CompilerAdapter just before
+ * it does a weave, and should return the set of binary source files (ie. those
+ * resources from injars and inpath) that are to be included in the weave.
+ * Used to manage incremental compilation of binary sources.
+ */
+public interface IBinarySourceProvider {
+
+ Map /* fileName |-> List<UnwovenClassFile> */ getBinarySourcesForThisWeave();
+
+}
package org.aspectj.ajdt.internal.core.builder;
import java.io.File;
+import java.io.FileFilter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.aspectj.util.FileUtil;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
/**
public static final String AJLINT_WARN = "warn";
public static final String AJLINT_ERROR = "error";
public static final String AJLINT_DEFAULT = "default";
-
+
private File outputDir;
private File outputJar;
private List/*File*/ sourceRoots = new ArrayList();
private List/*File*/ files = new ArrayList();
+ private List /*File*/ binaryFiles = new ArrayList(); // .class files in indirs...
private List/*File*/ inJars = new ArrayList();
private List/*File*/ inPath = new ArrayList();
private Map/*String->File*/ sourcePathResources = new HashMap();
private boolean incrementalMode;
private File incrementalFile;
+ public static class BinarySourceFile {
+ public BinarySourceFile(File dir, File src) {
+ this.fromInPathDirectory = dir;
+ this.binSrc = src;
+ }
+ public File fromInPathDirectory;
+ public File binSrc;
+
+ public boolean equals(Object obj) {
+ if ((obj instanceof BinarySourceFile) &&
+ (obj != null)) {
+ BinarySourceFile other = (BinarySourceFile)obj;
+ return(binSrc.equals(other.binSrc));
+ }
+ return false;
+ }
+ public int hashCode() {
+ return binSrc != null ? binSrc.hashCode() : 0;
+ }
+ }
+
/**
* Intialises the javaOptions Map to hold the default
* JDT Compiler settings. Added by AMC 01.20.2003 in reponse
return files;
}
+ /**
+ * returned files includes all .class files found in
+ * a directory on the inpath, but does not include
+ * .class files contained within jars.
+ */
+ public List/*BinarySourceFile*/ getBinaryFiles() {
+ return binaryFiles;
+ }
+
public File getOutputDir() {
return outputDir;
}
public void setInPath(List dirsOrJars) {
inPath = dirsOrJars;
+
+ // remember all the class files in directories on the inpath
+ binaryFiles = new ArrayList();
+ FileFilter filter = new FileFilter() {
+ public boolean accept(File pathname) {
+ return pathname.getPath().endsWith(".class");
+ }};
+ for (Iterator iter = dirsOrJars.iterator(); iter.hasNext();) {
+ File inpathElement = (File) iter.next();
+ if (inpathElement.isDirectory()) {
+ File[] files = FileUtil.listFiles(inpathElement, filter);
+ for (int i = 0; i < files.length; i++) {
+ binaryFiles.add(new BinarySourceFile(inpathElement,files[i]));
+ }
+ }
+ }
}
public List getSourceRoots() {
import java.util.zip.ZipEntry;
import org.aspectj.ajdt.internal.compiler.AjCompilerAdapter;
+import org.aspectj.ajdt.internal.compiler.IBinarySourceProvider;
import org.aspectj.ajdt.internal.compiler.IIntermediateResultsRequestor;
import org.aspectj.ajdt.internal.compiler.IOutputClassFileNameProvider;
import org.aspectj.ajdt.internal.compiler.InterimCompilationResult;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
//import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
-public class AjBuildManager implements IOutputClassFileNameProvider,ICompilerAdapterFactory {
+public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourceProvider,ICompilerAdapterFactory {
private static final String CANT_WRITE_RESULT = "unable to write compilation result";
private static final String MANIFEST_NAME = "META-INF/MANIFEST.MF";
static final boolean COPY_INPATH_DIR_RESOURCES = false;
static final boolean FAIL_IF_RUNTIME_NOT_FOUND = false;
+
+ private static final FileFilter binarySourceFilter =
+ new FileFilter() {
+ public boolean accept(File f) {
+ return f.getName().endsWith(".class");
+ }};
+
private IProgressListener progressListener = null;
private int compiledCount;
private boolean batchCompile = true;
private INameEnvironment environment;
+ private Map /* String -> List<UCF>*/ binarySourcesForTheNextCompile = new HashMap();
+
private IHierarchy structureModel;
public AjBuildConfig buildConfig;
bcelWorld.setModel(AsmManager.getDefault().getHierarchy());
// in incremental build, only get updated model?
}
+ binarySourcesForTheNextCompile = state.getBinaryFilesToCompile();
performCompilation(buildConfig.getFiles());
if (handler.hasErrors()) {
return false;
// }
// System.err.println("XXXX start inc ");
List files = state.getFilesToCompile(true);
- for (int i = 0; (i < 5) && !files.isEmpty(); i++) {
+ binarySourcesForTheNextCompile = state.getBinaryFilesToCompile();
+ boolean hereWeGoAgain = !(files.isEmpty() && binarySourcesForTheNextCompile.isEmpty());
+ for (int i = 0; (i < 5) && hereWeGoAgain; i++) {
// System.err.println("XXXX inc: " + files);
performCompilation(files);
if (handler.hasErrors() || (progressListener!=null && progressListener.isCancelledRequested())) {
return false;
}
files = state.getFilesToCompile(false);
+ binarySourcesForTheNextCompile = state.getBinaryFilesToCompile();
+ hereWeGoAgain = !(files.isEmpty() && binarySourcesForTheNextCompile.isEmpty());
}
if (!files.isEmpty()) {
return batchBuild(buildConfig, baseHandler);
for (Iterator i = buildConfig.getInpath().iterator(); i.hasNext(); ) {
File inPathElement = (File)i.next();
- List unwovenClasses = bcelWeaver.addJarFile(inPathElement,buildConfig.getOutputDir(),true);
- state.binarySourceFiles.put(inPathElement.getPath(),unwovenClasses); // good enough for ajc to lump these together
+ if (!inPathElement.isDirectory()) {
+ // its a jar file on the inpath
+ // the weaver method can actually handle dirs, but we don't call it, see next block
+ List unwovenClasses = bcelWeaver.addJarFile(inPathElement,buildConfig.getOutputDir(),true);
+ state.binarySourceFiles.put(inPathElement.getPath(),unwovenClasses);
+ } else {
+ // add each class file in an in-dir individually, this gives us the best error reporting
+ // (they are like 'source' files then), and enables a cleaner incremental treatment of
+ // class file changes in indirs.
+ File[] binSrcs = FileUtil.listFiles(inPathElement, binarySourceFilter);
+ for (int j = 0; j < binSrcs.length; j++) {
+ UnwovenClassFile ucf =
+ bcelWeaver.addClassFile(binSrcs[j], inPathElement, buildConfig.getOutputDir());
+ List ucfl = new ArrayList();
+ ucfl.add(ucf);
+ state.binarySourceFiles.put(binSrcs[j].getPath(),ucfl);
+ }
+ }
}
-// if (buildConfig.getSourcePathResources() != null) {
-// // XXX buildConfig.getSourcePathResources always returns null (CompileCommand.java)
-// for (Iterator i = buildConfig.getSourcePathResources().keySet().iterator(); i.hasNext(); ) {
-// // File resource = (File)i.next();
-// String resource = (String)i.next();
-// bcelWeaver.addResource(resource, (File)buildConfig.getSourcePathResources().get(resource), buildConfig.getOutputDir());
-// // bcelWeaver.addResource(resource, buildConfig.getOutputDir());
-// }
-// }
bcelWeaver.setReweavableMode(buildConfig.isXreweavable(),buildConfig.getXreweavableCompressClasses());
options.produceReferenceInfo(true); //TODO turn off when not needed
try {
- compiler.compile(getCompilationUnits(filenames, encodings));
+ compiler.compile(getCompilationUnits(filenames, encodings));
} catch (OperationCanceledException oce) {
handler.handleMessage(new Message("build cancelled:"+oce.getMessage(),IMessage.WARNING,null,null));
}
factory,
getInterimResultRequestor(),
progressListener,
- this,
+ this, // IOutputFilenameProvider
+ this, // IBinarySourceProvider
state.binarySourceFiles,
state.resultsFromFile.values(),
buildConfig.isNoWeave());
}
+
+ /* (non-Javadoc)
+ * @see org.aspectj.ajdt.internal.compiler.IBinarySourceProvider#getBinarySourcesForThisWeave()
+ */
+ public Map getBinarySourcesForThisWeave() {
+ return binarySourcesForTheNextCompile;
+ }
} // class AjBuildManager
import java.util.Set;
import org.aspectj.ajdt.internal.compiler.InterimCompilationResult;
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.Message;
+import org.aspectj.bridge.SourceLocation;
import org.aspectj.util.FileUtil;
import org.aspectj.weaver.bcel.UnwovenClassFile;
import org.eclipse.jdt.internal.compiler.CompilationResult;
Set addedFiles;
Set deletedFiles;
+ Set /*BinarySourceFile*/addedBinaryFiles;
+ Set /*BinarySourceFile*/deletedBinaryFiles;
List addedClassFiles;
deletedFiles = new HashSet(oldFiles);
deletedFiles.removeAll(newFiles);
+ Set oldBinaryFiles = new HashSet(buildConfig.getBinaryFiles());
+ Set newBinaryFiles = new HashSet(newBuildConfig.getBinaryFiles());
+
+ addedBinaryFiles = new HashSet(newBinaryFiles);
+ addedBinaryFiles.removeAll(oldBinaryFiles);
+ deletedBinaryFiles = new HashSet(oldBinaryFiles);
+ deletedBinaryFiles.removeAll(newBinaryFiles);
+
this.newBuildConfig = newBuildConfig;
return true;
return ret;
}
+ private Collection getModifiedBinaryFiles() {
+ return getModifiedBinaryFiles(lastSuccessfulBuildTime);
+ }
+
+ Collection getModifiedBinaryFiles(long lastBuildTime) {
+ List ret = new ArrayList();
+ //not our job to account for new and deleted files
+ for (Iterator i = buildConfig.getBinaryFiles().iterator(); i.hasNext(); ) {
+ AjBuildConfig.BinarySourceFile bsfile = (AjBuildConfig.BinarySourceFile)i.next();
+ File file = bsfile.binSrc;
+ if (!file.exists()) continue;
+
+ long modTime = file.lastModified();
+ //System.out.println("check: " + file + " mod " + modTime + " build " + lastBuildTime);
+ if (modTime >= lastBuildTime) {
+ ret.add(bsfile);
+ }
+ }
+ return ret;
+ }
+
private boolean pathChange(AjBuildConfig oldConfig, AjBuildConfig newConfig) {
boolean changed = false;
List oldClasspath = oldConfig.getClasspath();
if (!oldPath.get(i).equals(newPath.get(i))) {
return true;
}
- File f = new File((String)oldPath.get(i));
+ Object o = oldPath.get(i); // String on classpath, File on other paths
+ File f = null;
+ if (o instanceof String) {
+ f = new File((String)o);
+ } else {
+ f = (File) o;
+ }
if (f.exists() && !f.isDirectory() && (f.lastModified() >= lastSuccessfulBuildTime)) {
return true;
}
return thisTime;
}
+ public Map /* String -> List<ucf> */ getBinaryFilesToCompile() {
+ if (lastSuccessfulBuildTime == -1 || buildConfig == null) {
+ return binarySourceFiles;
+ }
+ // else incremental...
+ Map toWeave = new HashMap();
+ List addedOrModified = new ArrayList();
+ addedOrModified.addAll(addedBinaryFiles);
+ addedOrModified.addAll(getModifiedBinaryFiles());
+ for (Iterator iter = addedOrModified.iterator(); iter.hasNext();) {
+ AjBuildConfig.BinarySourceFile bsf = (AjBuildConfig.BinarySourceFile) iter.next();
+ UnwovenClassFile ucf = createUnwovenClassFile(bsf);
+ if (ucf == null) continue;
+ List ucfs = new ArrayList();
+ ucfs.add(ucf);
+ binarySourceFiles.put(bsf.binSrc.getPath(),ucfs);
+ toWeave.put(bsf.binSrc.getPath(),ucfs);
+ }
+ deleteBinaryClassFiles();
+ return toWeave;
+ }
+
private void deleteClassFiles() {
for (Iterator i = deletedFiles.iterator(); i.hasNext(); ) {
File deletedFile = (File)i.next();
}
}
+ private void deleteBinaryClassFiles() {
+ // range of bsf is ucfs, domain is files (.class and jars) in inpath/jars
+ for (Iterator iter = deletedBinaryFiles.iterator(); iter.hasNext();) {
+ AjBuildConfig.BinarySourceFile deletedFile = (AjBuildConfig.BinarySourceFile) iter.next();
+ List ucfs = (List) binarySourceFiles.get(deletedFile.binSrc.getPath());
+ binarySourceFiles.remove(deletedFile.binSrc.getPath());
+ deleteClassFile((UnwovenClassFile)ucfs.get(0));
+ }
+ }
+
private void deleteResources() {
List oldResources = new ArrayList();
oldResources.addAll(resources);
}
}
- private void deleteClassFile(UnwovenClassFile classFile) {
+
+ private void deleteClassFile(UnwovenClassFile classFile) {
classesFromName.remove(classFile.getClassName());
buildManager.bcelWeaver.deleteClassFile(classFile.getClassName());
}
}
+ private UnwovenClassFile createUnwovenClassFile(AjBuildConfig.BinarySourceFile bsf) {
+ UnwovenClassFile ucf = null;
+ try {
+ ucf = buildManager.bcelWeaver.addClassFile(bsf.binSrc, bsf.fromInPathDirectory, buildConfig.getOutputDir());
+ } catch(IOException ex) {
+ IMessage msg = new Message("can't read class file " + bsf.binSrc.getPath(),
+ new SourceLocation(bsf.binSrc,0),false);
+ buildManager.handler.handleMessage(msg);
+ }
+ return ucf;
+ }
+
public void noteResult(InterimCompilationResult result) {
File sourceFile = new File(result.fileName());
CompilationResult cr = result.result();
// For each file, add it either as a real .class file or as a resource
for (int i = 0; i < files.length; i++) {
-
- FileInputStream fis = new FileInputStream(files[i]);
- byte[] bytes = FileUtil.readAsByteArray(fis);
- // String relativePath = files[i].getPath();
-
- // ASSERT: files[i].getAbsolutePath().startsWith(inFile.getAbsolutePath()
- // or we are in trouble...
- String filename = files[i].getAbsolutePath().substring(
- inFile.getAbsolutePath().length()+1);
- UnwovenClassFile classFile = new UnwovenClassFile(new File(outDir,filename).getAbsolutePath(),bytes);
- if (filename.endsWith(".class")) {
- // System.err.println("BCELWeaver: processing class from input directory "+classFile);
- this.addClassFile(classFile);
- addedClassFiles.add(classFile);
-// } else {
-// if (CopyResourcesFromInpathDirectoriesToOutput) {
-// // System.err.println("BCELWeaver: processing resource from input directory "+filename);
-// addResource(filename,classFile);
-// }
- }
- fis.close();
+ addedClassFiles.add(addClassFile(files[i],inFile,outDir));
}
return addedClassFiles;
// }
world.addSourceObjectType(classFile.getJavaClass());
}
+
+ public UnwovenClassFile addClassFile(File classFile, File inPathDir, File outDir) throws IOException {
+ FileInputStream fis = new FileInputStream(classFile);
+ byte[] bytes = FileUtil.readAsByteArray(fis);
+ // String relativePath = files[i].getPath();
+
+ // ASSERT: files[i].getAbsolutePath().startsWith(inFile.getAbsolutePath()
+ // or we are in trouble...
+ String filename = classFile.getAbsolutePath().substring(
+ inPathDir.getAbsolutePath().length()+1);
+ UnwovenClassFile ucf = new UnwovenClassFile(new File(outDir,filename).getAbsolutePath(),bytes);
+ if (filename.endsWith(".class")) {
+ // System.err.println("BCELWeaver: processing class from input directory "+classFile);
+ this.addClassFile(ucf);
+ }
+ fis.close();
+ return ucf;
+ }
public void deleteClassFile(String typename) {