diff options
author | acolyer <acolyer> | 2004-03-15 15:10:46 +0000 |
---|---|---|
committer | acolyer <acolyer> | 2004-03-15 15:10:46 +0000 |
commit | 40680b6fe4d28b2d061fc4cf9b3efa6640c12f44 (patch) | |
tree | 9d90cff75d3b351d06b42dd9088f543de2debbd2 /weaver | |
parent | ec9ac363b0379ce8bb8c0783ab338d8ffaa9da02 (diff) | |
download | aspectj-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')
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(); + } +} |