@@ -24,47 +24,39 @@ import org.aspectj.weaver.ResolvedMember; | |||
import org.aspectj.weaver.ResolvedType; | |||
/** | |||
* This type munger will modify a given class (see the munge() method) to include | |||
* a field representing a CflowCounter object. | |||
* This type munger will modify a given class (see the munge() method) to include a field representing a CflowCounter object. | |||
*/ | |||
public class BcelCflowCounterFieldAdder extends BcelTypeMunger { | |||
private ResolvedMember cflowCounterField; | |||
public BcelCflowCounterFieldAdder(ResolvedMember cflowCounterField) { | |||
super(null,(ResolvedType)cflowCounterField.getDeclaringType()); | |||
super(null, (ResolvedType) cflowCounterField.getDeclaringType()); | |||
this.cflowCounterField = cflowCounterField; | |||
} | |||
public boolean munge(BcelClassWeaver weaver) { | |||
LazyClassGen gen = weaver.getLazyClassGen(); | |||
// Only munge one type! | |||
if (!gen.getType().equals(cflowCounterField.getDeclaringType())) return false; | |||
if (!gen.getType().equals(cflowCounterField.getDeclaringType())) | |||
return false; | |||
// Create the field declaration. | |||
// Something like: "public static final CflowCounter ajc$cflowCounter$0;" | |||
FieldGen f = new FieldGen(cflowCounterField.getModifiers(), | |||
BcelWorld.makeBcelType(cflowCounterField.getReturnType()), | |||
cflowCounterField.getName(), | |||
gen.getConstantPool()); | |||
gen.addField(f,getSourceLocation()); | |||
// Modify the ajc$preClinit() method to initialize it. | |||
// Something like: "ajc$cflowCounter$0 = new CflowCounter();" | |||
LazyMethodGen clinit = gen.getAjcPreClinit(); //StaticInitializer(); | |||
FieldGen f = new FieldGen(cflowCounterField.getModifiers(), BcelWorld.makeBcelType(cflowCounterField.getReturnType()), | |||
cflowCounterField.getName(), gen.getConstantPool()); | |||
gen.addField(f, getSourceLocation()); | |||
// Modify the ajc$preClinit() method to initialize it. | |||
// Something like: "ajc$cflowCounter$0 = new CflowCounter();" | |||
LazyMethodGen clinit = gen.getAjcPreClinit(); // StaticInitializer(); | |||
InstructionList setup = new InstructionList(); | |||
InstructionFactory fact = gen.getFactory(); | |||
setup.append(fact.createNew(new ObjectType(NameMangler.CFLOW_COUNTER_TYPE))); | |||
setup.append(InstructionFactory.createDup(1)); | |||
setup.append(fact.createInvoke( | |||
NameMangler.CFLOW_COUNTER_TYPE, | |||
"<init>", | |||
Type.VOID, | |||
new Type[0], | |||
Constants.INVOKESPECIAL)); | |||
setup.append(fact.createInvoke(NameMangler.CFLOW_COUNTER_TYPE, "<init>", Type.VOID, new Type[0], Constants.INVOKESPECIAL)); | |||
setup.append(Utility.createSet(fact, cflowCounterField)); | |||
clinit.getBody().insert(setup); | |||
@@ -72,7 +64,6 @@ public class BcelCflowCounterFieldAdder extends BcelTypeMunger { | |||
return true; | |||
} | |||
public ResolvedMember getMatchingSyntheticMember(Member member) { | |||
return null; | |||
} | |||
@@ -84,12 +75,14 @@ public class BcelCflowCounterFieldAdder extends BcelTypeMunger { | |||
public boolean matches(ResolvedType onType) { | |||
return onType.equals(cflowCounterField.getDeclaringType()); | |||
} | |||
public boolean existsToSupportShadowMunging() { | |||
return true; | |||
} | |||
public String toString() { | |||
return "(BcelTypeMunger: CflowField "+cflowCounterField.getDeclaringType().getName()+" "+cflowCounterField.getName()+")"; | |||
return "(BcelTypeMunger: CflowField " + cflowCounterField.getDeclaringType().getName() + " " + cflowCounterField.getName() | |||
+ ")"; | |||
} | |||
} |
@@ -10,7 +10,6 @@ | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver.bcel; | |||
import org.aspectj.apache.bcel.Constants; | |||
@@ -20,8 +19,7 @@ import org.aspectj.apache.bcel.generic.InstructionList; | |||
import org.aspectj.weaver.ResolvedType; | |||
/** | |||
* XXX Erik and I need to discuss this hierarchy. Having FieldRef | |||
* extend Var is convenient, but hopefully there's a better design. | |||
* XXX Erik and I need to discuss this hierarchy. Having FieldRef extend Var is convenient, but hopefully there's a better design. | |||
* | |||
* This is always a static reference. | |||
*/ | |||
@@ -39,65 +37,64 @@ public class BcelFieldRef extends BcelVar { | |||
return "BcelFieldRef(" + getType() + " " + className + "." + fieldName + ")"; | |||
} | |||
//public int getSlot() { return slot; } | |||
// public int getSlot() { return slot; } | |||
public Instruction createLoad(InstructionFactory fact) { | |||
return fact.createFieldAccess(className, fieldName, BcelWorld.makeBcelType(getType()), Constants.GETSTATIC); | |||
} | |||
public Instruction createStore(InstructionFactory fact) { | |||
return fact.createFieldAccess(className, fieldName, BcelWorld.makeBcelType(getType()), Constants.PUTSTATIC); | |||
} | |||
public Instruction createLoad(InstructionFactory fact) { | |||
return fact.createFieldAccess(className, fieldName, | |||
BcelWorld.makeBcelType(getType()), Constants.GETSTATIC); | |||
} | |||
public Instruction createStore(InstructionFactory fact) { | |||
return fact.createFieldAccess(className, fieldName, | |||
BcelWorld.makeBcelType(getType()), Constants.PUTSTATIC); | |||
} | |||
public InstructionList createCopyFrom(InstructionFactory fact, int oldSlot) { | |||
throw new RuntimeException("unimplemented"); | |||
} | |||
public InstructionList createCopyFrom(InstructionFactory fact, int oldSlot) { | |||
throw new RuntimeException("unimplemented"); | |||
} | |||
// this is an array var | |||
// void appendConvertableArrayLoad( | |||
// InstructionList il, | |||
// InstructionFactory fact, | |||
// int index, | |||
// ResolvedType convertTo) | |||
// { | |||
// ResolvedType convertFromType = getType().getResolvedComponentType(); | |||
// appendLoad(il, fact); | |||
// il.append(Utility.createConstant(fact, index)); | |||
// il.append(fact.createArrayLoad(BcelWorld.makeBcelType(convertFromType))); | |||
// Utility.appendConversion(il, fact, convertFromType, convertTo); | |||
// } | |||
// | |||
// void appendConvertableArrayStore( | |||
// InstructionList il, | |||
// InstructionFactory fact, | |||
// int index, | |||
// BcelFieldRef storee) | |||
// { | |||
// ResolvedType convertToType = getType().getResolvedComponentType(); | |||
// appendLoad(il, fact); | |||
// il.append(Utility.createConstant(fact, index)); | |||
// storee.appendLoad(il, fact); | |||
// Utility.appendConversion(il, fact, storee.getType(), convertToType); | |||
// il.append(fact.createArrayStore(BcelWorld.makeBcelType(convertToType))); | |||
// } | |||
// | |||
// InstructionList createConvertableArrayStore( | |||
// InstructionFactory fact, | |||
// int index, | |||
// BcelFieldRef storee) | |||
// { | |||
// InstructionList il = new InstructionList(); | |||
// appendConvertableArrayStore(il, fact, index, storee); | |||
// return il; | |||
// } | |||
// InstructionList createConvertableArrayLoad( | |||
// InstructionFactory fact, | |||
// int index, | |||
// ResolvedType convertTo) | |||
// { | |||
// InstructionList il = new InstructionList(); | |||
// appendConvertableArrayLoad(il, fact, index, convertTo); | |||
// return il; | |||
// } | |||
// this is an array var | |||
// void appendConvertableArrayLoad( | |||
// InstructionList il, | |||
// InstructionFactory fact, | |||
// int index, | |||
// ResolvedType convertTo) | |||
// { | |||
// ResolvedType convertFromType = getType().getResolvedComponentType(); | |||
// appendLoad(il, fact); | |||
// il.append(Utility.createConstant(fact, index)); | |||
// il.append(fact.createArrayLoad(BcelWorld.makeBcelType(convertFromType))); | |||
// Utility.appendConversion(il, fact, convertFromType, convertTo); | |||
// } | |||
// | |||
// void appendConvertableArrayStore( | |||
// InstructionList il, | |||
// InstructionFactory fact, | |||
// int index, | |||
// BcelFieldRef storee) | |||
// { | |||
// ResolvedType convertToType = getType().getResolvedComponentType(); | |||
// appendLoad(il, fact); | |||
// il.append(Utility.createConstant(fact, index)); | |||
// storee.appendLoad(il, fact); | |||
// Utility.appendConversion(il, fact, storee.getType(), convertToType); | |||
// il.append(fact.createArrayStore(BcelWorld.makeBcelType(convertToType))); | |||
// } | |||
// | |||
// InstructionList createConvertableArrayStore( | |||
// InstructionFactory fact, | |||
// int index, | |||
// BcelFieldRef storee) | |||
// { | |||
// InstructionList il = new InstructionList(); | |||
// appendConvertableArrayStore(il, fact, index, storee); | |||
// return il; | |||
// } | |||
// InstructionList createConvertableArrayLoad( | |||
// InstructionFactory fact, | |||
// int index, | |||
// ResolvedType convertTo) | |||
// { | |||
// InstructionList il = new InstructionList(); | |||
// appendConvertableArrayLoad(il, fact, index, convertTo); | |||
// return il; | |||
// } | |||
} |
@@ -10,7 +10,6 @@ | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver.bcel; | |||
import org.aspectj.apache.bcel.generic.Instruction; | |||
@@ -31,91 +30,78 @@ public class BcelVar extends Var { | |||
} | |||
public String toString() { | |||
return "BcelVar(" + getType() + " " + slot + | |||
((positionInAroundState != -1) ? (" " + positionInAroundState) : "") + | |||
return "BcelVar(" + getType() + " " + slot + ((positionInAroundState != -1) ? (" " + positionInAroundState) : "") + | |||
")"; | |||
} | |||
public int getSlot() { return slot; } | |||
public int getSlot() { | |||
return slot; | |||
} | |||
// fact is used in the subtypes | |||
public Instruction createLoad(InstructionFactory fact) { | |||
return InstructionFactory.createLoad(BcelWorld.makeBcelType(getType()), slot); | |||
} | |||
public Instruction createStore(InstructionFactory fact) { | |||
return InstructionFactory.createStore(BcelWorld.makeBcelType(getType()), slot); | |||
} | |||
public Instruction createLoad(InstructionFactory fact) { | |||
return InstructionFactory.createLoad(BcelWorld.makeBcelType(getType()), slot); | |||
} | |||
public Instruction createStore(InstructionFactory fact) { | |||
return InstructionFactory.createStore(BcelWorld.makeBcelType(getType()), slot); | |||
} | |||
public void appendStore(InstructionList il, InstructionFactory fact) { | |||
il.append(createStore(fact)); | |||
} | |||
public void appendLoad(InstructionList il, InstructionFactory fact) { | |||
il.append(createLoad(fact)); | |||
} | |||
public void appendLoadAndConvert( | |||
InstructionList il, | |||
InstructionFactory fact, | |||
ResolvedType toType) { | |||
public void appendLoad(InstructionList il, InstructionFactory fact) { | |||
il.append(createLoad(fact)); | |||
} | |||
public void appendLoadAndConvert(InstructionList il, InstructionFactory fact, ResolvedType toType) { | |||
il.append(createLoad(fact)); | |||
Utility.appendConversion(il, fact, getType(), toType); | |||
} | |||
public void insertLoad(InstructionList il, InstructionFactory fact) { | |||
il.insert(createLoad(fact)); | |||
} | |||
public InstructionList createCopyFrom(InstructionFactory fact, int oldSlot) { | |||
InstructionList il = new InstructionList(); | |||
il.append(InstructionFactory.createLoad(BcelWorld.makeBcelType(getType()), oldSlot)); | |||
il.append(createStore(fact)); | |||
return il; | |||
} | |||
// this is an array var | |||
void appendConvertableArrayLoad( | |||
InstructionList il, | |||
InstructionFactory fact, | |||
int index, | |||
ResolvedType convertTo) | |||
{ | |||
ResolvedType convertFromType = getType().getResolvedComponentType(); | |||
appendLoad(il, fact); | |||
il.append(Utility.createConstant(fact, index)); | |||
il.append(InstructionFactory.createArrayLoad(BcelWorld.makeBcelType(convertFromType))); | |||
Utility.appendConversion(il, fact, convertFromType, convertTo); | |||
} | |||
void appendConvertableArrayStore( | |||
InstructionList il, | |||
InstructionFactory fact, | |||
int index, | |||
BcelVar storee) | |||
{ | |||
ResolvedType convertToType = getType().getResolvedComponentType(); | |||
appendLoad(il, fact); | |||
il.append(Utility.createConstant(fact, index)); | |||
storee.appendLoad(il, fact); | |||
Utility.appendConversion(il, fact, storee.getType(), convertToType); | |||
il.append(InstructionFactory.createArrayStore(BcelWorld.makeBcelType(convertToType))); | |||
} | |||
InstructionList createConvertableArrayStore( | |||
InstructionFactory fact, | |||
int index, | |||
BcelVar storee) | |||
{ | |||
InstructionList il = new InstructionList(); | |||
appendConvertableArrayStore(il, fact, index, storee); | |||
return il; | |||
} | |||
InstructionList createConvertableArrayLoad( | |||
InstructionFactory fact, | |||
int index, | |||
ResolvedType convertTo) | |||
{ | |||
InstructionList il = new InstructionList(); | |||
appendConvertableArrayLoad(il, fact, index, convertTo); | |||
return il; | |||
} | |||
} | |||
public void insertLoad(InstructionList il, InstructionFactory fact) { | |||
il.insert(createLoad(fact)); | |||
} | |||
public InstructionList createCopyFrom(InstructionFactory fact, int oldSlot) { | |||
InstructionList il = new InstructionList(); | |||
il.append(InstructionFactory.createLoad(BcelWorld.makeBcelType(getType()), oldSlot)); | |||
il.append(createStore(fact)); | |||
return il; | |||
} | |||
// this is an array var | |||
void appendConvertableArrayLoad(InstructionList il, InstructionFactory fact, int index, ResolvedType convertTo) { | |||
ResolvedType convertFromType = getType().getResolvedComponentType(); | |||
appendLoad(il, fact); | |||
il.append(Utility.createConstant(fact, index)); | |||
il.append(InstructionFactory.createArrayLoad(BcelWorld.makeBcelType(convertFromType))); | |||
Utility.appendConversion(il, fact, convertFromType, convertTo); | |||
} | |||
void appendConvertableArrayStore(InstructionList il, InstructionFactory fact, int index, BcelVar storee) { | |||
ResolvedType convertToType = getType().getResolvedComponentType(); | |||
appendLoad(il, fact); | |||
il.append(Utility.createConstant(fact, index)); | |||
storee.appendLoad(il, fact); | |||
Utility.appendConversion(il, fact, storee.getType(), convertToType); | |||
il.append(InstructionFactory.createArrayStore(BcelWorld.makeBcelType(convertToType))); | |||
} | |||
InstructionList createConvertableArrayStore(InstructionFactory fact, int index, BcelVar storee) { | |||
InstructionList il = new InstructionList(); | |||
appendConvertableArrayStore(il, fact, index, storee); | |||
return il; | |||
} | |||
InstructionList createConvertableArrayLoad(InstructionFactory fact, int index, ResolvedType convertTo) { | |||
InstructionList il = new InstructionList(); | |||
appendConvertableArrayLoad(il, fact, index, convertTo); | |||
return il; | |||
} | |||
public int getPositionInAroundState() { | |||
return positionInAroundState; | |||
} | |||
@@ -125,7 +111,7 @@ public class BcelVar extends Var { | |||
} | |||
// random useful fields | |||
public static final BcelVar[] NONE = new BcelVar[] {}; | |||
} |
@@ -1774,7 +1774,8 @@ public class BcelWeaver { | |||
if (world.isXmlConfigured() && world.getXmlConfiguration().excludesType(resolvedClassType)) { | |||
if (!world.getMessageHandler().isIgnoring(IMessage.INFO)) { | |||
world.getMessageHandler().handleMessage( | |||
MessageUtil.info("Type '" + resolvedClassType.getName() + "' not woven due to exclusion via XML weaver exclude section")); | |||
MessageUtil.info("Type '" + resolvedClassType.getName() | |||
+ "' not woven due to exclusion via XML weaver exclude section")); | |||
} | |||
if (dump) { |
@@ -404,7 +404,7 @@ public class BcelWorld extends World implements Repository { | |||
return null; | |||
} finally { | |||
if (file != null) { | |||
file.close(); | |||
file.close(); | |||
} | |||
} | |||
} | |||
@@ -945,8 +945,7 @@ public class BcelWorld extends World implements Repository { | |||
for (String includePattern : includePatterns) { | |||
if (includePattern.endsWith("..*")) { | |||
// from 'blah.blah.blah..*' leave the 'blah.blah.blah.' | |||
includedFastMatchPatterns.add(includePattern | |||
.substring(0, includePattern.length() - 2)); | |||
includedFastMatchPatterns.add(includePattern.substring(0, includePattern.length() - 2)); | |||
} else { | |||
TypePattern includedPattern = new PatternParser(includePattern).parseTypePattern(); | |||
includedPatterns.add(includedPattern); | |||
@@ -960,8 +959,7 @@ public class BcelWorld extends World implements Repository { | |||
for (String excludePattern : excludePatterns) { | |||
if (excludePattern.endsWith("..*")) { | |||
// from 'blah.blah.blah..*' leave the 'blah.blah.blah.' | |||
excludedFastMatchPatterns.add(excludePattern | |||
.substring(0, excludePattern.length() - 2)); | |||
excludedFastMatchPatterns.add(excludePattern.substring(0, excludePattern.length() - 2)); | |||
} else { | |||
TypePattern excludedPattern = new PatternParser(excludePattern).parseTypePattern(); | |||
excludedPatterns.add(excludedPattern); |
@@ -10,39 +10,37 @@ | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver.bcel; | |||
import org.aspectj.apache.bcel.generic.InstructionHandle; | |||
import org.aspectj.apache.bcel.generic.InstructionList; | |||
import org.aspectj.weaver.UnresolvedType; | |||
/** exceptionRanges are set initially to be low priority. The various setPriority methods | |||
* should be used accordingly. The priority is used when we pack the exception table into | |||
* a method... the exception table should be sorted from high to low priority. Exceptions we generate | |||
* for advice is either high priority (higher than anything coming from the original method... | |||
* most kinds of non-execution advice) or low priority (lower than anything coming from the | |||
* original method, for execution advice). | |||
/** | |||
* exceptionRanges are set initially to be low priority. The various setPriority methods should be used accordingly. The priority is | |||
* used when we pack the exception table into a method... the exception table should be sorted from high to low priority. Exceptions | |||
* we generate for advice is either high priority (higher than anything coming from the original method... most kinds of | |||
* non-execution advice) or low priority (lower than anything coming from the original method, for execution advice). | |||
* | |||
* <p> ??? This does not account for handler, or any other | |||
* "statement-level" advice. When such statement level advice happens, we may want to go to a float level, | |||
* so we can set the priority of advice to be lower than anything it encloses, and higher than | |||
* anything enclosing it. | |||
*/ | |||
/* we're actually using the fact that we're an instruction targeter, for the | |||
* handler */ | |||
* <p> | |||
* ??? This does not account for handler, or any other "statement-level" advice. When such statement level advice happens, we may | |||
* want to go to a float level, so we can set the priority of advice to be lower than anything it encloses, and higher than anything | |||
* enclosing it. | |||
*/ | |||
/* | |||
* we're actually using the fact that we're an instruction targeter, for the handler | |||
*/ | |||
public final class ExceptionRange extends Range { | |||
private InstructionHandle handler; | |||
private final UnresolvedType exceptionType; | |||
private final int priority; | |||
private InstructionHandle handler; | |||
private final UnresolvedType exceptionType; | |||
private final int priority; | |||
// ---- initialization | |||
/** | |||
* After this constructor is called, this range is not well situated unless | |||
* {@link #associateWithTargets} is called | |||
* After this constructor is called, this range is not well situated unless {@link #associateWithTargets} is called | |||
* | |||
* XXX priority should be fixed | |||
*/ | |||
@@ -51,18 +49,15 @@ public final class ExceptionRange extends Range { | |||
this.exceptionType = exceptionType; | |||
this.priority = priority; | |||
} | |||
/** | |||
* @param insideExisting | |||
* @param insideExisting | |||
*/ | |||
public ExceptionRange(InstructionList body, UnresolvedType exceptionType, boolean insideExisting) { | |||
this(body, exceptionType, insideExisting ? Integer.MAX_VALUE : -1); | |||
} | |||
public void associateWithTargets( | |||
InstructionHandle start, | |||
InstructionHandle end, | |||
InstructionHandle handler) | |||
{ | |||
public void associateWithTargets(InstructionHandle start, InstructionHandle end, InstructionHandle handler) { | |||
// assert body.contains(start) && body.contains(end) && body.contains(handler) | |||
this.start = start; | |||
this.end = end; | |||
@@ -72,82 +67,85 @@ public final class ExceptionRange extends Range { | |||
handler.addTargeter(this); | |||
} | |||
// ---- | |||
public InstructionHandle getHandler() { | |||
return handler; | |||
} | |||
public UnresolvedType getCatchType() { | |||
return exceptionType; | |||
} | |||
public int getPriority() { | |||
return priority; | |||
} | |||
// ---- from object | |||
public String toString() { | |||
String str; | |||
if (exceptionType == null) { | |||
str = "finally"; | |||
} else { | |||
str = "catch " + exceptionType; | |||
} | |||
// if (priority >= 0 && priority < Integer.MAX_VALUE) { | |||
// str += " (priority " + priority + ")"; | |||
// } | |||
return str; | |||
} | |||
public boolean equals(Object other) { | |||
if (!(other instanceof ExceptionRange)) return false; | |||
ExceptionRange o = (ExceptionRange) other; | |||
return o.getStart() == getStart() | |||
&& o.getEnd() == getEnd() | |||
&& o.handler == handler | |||
&& ((o.exceptionType == null) | |||
? (exceptionType == null) : | |||
o.exceptionType.equals(exceptionType)) | |||
&& o.priority == priority; | |||
} | |||
private volatile int hashCode = 0; | |||
public int hashCode() { | |||
if (hashCode == 0) { | |||
int ret = 17; | |||
ret = 37*ret + getStart().hashCode(); | |||
ret = 37*ret + getEnd().hashCode(); | |||
ret = 37*ret + handler.hashCode(); | |||
ret = 37*ret + ((exceptionType == null) ? 0 : exceptionType.hashCode()); | |||
ret = 37*ret + priority; | |||
hashCode = ret; | |||
} | |||
return hashCode; | |||
} | |||
public void updateTarget( | |||
InstructionHandle oldIh, | |||
InstructionHandle newIh, | |||
InstructionList newBody) | |||
{ | |||
super.updateTarget(oldIh, newIh, newBody); | |||
// we're guaranteed that start, end, and handler are distinct instruction handles. | |||
if (oldIh == handler) { | |||
handler = newIh; | |||
} | |||
} | |||
// ---- | |||
public InstructionHandle getHandler() { | |||
return handler; | |||
} | |||
public UnresolvedType getCatchType() { | |||
return exceptionType; | |||
} | |||
public int getPriority() { | |||
return priority; | |||
} | |||
// ---- from object | |||
public String toString() { | |||
String str; | |||
if (exceptionType == null) { | |||
str = "finally"; | |||
} else { | |||
str = "catch " + exceptionType; | |||
} | |||
// if (priority >= 0 && priority < Integer.MAX_VALUE) { | |||
// str += " (priority " + priority + ")"; | |||
// } | |||
return str; | |||
} | |||
public boolean equals(Object other) { | |||
if (!(other instanceof ExceptionRange)) | |||
return false; | |||
ExceptionRange o = (ExceptionRange) other; | |||
return o.getStart() == getStart() && o.getEnd() == getEnd() && o.handler == handler | |||
&& ((o.exceptionType == null) ? (exceptionType == null) : o.exceptionType.equals(exceptionType)) | |||
&& o.priority == priority; | |||
} | |||
private volatile int hashCode = 0; | |||
public int hashCode() { | |||
if (hashCode == 0) { | |||
int ret = 17; | |||
ret = 37 * ret + getStart().hashCode(); | |||
ret = 37 * ret + getEnd().hashCode(); | |||
ret = 37 * ret + handler.hashCode(); | |||
ret = 37 * ret + ((exceptionType == null) ? 0 : exceptionType.hashCode()); | |||
ret = 37 * ret + priority; | |||
hashCode = ret; | |||
} | |||
return hashCode; | |||
} | |||
public void updateTarget(InstructionHandle oldIh, InstructionHandle newIh, InstructionList newBody) { | |||
super.updateTarget(oldIh, newIh, newBody); | |||
// we're guaranteed that start, end, and handler are distinct instruction handles. | |||
if (oldIh == handler) { | |||
handler = newIh; | |||
} | |||
} | |||
public static boolean isExceptionStart(InstructionHandle ih) { | |||
if (! isRangeHandle(ih)) return false; | |||
if (!isRangeHandle(ih)) | |||
return false; | |||
Range r = getRange(ih); | |||
if (! (r instanceof ExceptionRange)) return false; | |||
if (!(r instanceof ExceptionRange)) | |||
return false; | |||
ExceptionRange er = (ExceptionRange) r; | |||
return er.getStart() == ih; | |||
} | |||
public static boolean isExceptionEnd(InstructionHandle ih) { | |||
if (! isRangeHandle(ih)) return false; | |||
if (!isRangeHandle(ih)) | |||
return false; | |||
Range r = getRange(ih); | |||
if (! (r instanceof ExceptionRange)) return false; | |||
if (!(r instanceof ExceptionRange)) | |||
return false; | |||
ExceptionRange er = (ExceptionRange) r; | |||
return er.getEnd() == ih; | |||
} | |||
} |
@@ -22,50 +22,47 @@ import org.aspectj.util.FileUtil; | |||
import org.aspectj.weaver.UnresolvedType; | |||
public abstract class ExtensibleURLClassLoader extends URLClassLoader { | |||
private ClassPathManager classPath; | |||
public ExtensibleURLClassLoader (URL[] urls, ClassLoader parent) { | |||
super(urls,parent); | |||
// System.err.println("? ExtensibleURLClassLoader.<init>() path=" + WeavingAdaptor.makeClasspath(urls)); | |||
public ExtensibleURLClassLoader(URL[] urls, ClassLoader parent) { | |||
super(urls, parent); | |||
// System.err.println("? ExtensibleURLClassLoader.<init>() path=" + WeavingAdaptor.makeClasspath(urls)); | |||
try { | |||
classPath = new ClassPathManager(FileUtil.makeClasspath(urls),null); | |||
} | |||
catch (ExceptionInInitializerError ex) { | |||
classPath = new ClassPathManager(FileUtil.makeClasspath(urls), null); | |||
} catch (ExceptionInInitializerError ex) { | |||
ex.printStackTrace(System.out); | |||
throw ex; | |||
} | |||
} | |||
protected void addURL(URL url) { | |||
super.addURL(url); // amc - this call was missing and is needed in | |||
// WeavingURLClassLoader chains | |||
classPath.addPath(url.getPath(),null); | |||
super.addURL(url); // amc - this call was missing and is needed in | |||
// WeavingURLClassLoader chains | |||
classPath.addPath(url.getPath(), null); | |||
} | |||
protected Class findClass(String name) throws ClassNotFoundException { | |||
// System.err.println("? ExtensibleURLClassLoader.findClass(" + name + ")"); | |||
// System.err.println("? ExtensibleURLClassLoader.findClass(" + name + ")"); | |||
try { | |||
byte[] bytes = getBytes(name); | |||
if (bytes != null) { | |||
return defineClass(name,bytes); | |||
} | |||
else { | |||
return defineClass(name, bytes); | |||
} else { | |||
throw new ClassNotFoundException(name); | |||
} | |||
} | |||
catch (IOException ex) { | |||
} catch (IOException ex) { | |||
throw new ClassNotFoundException(name); | |||
} | |||
} | |||
protected Class defineClass(String name, byte[] b, CodeSource cs) throws IOException { | |||
// System.err.println("? ExtensibleURLClassLoader.defineClass(" + name + ",[" + b.length + "])"); | |||
// System.err.println("? ExtensibleURLClassLoader.defineClass(" + name + ",[" + b.length + "])"); | |||
return defineClass(name, b, 0, b.length, cs); | |||
} | |||
protected byte[] getBytes (String name) throws IOException { | |||
protected byte[] getBytes(String name) throws IOException { | |||
byte[] b = null; | |||
ClassPathManager.ClassFile classFile = classPath.find(UnresolvedType.forName(name)); | |||
if (classFile != null) { | |||
@@ -78,21 +75,21 @@ public abstract class ExtensibleURLClassLoader extends URLClassLoader { | |||
return b; | |||
} | |||
private Class defineClass(String name, byte[] bytes /*ClassPathManager.ClassFile classFile*/) throws IOException { | |||
private Class defineClass(String name, byte[] bytes /* ClassPathManager.ClassFile classFile */) throws IOException { | |||
String packageName = getPackageName(name); | |||
if (packageName != null) { | |||
Package pakkage = getPackage(packageName); | |||
if (pakkage == null) { | |||
definePackage(packageName,null,null,null,null,null,null,null); | |||
definePackage(packageName, null, null, null, null, null, null, null); | |||
} | |||
} | |||
return defineClass(name, bytes, null); | |||
} | |||
private String getPackageName (String className) { | |||
private String getPackageName(String className) { | |||
int offset = className.lastIndexOf('.'); | |||
return (offset == -1)? null : className.substring(0,offset); | |||
return (offset == -1) ? null : className.substring(0, offset); | |||
} | |||
} |
@@ -19,22 +19,21 @@ import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen; | |||
import org.aspectj.apache.bcel.classfile.annotation.NameValuePair; | |||
/** | |||
* For implementing declare @type interacting with declare @parents during compilation - we need to be | |||
* able to add an annotation to 'binary type binding' (this is how types are seen during incremental compilation). | |||
* Unlike a SourceTypeBinding - a BinaryTypeBinding does not allow easy interaction with its annotations - | |||
* so what we do is take the eclipse annotation, suck out the name/signature and visibility and put that information | |||
* in a 'FakeAnnotation'. The FakeAnnotation is attached to the BCEL delegate for the binary type binding - | |||
* this will allow type resolution to succeed correctly. The FakeAnnotation never makes it to disk, since the weaver | |||
* does the job properly, attaching a real annotation. | |||
* For implementing declare @type interacting with declare @parents during compilation - we need to be able to add an annotation to | |||
* 'binary type binding' (this is how types are seen during incremental compilation). Unlike a SourceTypeBinding - a | |||
* BinaryTypeBinding does not allow easy interaction with its annotations - so what we do is take the eclipse annotation, suck out | |||
* the name/signature and visibility and put that information in a 'FakeAnnotation'. The FakeAnnotation is attached to the BCEL | |||
* delegate for the binary type binding - this will allow type resolution to succeed correctly. The FakeAnnotation never makes it to | |||
* disk, since the weaver does the job properly, attaching a real annotation. | |||
*/ | |||
public class FakeAnnotation extends AnnotationGen { | |||
private String name; | |||
private String sig; | |||
private boolean isRuntimeVisible; | |||
public FakeAnnotation(String name,String sig,boolean isRuntimeVisible) { | |||
super(null,null,true,null); | |||
public FakeAnnotation(String name, String sig, boolean isRuntimeVisible) { | |||
super(null, null, true, null); | |||
this.name = name; | |||
this.sig = sig; | |||
this.isRuntimeVisible = isRuntimeVisible; | |||
@@ -72,7 +71,7 @@ public class FakeAnnotation extends AnnotationGen { | |||
} | |||
public String toShortString() { | |||
return "@"+this.name; | |||
return "@" + this.name; | |||
} | |||
public String toString() { |
@@ -10,7 +10,6 @@ | |||
* Andy Clement initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver.bcel; | |||
import org.aspectj.apache.bcel.Constants; | |||
@@ -23,16 +22,15 @@ import org.aspectj.weaver.ResolvedType; | |||
import org.aspectj.weaver.UnresolvedType; | |||
/** | |||
* Used for @this() @target() @args() - represents accessing an annotated | |||
* 'thing'. Main use is to create the instructions that retrieve the | |||
* annotation from the 'thing' - see createLoadInstructions() | |||
* Used for @this() @target() @args() - represents accessing an annotated 'thing'. Main use is to create the instructions that | |||
* retrieve the annotation from the 'thing' - see createLoadInstructions() | |||
*/ | |||
public class TypeAnnotationAccessVar extends BcelVar { | |||
private BcelVar target; | |||
public TypeAnnotationAccessVar(ResolvedType type,BcelVar theAnnotatedTargetIsStoredHere) { | |||
super(type,0); | |||
public TypeAnnotationAccessVar(ResolvedType type, BcelVar theAnnotatedTargetIsStoredHere) { | |||
super(type, 0); | |||
target = theAnnotatedTargetIsStoredHere; | |||
} | |||
@@ -40,17 +38,18 @@ public class TypeAnnotationAccessVar extends BcelVar { | |||
return "TypeAnnotationAccessVar(" + getType() + ")"; | |||
} | |||
public Instruction createLoad(InstructionFactory fact) { | |||
public Instruction createLoad(InstructionFactory fact) { | |||
throw new RuntimeException("unimplemented"); | |||
} | |||
public Instruction createStore(InstructionFactory fact) { | |||
throw new RuntimeException("unimplemented"); | |||
} | |||
public Instruction createStore(InstructionFactory fact) { | |||
throw new RuntimeException("unimplemented"); | |||
} | |||
public InstructionList createCopyFrom(InstructionFactory fact, int oldSlot) { | |||
throw new RuntimeException("unimplemented"); | |||
} | |||
} | |||
public InstructionList createCopyFrom(InstructionFactory fact, int oldSlot) { | |||
throw new RuntimeException("unimplemented"); | |||
} | |||
public void appendLoad(InstructionList il, InstructionFactory fact) { | |||
il.append(createLoadInstructions(getType(), fact)); | |||
} | |||
@@ -59,20 +58,18 @@ public class TypeAnnotationAccessVar extends BcelVar { | |||
InstructionList il = new InstructionList(); | |||
Type jlClass = BcelWorld.makeBcelType(UnresolvedType.JAVA_LANG_CLASS); | |||
Type jlaAnnotation = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava.lang.annotation.Annotation;")); | |||
il.append(target.createLoad(fact)); | |||
il.append(fact.createInvoke("java/lang/Object","getClass",jlClass,new Type[]{},Constants.INVOKEVIRTUAL)); | |||
il.append(target.createLoad(fact)); | |||
il.append(fact.createInvoke("java/lang/Object", "getClass", jlClass, new Type[] {}, Constants.INVOKEVIRTUAL)); | |||
il.append(fact.createConstant(new ObjectType(toType.getName()))); | |||
il.append(fact.createInvoke("java/lang/Class","getAnnotation",jlaAnnotation,new Type[]{jlClass},Constants.INVOKEVIRTUAL)); | |||
il.append(Utility.createConversion(fact,jlaAnnotation,BcelWorld.makeBcelType(toType))); | |||
il.append(fact.createInvoke("java/lang/Class", "getAnnotation", jlaAnnotation, new Type[] { jlClass }, | |||
Constants.INVOKEVIRTUAL)); | |||
il.append(Utility.createConversion(fact, jlaAnnotation, BcelWorld.makeBcelType(toType))); | |||
return il; | |||
} | |||
public void appendLoadAndConvert( | |||
InstructionList il, | |||
InstructionFactory fact, | |||
ResolvedType toType) { | |||
il.append(createLoadInstructions(toType, fact)); | |||
public void appendLoadAndConvert(InstructionList il, InstructionFactory fact, ResolvedType toType) { | |||
il.append(createLoadInstructions(toType, fact)); | |||
} | |||
@@ -11,31 +11,25 @@ | |||
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. | |||
* @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 { | |||
public class UnwovenClassFileWithThirdPartyManagedBytecode extends UnwovenClassFile { | |||
IByteCodeProvider provider; | |||
public interface IByteCodeProvider { | |||
byte[] getBytes(); | |||
} | |||
// OPTIMIZE make classname an input char[] | |||
public UnwovenClassFileWithThirdPartyManagedBytecode(String filename,String classname, | |||
IByteCodeProvider provider) { | |||
super(filename,classname,null); | |||
public UnwovenClassFileWithThirdPartyManagedBytecode(String filename, String classname, IByteCodeProvider provider) { | |||
super(filename, classname, null); | |||
this.provider = provider; | |||
} | |||
public byte[] getBytes() { | |||
return provider.getBytes(); | |||
} |