ensure messages are associated with source wherever possibletags/Root_ajdt_support
@@ -0,0 +1,37 @@ | |||
/******************************************************************************* | |||
* 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; | |||
} | |||
} |
@@ -1,69 +1,656 @@ | |||
/* ******************************************************************* | |||
* 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; | |||
// } | |||
// } | |||
// | |||
//} |
@@ -0,0 +1,231 @@ | |||
/******************************************************************************* | |||
* 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); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,50 @@ | |||
/******************************************************************************* | |||
* 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; | |||
} | |||
} |
@@ -0,0 +1,21 @@ | |||
/******************************************************************************* | |||
* 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); | |||
} |
@@ -0,0 +1,24 @@ | |||
/******************************************************************************* | |||
* 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); | |||
} |
@@ -0,0 +1,68 @@ | |||
/******************************************************************************* | |||
* 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(); | |||
} | |||
} |
@@ -0,0 +1,163 @@ | |||
/******************************************************************************* | |||
* 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); | |||
} | |||
} | |||
} |
@@ -0,0 +1,176 @@ | |||
/******************************************************************************* | |||
* 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; | |||
} | |||
} | |||
@@ -39,6 +39,18 @@ public class EclipseSourceLocation implements ISourceLocation { | |||
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) { |
@@ -577,7 +577,7 @@ public abstract class ResolvedTypeX extends TypeX { | |||
} | |||
public boolean isExposedToWeaver() { | |||
return delegate.isExposedToWeaver(); //??? where does this belong | |||
return (delegate == null) || delegate.isExposedToWeaver(); //??? where does this belong | |||
} | |||
public WeaverStateInfo getWeaverState() { | |||
@@ -652,7 +652,7 @@ public abstract class ResolvedTypeX extends TypeX { | |||
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) { |
@@ -18,6 +18,7 @@ import java.util.HashMap; | |||
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; | |||
@@ -32,7 +33,7 @@ public abstract class World { | |||
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); | |||
@@ -72,7 +73,7 @@ public abstract class World { | |||
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()) { | |||
@@ -387,5 +388,75 @@ public abstract class World { | |||
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()) | |||
); | |||
} | |||
} | |||
} |
@@ -285,7 +285,7 @@ class BcelClassWeaver implements IClassWeaver { | |||
// ---- | |||
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", | |||
@@ -301,8 +301,7 @@ class BcelClassWeaver implements IClassWeaver { | |||
// 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(); | |||
@@ -327,13 +326,12 @@ class BcelClassWeaver implements IClassWeaver { | |||
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}. | |||
@@ -351,6 +349,7 @@ class BcelClassWeaver implements IClassWeaver { | |||
} | |||
if (! isChanged) return false; | |||
// now we weave all but the initialization shadows | |||
for (Iterator i = methodGens.iterator(); i.hasNext();) { | |||
LazyMethodGen mg = (LazyMethodGen)i.next(); | |||
@@ -785,72 +784,7 @@ class BcelClassWeaver implements IClassWeaver { | |||
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 { | |||
@@ -890,6 +824,76 @@ class BcelClassWeaver implements IClassWeaver { | |||
} | |||
} | |||
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(); |
@@ -216,7 +216,22 @@ public class BcelObjectType extends ResolvedTypeX.ConcreteName { | |||
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; | |||
} |
@@ -13,7 +13,7 @@ | |||
package org.aspectj.weaver.bcel; | |||
import java.io.BufferedOutputStream; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.File; | |||
import java.io.FileFilter; | |||
@@ -41,6 +41,8 @@ import org.aspectj.bridge.IProgressListener; | |||
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; | |||
@@ -59,7 +61,6 @@ public class BcelWeaver implements IWeaver { | |||
private double progressPerClassFile; | |||
private boolean inReweavableMode = false; | |||
private boolean compressReweavableAttributes = false; | |||
public BcelWeaver(BcelWorld world) { | |||
super(); | |||
@@ -72,7 +73,7 @@ public class BcelWeaver implements IWeaver { | |||
} | |||
// ---- 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 */ | |||
@@ -139,13 +140,15 @@ public class BcelWeaver implements IWeaver { | |||
// 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() { | |||
@@ -170,6 +173,7 @@ public class BcelWeaver implements IWeaver { | |||
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); | |||
@@ -179,18 +183,20 @@ public class BcelWeaver implements IWeaver { | |||
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 | |||
@@ -205,6 +211,7 @@ public class BcelWeaver implements IWeaver { | |||
if (filename.endsWith(".class")) { | |||
this.addClassFile(classFile); | |||
addedClassFiles.add(classFile); | |||
} | |||
else if (!entry.isDirectory()) { | |||
@@ -216,6 +223,8 @@ public class BcelWeaver implements IWeaver { | |||
} | |||
inStream.close(); | |||
} | |||
return addedClassFiles; | |||
} | |||
public void addResource(String name, File inPath, File outDir) throws IOException { | |||
@@ -232,21 +241,25 @@ public class BcelWeaver implements IWeaver { | |||
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)); | |||
} | |||
@@ -297,23 +310,23 @@ public class BcelWeaver implements IWeaver { | |||
}); | |||
} | |||
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()); | |||
@@ -322,6 +335,7 @@ public class BcelWeaver implements IWeaver { | |||
UnwovenClassFile res = (UnwovenClassFile)resources.get(i.next()); | |||
dumpUnchanged(res); | |||
} | |||
//resources = new HashMap(); | |||
} | |||
/* BUG #40943 */ | |||
@@ -333,127 +347,248 @@ public class BcelWeaver implements IWeaver { | |||
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(); | |||
@@ -622,9 +757,11 @@ public class BcelWeaver implements IWeaver { | |||
public void setReweavableMode(boolean mode,boolean compress) { | |||
inReweavableMode = mode; | |||
compressReweavableAttributes = compress; | |||
WeaverStateInfo.setReweavableModeDefaults(mode,compress); | |||
BcelClassWeaver.setReweavableMode(mode,compress); | |||
} | |||
public boolean isReweavable() { | |||
return inReweavableMode; | |||
} | |||
} |
@@ -0,0 +1,41 @@ | |||
/******************************************************************************* | |||
* 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(); | |||
} | |||
} |