aboutsummaryrefslogtreecommitdiffstats
path: root/loadtime/src
diff options
context:
space:
mode:
authoraclement <aclement>2009-12-10 20:03:37 +0000
committeraclement <aclement>2009-12-10 20:03:37 +0000
commit1d471f7cfaf166d4321c56b52fe47859e9974441 (patch)
tree4214e926f363914f4e8475bc9e2ca652bee8d10f /loadtime/src
parent95ae07b5aa70a702bac463a7775ec36487936bb9 (diff)
downloadaspectj-1d471f7cfaf166d4321c56b52fe47859e9974441.tar.gz
aspectj-1d471f7cfaf166d4321c56b52fe47859e9974441.zip
296734: various optimizations for LTW and aop.xml include/exclude processing
Diffstat (limited to 'loadtime/src')
-rw-r--r--loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java271
-rw-r--r--loadtime/src/org/aspectj/weaver/loadtime/ConcreteAspectCodeGen.java11
2 files changed, 216 insertions, 66 deletions
diff --git a/loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java b/loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java
index b8dc0ff1d..694e7afb5 100644
--- a/loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java
+++ b/loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java
@@ -63,10 +63,21 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
private List m_dumpTypePattern = new ArrayList();
private boolean m_dumpBefore = false;
private boolean dumpDirPerClassloader = false;
- private List m_includeTypePattern = new ArrayList();
- private List m_excludeTypePattern = new ArrayList();
- private List m_includeStartsWith = new ArrayList();
- private List m_excludeStartsWith = new ArrayList();
+
+ private boolean hasExcludes = false;
+ private List<TypePattern> excludeTypePattern = new ArrayList<TypePattern>(); // anything
+ private List<String> excludeStartsWith = new ArrayList<String>(); // com.foo..*
+ private List<String> excludeStarDotDotStar = new ArrayList<String>(); // *..*CGLIB*
+ private List<String> excludeExactName = new ArrayList<String>(); // com.foo.Bar
+ private List<String> excludeEndsWith = new ArrayList<String>(); // com.foo.Bar
+ private List<String[]> excludeSpecial = new ArrayList<String[]>();
+
+ private boolean hasIncludes = false;
+ private List<TypePattern> includeTypePattern = new ArrayList<TypePattern>();
+ private List<String> m_includeStartsWith = new ArrayList<String>();
+ private List<String> includeExactName = new ArrayList<String>();
+ private boolean includeStar = false;
+
private List m_aspectExcludeTypePattern = new ArrayList();
private List m_aspectExcludeStartsWith = new ArrayList();
private List m_aspectIncludeTypePattern = new ArrayList();
@@ -135,7 +146,6 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
}
boolean success = true;
- // if (trace.isTraceEnabled()) trace.enter("initialize",this,new Object[] { classLoader, context });
this.weavingContext = context;
if (weavingContext == null) {
@@ -155,9 +165,8 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
return;
}
- bcelWorld = new LTWWorld(classLoader, weavingContext, // TODO when the world works in terms of the context, we can remove
- // the loader...
- getMessageHandler(), null);
+ // TODO when the world works in terms of the context, we can remove the loader
+ bcelWorld = new LTWWorld(classLoader, weavingContext, getMessageHandler(), null);
weaver = new BcelWeaver(bcelWorld);
@@ -371,6 +380,9 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
bcelWorld.getLint().loadDefaultProperties();
} else {
bcelWorld.getLint().setAll(weaverOption.lint);
+ if (weaverOption.lint.equals("ignore")) {
+ bcelWorld.setAllLintIgnored();
+ }
}
}
// TODO proceedOnError option
@@ -474,7 +486,8 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
break;
}
- ((BcelWorld) weaver.getWorld()).addSourceObjectType(Utility.makeJavaClass(concreteAspect.name, gen.getBytes()));
+ ((BcelWorld) weaver.getWorld()).addSourceObjectType(Utility.makeJavaClass(concreteAspect.name, gen.getBytes()),
+ true);
concreteAspects.add(gen);
@@ -534,7 +547,7 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
}
/**
- * Register the include / exclude filters We duplicate simple patterns in startWith filters that will allow faster matching
+ * Register the include / exclude filters. We duplicate simple patterns in startWith filters that will allow faster matching
* without ResolvedType
*
* @param weaver
@@ -546,38 +559,120 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
Definition definition = (Definition) iterator.next();
for (Iterator iterator1 = definition.getIncludePatterns().iterator(); iterator1.hasNext();) {
+ hasIncludes = true;
String include = (String) iterator1.next();
- TypePattern includePattern = new PatternParser(include).parseTypePattern();
- m_includeTypePattern.add(includePattern);
fastMatchInfo = looksLikeStartsWith(include);
if (fastMatchInfo != null) {
m_includeStartsWith.add(fastMatchInfo);
+ } else if (include.equals("*")) {
+ includeStar = true;
+ } else if ((fastMatchInfo = looksLikeExactName(include)) != null) {
+ includeExactName.add(fastMatchInfo);
+ } else {
+ TypePattern includePattern = new PatternParser(include).parseTypePattern();
+ includeTypePattern.add(includePattern);
}
}
for (Iterator iterator1 = definition.getExcludePatterns().iterator(); iterator1.hasNext();) {
+ hasExcludes = true;
String exclude = (String) iterator1.next();
- TypePattern excludePattern = new PatternParser(exclude).parseTypePattern();
- m_excludeTypePattern.add(excludePattern);
fastMatchInfo = looksLikeStartsWith(exclude);
if (fastMatchInfo != null) {
- m_excludeStartsWith.add(fastMatchInfo);
+ excludeStartsWith.add(fastMatchInfo);
+ } else if ((fastMatchInfo = looksLikeStarDotDotStarExclude(exclude)) != null) {
+ excludeStarDotDotStar.add(fastMatchInfo);
+ } else if ((fastMatchInfo = looksLikeExactName(exclude)) != null) {
+ excludeExactName.add(exclude);
+ } else if ((fastMatchInfo = looksLikeEndsWith(exclude)) != null) {
+ excludeEndsWith.add(fastMatchInfo);
+ } else if (exclude
+ .equals("org.codehaus.groovy..* && !org.codehaus.groovy.grails.web.servlet.mvc.SimpleGrailsController*")) {
+ // TODO need a more sophisticated analysis here, to allow for similar situations
+ excludeSpecial.add(new String[] { "org.codehaus.groovy.",
+ "org.codehaus.groovy.grails.web.servlet.mvc.SimpleGrailsController" });
+ // for the related test:
+ // } else if (exclude.equals("testdata..* && !testdata.sub.Oran*")) {
+ // excludeSpecial.add(new String[] { "testdata.", "testdata.sub.Oran" });
+ } else {
+ TypePattern excludePattern = new PatternParser(exclude).parseTypePattern();
+ excludeTypePattern.add(excludePattern);
}
}
}
}
/**
- * Checks if the type pattern can be handled as a startswith check
- *
- * TODO AV - enhance to support "char.sss" ie FQN direclty (match iff equals) we could also add support for "*..*charss"
- * endsWith style?
+ * Checks if the pattern looks like "*..*XXXX*" and if so returns XXXX. This will enable fast name matching of CGLIB exclusion
*
- * @param typePattern
- * @return null if not possible, or the startWith sequence to test against
+ */
+ private String looksLikeStarDotDotStarExclude(String typePattern) {
+ if (!typePattern.startsWith("*..*")) {
+ return null;
+ }
+ if (!typePattern.endsWith("*")) {
+ return null;
+ }
+ String subPattern = typePattern.substring(4, typePattern.length() - 1);
+ if (hasStarDot(subPattern, 0)) {
+ return null;
+ }
+ return subPattern.replace('$', '.');
+ }
+
+ /**
+ * Checks if the pattern looks like "com.foo.Bar" - an exact name
+ */
+ private String looksLikeExactName(String typePattern) {
+ if (hasSpaceAnnotationPlus(typePattern, 0) || typePattern.indexOf("*") != -1) {
+ return null;
+ }
+ return typePattern.replace('$', '.');
+ }
+
+ /**
+ * Checks if the pattern looks like "*Exception"
+ */
+ private String looksLikeEndsWith(String typePattern) {
+ if (typePattern.charAt(0) != '*') {
+ return null;
+ }
+ if (hasSpaceAnnotationPlus(typePattern, 1) || hasStarDot(typePattern, 1)) {
+ return null;
+ }
+ return typePattern.substring(1).replace('$', '.');
+ }
+
+ /**
+ * Determine if something in the string is going to affect our ability to optimize. Checks for: ' ' '@' '+'
+ */
+ private boolean hasSpaceAnnotationPlus(String string, int pos) {
+ for (int i = pos, max = string.length(); i < max; i++) {
+ char ch = string.charAt(i);
+ if (ch == ' ' || ch == '@' || ch == '+') {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Determine if something in the string is going to affect our ability to optimize. Checks for: '*' '.'
+ */
+ private boolean hasStarDot(String string, int pos) {
+ for (int i = pos, max = string.length(); i < max; i++) {
+ char ch = string.charAt(i);
+ if (ch == '*' || ch == '.') {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Checks if the type pattern looks like "com.foo..*"
*/
private String looksLikeStartsWith(String typePattern) {
- if (typePattern.indexOf('@') >= 0 || typePattern.indexOf('+') >= 0 || typePattern.indexOf(' ') >= 0
- || typePattern.charAt(typePattern.length() - 1) != '*') {
+ if (hasSpaceAnnotationPlus(typePattern, 0) || typePattern.charAt(typePattern.length() - 1) != '*') {
return null;
}
// now must looks like with "charsss..*" or "cha.rss..*" etc
@@ -586,9 +681,8 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
int length = typePattern.length();
if (typePattern.endsWith("..*") && length > 3) {
if (typePattern.indexOf("..") == length - 3 // no ".." before last sequence
- && typePattern.indexOf('*') == length - 1) { // no "*" before last sequence
- return typePattern.substring(0, length - 2).replace('$', '.');
- // ie "charsss." or "char.rss." etc
+ && typePattern.indexOf('*') == length - 1) { // no earlier '*'
+ return typePattern.substring(0, length - 2).replace('$', '.'); // "charsss." or "char.rss." etc
}
}
return null;
@@ -618,67 +712,120 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
}
}
+ /**
+ * Determine whether a type should be accepted for weaving, by checking it against any includes/excludes.
+ *
+ * @param className the name of the type to possibly accept
+ * @param bytes the bytecode for the type (in case we need to look inside, eg. annotations)
+ * @return true if it should be accepted for weaving
+ */
@Override
protected boolean accept(String className, byte[] bytes) {
- // avoid ResolvedType if not needed
- if (m_excludeTypePattern.isEmpty() && m_includeTypePattern.isEmpty()) {
+
+ if (!hasExcludes && !hasIncludes) {
return true;
}
// still try to avoid ResolvedType if we have simple patterns
String fastClassName = className.replace('/', '.').replace('$', '.');
- for (int i = 0; i < m_excludeStartsWith.size(); i++) {
- if (fastClassName.startsWith((String) m_excludeStartsWith.get(i))) {
+ for (String excludeStartsWithString : excludeStartsWith) {
+ if (fastClassName.startsWith(excludeStartsWithString)) {
return false;
}
}
+ // Fast exclusion of patterns like: "*..*CGLIB*"
+ if (!excludeStarDotDotStar.isEmpty()) {
+ for (String namePiece : excludeStarDotDotStar) {
+ int index = fastClassName.lastIndexOf('.');
+ if (fastClassName.indexOf(namePiece, index + 1) != -1) {
+ return false;
+ }
+ }
+ }
+
+ if (!excludeEndsWith.isEmpty()) {
+ for (String lastPiece : excludeEndsWith) {
+ if (fastClassName.endsWith(lastPiece)) {
+ return false;
+ }
+ }
+ }
+
+ // Fast exclusion of exact names
+ if (!excludeExactName.isEmpty()) {
+ for (String name : excludeExactName) {
+ if (fastClassName.equals(name)) {
+ return false;
+ }
+ }
+ }
+
+ if (!excludeSpecial.isEmpty()) {
+ for (String[] entry : excludeSpecial) {
+ String excludeThese = entry[0];
+ String exceptThese = entry[1];
+ if (fastClassName.startsWith(excludeThese) && !fastClassName.startsWith(exceptThese)) {
+ return false;
+ }
+ }
+ }
+
/*
* Bug 120363 If we have an exclude pattern that cannot be matched using "starts with" then we cannot fast accept
*/
- if (m_excludeTypePattern.isEmpty()) {
+ boolean didSomeIncludeMatching = false;
+ if (excludeTypePattern.isEmpty()) {
+ if (includeStar) {
+ return true;
+ }
+ if (!includeExactName.isEmpty()) {
+ didSomeIncludeMatching = true;
+ for (String exactname : includeExactName) {
+ if (fastClassName.equals(exactname)) {
+ return true;
+ }
+ }
+ }
boolean fastAccept = false;// defaults to false if no fast include
for (int i = 0; i < m_includeStartsWith.size(); i++) {
- fastAccept = fastClassName.startsWith((String) m_includeStartsWith.get(i));
+ didSomeIncludeMatching = true;
+ fastAccept = fastClassName.startsWith(m_includeStartsWith.get(i));
if (fastAccept) {
- break;
+ return true;
}
}
+ // We may have processed all patterns now... check that and return
+ if (includeTypePattern.isEmpty()) {
+ return !didSomeIncludeMatching;
+ }
}
- // needs further analysis
- // TODO AV - needs refactoring
- // during LTW this calling resolve at that stage is BAD as we do have the bytecode from the classloader hook
- // but still go thru resolve that will do a getResourcesAsStream on disk
- // this is also problematic for jit stub which are not on disk - as often underlying infra
- // does returns null or some other info for getResourceAsStream (f.e. WLS 9 CR248491)
- // Instead I parse the given bytecode. But this also means it will be parsed again in
- // new WeavingClassFileProvider() from WeavingAdaptor.getWovenBytes()...
-
- ensureDelegateInitialized(className, bytes);
- ResolvedType classInfo = delegateForCurrentClass.getResolvedTypeX();// BAD:
- // weaver.getWorld().resolve(UnresolvedType.forName(
- // className), true);
+ boolean accept;
+ try {
+ ensureDelegateInitialized(className, bytes);
- // exclude are "AND"ed
- for (Iterator iterator = m_excludeTypePattern.iterator(); iterator.hasNext();) {
- TypePattern typePattern = (TypePattern) iterator.next();
- if (typePattern.matchesStatically(classInfo)) {
- // exclude match - skip
- return false;
+ ResolvedType classInfo = delegateForCurrentClass.getResolvedTypeX();
+
+ // exclude are "AND"ed
+ for (TypePattern typePattern : excludeTypePattern) {
+ if (typePattern.matchesStatically(classInfo)) {
+ // exclude match - skip
+ return false;
+ }
}
- }
- // include are "OR"ed
- boolean accept = true;// defaults to true if no include
- for (Iterator iterator = m_includeTypePattern.iterator(); iterator.hasNext();) {
- TypePattern typePattern = (TypePattern) iterator.next();
- accept = typePattern.matchesStatically(classInfo);
- if (accept) {
- break;
+ // include are "OR"ed
+ accept = !didSomeIncludeMatching; // only true if no includes at all
+ for (TypePattern typePattern : includeTypePattern) {
+ accept = typePattern.matchesStatically(classInfo);
+ if (accept) {
+ break;
+ }
+ // goes on if this include did not match ("OR"ed)
}
- // goes on if this include did not match ("OR"ed)
+ } finally {
+ this.bcelWorld.demote();
}
- this.bcelWorld.demote();
return accept;
}
diff --git a/loadtime/src/org/aspectj/weaver/loadtime/ConcreteAspectCodeGen.java b/loadtime/src/org/aspectj/weaver/loadtime/ConcreteAspectCodeGen.java
index 18176f0e2..41b9b4ca3 100644
--- a/loadtime/src/org/aspectj/weaver/loadtime/ConcreteAspectCodeGen.java
+++ b/loadtime/src/org/aspectj/weaver/loadtime/ConcreteAspectCodeGen.java
@@ -270,12 +270,14 @@ public class ConcreteAspectCodeGen {
// hierarchy that have not been
// concretized.
private void getOutstandingAbstractMethodsHelper(ResolvedType type, Map collector) {
- if (type == null)
+ if (type == null) {
return;
+ }
// Get to the top
if (!type.equals(ResolvedType.OBJECT)) {
- if (type.getSuperclass() != null)
+ if (type.getSuperclass() != null) {
getOutstandingAbstractMethodsHelper(type.getSuperclass(), collector);
+ }
}
ResolvedMember[] rms = type.getDeclaredMethods();
if (rms != null) {
@@ -309,8 +311,9 @@ public class ConcreteAspectCodeGen {
private boolean hasPointcutAnnotation(ResolvedMember member) {
AnnotationAJ[] as = member.getAnnotations();
- if (as == null || as.length == 0)
+ if (as == null || as.length == 0) {
return false;
+ }
for (int i = 0; i < as.length; i++) {
if (as[i].getTypeSignature().equals("Lorg/aspectj/lang/annotation/Pointcut;")) {
return true;
@@ -440,7 +443,7 @@ public class ConcreteAspectCodeGen {
// register the fresh new class into the world repository as it does not
// exist on the classpath anywhere
JavaClass jc = cg.getJavaClass((BcelWorld) world);
- ((BcelWorld) world).addSourceObjectType(jc);
+ ((BcelWorld) world).addSourceObjectType(jc, true);
return jc.getBytes();
}