Browse Source

335619

tags/V1_6_11RC1
aclement 13 years ago
parent
commit
ecb01f75fd
1 changed files with 107 additions and 41 deletions
  1. 107
    41
      weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java

+ 107
- 41
weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java View File

@@ -39,7 +39,6 @@ import java.util.zip.ZipOutputStream;
import org.aspectj.apache.bcel.classfile.ClassParser;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.asm.AsmManager;
import org.aspectj.asm.IHierarchy;
import org.aspectj.asm.IProgramElement;
import org.aspectj.asm.internal.AspectJElementHierarchy;
import org.aspectj.bridge.IMessage;
@@ -228,7 +227,8 @@ public class BcelWeaver {

/**
*
* @param inFile directory containing classes or zip/jar class archive
* @param inFile
* directory containing classes or zip/jar class archive
*/
public void addLibraryJarFile(File inFile) throws IOException {
List<ResolvedType> addedAspects = null;
@@ -281,7 +281,8 @@ public class BcelWeaver {
/**
* Look for .class files that represent aspects in the supplied directory - return the list of accumulated aspects.
*
* @param directory the directory in which to look for Aspect .class files
* @param directory
* the directory in which to look for Aspect .class files
* @return the list of discovered aspects
* @throws FileNotFoundException
* @throws IOException
@@ -309,9 +310,12 @@ public class BcelWeaver {
* Determine if the supplied bytes represent an aspect, if they do then create a ResolvedType instance for the aspect and return
* it, otherwise return null
*
* @param classbytes the classbytes that might represent an aspect
* @param name the name of the class
* @param directory directory which contained the class file
* @param classbytes
* the classbytes that might represent an aspect
* @param name
* the name of the class
* @param directory
* directory which contained the class file
* @return a ResolvedType if the classbytes represent an aspect, otherwise null
*/
private ResolvedType isAspect(byte[] classbytes, String name, File dir) throws IOException {
@@ -1004,6 +1008,8 @@ public class BcelWeaver {
return c;
}

private Set<IProgramElement> candidatesForRemoval = null;

// variation of "weave" that sources class files from an external source.
public Collection<String> weave(IClassFileProvider input) throws IOException {
if (trace.isTraceEnabled()) {
@@ -1013,11 +1019,16 @@ public class BcelWeaver {
Collection<String> wovenClassNames = new ArrayList<String>();
IWeaveRequestor requestor = input.getRequestor();

for (Iterator<UnwovenClassFile> i = input.getClassFileIterator(); i.hasNext();) {
UnwovenClassFile classFile = i.next();
if (world.getModel() != null /* AsmManager.isCreatingModel() */&& !isBatchWeave) {
// remove all relationships where this file being woven is the target of the relationship
world.getModelAsAsmManager().removeRelationshipsTargettingThisType(classFile.getClassName());
if (world.getModel() != null && world.isMinimalModel()) {
candidatesForRemoval = new HashSet<IProgramElement>();
}
if (world.getModel() != null && !isBatchWeave) {
AsmManager manager = world.getModelAsAsmManager();
for (Iterator<UnwovenClassFile> i = input.getClassFileIterator(); i.hasNext();) {
UnwovenClassFile classFile = i.next();
// remove all relationships where this file being woven is
// the target of the relationship
manager.removeRelationshipsTargettingThisType(classFile.getClassName());
}
}

@@ -1184,6 +1195,9 @@ public class BcelWeaver {
if (trace.isTraceEnabled()) {
trace.exit("weave", wovenClassNames);
}
if (world.getModel() != null && world.isMinimalModel()) {
candidatesForRemoval.clear();
}
return wovenClassNames;
}

@@ -1716,45 +1730,37 @@ public class BcelWeaver {
// can we remove it from the model now? we know it contains no relationship endpoints...
AsmManager model = world.getModelAsAsmManager();
if (world.isMinimalModel() && model != null && !classType.isAspect()) {
IHierarchy hierarchy = model.getHierarchy();
AspectJElementHierarchy hierarchy = (AspectJElementHierarchy) model.getHierarchy();
String pkgname = classType.getResolvedTypeX().getPackageName();
String tname = classType.getResolvedTypeX().getSimpleBaseName();
IProgramElement typeElement = hierarchy.findElementForType(pkgname, tname);
if (typeElement != null && hasInnerType(typeElement)) {
// Cannot remove it right now (has inner type), schedule it
// for possible deletion later if all inner types are
// removed
candidatesForRemoval.add(typeElement);
}
if (typeElement != null && !hasInnerType(typeElement)) {

// Set<String> deleted = new HashSet<String>();
// deleted.add(model.getCanonicalFilePath(typeElement.getSourceLocation().getSourceFile()));
// hierarchy.updateHandleMap(deleted);
IProgramElement parent = typeElement.getParent();
// parent may have children: PACKAGE DECL, IMPORT-REFERENCE, TYPE_DECL
if (parent != null) {
// if it was the only type we should probably remove the others too.
// if it was the only type we should probably remove
// the others too.
parent.removeChild(typeElement);
if (parent.getKind().isSourceFile()) {
IProgramElement compilationUnit = parent;
boolean anyOtherTypeDeclarations = false;
for (IProgramElement child : compilationUnit.getChildren()) {
IProgramElement.Kind k = child.getKind();
if (k.isType()) {
anyOtherTypeDeclarations = true;
break;
}
}
// If the compilation unit node contained no other types, there is no need to keep it
if (!anyOtherTypeDeclarations) {
IProgramElement cuParent = compilationUnit.getParent();
if (cuParent != null) {
compilationUnit.setParent(null);
cuParent.removeChild(compilationUnit);
}
// need to update some caches and structures too?
((AspectJElementHierarchy) model.getHierarchy()).forget(parent, typeElement);
} else {
((AspectJElementHierarchy) model.getHierarchy()).forget(null, typeElement);
}
removeSourceFileIfNoMoreTypeDeclarationsInside(hierarchy, typeElement, parent);
} else {
((AspectJElementHierarchy) model.getHierarchy()).forget(null, typeElement);
hierarchy.forget(null, typeElement);
// At this point, the child has been removed. We
// should now check if the parent is in our
// 'candidatesForRemoval' set. If it is then that
// means we were going to remove it but it had a
// child. Now we can check if it still has a child -
// if it doesn't it can also be removed!

walkUpRemovingEmptyTypesAndPossiblyEmptySourceFile(hierarchy, tname, parent);
}

}
}
}
@@ -1779,6 +1785,64 @@ public class BcelWeaver {
}
}

private void walkUpRemovingEmptyTypesAndPossiblyEmptySourceFile(AspectJElementHierarchy hierarchy, String tname,
IProgramElement typeThatHasChildRemoved) {
// typeThatHasChildRemoved might be a source file, type or a method/ctor
// - for a method/ctor find the type/sourcefile
while (typeThatHasChildRemoved != null
&& !(typeThatHasChildRemoved.getKind().isType() || typeThatHasChildRemoved.getKind().isSourceFile())) {
// this will take us 'up' through methods that contain anonymous
// inner classes
typeThatHasChildRemoved = typeThatHasChildRemoved.getParent();
}
// now typeThatHasChildRemoved points to the type or sourcefile that has
// had something removed
if (candidatesForRemoval.contains(typeThatHasChildRemoved) && !hasInnerType(typeThatHasChildRemoved)) {
// now we can get rid of it
IProgramElement parent = typeThatHasChildRemoved.getParent();
if (parent != null) {
parent.removeChild(typeThatHasChildRemoved);
candidatesForRemoval.remove(typeThatHasChildRemoved);
if (parent.getKind().isSourceFile()) {
removeSourceFileIfNoMoreTypeDeclarationsInside(hierarchy, typeThatHasChildRemoved, parent);
// System.out.println("Removed on second pass: " +
// typeThatHasChildRemoved.getName());
} else {
// System.out.println("On later pass, parent of type " +
// typeThatHasChildRemoved.getName()
// + " was found not to be a sourcefile, recursing up...");
walkUpRemovingEmptyTypesAndPossiblyEmptySourceFile(hierarchy, tname, parent);
}
}
}
}

private void removeSourceFileIfNoMoreTypeDeclarationsInside(AspectJElementHierarchy hierarchy, IProgramElement typeElement,
IProgramElement sourceFileNode) {
IProgramElement compilationUnit = sourceFileNode;
boolean anyOtherTypeDeclarations = false;
for (IProgramElement child : compilationUnit.getChildren()) {
IProgramElement.Kind k = child.getKind();
if (k.isType()) {
anyOtherTypeDeclarations = true;
break;
}
}
// If the compilation unit node contained no
// other types, there is no need to keep it
if (!anyOtherTypeDeclarations) {
IProgramElement cuParent = compilationUnit.getParent();
if (cuParent != null) {
compilationUnit.setParent(null);
cuParent.removeChild(compilationUnit);
}
// need to update some caches and structures too?
hierarchy.forget(sourceFileNode, typeElement);
} else {
hierarchy.forget(null, typeElement);
}
}

// ---- writing

// TODO could be smarter - really only matters if inner type has been woven, but there is a chance we haven't woven it *yet*
@@ -1858,8 +1922,10 @@ public class BcelWeaver {
* Perform a fast match of the specified list of shadowmungers against the specified type. A subset of those that might match is
* returned.
*
* @param list list of all shadow mungers that might match
* @param type the target type
* @param list
* list of all shadow mungers that might match
* @param type
* the target type
* @return a list of shadow mungers that might match with those that cannot (according to fast match rules) removed
*/
private List<ShadowMunger> fastMatch(List<ShadowMunger> list, ResolvedType type) {

Loading…
Cancel
Save