Browse Source

move weaving to inside of the compiler.compile loop.

ensure messages are associated with source wherever possible
tags/Root_ajdt_support
acolyer 20 years ago
parent
commit
40680b6fe4

+ 37
- 0
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjClassFile.java View File

@@ -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;
}
}

+ 656
- 69
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjCompiler.java View File

@@ -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;
// }
// }
//
//}

+ 231
- 0
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjCompilerAdapter.java View File

@@ -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);
}
}
}
}

+ 50
- 0
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ClassFileBasedByteCodeProvider.java View File

@@ -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;
}
}

+ 21
- 0
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/IIntermediateResultsRequestor.java View File

@@ -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);
}

+ 24
- 0
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/IOutputClassFileNameProvider.java View File

@@ -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);
}

+ 68
- 0
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/InterimCompilationResult.java View File

@@ -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();
}
}

+ 163
- 0
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/WeaverAdapter.java View File

@@ -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);
}
}
}

+ 176
- 0
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/WeaverMessageHandler.java View File

@@ -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&gt;Preferences&gt;Java&gt;Code Generation&gt;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;
}
}


+ 12
- 0
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceLocation.java View File

@@ -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) {

+ 2
- 2
weaver/src/org/aspectj/weaver/ResolvedTypeX.java View 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) {

+ 74
- 3
weaver/src/org/aspectj/weaver/World.java View File

@@ -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())
);
}
}
}

+ 75
- 71
weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java View File

@@ -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();

+ 16
- 1
weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java View File

@@ -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;
}

+ 264
- 127
weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java View File

@@ -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;
}
}

+ 41
- 0
weaver/src/org/aspectj/weaver/bcel/UnwovenClassFileWithThirdPartyManagedBytecode.java View File

@@ -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();
}
}

Loading…
Cancel
Save