@@ -43,6 +43,21 @@ | |||
aspect. | |||
</para> | |||
<para> | |||
In addition, <literal>pertypewithin</literal> aspects have a | |||
<literal>getWithinTypeName</literal> method that can be called | |||
to return the package qualified name of the type for which the | |||
aspect instance has been created. | |||
</para> | |||
<programlisting><![CDATA[ | |||
/** | |||
* return the package qualified name (eg. com.foo.MyClass) of the type | |||
* for which the aspect instance has been instantiated. | |||
*/ | |||
public String getWithinTypeName() | |||
]]></programlisting> | |||
<para> | |||
In common with the other per-clause instantiation models, the execution | |||
of any advice declared within a <literal>pertypewithin</literal> aspect |
@@ -75,7 +75,7 @@ public class AspectDeclaration extends TypeDeclaration { | |||
private AjAttribute.Aspect aspectAttribute; | |||
public PerClause perClause; | |||
public ResolvedMember aspectOfMethod; | |||
//public ResolvedMember ptwGetWithinTypeMethod; | |||
public ResolvedMember ptwGetWithinTypeNameMethod; | |||
public ResolvedMember hasAspectMethod; | |||
@@ -368,8 +368,7 @@ public class AspectDeclaration extends TypeDeclaration { | |||
generatePerTypeWithinGetInstanceMethod(classFile); // private static <aspecttype> ajc$getInstance(Class c) throws Exception | |||
generatePerTypeWithinHasAspectMethod(classFile); | |||
generatePerTypeWithinCreateAspectInstanceMethod(classFile); // generate public static X ajc$createAspectInstance(Class forClass) { | |||
// PTWIMPL getWithinType() would need this... | |||
//generatePerTypeWithinGetWithinTypeMethod(classFile); // generate public Class getWithinType() { | |||
generatePerTypeWithinGetWithinTypeNameMethod(classFile); | |||
} else { | |||
throw new RuntimeException("unimplemented"); | |||
} | |||
@@ -728,6 +727,26 @@ public class AspectDeclaration extends TypeDeclaration { | |||
}}); | |||
} | |||
private void generatePerTypeWithinGetWithinTypeNameMethod(ClassFile classFile) { | |||
final EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(this.scope); | |||
// Code: | |||
/* | |||
Code: | |||
Stack=1, Locals=1, Args_size=1 | |||
0: aload_0 | |||
1: getfield #14; //Field ajc$withinType:Ljava/lang/String; | |||
4: areturn | |||
*/ | |||
generateMethod(classFile, AjcMemberMaker.perTypeWithinGetWithinTypeNameMethod(world.fromBinding(binding),world.getWorld().isInJava5Mode()), | |||
new BodyGenerator() { | |||
public void generate(CodeStream codeStream) { | |||
ExceptionLabel exc = new ExceptionLabel(codeStream,world.makeTypeBinding(UnresolvedType.JAVA_LANG_EXCEPTION)); | |||
exc.placeStart(); | |||
codeStream.aload_0(); | |||
codeStream.getfield(world.makeFieldBinding(AjcMemberMaker.perTypeWithinWithinTypeField(typeX,typeX))); | |||
codeStream.areturn(); | |||
}}); | |||
} | |||
// PTWIMPL Generate getInstance method | |||
private void generatePerTypeWithinGetInstanceMethod(ClassFile classFile) { | |||
final EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(this.scope); | |||
@@ -1044,8 +1063,8 @@ public class AspectDeclaration extends TypeDeclaration { | |||
// PTWIMPL Use these variants of aspectOf()/hasAspect() | |||
aspectOfMethod = AjcMemberMaker.perTypeWithinAspectOfMethod(typeX,world.getWorld().isInJava5Mode()); | |||
hasAspectMethod = AjcMemberMaker.perTypeWithinHasAspectMethod(typeX,world.getWorld().isInJava5Mode()); | |||
//ptwGetWithinTypeMethod = AjcMemberMaker.perTypeWithinGetWithinTypeMethod(typeX,world.getWorld().isInJava5Mode()); | |||
//binding.addMethod(world.makeMethodBinding(ptwGetWithinTypeMethod)); | |||
ptwGetWithinTypeNameMethod = AjcMemberMaker.perTypeWithinGetWithinTypeNameMethod(typeX,world.getWorld().isInJava5Mode()); | |||
binding.addMethod(world.makeMethodBinding(ptwGetWithinTypeNameMethod)); | |||
} else { | |||
throw new RuntimeException("bad per clause: " + perClause); | |||
} |
@@ -58,7 +58,7 @@ public class TheWholeShow { | |||
for (Method m : ms) { | |||
if (!m.isSynthetic()) { | |||
String name = m.getName(); | |||
if (name.equals("aspectOf") || name.equals("hasAspect")) continue; | |||
if (name.equals("aspectOf") || name.equals("hasAspect") || name.equals("getWithinTypeName")) continue; | |||
if ( ! (name.startsWith("ajc$before") || name.startsWith("ajc$after") || name.startsWith("ajc$around") || | |||
name.startsWith("ajc$interMethod$"))) { | |||
System.err.println("Found non-synthetic method: " + m.getName() + " in " + c.getName()); |
@@ -0,0 +1,27 @@ | |||
import java.lang.reflect.Method; | |||
import org.aspectj.lang.annotation.*; | |||
import org.aspectj.lang.*; | |||
class AClass {} | |||
class BClass {} | |||
class CClass {} | |||
@Aspect("pertypewithin(*Class)") | |||
public class CaseFive { | |||
public static void main(String []argv) throws Exception { | |||
new Runner().run(); | |||
} | |||
} | |||
class Runner { | |||
public void run() throws Exception { | |||
if (Aspects14.hasAspect(CaseFive.class,AClass.class)) { | |||
System.out.println("AClass has an aspect instance"); | |||
CaseFive instance = (CaseFive)Aspects14.aspectOf(CaseFive.class,AClass.class); | |||
Method m = CaseFive.class.getDeclaredMethod("getWithinTypeName",null); | |||
String s = (String)m.invoke(instance,null); | |||
System.out.println("The aspect instance thinks it is for type name "+s); | |||
} | |||
} | |||
} |
@@ -0,0 +1,28 @@ | |||
// Types in packages | |||
package a.b; | |||
class AClass {} | |||
class BClass {} | |||
class CClass {} | |||
public aspect CaseFour pertypewithin(*Class) { | |||
public static void main(String []argv) { | |||
new Runner().run(); | |||
} | |||
} | |||
class Runner { | |||
public void run() { | |||
CaseFour aInstance = (CaseFour.hasAspect(AClass.class)?CaseFour.aspectOf(AClass.class):null); | |||
CaseFour bInstance = (CaseFour.hasAspect(BClass.class)?CaseFour.aspectOf(BClass.class):null); | |||
CaseFour cInstance = (CaseFour.hasAspect(CClass.class)?CaseFour.aspectOf(CClass.class):null); | |||
System.out.println("BClass aspect instance gives a within type name of "+ | |||
(bInstance==null?"<null>":bInstance.getWithinTypeName())); | |||
System.out.println("CClass aspect instance gives a within type name of "+ | |||
(cInstance==null?"<null>":cInstance.getWithinTypeName())); | |||
System.out.println("AClass aspect instance gives a within type name of "+ | |||
(aInstance==null?"<null>":aInstance.getWithinTypeName())); | |||
} | |||
} |
@@ -0,0 +1,22 @@ | |||
// Types not in packages | |||
class AClass {} | |||
class BClass {} | |||
class CClass {} | |||
public aspect CaseOne pertypewithin(*Class) { | |||
public static void main(String []argv) { | |||
new Runner().run(); | |||
} | |||
} | |||
class Runner { | |||
public void run() { | |||
if (CaseOne.hasAspect(AClass.class)) { | |||
System.out.println("AClass has an aspect instance"); | |||
CaseOne instance = CaseOne.aspectOf(AClass.class); | |||
String name = instance.getWithinTypeName(); | |||
System.out.println("The aspect instance thinks it is for type name "+name); | |||
} | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
// Types not in packages - BClass won't get an aspect | |||
class AClass {} | |||
class BClass {} | |||
class CClass {} | |||
public aspect CaseThree pertypewithin(*Class && !BClass) { | |||
public static void main(String []argv) { | |||
new Runner().run(); | |||
} | |||
} | |||
class Runner { | |||
public void run() { | |||
CaseThree aInstance = (CaseThree.hasAspect(AClass.class)?CaseThree.aspectOf(AClass.class):null); | |||
CaseThree bInstance = (CaseThree.hasAspect(BClass.class)?CaseThree.aspectOf(BClass.class):null); | |||
CaseThree cInstance = (CaseThree.hasAspect(CClass.class)?CaseThree.aspectOf(CClass.class):null); | |||
System.out.println("BClass aspect instance gives a within type name of "+ | |||
(bInstance==null?"<null>":bInstance.getWithinTypeName())); | |||
System.out.println("CClass aspect instance gives a within type name of "+ | |||
(cInstance==null?"<null>":cInstance.getWithinTypeName())); | |||
System.out.println("AClass aspect instance gives a within type name of "+ | |||
(aInstance==null?"<null>":aInstance.getWithinTypeName())); | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
// Types not in packages, and multiple mixed up instances | |||
class AClass {} | |||
class BClass {} | |||
class CClass {} | |||
public aspect CaseTwo pertypewithin(*Class) { | |||
public static void main(String []argv) { | |||
new Runner().run(); | |||
} | |||
} | |||
class Runner { | |||
public void run() { | |||
CaseTwo aInstance = (CaseTwo.hasAspect(AClass.class)?CaseTwo.aspectOf(AClass.class):null); | |||
CaseTwo bInstance = (CaseTwo.hasAspect(BClass.class)?CaseTwo.aspectOf(BClass.class):null); | |||
CaseTwo cInstance = (CaseTwo.hasAspect(CClass.class)?CaseTwo.aspectOf(CClass.class):null); | |||
System.out.println("BClass aspect instance gives a within type name of "+ | |||
(bInstance==null?"<null>":bInstance.getWithinTypeName())); | |||
System.out.println("CClass aspect instance gives a within type name of "+ | |||
(cInstance==null?"<null>":cInstance.getWithinTypeName())); | |||
System.out.println("AClass aspect instance gives a within type name of "+ | |||
(aInstance==null?"<null>":aInstance.getWithinTypeName())); | |||
} | |||
} |
@@ -28,6 +28,11 @@ public class Ajc153Tests extends org.aspectj.testing.XMLBasedAjcTestCase { | |||
// public void testCFlowXMLAspectLTW_pr149096() { runTest("cflow xml concrete aspect"); } | |||
// public void testAmbiguousBinding_pr121805() { runTest("ambiguous binding");} | |||
// public void testNegatedAnnotationMatchingProblem_pr153464() { runTest("negated annotation matching problem");} | |||
public void testPTWgetWithinTypeName_pr123423_1() { runTest("basic usage of getWithinTypeName");} | |||
public void testPTWgetWithinTypeName_pr123423_2() { runTest("basic usage of getWithinTypeName - multiple types");} | |||
public void testPTWgetWithinTypeName_pr123423_3() { runTest("basic usage of getWithinTypeName - non matching types");} | |||
public void testPTWgetWithinTypeName_pr123423_4() { runTest("basic usage of getWithinTypeName - types in packages");} | |||
public void testPTWgetWithinTypeName_pr123423_5() { runTest("basic usage of getWithinTypeName - annotation style");} | |||
public void testTurningOffBcelCaching_pr160674() { runTest("turning off bcel caching");} | |||
public void testNoIllegalStateExceptionWithGenericInnerAspect_pr156058() { runTest("no IllegalStateException with generic inner aspect"); } | |||
public void testNoIllegalStateExceptionWithGenericInnerAspect_pr156058_2() { runTest("no IllegalStateException with generic inner aspect - 2"); } |
@@ -51,6 +51,59 @@ | |||
</compile> | |||
</ajc-test> | |||
<ajc-test dir="features153/ptw" title="basic usage of getWithinTypeName"> | |||
<compile files="CaseOne.java"/> | |||
<run class="CaseOne"> | |||
<stdout> | |||
<line text="AClass has an aspect instance"/> | |||
<line text="The aspect instance thinks it is for type name AClass"/> | |||
</stdout> | |||
</run> | |||
</ajc-test> | |||
<ajc-test dir="features153/ptw" title="basic usage of getWithinTypeName - annotation style"> | |||
<compile files="CaseFive.java" options="-1.5"/> | |||
<run class="CaseFive"> | |||
<stdout> | |||
<line text="AClass has an aspect instance"/> | |||
<line text="The aspect instance thinks it is for type name AClass"/> | |||
</stdout> | |||
</run> | |||
</ajc-test> | |||
<ajc-test dir="features153/ptw" title="basic usage of getWithinTypeName - multiple types"> | |||
<compile files="CaseTwo.java"/> | |||
<run class="CaseTwo"> | |||
<stdout> | |||
<line text="BClass aspect instance gives a within type name of BClass"/> | |||
<line text="CClass aspect instance gives a within type name of CClass"/> | |||
<line text="AClass aspect instance gives a within type name of AClass"/> | |||
</stdout> | |||
</run> | |||
</ajc-test> | |||
<ajc-test dir="features153/ptw" title="basic usage of getWithinTypeName - non matching types"> | |||
<compile files="CaseThree.java"/> | |||
<run class="CaseThree"> | |||
<stdout> | |||
<line text="BClass aspect instance gives a within type name of <null>"/> | |||
<line text="CClass aspect instance gives a within type name of CClass"/> | |||
<line text="AClass aspect instance gives a within type name of AClass"/> | |||
</stdout> | |||
</run> | |||
</ajc-test> | |||
<ajc-test dir="features153/ptw" title="basic usage of getWithinTypeName - types in packages"> | |||
<compile files="CaseFour.java"/> | |||
<run class="a.b.CaseFour"> | |||
<stdout> | |||
<line text="BClass aspect instance gives a within type name of a.b.BClass"/> | |||
<line text="CClass aspect instance gives a within type name of a.b.CClass"/> | |||
<line text="AClass aspect instance gives a within type name of a.b.AClass"/> | |||
</stdout> | |||
</run> | |||
</ajc-test> | |||
<ajc-test dir="bugs153/pr158126" title="annotations, call and constructors problem"> | |||
<compile files="A.java,B.java,MyAnnotation.java,MyAspect.java" options="-1.5 -showWeaveInfo"> | |||
<message kind="weave" text="Join point 'constructor-call(void B.<init>())' in Type 'A' (A.java:5) advised by before advice from 'MyAspect' (MyAspect.java:3)"/> |
@@ -189,6 +189,20 @@ public class AjcMemberMaker { | |||
); | |||
return rm; | |||
} | |||
// PTWIMPL ResolvedMember for getWithinTypeName() method | |||
public static ResolvedMember perTypeWithinGetWithinTypeNameMethod(UnresolvedType declaringType, boolean inJava5Mode) { | |||
// public String getWithinTypeName() | |||
ResolvedMemberImpl rm = new ResolvedMemberImpl( | |||
Member.METHOD, | |||
declaringType, | |||
Modifier.PUBLIC, | |||
UnresolvedType.JAVA_LANG_STRING, // return value | |||
NameMangler.PERTYPEWITHIN_GETWITHINTYPENAME_METHOD, | |||
UnresolvedType.NONE | |||
); | |||
return rm; | |||
} | |||
public static ResolvedMember perTypeWithinCreateAspectInstance(UnresolvedType declaringType) { | |||
// public static a.X ajc$createAspectInstance(java.lang.String) |
@@ -47,6 +47,7 @@ public class NameMangler { | |||
public static final String PERTYPEWITHIN_GETINSTANCE_METHOD = PREFIX + "getInstance"; | |||
public static final String PERTYPEWITHIN_CREATEASPECTINSTANCE_METHOD = PREFIX + "createAspectInstance"; | |||
public static final String PERTYPEWITHIN_WITHINTYPEFIELD = PREFIX + "withinType"; | |||
public static final String PERTYPEWITHIN_GETWITHINTYPENAME_METHOD = "getWithinTypeName"; | |||
public static final String AJC_PRE_CLINIT_NAME = PREFIX + "preClinit"; | |||
@@ -124,6 +124,7 @@ public class BcelPerClauseAspectAdder extends BcelTypeMunger { | |||
generatePerTWHasAspectMethod(gen); | |||
generatePerTWGetInstanceMethod(gen); | |||
generatePerTWCreateAspectInstanceMethod(gen); | |||
generatePerTWGetWithinTypeNameMethod(gen); | |||
} else { | |||
throw new Error("should not happen - not such kind " + kind.getName()); | |||
} | |||
@@ -177,7 +178,7 @@ public class BcelPerClauseAspectAdder extends BcelTypeMunger { | |||
// pr144602 - don't need to do this, PerObjectInterface munger will do it | |||
// } else if (kind == PerClause.PEROBJECT) { | |||
// ResolvedMember perObjectFieldInfo = AjcMemberMaker.perObjectField(aspectType, aspectType); | |||
// classGen.addField(makeFieldGen(classGen, perObjectFieldInfo).getField(), null); | |||
// classGen.addField(makeFieldGen(classGen, perObjectFieldInfo).(), null); | |||
// // if lazy generation of the inner interface MayHaveAspect works on LTW (see previous note) | |||
// // it should be done here. | |||
} else if (kind == PerClause.PERCFLOW) { | |||
@@ -471,6 +472,21 @@ public class BcelPerClauseAspectAdder extends BcelTypeMunger { | |||
); | |||
} | |||
// Create 'public String getWithinTypeName() { return ajc$withinType;}' | |||
private void generatePerTWGetWithinTypeNameMethod(LazyClassGen classGen) { | |||
InstructionFactory factory = classGen.getFactory(); | |||
LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perTypeWithinGetWithinTypeNameMethod(aspectType,classGen.getWorld().isInJava5Mode())); | |||
flagAsSynthetic(method, false); | |||
classGen.addMethodGen(method); | |||
// 0: aload_0 | |||
// 1: getfield #14; //Field ajc$withinType:Ljava/lang/String; | |||
// 4: areturn | |||
InstructionList il = method.getBody(); | |||
il.append(InstructionConstants.ALOAD_0); | |||
il.append(Utility.createGet(factory, AjcMemberMaker.perTypeWithinWithinTypeField(aspectType, aspectType))); | |||
il.append(InstructionConstants.ARETURN); | |||
} | |||
private void generatePerTWHasAspectMethod(LazyClassGen classGen) { | |||
InstructionFactory factory = classGen.getFactory(); | |||
LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perTypeWithinHasAspectMethod(aspectType,classGen.getWorld().isInJava5Mode())); |