summaryrefslogtreecommitdiffstats
path: root/weaver
diff options
context:
space:
mode:
authoracolyer <acolyer>2004-03-15 15:10:46 +0000
committeracolyer <acolyer>2004-03-15 15:10:46 +0000
commit40680b6fe4d28b2d061fc4cf9b3efa6640c12f44 (patch)
tree9d90cff75d3b351d06b42dd9088f543de2debbd2 /weaver
parentec9ac363b0379ce8bb8c0783ab338d8ffaa9da02 (diff)
downloadaspectj-40680b6fe4d28b2d061fc4cf9b3efa6640c12f44.tar.gz
aspectj-40680b6fe4d28b2d061fc4cf9b3efa6640c12f44.zip
move weaving to inside of the compiler.compile loop.
ensure messages are associated with source wherever possible
Diffstat (limited to 'weaver')
-rw-r--r--weaver/src/org/aspectj/weaver/ResolvedTypeX.java4
-rw-r--r--weaver/src/org/aspectj/weaver/World.java77
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java146
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java17
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java391
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/UnwovenClassFileWithThirdPartyManagedBytecode.java41
6 files changed, 472 insertions, 204 deletions
diff --git a/weaver/src/org/aspectj/weaver/ResolvedTypeX.java b/weaver/src/org/aspectj/weaver/ResolvedTypeX.java
index 81327819e..15c86bdbb 100644
--- a/weaver/src/org/aspectj/weaver/ResolvedTypeX.java
+++ b/weaver/src/org/aspectj/weaver/ResolvedTypeX.java
@@ -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) {
diff --git a/weaver/src/org/aspectj/weaver/World.java b/weaver/src/org/aspectj/weaver/World.java
index 481778532..0d019fd1c 100644
--- a/weaver/src/org/aspectj/weaver/World.java
+++ b/weaver/src/org/aspectj/weaver/World.java
@@ -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())
+ );
+ }
+ }
}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java
index 7c6ddb9fd..e0997573a 100644
--- a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java
@@ -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();
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java b/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java
index 1c8a44c0c..553e7c72d 100644
--- a/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java
@@ -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;
}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java
index 5d92584af..e71707cae 100644
--- a/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java
@@ -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;
+ }
}
diff --git a/weaver/src/org/aspectj/weaver/bcel/UnwovenClassFileWithThirdPartyManagedBytecode.java b/weaver/src/org/aspectj/weaver/bcel/UnwovenClassFileWithThirdPartyManagedBytecode.java
new file mode 100644
index 000000000..d7e6c96ac
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/UnwovenClassFileWithThirdPartyManagedBytecode.java
@@ -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();
+ }
+}