--- /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 org.eclipse.jdt.internal.compiler.ClassFile;
+
+/**
+ * @author colyer
+ *
+ * XXX lightweight subclass of ClassFile that only genuinely supports fileName and getBytes
+ * operations. This nasty hack enables us to keep the rest of the implementation much simpler.
+ */
+public class AjClassFile extends ClassFile {
+ char[] filename;
+ byte[] bytes;
+
+ public AjClassFile(char[] fileName, byte[] byteCodes) {
+ this.filename = fileName;
+ bytes = byteCodes;
+ }
+
+ public char[] fileName() {
+ return filename;
+ }
+
+ public byte[] getBytes() {
+ return bytes;
+ }
+}
-/* *******************************************************************
- * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
- * All rights reserved.
- * This program and the accompanying materials are made available
- * under the terms of the Common Public License v1.0
- * which accompanies this distribution and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- * PARC initial implementation
- * ******************************************************************/
-
-
-package org.aspectj.ajdt.internal.compiler;
-
-import java.util.Map;
-
-import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
-import org.aspectj.bridge.IMessage;
-import org.eclipse.jdt.internal.compiler.Compiler;
-import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
-import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
-import org.eclipse.jdt.internal.compiler.IProblemFactory;
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
-
-
-public class AjCompiler extends Compiler {
-
- public AjCompiler(
- INameEnvironment environment,
- IErrorHandlingPolicy policy,
- Map settings,
- ICompilerRequestor requestor,
- IProblemFactory problemFactory) {
- super(environment, policy, settings, requestor, problemFactory);
- }
-
- public AjCompiler(
- INameEnvironment environment,
- IErrorHandlingPolicy policy,
- Map settings,
- ICompilerRequestor requestor,
- IProblemFactory problemFactory,
- boolean parseLiteralExpressionsAsConstants) {
- super(
- environment,
- policy,
- settings,
- requestor,
- problemFactory,
- parseLiteralExpressionsAsConstants);
- }
-
- /**
- * In addition to processing each compilation unit in the normal ways,
- * we also need to do weaving for inter-type declarations. This
- * must be done before we use the signatures of these types to do any
- * name binding.
- */
- public void process(CompilationUnitDeclaration unit, int i) {
- EclipseFactory world =
- EclipseFactory.fromLookupEnvironment(lookupEnvironment);
- world.showMessage(IMessage.INFO, "compiling " + new String(unit.getFileName()), null, null);
- super.process(unit, i);
-
- world.finishedCompilationUnit(unit);
- }
-}
+///* *******************************************************************
+// * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+// * All rights reserved.
+// * This program and the accompanying materials are made available
+// * under the terms of the Common Public License v1.0
+// * which accompanies this distribution and is available at
+// * http://www.eclipse.org/legal/cpl-v10.html
+// *
+// * Contributors:
+// * PARC initial implementation
+// * ******************************************************************/
+//
+//
+//package org.aspectj.ajdt.internal.compiler;
+//
+//import java.io.IOException;
+//import java.util.ArrayList;
+//import java.util.Collection;
+//import java.util.Collections;
+//import java.util.Enumeration;
+//import java.util.Hashtable;
+//import java.util.Iterator;
+//import java.util.List;
+//import java.util.Map;
+//
+//import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
+//import org.aspectj.ajdt.internal.compiler.lookup.EclipseSourceLocation;
+//import org.aspectj.bridge.AbortException;
+//import org.aspectj.bridge.IMessage;
+//import org.aspectj.bridge.IMessageHandler;
+//import org.aspectj.bridge.ISourceLocation;
+//import org.aspectj.bridge.IMessage.Kind;
+//import org.aspectj.weaver.IClassFileProvider;
+//import org.aspectj.weaver.IWeaveRequestor;
+//import org.aspectj.weaver.bcel.BcelWeaver;
+//import org.aspectj.weaver.bcel.BcelWorld;
+//import org.aspectj.weaver.bcel.Pause;
+//import org.aspectj.weaver.bcel.UnwovenClassFile;
+//import org.aspectj.weaver.bcel.UnwovenClassFileWithThirdPartyManagedBytecode;
+//import org.eclipse.jdt.core.compiler.IProblem;
+//import org.eclipse.jdt.internal.compiler.ClassFile;
+//import org.eclipse.jdt.internal.compiler.CompilationResult;
+//import org.eclipse.jdt.internal.compiler.Compiler;
+//import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
+//import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
+//import org.eclipse.jdt.internal.compiler.IProblemFactory;
+//import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+//import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
+//import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
+//import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
+//import org.eclipse.jdt.internal.compiler.problem.DefaultProblem;
+//import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
+//
+//
+//public class AjCompiler extends Compiler {
+//
+// private List /*InterimResult*/ resultsPendingWeave = new ArrayList();
+// private BcelWorld bcelWorld;
+// private BcelWeaver bcelWeaver;
+// private IIntermediateResultsRequestor intermediateResultRequestor;
+// private IOutputClassFileNameProvider nameProvider;
+// private List /*<InterimResult>*/ binarySources = new ArrayList();
+// private boolean skipTheWeavePhase = false;
+// private boolean reportedErrors = false;
+// private WeaverMessageHandler wmHandler;
+// private boolean isBatchCompile = false;
+// private Collection /*InterimResult*/ resultSetForFullWeave = Collections.EMPTY_LIST;
+//
+// public interface IIntermediateResultsRequestor {
+// void acceptResult(InterimResult intRes);
+// }
+//
+// public interface IOutputClassFileNameProvider {
+// String getOutputClassFileName(char[] eclipseClassFileName, CompilationResult result);
+// }
+//
+// public AjCompiler(
+// INameEnvironment environment,
+// IErrorHandlingPolicy policy,
+// Map settings,
+// ICompilerRequestor requestor,
+// IProblemFactory problemFactory) {
+// super(environment, policy, settings, requestor, problemFactory);
+// }
+//
+// public AjCompiler(
+// INameEnvironment environment,
+// IErrorHandlingPolicy policy,
+// Map settings,
+// ICompilerRequestor requestor,
+// IProblemFactory problemFactory,
+// boolean parseLiteralExpressionsAsConstants) {
+// super(
+// environment,
+// policy,
+// settings,
+// requestor,
+// problemFactory,
+// parseLiteralExpressionsAsConstants);
+// }
+//
+//
+// public void setWeaver(BcelWeaver weaver) {
+// this.bcelWeaver = weaver;
+// }
+//
+// public void setWorld(BcelWorld world) {
+// this.bcelWorld = world;
+// IMessageHandler msgHandler = world.getMessageHandler();
+// wmHandler = new WeaverMessageHandler(msgHandler);
+// world.setMessageHandler(wmHandler);
+// }
+//
+// public void prepareForBatchCompilation() {
+// isBatchCompile = true;
+// }
+//
+// public void setIntermediateResultsRequestor(IIntermediateResultsRequestor intReq) {
+// this.intermediateResultRequestor = intReq;
+// }
+//
+// public void setNoWeave(boolean noWeave) {
+// skipTheWeavePhase = noWeave;
+// }
+//
+// public void setFullWeaveResults(Collection compilationResults) {
+// resultSetForFullWeave = compilationResults;
+// }
+//
+// public void setOutputFileNameProvider(IOutputClassFileNameProvider p) {
+// this.nameProvider = p;
+// }
+//
+// public void addBinarySourceFiles(Map binarySourceEntries) {
+// // Map is fileName |-> List<UnwovenClassFile>
+// for (Iterator binIter = binarySourceEntries.keySet().iterator(); binIter.hasNext();) {
+// String sourceFileName = (String) binIter.next();
+// List unwovenClassFiles = (List) binarySourceEntries.get(sourceFileName);
+//
+// CompilationResult result = new CompilationResult(sourceFileName.toCharArray(),0,0,20);
+// result.noSourceAvailable();
+// InterimResult binarySource = new InterimResult(result,nameProvider);
+// binarySource.unwovenClassFiles = new UnwovenClassFile[unwovenClassFiles.size()];
+// int index = 0;
+// for (Iterator iter = unwovenClassFiles.iterator(); iter.hasNext();) {
+// UnwovenClassFile element = (UnwovenClassFile) iter.next();
+// binarySource.unwovenClassFiles[index] = element;
+// AjClassFile ajcf = new AjClassFile(element.getClassName().replace('.', '/').toCharArray(),
+// element.getBytes());
+// result.record(ajcf.fileName(),ajcf);
+// index++;
+// }
+// binarySources.add(binarySource);
+// }
+// }
+//
+//
+// /**
+// * In addition to processing each compilation unit in the normal ways,
+// * we also need to do weaving for inter-type declarations. This
+// * must be done before we use the signatures of these types to do any
+// * name binding.
+// */
+// public void process(CompilationUnitDeclaration unit, int i) {
+// EclipseFactory world =
+// EclipseFactory.fromLookupEnvironment(lookupEnvironment);
+// world.showMessage(IMessage.INFO, "compiling " + new String(unit.getFileName()), null, null);
+// super.process(unit, i);
+//
+// world.finishedCompilationUnit(unit);
+// }
+//
+//
+// /* (non-Javadoc)
+// * @see org.eclipse.jdt.internal.compiler.Compiler#compile(org.eclipse.jdt.internal.compiler.env.ICompilationUnit[])
+// * We override this method to defer handing of results to the caller until the weave phase has
+// * completed too. That way the class files are in final form and all error messages relating to the
+// * compilation unit have been reported (which is the contract the JDT expects from this method).
+// */
+// public void compile(ICompilationUnit[] sourceUnits) {
+// try {
+// resultsPendingWeave = new ArrayList();
+// reportedErrors = false;
+// super.compile(sourceUnits);
+// Pause.pause("After super compile");
+// try {
+// if (!(skipTheWeavePhase || reportedErrors)) {
+// weaveResults();
+// Pause.pause("After weave");
+// } else {
+// notifyRequestor(); // weaver notifies as it goes along...
+// }
+// } catch (IOException ex) {
+// // TODO
+// ex.printStackTrace();
+// }
+// } finally {
+// cleanup();
+// }
+// }
+//
+//
+// /* (non-Javadoc)
+// * @see org.eclipse.jdt.internal.compiler.Compiler#registerCompilationResult(org.eclipse.jdt.internal.compiler.CompilationResult)
+// */
+// protected void registerCompilationResult(int index, CompilationResult result) {
+// InterimResult intRes = new InterimResult(result,nameProvider);
+// resultsPendingWeave.add(intRes);
+// if (result.hasErrors()) reportedErrors = true;
+// if (intermediateResultRequestor != null) {
+// intermediateResultRequestor.acceptResult(intRes);
+// }
+// }
+//
+// /* (non-Javadoc)
+// * @see org.eclipse.jdt.internal.compiler.Compiler#reset()
+// * Super does this too early for us...
+// */
+// public void reset() {
+// // no-op, super calls this too early for us...
+// }
+//
+// /* (non-Javadoc)
+// * @see org.eclipse.jdt.internal.compiler.Compiler#resolve(org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration, org.eclipse.jdt.internal.compiler.env.ICompilationUnit, boolean, boolean, boolean)
+// */
+// public CompilationUnitDeclaration resolve(CompilationUnitDeclaration unit,
+// ICompilationUnit sourceUnit, boolean verifyMethods,
+// boolean analyzeCode, boolean generateCode) {
+// // TODO include weave phase in resolution too...
+// return super.resolve(unit, sourceUnit, verifyMethods, analyzeCode,
+// generateCode);
+// }
+//
+//
+// // AspectJ helper methods, called from compile...
+// private void weaveResults() throws IOException {
+// // ensure weaver state is set up correctly
+// for (Iterator iter = resultsPendingWeave.iterator(); iter.hasNext();) {
+// InterimResult iresult = (InterimResult) iter.next();
+// for (int i = 0; i < iresult.unwovenClassFiles.length; i++) {
+// bcelWeaver.addClassFile(iresult.unwovenClassFiles[i]);
+// }
+// }
+// Pause.pause("After adding class files to weaver");
+// bcelWeaver.prepareForWeave();
+// Pause.pause("After preparing for weave");
+// if (isBatchCompile) {
+// resultsPendingWeave.addAll(binarySources);
+// // passed into the compiler, the set of classes in injars and inpath...
+// } else if (bcelWeaver.needToReweaveWorld()) {
+// addAllKnownClassesToWeaveList();
+// }
+// Pause.pause("After adding binary sources to weaver");
+// bcelWeaver.weave(new WeaverAdaptor(this));
+// }
+//
+// private void notifyRequestor() {
+// for (Iterator iter = resultsPendingWeave.iterator(); iter.hasNext();) {
+// InterimResult iresult = (InterimResult) iter.next();
+// requestor.acceptResult(iresult.result.tagAsAccepted());
+// }
+// }
+//
+// private void cleanup() {
+// resultsPendingWeave = null;
+// isBatchCompile = false;
+// binarySources = new ArrayList();
+// resultSetForFullWeave = Collections.EMPTY_LIST;
+// super.reset();
+// Pause.pause("After notify and cleanup");
+// }
+//
+// private void addAllKnownClassesToWeaveList() {
+// // results pending weave already has some results from this (incremental) compile
+// // add in results from any other source
+// for (Iterator iter = resultSetForFullWeave.iterator(); iter.hasNext();) {
+// InterimResult ir = (InterimResult) iter.next();
+// if (!resultsPendingWeave.contains(ir)) { // equality based on source file name...
+// ir.result.hasBeenAccepted = false; // it may have been accepted before, start again
+// resultsPendingWeave.add(ir);
+// }
+// }
+// }
+//
+// // Helper class that feeds input to the weaver, and accepts results
+// // =======================================================================================
+// private static class WeaverAdaptor implements IClassFileProvider, IWeaveRequestor, Iterator {
+//
+// private AjCompiler compiler;
+// private Iterator resultIterator;
+// private int classFileIndex = 0;
+// private InterimResult nowProcessing;
+// private InterimResult lastReturnedResult;
+//// private CompilationResult lastAcceptedResult;
+// private boolean finalPhase = false;
+//
+//
+// public WeaverAdaptor(AjCompiler forCompiler) { this.compiler = forCompiler; }
+//
+// /* (non-Javadoc)
+// * @see org.aspectj.weaver.IClassFileProvider#getClassFileIterator()
+// */
+// public Iterator getClassFileIterator() {
+// classFileIndex = 0;
+// nowProcessing = null;
+// lastReturnedResult = null;
+// resultIterator = compiler.resultsPendingWeave.iterator();
+// return this;
+// }
+// /* (non-Javadoc)
+// * @see org.aspectj.weaver.IClassFileProvider#getRequestor()
+// */
+// public IWeaveRequestor getRequestor() {
+// return this;
+// }
+// /* (non-Javadoc)
+// * @see org.aspectj.weaver.IWeaveRequestor#acceptResult(org.aspectj.weaver.bcel.UnwovenClassFile)
+// */
+// public void acceptResult(UnwovenClassFile result) {
+// char[] key = result.getClassName().replace('.','/').toCharArray();
+// removeFromHashtable(lastReturnedResult.result.compiledTypes,key);
+// String className = result.getClassName().replace('.', '/');
+// AjClassFile ajcf = new AjClassFile(className.toCharArray(),
+// result.getBytes());
+// lastReturnedResult.result.record(ajcf.fileName(),ajcf);
+//// if ( f(lastAcceptedResult != null) && (lastReturnedResult.result != lastAcceptedResult)) {
+//// // we've got everything we need for lastAcceptedResult, push the result out
+//// // and free up the memory.
+//// finishedWith(lastAcceptedResult);
+//// }
+//// lastAcceptedResult = lastReturnedResult.result;
+// }
+//
+// private void finishedWith(InterimResult result) {
+// compiler.requestor.acceptResult(result.result.tagAsAccepted());
+// for (int i = 0; i < compiler.unitsToProcess.length; i++) {
+// if (compiler.unitsToProcess[i] != null) {
+// if (compiler.unitsToProcess[i].compilationResult == result.result) {
+// compiler.unitsToProcess[i] = null;
+// }
+// }
+// }
+// }
+//
+// /* (non-Javadoc)
+// * @see java.util.Iterator#hasNext()
+// */
+// public boolean hasNext() {
+// if (nowProcessing == null) {
+// if (!resultIterator.hasNext()) return false;
+// nowProcessing = (InterimResult) resultIterator.next();
+// classFileIndex = 0;
+// }
+// while (nowProcessing.unwovenClassFiles.length == 0 ) {
+// if (!resultIterator.hasNext()) return false;
+// nowProcessing = (InterimResult) resultIterator.next();
+// }
+// if (classFileIndex < nowProcessing.unwovenClassFiles.length) {
+// return true;
+// } else {
+// classFileIndex = 0;
+// if (!resultIterator.hasNext()) return false;
+// nowProcessing = (InterimResult) resultIterator.next();
+// while (nowProcessing.unwovenClassFiles.length == 0 ) {
+// if (!resultIterator.hasNext()) return false;
+// nowProcessing = (InterimResult) resultIterator.next();
+// }
+// }
+// return true;
+// }
+// /* (non-Javadoc)
+// * @see java.util.Iterator#next()
+// */
+// public Object next() {
+// if (!hasNext()) return null; // sets up indices correctly
+// if (finalPhase) {
+// if ((lastReturnedResult != null) && (lastReturnedResult != nowProcessing)) {
+// // we're done with the lastReturnedResult
+// finishedWith(lastReturnedResult);
+// }
+// }
+// lastReturnedResult = nowProcessing;
+// compiler.wmHandler.setCurrentResult(nowProcessing.result);
+// return nowProcessing.unwovenClassFiles[classFileIndex++];
+// }
+// /* (non-Javadoc)
+// * @see java.util.Iterator#remove()
+// */
+// public void remove() {
+// throw new UnsupportedOperationException();
+// }
+//
+// public void processingReweavableState() {}
+// public void addingTypeMungers() {}
+// public void weavingAspects() {}
+// public void weavingClasses() {finalPhase = true;}
+// public void weaveCompleted() {
+// if ((lastReturnedResult != null) && (!lastReturnedResult.result.hasBeenAccepted)) {
+// finishedWith(lastReturnedResult);
+// }
+// }
+//
+// private void removeFromHashtable(Hashtable table, char[] key) {
+// // jdt uses char[] as a key in the hashtable, which is not very useful as equality is based on being
+// // the same array, not having the same content.
+// String skey = new String(key);
+// char[] victim = null;
+// for (Enumeration iter = table.keys(); iter.hasMoreElements();) {
+// char[] thisKey = (char[]) iter.nextElement();
+// if (skey.equals(new String(thisKey))) {
+// victim = thisKey;
+// break;
+// }
+// }
+// if (victim != null) {
+// table.remove(victim);
+// }
+// }
+//}
+//
+// // Holder for intermediate form (class files)
+// // =======================================================================================
+// public static class InterimResult {
+// public CompilationResult result;
+// public UnwovenClassFile[] unwovenClassFiles; // longer term would be nice not to have two copies of
+// // the byte codes, one in result.classFiles and another
+// // in unwovenClassFiles;
+// private AjCompiler.IOutputClassFileNameProvider nameGen;
+//// public String[] classNames; // entry at index i is the name of the class at unwovenClassFiles[i]
+//// public BcelObjectType[] classTypes; // entry at i is the resolved type of the class at unwovenClassFiles[i]
+// public InterimResult(CompilationResult cr, AjCompiler.IOutputClassFileNameProvider np) {
+// result = cr;
+// nameGen = np;
+// unwovenClassFiles = ClassFileBasedByteCodeProvider.unwovenClassFilesFor(result,nameGen);
+// }
+//
+// public String fileName() {
+// return new String(result.fileName);
+// }
+//
+// public boolean equals(Object other) {
+// if( other == null || !(other instanceof InterimResult)) {
+// return false;
+// }
+// InterimResult ir = (InterimResult) other;
+// return fileName().equals(ir.fileName());
+// }
+// public int hashCode() {
+// return fileName().hashCode();
+// }
+// };
+//
+//
+//
+// // XXX lightweight subclass of ClassFile that only genuinely supports fileName and getBytes
+// // operations.
+// // =========================================================================================
+// private static class AjClassFile extends ClassFile {
+//
+// char[] filename;
+// byte[] bytes;
+//
+// public AjClassFile(char[] fileName, byte[] byteCodes) {
+// this.filename = fileName;
+// bytes = byteCodes;
+// }
+//
+// public char[] fileName() {
+// return filename;
+// }
+//
+// public byte[] getBytes() {
+// return bytes;
+// }
+// };
+//
+//
+// // Adaptor for ClassFiles that lets them act as the bytecode repository
+// // for UnwovenClassFiles (asking a ClassFile for its bytes causes a
+// // copy to be made).
+// private static class ClassFileBasedByteCodeProvider
+// implements UnwovenClassFileWithThirdPartyManagedBytecode.IByteCodeProvider {
+// private ClassFile cf;
+//
+// public ClassFileBasedByteCodeProvider(ClassFile cf) {
+// this.cf = cf;
+// }
+//
+// public byte[] getBytes() {
+// return cf.getBytes();
+// }
+//
+// public static UnwovenClassFile[] unwovenClassFilesFor(CompilationResult result,
+// AjCompiler.IOutputClassFileNameProvider nameProvider) {
+// ClassFile[] cfs = result.getClassFiles();
+// UnwovenClassFile[] ret = new UnwovenClassFile[cfs.length];
+// for (int i = 0; i < ret.length; i++) {
+// ClassFileBasedByteCodeProvider p = new ClassFileBasedByteCodeProvider(cfs[i]);
+// String fileName = nameProvider.getOutputClassFileName(cfs[i].fileName(), result);
+// ret[i] = new UnwovenClassFileWithThirdPartyManagedBytecode(fileName,p);
+// }
+// return ret;
+// }
+//
+// }
+//
+// // Inner class for handling messages produced by the weaver
+// // ==========================================================
+//
+// private class WeaverMessageHandler implements IMessageHandler {
+// IMessageHandler sink;
+// CompilationResult currentlyWeaving;
+//
+// public WeaverMessageHandler(IMessageHandler handler) {
+// this.sink = handler;
+// }
+//
+// public void setCurrentResult(CompilationResult result) {
+// currentlyWeaving = result;
+// }
+//
+// public boolean handleMessage(IMessage message) throws AbortException {
+// if (! (message.isError() || message.isWarning()) ) return sink.handleMessage(message);
+// // we only care about warnings and errors here...
+// ISourceLocation sLoc = message.getSourceLocation();
+// CompilationResult problemSource = currentlyWeaving;
+// if (problemSource == null) {
+// // must be a problem found during completeTypeBindings phase of begin to compile
+// if (sLoc instanceof EclipseSourceLocation) {
+// problemSource = ((EclipseSourceLocation)sLoc).getCompilationResult();
+// }
+// if (problemSource == null) {
+// // XXX this is ok for ajc, will have to do better for AJDT in time...
+// return sink.handleMessage(message);
+// }
+// }
+// int startPos = getStartPos(sLoc,problemSource);
+// int endPos = getEndPos(sLoc,problemSource);
+// int severity = message.isError() ? ProblemSeverities.Error : ProblemSeverities.Warning;
+// char[] filename = problemSource.fileName;
+// boolean usedBinarySourceFileName = false;
+// if (problemSource.isFromBinarySource()) {
+// if (sLoc != null) {
+// filename = sLoc.getSourceFile().getPath().toCharArray();
+// usedBinarySourceFileName = true;
+// }
+// }
+// ReferenceContext referenceContext = findReferenceContextFor(problemSource);
+// IProblem problem = problemReporter.createProblem(
+// filename,
+// IProblem.Unclassified,
+// new String[0],
+// new String[] {message.getMessage()},
+// severity,
+// startPos,
+// endPos,
+// sLoc != null ? sLoc.getLine() : 1,
+// referenceContext,
+// problemSource
+// );
+// IProblem[] seeAlso = buildSeeAlsoProblems(message.getExtraSourceLocations(),
+// problemSource,
+// usedBinarySourceFileName);
+// problem.setSeeAlsoProblems(seeAlso);
+// if (message.getDetails() != null) {
+// problem.setSupplementaryMessageInfo(message.getDetails());
+// }
+// problemReporter.record(problem, problemSource, referenceContext);
+// return true;
+//// if (weavingPhase) {
+//// return sink.handleMessage(message);
+//// } else {
+//// return true; // message will be reported back in compilation result later...
+//// }
+// }
+//
+// public boolean isIgnoring(Kind kind) {
+// return sink.isIgnoring(kind);
+// }
+//
+// private int getStartPos(ISourceLocation sLoc,CompilationResult result) {
+// int pos = 0;
+// if (sLoc == null) return 0;
+// int line = sLoc.getLine();
+// if (sLoc instanceof EclipseSourceLocation) {
+// pos = ((EclipseSourceLocation)sLoc).getStartPos();
+// } else {
+// if (line <= 1) return 0;
+// if (result != null) {
+// if ((result.lineSeparatorPositions != null) &&
+// (result.lineSeparatorPositions.length >= (line-1))) {
+// pos = result.lineSeparatorPositions[line-2] + 1;
+// }
+// }
+// }
+// return pos;
+// }
+//
+// private int getEndPos(ISourceLocation sLoc,CompilationResult result) {
+// int pos = 0;
+// if (sLoc == null) return 0;
+// int line = sLoc.getLine();
+// if (line <= 0) line = 1;
+// if (sLoc instanceof EclipseSourceLocation) {
+// pos = ((EclipseSourceLocation)sLoc).getEndPos();
+// } else {
+// if (result != null) {
+// if ((result.lineSeparatorPositions != null) &&
+// (result.lineSeparatorPositions.length >= line)) {
+// pos = result.lineSeparatorPositions[line -1] -1;
+// }
+// }
+// }
+// return pos;
+// }
+//
+// private ReferenceContext findReferenceContextFor(CompilationResult result) {
+// ReferenceContext context = null;
+// if (unitsToProcess == null) return null;
+// for (int i = 0; i < unitsToProcess.length; i++) {
+// if ((unitsToProcess[i] != null) &&
+// (unitsToProcess[i].compilationResult == result)) {
+// context = unitsToProcess[i];
+// break;
+// }
+// }
+// return context;
+// }
+//
+// private IProblem[] buildSeeAlsoProblems(List sourceLocations,
+// CompilationResult problemSource,
+// boolean usedBinarySourceFileName) {
+// int probLength = sourceLocations.size();
+// if (usedBinarySourceFileName) probLength++;
+// IProblem[] ret = new IProblem[probLength];
+// for (int i = 0; i < sourceLocations.size(); i++) {
+// ISourceLocation loc = (ISourceLocation) sourceLocations.get(i);
+// ret[i] = new DefaultProblem(loc.getSourceFile().getPath().toCharArray(),
+// "see also",
+// 0,
+// new String[] {},
+// ProblemSeverities.Ignore,
+// getStartPos(loc,null),
+// getEndPos(loc,null),
+// loc.getLine());
+// }
+// if (usedBinarySourceFileName) {
+// ret[ret.length -1] = new DefaultProblem(problemSource.fileName,"see also",0,new String[] {},
+// ProblemSeverities.Ignore,0,
+// 0,0);
+// }
+// return ret;
+// }
+// }
+//
+//}
--- /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.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.IMessageHandler;
+import org.aspectj.weaver.bcel.BcelWeaver;
+import org.aspectj.weaver.bcel.BcelWorld;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.Compiler;
+import org.eclipse.jdt.internal.compiler.ICompilerAdapter;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
+
+/**
+ * @author colyer
+ *
+ * Adapts standard JDT Compiler to add in AspectJ specific behaviours.
+ */
+public class AjCompilerAdapter implements ICompilerAdapter {
+
+ private Compiler compiler;
+ private BcelWeaver weaver;
+ private EclipseFactory eWorld;
+ private boolean isBatchCompile;
+ private boolean reportedErrors;
+ private boolean isXNoWeave;
+ private IIntermediateResultsRequestor intermediateResultsRequestor;
+ private IOutputClassFileNameProvider outputFileNameProvider;
+ private WeaverMessageHandler weaverMessageHandler;
+ private List /* InterimCompilationResult */ binarySources = new ArrayList();
+ private Collection /*InterimCompilationResult*/ resultSetForFullWeave = Collections.EMPTY_LIST;
+
+
+ List /*InterimResult*/ resultsPendingWeave = new ArrayList();
+
+ /**
+ * Create an adapter, and tell it everything it needs to now to drive the AspectJ
+ * parts of a compile cycle.
+ * @param compiler the JDT compiler that produces class files from source
+ * @param isBatchCompile true if this is a full build (non-incremental)
+ * @param world the bcelWorld used for type resolution during weaving
+ * @param weaver the weaver
+ * @param intRequestor recipient of interim compilation results from compiler (pre-weave)
+ * @param outputFileNameProvider implementor of a strategy providing output file names for results
+ * @param binarySourceEntries binary source that we didn't compile, but that we need to weave
+ * @param resultSetForFullWeave if we are doing an incremental build, and the weaver determines
+ * that we need to weave the world, this is the set of intermediate
+ * results that will be passed to the weaver.
+ * @param isXNoWeave
+ */
+ public AjCompilerAdapter(Compiler compiler,
+ boolean isBatchCompile,
+ BcelWorld world,
+ BcelWeaver weaver,
+ EclipseFactory eFactory,
+ IIntermediateResultsRequestor intRequestor,
+ IOutputClassFileNameProvider outputFileNameProvider,
+ Map binarySourceEntries, /* fileName |-> List<UnwovenClassFile> */
+ Collection /* InterimCompilationResult */ resultSetForFullWeave,
+ boolean isXNoWeave) {
+ this.compiler = compiler;
+ this.isBatchCompile = isBatchCompile;
+ this.weaver = weaver;
+ this.intermediateResultsRequestor = intRequestor;
+ this.outputFileNameProvider = outputFileNameProvider;
+ this.isXNoWeave = isXNoWeave;
+ 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) {
+ resultsPendingWeave = new ArrayList();
+ reportedErrors = false;
+ }
+
+ public void afterCompiling() {
+ try {
+ if (isXNoWeave || reportedErrors) {
+ // no point weaving... just tell the requestor we're done
+ notifyRequestor();
+ } else {
+ weave(); // notification happens as weave progresses...
+ }
+ } catch (IOException ex) {
+ AbortCompilation ac = new AbortCompilation();
+ ac.initCause(ex);
+ throw ac;
+ }
+ }
+
+ public void beforeProcessing(CompilationUnitDeclaration unit) {
+ eWorld.showMessage(IMessage.INFO, "compiling " + new String(unit.getFileName()), null, null);
+ }
+
+ public void afterProcessing(CompilationUnitDeclaration unit, int unitIndex) {
+ eWorld.finishedCompilationUnit(unit);
+ InterimCompilationResult intRes = new InterimCompilationResult(unit.compilationResult,outputFileNameProvider);
+ if (unit.compilationResult.hasErrors()) reportedErrors = true;
+
+ if (intermediateResultsRequestor != null) {
+ intermediateResultsRequestor.acceptResult(intRes);
+ }
+
+ if (isXNoWeave) {
+ acceptResult(unit.compilationResult);
+ } else {
+ resultsPendingWeave.add(intRes);
+ }
+ }
+
+ public void beforeResolving(CompilationUnitDeclaration unit, ICompilationUnit sourceUnit, boolean verifyMethods, boolean analyzeCode, boolean generateCode) {
+ resultsPendingWeave = new ArrayList();
+ reportedErrors = false;
+ }
+
+ public void afterResolving(CompilationUnitDeclaration unit, ICompilationUnit sourceUnit, boolean verifyMethods, boolean analyzeCode, boolean generateCode) {
+ InterimCompilationResult intRes = new InterimCompilationResult(unit.compilationResult,outputFileNameProvider);
+ if (unit.compilationResult.hasErrors()) reportedErrors = true;
+ if (isXNoWeave || !generateCode) {
+ acceptResult(unit.compilationResult);
+ } else if (generateCode){
+ resultsPendingWeave.add(intRes);
+ try {
+ weave();
+ } catch (IOException ex) {
+ AbortCompilation ac = new AbortCompilation();
+ ac.initCause(ex);
+ throw ac;
+ }
+ }
+ }
+
+ // helper methods...
+ // ==================================================================================
+
+ /*
+ * Called from the weaverAdapter once it has finished weaving the class files
+ * associated with a given compilation result.
+ */
+ public void acceptResult(CompilationResult result) {
+ compiler.requestor.acceptResult(result.tagAsAccepted());
+ if (compiler.unitsToProcess != null) {
+ for (int i = 0; i < compiler.unitsToProcess.length; i++) {
+ if (compiler.unitsToProcess[i] != null) {
+ if (compiler.unitsToProcess[i].compilationResult == result) {
+ compiler.unitsToProcess[i] = null;
+ }
+ }
+ }
+ }
+ }
+
+ private void addBinarySource(Map binarySourceEntries) {
+ // Map is fileName |-> List<UnwovenClassFile>
+ for (Iterator binIter = binarySourceEntries.keySet().iterator(); binIter.hasNext();) {
+ String sourceFileName = (String) binIter.next();
+ List unwovenClassFiles = (List) binarySourceEntries.get(sourceFileName);
+
+ CompilationResult result = new CompilationResult(sourceFileName.toCharArray(),0,0,20);
+ result.noSourceAvailable();
+ InterimCompilationResult binarySource =
+ new InterimCompilationResult(result,unwovenClassFiles);
+ binarySources.add(binarySource);
+ }
+ }
+
+ private void notifyRequestor() {
+ for (Iterator iter = resultsPendingWeave.iterator(); iter.hasNext();) {
+ InterimCompilationResult iresult = (InterimCompilationResult) iter.next();
+ compiler.requestor.acceptResult(iresult.result().tagAsAccepted());
+ }
+ }
+
+ private void weave() throws IOException {
+ // ensure weaver state is set up correctly
+ for (Iterator iter = resultsPendingWeave.iterator(); iter.hasNext();) {
+ InterimCompilationResult iresult = (InterimCompilationResult) iter.next();
+ for (int i = 0; i < iresult.unwovenClassFiles().length; i++) {
+ weaver.addClassFile(iresult.unwovenClassFiles()[i]);
+ }
+ }
+
+ weaver.prepareForWeave();
+
+ if (isBatchCompile) {
+ resultsPendingWeave.addAll(binarySources);
+ // passed into the compiler, the set of classes in injars and inpath...
+ } else if (weaver.needToReweaveWorld()) {
+ addAllKnownClassesToWeaveList();
+ }
+
+ weaver.weave(new WeaverAdapter(this,weaverMessageHandler));
+ }
+
+ private void addAllKnownClassesToWeaveList() {
+ // results pending weave already has some results from this (incremental) compile
+ // add in results from any other source
+ for (Iterator iter = resultSetForFullWeave.iterator(); iter.hasNext();) {
+ InterimCompilationResult ir = (InterimCompilationResult) iter.next();
+ if (!resultsPendingWeave.contains(ir)) { // equality based on source file name...
+ ir.result().hasBeenAccepted = false; // it may have been accepted before, start again
+ resultsPendingWeave.add(ir);
+ }
+ }
+ }
+}
--- /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 org.aspectj.weaver.bcel.UnwovenClassFile;
+import org.aspectj.weaver.bcel.UnwovenClassFileWithThirdPartyManagedBytecode;
+import org.eclipse.jdt.internal.compiler.ClassFile;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+
+/**
+ * @author colyer
+ *
+ * Adaptor for ClassFiles that lets them act as the bytecode repository
+ * for UnwovenClassFiles (asking a ClassFile for its bytes causes a
+ * copy to be made).
+ */
+public class ClassFileBasedByteCodeProvider
+ implements UnwovenClassFileWithThirdPartyManagedBytecode.IByteCodeProvider{
+
+ private ClassFile cf;
+
+ public ClassFileBasedByteCodeProvider(ClassFile cf) {
+ this.cf = cf;
+ }
+
+ public byte[] getBytes() {
+ return cf.getBytes();
+ }
+
+ public static UnwovenClassFile[] unwovenClassFilesFor(CompilationResult result,
+ IOutputClassFileNameProvider nameProvider) {
+ ClassFile[] cfs = result.getClassFiles();
+ UnwovenClassFile[] ret = new UnwovenClassFile[cfs.length];
+ for (int i = 0; i < ret.length; i++) {
+ ClassFileBasedByteCodeProvider p = new ClassFileBasedByteCodeProvider(cfs[i]);
+ String fileName = nameProvider.getOutputClassFileName(cfs[i].fileName(), result);
+ ret[i] = new UnwovenClassFileWithThirdPartyManagedBytecode(fileName,p);
+ }
+ return ret;
+ }
+
+}
--- /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;
+
+/**
+ * @author colyer
+ *
+ * Receives intermediate results from the compiler (post java-compile, but
+ * before weaving).
+ */
+public interface IIntermediateResultsRequestor {
+ void acceptResult(InterimCompilationResult intRes);
+}
--- /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 org.eclipse.jdt.internal.compiler.CompilationResult;
+
+/**
+ * @author colyer
+ *
+ * Implementors of this interface know how to create an output destination name
+ * for a given compilation result and class file. This interface capures the variation
+ * in strategy between ajc command-line compiles and an AJDT driven compilation.
+ */
+public interface IOutputClassFileNameProvider {
+ String getOutputClassFileName(char[] eclipseClassFileName, CompilationResult result);
+}
--- /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.List;
+
+import org.aspectj.weaver.bcel.UnwovenClassFile;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+
+/**
+ * Holds a compilation result produced by the Java compilation phase,
+ * ready for weaving in the weave phase.
+ * NOTE: This class defines equality based solely on the fileName
+ * of the compiled file (not the bytecodes produced for example)
+ */
+public class InterimCompilationResult {
+
+ private CompilationResult result;
+ private UnwovenClassFile[] unwovenClassFiles; // longer term would be nice not to have two copies of
+ // the byte codes, one in result.classFiles and another
+ // in unwovenClassFiles;
+
+ public InterimCompilationResult(CompilationResult cr,
+ IOutputClassFileNameProvider np) {
+ result = cr;
+ unwovenClassFiles = ClassFileBasedByteCodeProvider.unwovenClassFilesFor(result,np);
+ }
+
+ public InterimCompilationResult(CompilationResult cr, List ucfList) {
+ result = cr;
+ unwovenClassFiles = new UnwovenClassFile[ucfList.size()];
+ for (int i=0; i < ucfList.size(); i++) {
+ UnwovenClassFile element = (UnwovenClassFile) ucfList.get(i);
+ unwovenClassFiles[i] = element;
+ AjClassFile ajcf = new AjClassFile(element.getClassName().replace('.', '/').toCharArray(),
+ element.getBytes());
+ result.record(ajcf.fileName(),ajcf);
+ }
+ }
+
+ public CompilationResult result() { return result; }
+
+ public UnwovenClassFile[] unwovenClassFiles() { return unwovenClassFiles; }
+
+ public String fileName() {
+ return new String(result.fileName);
+ }
+
+ public boolean equals(Object other) {
+ if( other == null || !(other instanceof InterimCompilationResult)) {
+ return false;
+ }
+ InterimCompilationResult ir = (InterimCompilationResult) other;
+ return fileName().equals(ir.fileName());
+ }
+ public int hashCode() {
+ return fileName().hashCode();
+ }
+
+}
--- /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.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+
+import org.aspectj.weaver.IClassFileProvider;
+import org.aspectj.weaver.IWeaveRequestor;
+import org.aspectj.weaver.bcel.UnwovenClassFile;
+
+/**
+ * @author colyer
+ * This class provides the weaver with a source of class files to weave (via the
+ * iterator and IClassFileProvider interfaces). It receives results back from the
+ * weaver via the IWeaveRequestor interface.
+ */
+public class WeaverAdapter implements IClassFileProvider, IWeaveRequestor, Iterator {
+
+ private AjCompilerAdapter compilerAdapter;
+ private Iterator resultIterator;
+ private int classFileIndex = 0;
+ private InterimCompilationResult nowProcessing;
+ private InterimCompilationResult lastReturnedResult;
+ private WeaverMessageHandler weaverMessageHandler;
+ private boolean finalPhase = false;
+
+
+ public WeaverAdapter(AjCompilerAdapter forCompiler,
+ WeaverMessageHandler weaverMessageHandler) {
+ this.compilerAdapter = forCompiler;
+ this.weaverMessageHandler = weaverMessageHandler;
+ }
+
+ /* (non-Javadoc)
+ * @see org.aspectj.weaver.IClassFileProvider#getClassFileIterator()
+ */
+ public Iterator getClassFileIterator() {
+ classFileIndex = 0;
+ nowProcessing = null;
+ lastReturnedResult = null;
+ resultIterator = compilerAdapter.resultsPendingWeave.iterator();
+ return this;
+ }
+ /* (non-Javadoc)
+ * @see org.aspectj.weaver.IClassFileProvider#getRequestor()
+ */
+ public IWeaveRequestor getRequestor() {
+ return this;
+ }
+
+ // Iteration
+ // ================================================================
+
+ /* (non-Javadoc)
+ * @see java.util.Iterator#hasNext()
+ */
+ public boolean hasNext() {
+ if (nowProcessing == null) {
+ if (!resultIterator.hasNext()) return false;
+ nowProcessing = (InterimCompilationResult) resultIterator.next();
+ classFileIndex = 0;
+ }
+ while (nowProcessing.unwovenClassFiles().length == 0 ) {
+ if (!resultIterator.hasNext()) return false;
+ nowProcessing = (InterimCompilationResult) resultIterator.next();
+ }
+ if (classFileIndex < nowProcessing.unwovenClassFiles().length) {
+ return true;
+ } else {
+ classFileIndex = 0;
+ if (!resultIterator.hasNext()) return false;
+ nowProcessing = (InterimCompilationResult) resultIterator.next();
+ while (nowProcessing.unwovenClassFiles().length == 0 ) {
+ if (!resultIterator.hasNext()) return false;
+ nowProcessing = (InterimCompilationResult) resultIterator.next();
+ }
+ }
+ return true;
+ }
+ /* (non-Javadoc)
+ * @see java.util.Iterator#next()
+ */
+ public Object next() {
+ if (!hasNext()) return null; // sets up indices correctly
+ if (finalPhase) {
+ if ((lastReturnedResult != null) && (lastReturnedResult != nowProcessing)) {
+ // we're done with the lastReturnedResult
+ finishedWith(lastReturnedResult);
+ }
+ }
+ lastReturnedResult = nowProcessing;
+ weaverMessageHandler.setCurrentResult(nowProcessing.result());
+ return nowProcessing.unwovenClassFiles()[classFileIndex++];
+ }
+ /* (non-Javadoc)
+ * @see java.util.Iterator#remove()
+ */
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+
+ // IWeaveRequestor
+ // =====================================================================================
+
+ // weave phases as indicated by bcelWeaver...
+ public void processingReweavableState() {}
+ public void addingTypeMungers() {}
+ public void weavingAspects() {}
+ public void weavingClasses() {finalPhase = true;}
+
+ public void weaveCompleted() {
+ if ((lastReturnedResult != null) && (!lastReturnedResult.result().hasBeenAccepted)) {
+ finishedWith(lastReturnedResult);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.aspectj.weaver.IWeaveRequestor#acceptResult(org.aspectj.weaver.bcel.UnwovenClassFile)
+ */
+ public void acceptResult(UnwovenClassFile result) {
+ char[] key = result.getClassName().replace('.','/').toCharArray();
+ removeFromHashtable(lastReturnedResult.result().compiledTypes,key);
+ String className = result.getClassName().replace('.', '/');
+ AjClassFile ajcf = new AjClassFile(className.toCharArray(),
+ result.getBytes());
+ lastReturnedResult.result().record(ajcf.fileName(),ajcf);
+ }
+
+ // helpers...
+ // =================================================================
+
+ private void finishedWith(InterimCompilationResult result) {
+ compilerAdapter.acceptResult(result.result());
+ }
+
+ private void removeFromHashtable(Hashtable table, char[] key) {
+ // jdt uses char[] as a key in the hashtable, which is not very useful as equality is based on being
+ // the same array, not having the same content.
+ String skey = new String(key);
+ char[] victim = null;
+ for (Enumeration iter = table.keys(); iter.hasMoreElements();) {
+ char[] thisKey = (char[]) iter.nextElement();
+ if (skey.equals(new String(thisKey))) {
+ victim = thisKey;
+ break;
+ }
+ }
+ if (victim != null) {
+ table.remove(victim);
+ }
+ }
+}
\ No newline at end of file
--- /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.List;
+
+import org.aspectj.ajdt.internal.compiler.lookup.EclipseSourceLocation;
+import org.aspectj.bridge.AbortException;
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.IMessageHandler;
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.IMessage.Kind;
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.Compiler;
+import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
+import org.eclipse.jdt.internal.compiler.problem.DefaultProblem;
+import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
+
+/**
+ * @author colyer
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class WeaverMessageHandler implements IMessageHandler {
+ private IMessageHandler sink;
+ private CompilationResult currentlyWeaving;
+ private Compiler compiler;
+
+ public WeaverMessageHandler(IMessageHandler handler, Compiler compiler) {
+ this.sink = handler;
+ this.compiler = compiler;
+ }
+
+ public void setCurrentResult(CompilationResult result) {
+ currentlyWeaving = result;
+ }
+
+ public boolean handleMessage(IMessage message) throws AbortException {
+ if (! (message.isError() || message.isWarning()) ) return sink.handleMessage(message);
+ // we only care about warnings and errors here...
+ ISourceLocation sLoc = message.getSourceLocation();
+ CompilationResult problemSource = currentlyWeaving;
+ if (problemSource == null) {
+ // must be a problem found during completeTypeBindings phase of begin to compile
+ if (sLoc instanceof EclipseSourceLocation) {
+ problemSource = ((EclipseSourceLocation)sLoc).getCompilationResult();
+ }
+ if (problemSource == null) {
+ // XXX this is ok for ajc, will have to do better for AJDT in time...
+ return sink.handleMessage(message);
+ }
+ }
+ int startPos = getStartPos(sLoc,problemSource);
+ int endPos = getEndPos(sLoc,problemSource);
+ int severity = message.isError() ? ProblemSeverities.Error : ProblemSeverities.Warning;
+ char[] filename = problemSource.fileName;
+ boolean usedBinarySourceFileName = false;
+ if (problemSource.isFromBinarySource()) {
+ if (sLoc != null) {
+ filename = sLoc.getSourceFile().getPath().toCharArray();
+ usedBinarySourceFileName = true;
+ }
+ }
+ ReferenceContext referenceContext = findReferenceContextFor(problemSource);
+ IProblem problem = compiler.problemReporter.createProblem(
+ filename,
+ IProblem.Unclassified,
+ new String[0],
+ new String[] {message.getMessage()},
+ severity,
+ startPos,
+ endPos,
+ sLoc != null ? sLoc.getLine() : 1,
+ referenceContext,
+ problemSource
+ );
+ IProblem[] seeAlso = buildSeeAlsoProblems(message.getExtraSourceLocations(),
+ problemSource,
+ usedBinarySourceFileName);
+ problem.setSeeAlsoProblems(seeAlso);
+ if (message.getDetails() != null) {
+ problem.setSupplementaryMessageInfo(message.getDetails());
+ }
+ compiler.problemReporter.record(problem, problemSource, referenceContext);
+ return true;
+ }
+
+ public boolean isIgnoring(Kind kind) {
+ return sink.isIgnoring(kind);
+ }
+
+ private int getStartPos(ISourceLocation sLoc,CompilationResult result) {
+ int pos = 0;
+ if (sLoc == null) return 0;
+ int line = sLoc.getLine();
+ if (sLoc instanceof EclipseSourceLocation) {
+ pos = ((EclipseSourceLocation)sLoc).getStartPos();
+ } else {
+ if (line <= 1) return 0;
+ if (result != null) {
+ if ((result.lineSeparatorPositions != null) &&
+ (result.lineSeparatorPositions.length >= (line-1))) {
+ pos = result.lineSeparatorPositions[line-2] + 1;
+ }
+ }
+ }
+ return pos;
+ }
+
+ private int getEndPos(ISourceLocation sLoc,CompilationResult result) {
+ int pos = 0;
+ if (sLoc == null) return 0;
+ int line = sLoc.getLine();
+ if (line <= 0) line = 1;
+ if (sLoc instanceof EclipseSourceLocation) {
+ pos = ((EclipseSourceLocation)sLoc).getEndPos();
+ } else {
+ if (result != null) {
+ if ((result.lineSeparatorPositions != null) &&
+ (result.lineSeparatorPositions.length >= line)) {
+ pos = result.lineSeparatorPositions[line -1] -1;
+ }
+ }
+ }
+ return pos;
+ }
+
+ private ReferenceContext findReferenceContextFor(CompilationResult result) {
+ ReferenceContext context = null;
+ if (compiler.unitsToProcess == null) return null;
+ for (int i = 0; i < compiler.unitsToProcess.length; i++) {
+ if ((compiler.unitsToProcess[i] != null) &&
+ (compiler.unitsToProcess[i].compilationResult == result)) {
+ context = compiler.unitsToProcess[i];
+ break;
+ }
+ }
+ return context;
+ }
+
+ private IProblem[] buildSeeAlsoProblems(List sourceLocations,
+ CompilationResult problemSource,
+ boolean usedBinarySourceFileName) {
+ int probLength = sourceLocations.size();
+ if (usedBinarySourceFileName) probLength++;
+ IProblem[] ret = new IProblem[probLength];
+ for (int i = 0; i < sourceLocations.size(); i++) {
+ ISourceLocation loc = (ISourceLocation) sourceLocations.get(i);
+ ret[i] = new DefaultProblem(loc.getSourceFile().getPath().toCharArray(),
+ "see also",
+ 0,
+ new String[] {},
+ ProblemSeverities.Ignore,
+ getStartPos(loc,null),
+ getEndPos(loc,null),
+ loc.getLine());
+ }
+ if (usedBinarySourceFileName) {
+ ret[ret.length -1] = new DefaultProblem(problemSource.fileName,"see also",0,new String[] {},
+ ProblemSeverities.Ignore,0,
+ 0,0);
+ }
+ return ret;
+ }
+}
+
this.startPos = startPos;
this.endPos = endPos;
}
+
+ public CompilationResult getCompilationResult() {
+ return result;
+ }
+
+ public int getStartPos() {
+ return startPos;
+ }
+
+ public int getEndPos() {
+ return endPos;
+ }
public File getSourceFile() {
if (null == file) {
}
public boolean isExposedToWeaver() {
- return delegate.isExposedToWeaver(); //??? where does this belong
+ return (delegate == null) || delegate.isExposedToWeaver(); //??? where does this belong
}
public WeaverStateInfo getWeaverState() {
public static abstract class ConcreteName {
//protected ISourceContext sourceContext;
protected boolean exposedToWeaver;
- ResolvedTypeX.Name resolvedTypeX;
+ protected ResolvedTypeX.Name resolvedTypeX;
public ConcreteName(ResolvedTypeX.Name resolvedTypeX, boolean exposedToWeaver) {
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.WeakHashMap;
import org.aspectj.asm.IHierarchy;
import org.aspectj.bridge.IMessageHandler;
protected IMessageHandler messageHandler = IMessageHandler.SYSTEM_ERR;
protected ICrossReferenceHandler xrefHandler = null;
- protected Map typeMap = new HashMap(); // Signature to ResolvedType
+ protected TypeMap typeMap = new TypeMap(); // Signature to ResolvedType
protected CrosscuttingMembersSet crosscuttingMembersSet = new CrosscuttingMembersSet(this);
public ResolvedTypeX resolve(TypeX ty, boolean allowMissing) {
//System.out.println("resolve: " + ty + " world " + typeMap.keySet());
String signature = ty.getSignature();
- ResolvedTypeX ret = (ResolvedTypeX)typeMap.get(signature);
+ ResolvedTypeX ret = typeMap.get(signature);
if (ret != null) return ret;
if (ty.isArray()) {
return ret;
}
-
+
+// public void clearUnexposed() {
+// List toRemove = new ArrayList();
+// for (Iterator iter = typeMap.keySet().iterator(); iter.hasNext();) {
+// String sig = (String) iter.next();
+// ResolvedTypeX x = (ResolvedTypeX) typeMap.get(sig);
+// if (!x.isExposedToWeaver() && (!x.isPrimitive())) toRemove.add(sig);
+// }
+// for (Iterator iter = toRemove.iterator(); iter.hasNext();) {
+// typeMap.remove(iter.next());
+// }
+// }
+//
+// // for testing...
+// public void dumpTypeMap() {
+// int exposed = 0;
+// for (Iterator iter = typeMap.keySet().iterator(); iter.hasNext();) {
+// String sig = (String) iter.next();
+// ResolvedTypeX x = (ResolvedTypeX) typeMap.get(sig);
+// if (x.isExposedToWeaver()) exposed++;
+// }
+// System.out.println("type map contains " + typeMap.size() + " entries, " + exposed + " exposed to weaver");
+// }
+//
+// public void deepDumpTypeMap() {
+// for (Iterator iter = typeMap.keySet().iterator(); iter.hasNext();) {
+// String sig = (String) iter.next();
+// ResolvedTypeX x = (ResolvedTypeX) typeMap.get(sig);
+// if (! (x instanceof ResolvedTypeX.Name)) {
+// System.out.println(sig + " -> " + x.getClass().getName() + ", " + x.getClassName());
+// } else {
+// ResolvedTypeX.ConcreteName cname = ((ResolvedTypeX.Name)x).getDelegate();
+// System.out.println(sig + " -> " + cname.getClass().getName() + ", " + cname.toString());
+// }
+// }
+//
+// }
+
+ // Map of types in the world, with soft links to expendable ones
+ protected static class TypeMap {
+ private Map tMap = new HashMap();
+ private Map expendableMap = new WeakHashMap();
+
+ public ResolvedTypeX put(String key, ResolvedTypeX type) {
+ if (isExpendable(type)) {
+ return (ResolvedTypeX) expendableMap.put(key,type);
+ } else {
+ return (ResolvedTypeX) tMap.put(key,type);
+ }
+ }
+
+ public ResolvedTypeX get(String key) {
+ ResolvedTypeX ret = (ResolvedTypeX) tMap.get(key);
+ if (ret == null) ret = (ResolvedTypeX) expendableMap.get(key);
+ return ret;
+ }
+
+ public ResolvedTypeX remove(String key) {
+ ResolvedTypeX ret = (ResolvedTypeX) tMap.remove(key);
+ if (ret == null) ret = (ResolvedTypeX) expendableMap.remove(key);
+ return ret;
+ }
+
+ private boolean isExpendable(ResolvedTypeX type) {
+ return (
+ (type != null) &&
+ (!type.isExposedToWeaver()) &&
+ (!type.isPrimitive())
+ );
+ }
+ }
}
// ----
public boolean weave() {
-
+
if (clazz.isWoven() && !clazz.isReweavable()) {
world.showMessage(IMessage.ERROR,
"class \'" + clazz.getType().getName() + "\' is already woven and has not been built with -Xreweavable",
// we want to "touch" all aspects
if (clazz.getType().isAspect()) isChanged = true;
-
-
+
// start by munging all typeMungers
for (Iterator i = typeMungers.iterator(); i.hasNext(); ) {
Object o = i.next();
if (addedSuperInitializersAsList == null) {
throw new BCException("circularity in inter-types");
}
-
+
// this will create a static initializer if there isn't one
// this is in just as bad taste as NOPs
LazyMethodGen staticInit = clazz.getStaticInitializer();
staticInit.getBody().insert(genInitInstructions(addedClassInitializers, true));
-
// now go through each method, and match against each method. This
// sets up each method's {@link LazyMethodGen#matchedShadows} field,
// and it also possibly adds to {@link #initializationShadows}.
}
if (! isChanged) return false;
+
// now we weave all but the initialization shadows
for (Iterator i = methodGens.iterator(); i.hasNext();) {
LazyMethodGen mg = (LazyMethodGen)i.next();
List shadowAccumulator = new ArrayList();
// we want to match ajsynthetic constructors...
if (mg.getName().equals("<init>")) {
- // XXX the enclosing join point is wrong for things before ignoreMe.
- InstructionHandle superOrThisCall = findSuperOrThisCall(mg);
-
- // we don't walk bodies of things where it's a wrong constructor thingie
- if (superOrThisCall == null) return false;
-
- enclosingShadow = BcelShadow.makeConstructorExecution(world, mg, superOrThisCall);
-
- // walk the body
- boolean beforeSuperOrThisCall = true;
- if (shouldWeaveBody(mg)) {
- if (canMatchBodyShadows) {
- for (InstructionHandle h = mg.getBody().getStart();
- h != null;
- h = h.getNext()) {
- if (h == superOrThisCall) {
- beforeSuperOrThisCall = false;
- continue;
- }
- match(mg, h, beforeSuperOrThisCall ? null : enclosingShadow, shadowAccumulator);
- }
- }
- match(enclosingShadow, shadowAccumulator);
- }
-
- // XXX we don't do pre-inits of interfaces
-
- // now add interface inits
- if (superOrThisCall != null && ! isThisCall(superOrThisCall)) {
- InstructionHandle curr = enclosingShadow.getRange().getStart();
- for (Iterator i = addedSuperInitializersAsList.iterator(); i.hasNext(); ) {
- IfaceInitList l = (IfaceInitList) i.next();
-
- Member ifaceInitSig = AjcMemberMaker.interfaceConstructor(l.onType);
-
- BcelShadow initShadow =
- BcelShadow.makeIfaceInitialization(world, mg, ifaceInitSig);
-
- // insert code in place
- InstructionList inits = genInitInstructions(l.list, false);
- if (match(initShadow, shadowAccumulator) || !inits.isEmpty()) {
- initShadow.initIfaceInitializer(curr);
- initShadow.getRange().insert(inits, Range.OutsideBefore);
- }
- }
-
- // now we add our initialization code
- InstructionList inits = genInitInstructions(addedThisInitializers, false);
- enclosingShadow.getRange().insert(inits, Range.OutsideBefore);
- }
-
- // actually, you only need to inline the self constructors that are
- // in a particular group (partition the constructors into groups where members
- // call or are called only by those in the group). Then only inline
- // constructors
- // in groups where at least one initialization jp matched. Future work.
- boolean addedInitialization =
- match(
- BcelShadow.makeUnfinishedInitialization(world, mg),
- initializationShadows);
- addedInitialization |=
- match(
- BcelShadow.makeUnfinishedPreinitialization(world, mg),
- initializationShadows);
- mg.matchedShadows = shadowAccumulator;
- return addedInitialization || !shadowAccumulator.isEmpty();
+ return matchInit(mg, shadowAccumulator);
} else if (!shouldWeaveBody(mg)) { //.isAjSynthetic()) {
return false;
} else {
}
}
+ private boolean matchInit(LazyMethodGen mg, List shadowAccumulator) {
+ BcelShadow enclosingShadow;
+ // XXX the enclosing join point is wrong for things before ignoreMe.
+ InstructionHandle superOrThisCall = findSuperOrThisCall(mg);
+
+ // we don't walk bodies of things where it's a wrong constructor thingie
+ if (superOrThisCall == null) return false;
+
+ enclosingShadow = BcelShadow.makeConstructorExecution(world, mg, superOrThisCall);
+
+ // walk the body
+ boolean beforeSuperOrThisCall = true;
+ if (shouldWeaveBody(mg)) {
+ if (canMatchBodyShadows) {
+ for (InstructionHandle h = mg.getBody().getStart();
+ h != null;
+ h = h.getNext()) {
+ if (h == superOrThisCall) {
+ beforeSuperOrThisCall = false;
+ continue;
+ }
+ match(mg, h, beforeSuperOrThisCall ? null : enclosingShadow, shadowAccumulator);
+ }
+ }
+ match(enclosingShadow, shadowAccumulator);
+ }
+
+ // XXX we don't do pre-inits of interfaces
+
+ // now add interface inits
+ if (superOrThisCall != null && ! isThisCall(superOrThisCall)) {
+ InstructionHandle curr = enclosingShadow.getRange().getStart();
+ for (Iterator i = addedSuperInitializersAsList.iterator(); i.hasNext(); ) {
+ IfaceInitList l = (IfaceInitList) i.next();
+
+ Member ifaceInitSig = AjcMemberMaker.interfaceConstructor(l.onType);
+
+ BcelShadow initShadow =
+ BcelShadow.makeIfaceInitialization(world, mg, ifaceInitSig);
+
+ // insert code in place
+ InstructionList inits = genInitInstructions(l.list, false);
+ if (match(initShadow, shadowAccumulator) || !inits.isEmpty()) {
+ initShadow.initIfaceInitializer(curr);
+ initShadow.getRange().insert(inits, Range.OutsideBefore);
+ }
+ }
+
+ // now we add our initialization code
+ InstructionList inits = genInitInstructions(addedThisInitializers, false);
+ enclosingShadow.getRange().insert(inits, Range.OutsideBefore);
+ }
+
+ // actually, you only need to inline the self constructors that are
+ // in a particular group (partition the constructors into groups where members
+ // call or are called only by those in the group). Then only inline
+ // constructors
+ // in groups where at least one initialization jp matched. Future work.
+ boolean addedInitialization =
+ match(
+ BcelShadow.makeUnfinishedInitialization(world, mg),
+ initializationShadows);
+ addedInitialization |=
+ match(
+ BcelShadow.makeUnfinishedPreinitialization(world, mg),
+ initializationShadows);
+ mg.matchedShadows = shadowAccumulator;
+ return addedInitialization || !shadowAccumulator.isEmpty();
+ }
+
private boolean shouldWeaveBody(LazyMethodGen mg) {
if (mg.isAjSynthetic()) return mg.getName().equals("<clinit>");
AjAttribute.EffectiveSignatureAttribute a = mg.getEffectiveSignature();
isObject = (javaClass.getSuperclassNameIndex() == 0);
unpackAspectAttributes();
}
-
+
+ public void finishedWith() {
+ // memory usage experiments....
+// this.interfaces = null;
+// this.superClass = null;
+// this.fields = null;
+// this.methods = null;
+// this.pointcuts = null;
+// this.perClause = null;
+// this.weaverState = null;
+// this.lazyClassGen = null;
+ // this next line frees up memory, but need to understand incremental implications
+ // before leaving it in.
+// getResolvedTypeX().setSourceContext(null);
+ }
+
public WeaverStateInfo getWeaverState() {
return weaverState;
}
package org.aspectj.weaver.bcel;
-import java.io.BufferedOutputStream;
+
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileFilter;
import org.aspectj.util.FileUtil;
import org.aspectj.weaver.ConcreteTypeMunger;
import org.aspectj.weaver.CrosscuttingMembersSet;
+import org.aspectj.weaver.IClassFileProvider;
+import org.aspectj.weaver.IWeaveRequestor;
import org.aspectj.weaver.IWeaver;
import org.aspectj.weaver.NewParentTypeMunger;
import org.aspectj.weaver.ResolvedTypeMunger;
private double progressPerClassFile;
private boolean inReweavableMode = false;
- private boolean compressReweavableAttributes = false;
public BcelWeaver(BcelWorld world) {
super();
}
// ---- fields
- private Map sourceJavaClasses = new HashMap(); /* String -> UnwovenClassFile */
+// private Map sourceJavaClasses = new HashMap(); /* String -> UnwovenClassFile */
private List addedClasses = new ArrayList(); /* List<UnovenClassFile> */
private List deletedTypenames = new ArrayList(); /* List<String> */
private Map resources = new HashMap(); /* String -> UnwovenClassFile */
// The ANT copy task should be used to copy resources across.
private final static boolean CopyResourcesFromInpathDirectoriesToOutput=false;
+ private Set alreadyConfirmedReweavableState;
/**
* Add any .class files in the directory to the outdir. Anything other than .class files in
* the directory (or its subdirectories) are considered resources and are also copied.
*
*/
- public void addDirectoryContents(File inFile,File outDir) throws IOException {
+ public List addDirectoryContents(File inFile,File outDir) throws IOException {
+ List addedClassFiles = new ArrayList();
// Get a list of all files (i.e. everything that isnt a directory)
File[] files = FileUtil.listFiles(inFile,new FileFilter() {
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);
fis.close();
}
+ return addedClassFiles;
}
/** Adds all class files in the jar
*/
- public void addJarFile(File inFile, File outDir, boolean canBeDirectory) throws IOException {
+ public List addJarFile(File inFile, File outDir, boolean canBeDirectory) throws IOException {
// System.err.println("? addJarFile(" + inFile + ", " + outDir + ")");
+ List addedClassFiles = new ArrayList();
needToReweaveWorld = true;
// Is this a directory we are looking at?
if (inFile.isDirectory() && canBeDirectory) {
- addDirectoryContents(inFile,outDir);
+ addedClassFiles.addAll(addDirectoryContents(inFile,outDir));
} else {
ZipInputStream inStream = new ZipInputStream(new FileInputStream(inFile)); //??? buffered
if (filename.endsWith(".class")) {
this.addClassFile(classFile);
+ addedClassFiles.add(classFile);
}
else if (!entry.isDirectory()) {
}
inStream.close();
}
+
+ return addedClassFiles;
}
public void addResource(String name, File inPath, File outDir) throws IOException {
addResource(name,resourceFile);
}
}
-
+
+ public boolean needToReweaveWorld() {
+ return needToReweaveWorld;
+ }
+
/** Should be addOrReplace
*/
public void addClassFile(UnwovenClassFile classFile) {
addedClasses.add(classFile);
- if (null != sourceJavaClasses.put(classFile.getClassName(), classFile)) {
-// throw new RuntimeException(classFile.getClassName());
- }
+// if (null != sourceJavaClasses.put(classFile.getClassName(), classFile)) {
+//// throw new RuntimeException(classFile.getClassName());
+// }
world.addSourceObjectType(classFile.getJavaClass());
}
public void deleteClassFile(String typename) {
deletedTypenames.add(typename);
- sourceJavaClasses.remove(typename);
+// sourceJavaClasses.remove(typename);
world.deleteSourceObjectType(TypeX.forName(typename));
}
});
}
- public void dumpUnwoven(File file) throws IOException {
- BufferedOutputStream os = FileUtil.makeOutputStream(file);
- this.zipOutputStream = new ZipOutputStream(os);
- dumpUnwoven();
- /* BUG 40943*/
- dumpResourcesToOutJar();
- zipOutputStream.close(); //this flushes and closes the acutal file
- }
-
-
- public void dumpUnwoven() throws IOException {
- Collection filesToDump = new HashSet(sourceJavaClasses.values());
- for (Iterator i = filesToDump.iterator(); i.hasNext(); ) {
- UnwovenClassFile classFile = (UnwovenClassFile)i.next();
- dumpUnchanged(classFile);
- }
- }
+// public void dumpUnwoven(File file) throws IOException {
+// BufferedOutputStream os = FileUtil.makeOutputStream(file);
+// this.zipOutputStream = new ZipOutputStream(os);
+// dumpUnwoven();
+// /* BUG 40943*/
+// dumpResourcesToOutJar();
+// zipOutputStream.close(); //this flushes and closes the acutal file
+// }
+//
+//
+// public void dumpUnwoven() throws IOException {
+// Collection filesToDump = new HashSet(sourceJavaClasses.values());
+// for (Iterator i = filesToDump.iterator(); i.hasNext(); ) {
+// UnwovenClassFile classFile = (UnwovenClassFile)i.next();
+// dumpUnchanged(classFile);
+// }
+// }
public void dumpResourcesToOutPath() throws IOException {
// System.err.println("? dumpResourcesToOutPath() resources=" + resources.keySet());
UnwovenClassFile res = (UnwovenClassFile)resources.get(i.next());
dumpUnchanged(res);
}
+ //resources = new HashMap();
}
/* BUG #40943 */
UnwovenClassFile res = (UnwovenClassFile)resources.get(name);
writeZipEntry(name,res.getBytes());
}
+ //resources = new HashMap();
+ }
+
+ // halfway house for when the jar is managed outside of the weaver, but the resources
+ // to be copied are known in the weaver.
+ public void dumpResourcesToOutJar(ZipOutputStream zos) throws IOException {
+ this.zipOutputStream = zos;
+ dumpResourcesToOutJar();
}
// ---- weaving
+ // Used by some test cases...
public Collection weave(File file) throws IOException {
OutputStream os = FileUtil.makeOutputStream(file);
this.zipOutputStream = new ZipOutputStream(os);
- Collection c = weave();
+ prepareForWeave();
+ Collection c = weave( new IClassFileProvider() {
+
+ public Iterator getClassFileIterator() {
+ return addedClasses.iterator();
+ }
+
+ public IWeaveRequestor getRequestor() {
+ return new IWeaveRequestor() {
+ public void acceptResult(UnwovenClassFile result) {}
+ public void processingReweavableState() {}
+ public void addingTypeMungers() {}
+ public void weavingAspects() {}
+ public void weavingClasses() {}
+ public void weaveCompleted() {}
+ };
+ }
+ });
/* BUG 40943*/
dumpResourcesToOutJar();
zipOutputStream.close(); //this flushes and closes the acutal file
return c;
}
- public Collection weave() throws IOException {
- prepareForWeave();
- Collection filesToWeave;
-
- if (needToReweaveWorld) {
- filesToWeave = sourceJavaClasses.values();
- } else {
- filesToWeave = addedClasses;
- }
-
+// public Collection weave() throws IOException {
+// prepareForWeave();
+// Collection filesToWeave;
+//
+// if (needToReweaveWorld) {
+// filesToWeave = sourceJavaClasses.values();
+// } else {
+// filesToWeave = addedClasses;
+// }
+//
+// Collection wovenClassNames = new ArrayList();
+// world.showMessage(IMessage.INFO, "might need to weave " + filesToWeave +
+// "(world=" + needToReweaveWorld + ")", null, null);
+//
+//
+// //System.err.println("typeMungers: " + typeMungerList);
+//
+// prepareToProcessReweavableState();
+// // clear all state from files we'll be reweaving
+// for (Iterator i = filesToWeave.iterator(); i.hasNext(); ) {
+// UnwovenClassFile classFile = (UnwovenClassFile)i.next();
+// String className = classFile.getClassName();
+// BcelObjectType classType = getClassType(className);
+// processReweavableStateIfPresent(className, classType);
+// }
+//
+//
+//
+// //XXX this isn't quite the right place for this...
+// for (Iterator i = filesToWeave.iterator(); i.hasNext(); ) {
+// UnwovenClassFile classFile = (UnwovenClassFile)i.next();
+// String className = classFile.getClassName();
+// addTypeMungers(className);
+// }
+//
+// // first weave into aspects
+// for (Iterator i = filesToWeave.iterator(); i.hasNext(); ) {
+// UnwovenClassFile classFile = (UnwovenClassFile)i.next();
+// String className = classFile.getClassName();
+// BcelObjectType classType = BcelWorld.getBcelObjectType(world.resolve(className));
+// if (classType.isAspect()) {
+// weave(classFile, classType);
+// wovenClassNames.add(className);
+// }
+// }
+//
+// // then weave into non-aspects
+// for (Iterator i = filesToWeave.iterator(); i.hasNext(); ) {
+// UnwovenClassFile classFile = (UnwovenClassFile)i.next();
+// String className = classFile.getClassName();
+// BcelObjectType classType = BcelWorld.getBcelObjectType(world.resolve(className));
+// if (! classType.isAspect()) {
+// weave(classFile, classType);
+// wovenClassNames.add(className);
+// }
+// }
+//
+// if (zipOutputStream != null && !needToReweaveWorld) {
+// Collection filesToDump = new HashSet(sourceJavaClasses.values());
+// filesToDump.removeAll(filesToWeave);
+// for (Iterator i = filesToDump.iterator(); i.hasNext(); ) {
+// UnwovenClassFile classFile = (UnwovenClassFile)i.next();
+// dumpUnchanged(classFile);
+// }
+// }
+//
+// addedClasses = new ArrayList();
+// deletedTypenames = new ArrayList();
+//
+// return wovenClassNames;
+// }
+
+ // variation of "weave" that sources class files from an external source.
+ public Collection weave(IClassFileProvider input) throws IOException {
Collection wovenClassNames = new ArrayList();
- world.showMessage(IMessage.INFO, "might need to weave " + filesToWeave +
- "(world=" + needToReweaveWorld + ")", null, null);
-
-
- //System.err.println("typeMungers: " + typeMungerList);
-
+ IWeaveRequestor requestor = input.getRequestor();
- if (inReweavableMode)
- world.showMessage(IMessage.INFO, "weaver operating in reweavable mode. Need to verify any required types exist.", null, null);
-
-
- Set alreadyConfirmedOK = new HashSet();
+ requestor.processingReweavableState();
+ prepareToProcessReweavableState();
// clear all state from files we'll be reweaving
- for (Iterator i = filesToWeave.iterator(); i.hasNext(); ) {
- UnwovenClassFile classFile = (UnwovenClassFile)i.next();
- String className = classFile.getClassName();
- BcelObjectType classType = BcelWorld.getBcelObjectType(world.resolve(className));
+ for (Iterator i = input.getClassFileIterator(); i.hasNext(); ) {
+ UnwovenClassFile classFile = (UnwovenClassFile)i.next();
+ String className = classFile.getClassName();
+ BcelObjectType classType = getClassType(className);
+ processReweavableStateIfPresent(className, classType);
+ }
+
+ requestor.addingTypeMungers();
+ //XXX this isn't quite the right place for this...
+ for (Iterator i = input.getClassFileIterator(); i.hasNext(); ) {
+ UnwovenClassFile classFile = (UnwovenClassFile)i.next();
+ String className = classFile.getClassName();
+ addTypeMungers(className);
+ }
-
- // If the class is marked reweavable, check any aspects around when it was built are in this world
- WeaverStateInfo wsi = classType.getWeaverState();
- if (wsi!=null && wsi.isReweavable()) { // Check all necessary types are around!
- world.showMessage(IMessage.INFO,"processing reweavable type "+className+": "+classType.getSourceLocation().getSourceFile(),null,null);
- Set aspectsPreviouslyInWorld = wsi.getAspectsAffectingType();
- if (aspectsPreviouslyInWorld!=null) {
- for (Iterator iter = aspectsPreviouslyInWorld.iterator(); iter.hasNext();) {
- String requiredTypeName = (String) iter.next();
- if (!alreadyConfirmedOK.contains(requiredTypeName)) {
- ResolvedTypeX rtx = world.resolve(TypeX.forName(requiredTypeName),true);
- boolean exists = rtx!=ResolvedTypeX.MISSING;
- if (!exists) {
- world.showMessage(IMessage.ERROR, "type " + requiredTypeName +
- " is needed by reweavable type " + className,
- classType.getSourceLocation(), null);
- } else {
- if (!world.getMessageHandler().isIgnoring(IMessage.INFO))
- world.showMessage(IMessage.INFO,"successfully verified type "+requiredTypeName+
- " exists. Originates from "+rtx.getSourceLocation().getSourceFile(),null,null);
- alreadyConfirmedOK.add(requiredTypeName);
- }
- }
- }
- }
- classType.setJavaClass(Utility.makeJavaClass(classType.getJavaClass().getFileName(), wsi.getUnwovenClassFileData()));
- } else {
- classType.resetState();
- }
- }
-
-
-
- //XXX this isn't quite the right place for this...
- for (Iterator i = filesToWeave.iterator(); i.hasNext(); ) {
- UnwovenClassFile classFile = (UnwovenClassFile)i.next();
- String className = classFile.getClassName();
- ResolvedTypeX onType = world.resolve(className);
- weave(onType);
- }
-
+ requestor.weavingAspects();
// first weave into aspects
- for (Iterator i = filesToWeave.iterator(); i.hasNext(); ) {
- UnwovenClassFile classFile = (UnwovenClassFile)i.next();
- String className = classFile.getClassName();
- BcelObjectType classType = BcelWorld.getBcelObjectType(world.resolve(className));
- if (classType.isAspect()) {
- weave(classFile, classType);
- wovenClassNames.add(className);
- }
- }
+ for (Iterator i = input.getClassFileIterator(); i.hasNext(); ) {
+ UnwovenClassFile classFile = (UnwovenClassFile)i.next();
+ String className = classFile.getClassName();
+ BcelObjectType classType = BcelWorld.getBcelObjectType(world.resolve(className));
+ if (classType.isAspect()) {
+ weaveAndNotify(classFile, classType,requestor);
+ wovenClassNames.add(className);
+ }
+ }
+ requestor.weavingClasses();
// then weave into non-aspects
- for (Iterator i = filesToWeave.iterator(); i.hasNext(); ) {
- UnwovenClassFile classFile = (UnwovenClassFile)i.next();
- String className = classFile.getClassName();
- BcelObjectType classType = BcelWorld.getBcelObjectType(world.resolve(className));
- if (! classType.isAspect()) {
- weave(classFile, classType);
- wovenClassNames.add(className);
- }
- }
-
- if (zipOutputStream != null && !needToReweaveWorld) {
- Collection filesToDump = new HashSet(sourceJavaClasses.values());
- filesToDump.removeAll(filesToWeave);
- for (Iterator i = filesToDump.iterator(); i.hasNext(); ) {
- UnwovenClassFile classFile = (UnwovenClassFile)i.next();
- dumpUnchanged(classFile);
- }
- }
-
- addedClasses = new ArrayList();
- deletedTypenames = new ArrayList();
+ for (Iterator i = input.getClassFileIterator(); i.hasNext(); ) {
+ UnwovenClassFile classFile = (UnwovenClassFile)i.next();
+ String className = classFile.getClassName();
+ BcelObjectType classType = BcelWorld.getBcelObjectType(world.resolve(className));
+ if (! classType.isAspect()) {
+ weaveAndNotify(classFile, classType, requestor);
+ wovenClassNames.add(className);
+ }
+ }
- return wovenClassNames;
+ addedClasses = new ArrayList();
+ deletedTypenames = new ArrayList();
+ requestor.weaveCompleted();
+
+ return wovenClassNames;
+ }
+
+ public void prepareToProcessReweavableState() {
+ if (inReweavableMode)
+ world.showMessage(IMessage.INFO, "weaver operating in reweavable mode. Need to verify any required types exist.", null, null);
+
+ alreadyConfirmedReweavableState = new HashSet();
+ }
+
+ public void processReweavableStateIfPresent(String className, BcelObjectType classType) {
+ // If the class is marked reweavable, check any aspects around when it was built are in this world
+ WeaverStateInfo wsi = classType.getWeaverState();
+ if (wsi!=null && wsi.isReweavable()) { // Check all necessary types are around!
+ world.showMessage(IMessage.INFO,"processing reweavable type "+className+": "+classType.getSourceLocation().getSourceFile(),null,null);
+ Set aspectsPreviouslyInWorld = wsi.getAspectsAffectingType();
+ if (aspectsPreviouslyInWorld!=null) {
+ for (Iterator iter = aspectsPreviouslyInWorld.iterator(); iter.hasNext();) {
+ String requiredTypeName = (String) iter.next();
+ if (!alreadyConfirmedReweavableState.contains(requiredTypeName)) {
+ ResolvedTypeX rtx = world.resolve(TypeX.forName(requiredTypeName),true);
+ boolean exists = rtx!=ResolvedTypeX.MISSING;
+ if (!exists) {
+ world.showMessage(IMessage.ERROR, "type " + requiredTypeName +
+ " is needed by reweavable type " + className,
+ classType.getSourceLocation(), null);
+ } else {
+ if (!world.getMessageHandler().isIgnoring(IMessage.INFO))
+ world.showMessage(IMessage.INFO,"successfully verified type "+requiredTypeName+
+ " exists. Originates from "+rtx.getSourceLocation().getSourceFile(),null,null);
+ alreadyConfirmedReweavableState.add(requiredTypeName);
+ }
+ }
+ }
+ }
+ classType.setJavaClass(Utility.makeJavaClass(classType.getJavaClass().getFileName(), wsi.getUnwovenClassFileData()));
+ } else {
+ classType.resetState();
+ }
+ }
+
+ private void weaveAndNotify(UnwovenClassFile classFile, BcelObjectType classType,
+ IWeaveRequestor requestor) throws IOException {
+ LazyClassGen clazz = weaveWithoutDump(classFile,classType);
+ classType.finishedWith();
+ //clazz is null if the classfile was unchanged by weaving...
+ if (clazz != null) {
+ UnwovenClassFile[] newClasses = getClassFilesFor(clazz);
+ for (int i = 0; i < newClasses.length; i++) {
+ requestor.acceptResult(newClasses[i]);
+ }
+ } else {
+ requestor.acceptResult(classFile);
+ }
+ }
+
+ // helper method
+ public BcelObjectType getClassType(String forClass) {
+ return BcelWorld.getBcelObjectType(world.resolve(forClass));
+ }
+
+
+ public void addTypeMungers(String typeName) {
+ weave(world.resolve(typeName));
}
+ public UnwovenClassFile[] getClassFilesFor(LazyClassGen clazz) {
+ List childClasses = clazz.getChildClasses(world);
+ UnwovenClassFile[] ret = new UnwovenClassFile[1 + childClasses.size()];
+ ret[0] = new UnwovenClassFile(clazz.getFileName(),clazz.getJavaClass(world).getBytes());
+ int index = 1;
+ for (Iterator iter = childClasses.iterator(); iter.hasNext();) {
+ UnwovenClassFile.ChildClass element = (UnwovenClassFile.ChildClass) iter.next();
+ UnwovenClassFile childClass = new UnwovenClassFile(clazz.getFileName() + "$" + element.name, element.bytes);
+ ret[index++] = childClass;
+ }
+ return ret;
+ }
+
public void weave(ResolvedTypeX onType) {
onType.clearInterTypeMungers();
public void setReweavableMode(boolean mode,boolean compress) {
inReweavableMode = mode;
- compressReweavableAttributes = compress;
WeaverStateInfo.setReweavableModeDefaults(mode,compress);
BcelClassWeaver.setReweavableMode(mode,compress);
}
+ public boolean isReweavable() {
+ return inReweavableMode;
+ }
}
--- /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.weaver.bcel;
+
+/**
+ * @author colyer
+ * This subclass of UnwovenClassFile allows a third-party to
+ * manage the actual bytes that comprise the class. This means
+ * the third party can return a reference to an existing array,
+ * or create the bytes on demand, or apply any other strategy
+ * that makes sense. By refering to bytes held elsewhere, the
+ * goal is to reduce the overall memory consumption by not holding
+ * a copy.
+ */
+public class UnwovenClassFileWithThirdPartyManagedBytecode
+ extends UnwovenClassFile {
+
+ IByteCodeProvider provider;
+
+ public interface IByteCodeProvider {
+ byte[] getBytes();
+ }
+
+ public UnwovenClassFileWithThirdPartyManagedBytecode(String filename,
+ IByteCodeProvider provider) {
+ super(filename,null);
+ this.provider = provider;
+ }
+
+ public byte[] getBytes() {
+ return provider.getBytes();
+ }
+}