From f91ffb032fae7c7d9f59f4aedf27f067ba60919e Mon Sep 17 00:00:00 2001 From: aclement Date: Thu, 21 Jan 2010 18:39:53 +0000 Subject: [PATCH] 299552: private ITD fields stay private in target (with unmangled name) --- .../features169/transparent/DeclareAtTwo.java | 17 ++ tests/features169/transparent/Generics.java | 37 +++ .../transparent/InteractingOldAndNew.java | 38 +++ .../features169/transparent/OneDeclareAt.java | 13 + tests/features169/transparent/OneDefault.java | 6 + .../transparent/OneDefaultAnnotated.java | 12 + tests/features169/transparent/OnePrivate.java | 6 + .../transparent/OnePrivateAccessors.java | 21 ++ .../transparent/OnePrivateAnnotated.java | 12 + .../transparent/OnePrivateInitializer.java | 16 ++ tests/features169/transparent/Three.java | 7 + tests/features169/transparent/Two.java | 7 + .../transparent/TwoItdsOnTarget.java | 10 + .../TwoItdsOnTargetHasAlready.java | 11 + .../ajc169/TransparentWeavingTests.java | 229 ++++++++++++++++++ .../systemtest/ajc169/transparentweaving.xml | 68 ++++++ 16 files changed, 510 insertions(+) create mode 100644 tests/features169/transparent/DeclareAtTwo.java create mode 100644 tests/features169/transparent/Generics.java create mode 100644 tests/features169/transparent/InteractingOldAndNew.java create mode 100644 tests/features169/transparent/OneDeclareAt.java create mode 100644 tests/features169/transparent/OneDefault.java create mode 100644 tests/features169/transparent/OneDefaultAnnotated.java create mode 100644 tests/features169/transparent/OnePrivate.java create mode 100644 tests/features169/transparent/OnePrivateAccessors.java create mode 100644 tests/features169/transparent/OnePrivateAnnotated.java create mode 100644 tests/features169/transparent/OnePrivateInitializer.java create mode 100644 tests/features169/transparent/Three.java create mode 100644 tests/features169/transparent/Two.java create mode 100644 tests/features169/transparent/TwoItdsOnTarget.java create mode 100644 tests/features169/transparent/TwoItdsOnTargetHasAlready.java create mode 100644 tests/src/org/aspectj/systemtest/ajc169/TransparentWeavingTests.java create mode 100644 tests/src/org/aspectj/systemtest/ajc169/transparentweaving.xml diff --git a/tests/features169/transparent/DeclareAtTwo.java b/tests/features169/transparent/DeclareAtTwo.java new file mode 100644 index 000000000..57c321afe --- /dev/null +++ b/tests/features169/transparent/DeclareAtTwo.java @@ -0,0 +1,17 @@ +import java.lang.annotation.*; + +public class DeclareAtTwo { +} + +aspect X { + declare @field: int DeclareAtTwo.x: @Anno2; + + @Anno + private int DeclareAtTwo.x; +} + +@Retention(RetentionPolicy.RUNTIME) +@interface Anno {} + +@Retention(RetentionPolicy.RUNTIME) +@interface Anno2 {} diff --git a/tests/features169/transparent/Generics.java b/tests/features169/transparent/Generics.java new file mode 100644 index 000000000..c1cc12614 --- /dev/null +++ b/tests/features169/transparent/Generics.java @@ -0,0 +1,37 @@ +import java.util.*; + +public class Generics { + public static void main(String []argv) { + Generics inst = new Generics(); + List ls = new ArrayList(); + inst.setter(ls); + List newls = inst.getter(); + + inst.setThing("abc"); + String s = inst.getThing(); + } +} + +aspect X { + private List Generics.listOfString; + + public List Generics.getter() { + return listOfString; + } + + public void Generics.setter(List los) { + listOfString = los; + } +} + +aspect Y { + private T Generics.thing; + + public T Generics.getThing() { + return thing; + } + + public void Generics.setThing(T thing) { + this.thing = thing; + } +} diff --git a/tests/features169/transparent/InteractingOldAndNew.java b/tests/features169/transparent/InteractingOldAndNew.java new file mode 100644 index 000000000..387b21d55 --- /dev/null +++ b/tests/features169/transparent/InteractingOldAndNew.java @@ -0,0 +1,38 @@ +// Interacting private ITDs + +public class InteractingOldAndNew { + public static void main(String []argv) { + InteractingOldAndNew inst = new InteractingOldAndNew(); + inst.setI1(12); + inst.setI2(65); + int value = inst.getI1(); + if (value!=12) { throw new RuntimeException(Integer.toString(value)); } + value = inst.getI2(); + if (value!=65) { throw new RuntimeException(Integer.toString(value)); } + } +} + + +aspect X { + private int InteractingOldAndNew.i; + + public int InteractingOldAndNew.getI1() { + return i; + } + + public void InteractingOldAndNew.setI1(int newvalue) { + i = newvalue; + } +} + +aspect Y { + private int InteractingOldAndNew.i; + + public int InteractingOldAndNew.getI2() { + return i; + } + + public void InteractingOldAndNew.setI2(int newvalue) { + i = newvalue; + } +} diff --git a/tests/features169/transparent/OneDeclareAt.java b/tests/features169/transparent/OneDeclareAt.java new file mode 100644 index 000000000..3daa279d4 --- /dev/null +++ b/tests/features169/transparent/OneDeclareAt.java @@ -0,0 +1,13 @@ +import java.lang.annotation.*; + +public class OneDeclareAt { +} + +aspect X { + declare @field: int OneDeclareAt.x: @Anno; + + private int OneDeclareAt.x; +} + +@Retention(RetentionPolicy.RUNTIME) +@interface Anno {} diff --git a/tests/features169/transparent/OneDefault.java b/tests/features169/transparent/OneDefault.java new file mode 100644 index 000000000..b05375681 --- /dev/null +++ b/tests/features169/transparent/OneDefault.java @@ -0,0 +1,6 @@ +public class OneDefault { +} + +aspect X { + int OneDefault.x; +} diff --git a/tests/features169/transparent/OneDefaultAnnotated.java b/tests/features169/transparent/OneDefaultAnnotated.java new file mode 100644 index 000000000..3b603f9ee --- /dev/null +++ b/tests/features169/transparent/OneDefaultAnnotated.java @@ -0,0 +1,12 @@ +import java.lang.annotation.*; + +public class OneDefaultAnnotated { +} + +aspect X { + @Anno + int OneDefaultAnnotated.x; +} + +@Retention(RetentionPolicy.RUNTIME) +@interface Anno {} diff --git a/tests/features169/transparent/OnePrivate.java b/tests/features169/transparent/OnePrivate.java new file mode 100644 index 000000000..a0de744c7 --- /dev/null +++ b/tests/features169/transparent/OnePrivate.java @@ -0,0 +1,6 @@ +public class OnePrivate { +} + +aspect X { + private int OnePrivate.x; +} diff --git a/tests/features169/transparent/OnePrivateAccessors.java b/tests/features169/transparent/OnePrivateAccessors.java new file mode 100644 index 000000000..07bfbc98c --- /dev/null +++ b/tests/features169/transparent/OnePrivateAccessors.java @@ -0,0 +1,21 @@ +import java.lang.annotation.*; + +public class OnePrivateAccessors { + public static void main(String[] argv) { + int i = new OnePrivateAccessors().run(); + if (i!=37) throw new RuntimeException(Integer.toString(i)); + } +} + +aspect X { + @Anno + private int OnePrivateAccessors.x; + + public int OnePrivateAccessors.run() { + x = 37; + return x; + } +} + +@Retention(RetentionPolicy.RUNTIME) +@interface Anno {} diff --git a/tests/features169/transparent/OnePrivateAnnotated.java b/tests/features169/transparent/OnePrivateAnnotated.java new file mode 100644 index 000000000..c5e4e798d --- /dev/null +++ b/tests/features169/transparent/OnePrivateAnnotated.java @@ -0,0 +1,12 @@ +import java.lang.annotation.*; + +public class OnePrivateAnnotated { +} + +aspect X { + @Anno + private int OnePrivateAnnotated.x; +} + +@Retention(RetentionPolicy.RUNTIME) +@interface Anno {} diff --git a/tests/features169/transparent/OnePrivateInitializer.java b/tests/features169/transparent/OnePrivateInitializer.java new file mode 100644 index 000000000..33d9822af --- /dev/null +++ b/tests/features169/transparent/OnePrivateInitializer.java @@ -0,0 +1,16 @@ +import java.lang.annotation.*; + +public class OnePrivateInitializer { + public static void main(String[] argv) { + int i = new OnePrivateInitializer().run(); + if (i!=42) throw new RuntimeException(Integer.toString(i)); + } +} + +aspect X { + private int OnePrivateInitializer.x = 42; + + public int OnePrivateInitializer.run() { + return x; + } +} diff --git a/tests/features169/transparent/Three.java b/tests/features169/transparent/Three.java new file mode 100644 index 000000000..f288ce35b --- /dev/null +++ b/tests/features169/transparent/Three.java @@ -0,0 +1,7 @@ +public class Three { + private int x; +} + +aspect X { + private int Three.x; +} diff --git a/tests/features169/transparent/Two.java b/tests/features169/transparent/Two.java new file mode 100644 index 000000000..c01cdd74a --- /dev/null +++ b/tests/features169/transparent/Two.java @@ -0,0 +1,7 @@ +public class Two { + public int x; +} + +aspect X { + public int Two.x; +} diff --git a/tests/features169/transparent/TwoItdsOnTarget.java b/tests/features169/transparent/TwoItdsOnTarget.java new file mode 100644 index 000000000..d83a15210 --- /dev/null +++ b/tests/features169/transparent/TwoItdsOnTarget.java @@ -0,0 +1,10 @@ +public class TwoItdsOnTarget { +} + +aspect X { + private int TwoItdsOnTarget.x; +} + +aspect Y { + private int TwoItdsOnTarget.x; +} diff --git a/tests/features169/transparent/TwoItdsOnTargetHasAlready.java b/tests/features169/transparent/TwoItdsOnTargetHasAlready.java new file mode 100644 index 000000000..f26dbcd6d --- /dev/null +++ b/tests/features169/transparent/TwoItdsOnTargetHasAlready.java @@ -0,0 +1,11 @@ +public class TwoItdsOnTargetHasAlready { + private int x; +} + +aspect X { + private int TwoItdsOnTargetHasAlready.x; +} + +aspect Y { + private int TwoItdsOnTargetHasAlready.x; +} diff --git a/tests/src/org/aspectj/systemtest/ajc169/TransparentWeavingTests.java b/tests/src/org/aspectj/systemtest/ajc169/TransparentWeavingTests.java new file mode 100644 index 000000000..5086c0ead --- /dev/null +++ b/tests/src/org/aspectj/systemtest/ajc169/TransparentWeavingTests.java @@ -0,0 +1,229 @@ +/******************************************************************************* + * Copyright (c) 2008 Contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement - initial API and implementation + *******************************************************************************/ +package org.aspectj.systemtest.ajc169; + +import java.io.File; +import org.aspectj.apache.bcel.classfile.Method; +import java.lang.reflect.Modifier; + +import junit.framework.Test; + +import org.aspectj.apache.bcel.classfile.Field; +import org.aspectj.apache.bcel.classfile.JavaClass; +import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen; +import org.aspectj.apache.bcel.util.ClassPath; +import org.aspectj.apache.bcel.util.SyntheticRepository; +import org.aspectj.testing.XMLBasedAjcTestCase; + +/** + * What would a completely transparent weave be? Is there a minimal subset that makes sense? What is the roadmap to get there? What + * needs testing + * + * --- 'Transparent' here is meaning that the resultant bytecode is more representative of the original declarations, so that it + * looks like the intertype declaration and associated constructs have been seamless added to the affected targets. + * + * + * Fully transparent weaving, what would we like to have: - ITDs appear exactly as declared: 'private int A.i' will create 'private + * int i' in A + * + * - What is the benefit? - although this isn't really in keeping with the AspectJ definition of what an ITD represents, having the + * end result look like the declaration does make it easier for users simply looking at the resultant class file or attempting + * reflection to access what they just ITD'd in place + * + * + * testing For transparent weaving of ITD fields - annotations on new fields - AJDT model - AjType support - what happens to it? - + * advice on within() how does that get affected? - visibility - accessors created when required? - handling clashes with existing + * fields - handling clashes with other aspects - generic declarations - interface declarations - initializers - static and + * non-static - accessibility from advice, for read and write + * + * Design
+ * The intention will be 'new code' uses the new style whilst old code continues to cause the old code to be built. Whether the code + * wants to use the old or new naming should be apparent from the + * + * @author Andy Clement + */ +public class TransparentWeavingTests extends org.aspectj.testing.XMLBasedAjcTestCase { + + // Simple private ITD onto a target + public void testSimplePrivate() throws Exception { + runTest("one - private"); + checkForField("OnePrivate", Modifier.PRIVATE, "x"); + } + + // Default visibility ITD field + public void testSimpleDefault() throws Exception { + runTest("one - default"); + checkForField("OneDefault", 0, "x"); + } + + // annotated private ITD + public void testSimplePrivateAnnotated() throws Exception { + runTest("one - private - annotated"); + Field f = checkForField("OnePrivateAnnotated", Modifier.PRIVATE, "x"); + AnnotationGen[] annos = f.getAnnotations(); + assertTrue(annos.length > 0); // 0==Anno 1==ajcITD + assertEquals("LAnno;", annos[0].getTypeSignature()); + } + + // annotated default ITD + public void testSimpleDefaultAnnotated() throws Exception { + runTest("one - default - annotated"); + Field f = checkForField("OneDefaultAnnotated", 0, "x"); + AnnotationGen[] annos = f.getAnnotations(); + assertTrue(annos.length > 0); // 0==Anno 1==ajcITD + assertEquals("LAnno;", annos[0].getTypeSignature()); + } + + // Simple private ITD with getter/setter usage + public void testSimplePrivateWithAccessors() throws Exception { + runTest("one - private - accessors"); + } + + // check initializer runs OK + public void testSimplePrivateInitializer() throws Exception { + runTest("one - private - initializer"); + } + + public void testDeclareAtOnPrivateItd() throws Exception { + runTest("declare at on private itd"); + Field f = checkForField("OneDeclareAt", Modifier.PRIVATE, "x"); + AnnotationGen[] annos = f.getAnnotations(); + assertTrue(annos.length > 0); // 1==Anno 0==ajcITD + assertEquals("LAnno;", annos[1].getTypeSignature()); + } + + // declare @field on a field that already has one + public void testDeclareAtTwo() throws Exception { + runTest("declare at two"); + Field f = checkForField("DeclareAtTwo", Modifier.PRIVATE, "x"); + AnnotationGen[] annos = f.getAnnotations(); + assertTrue(annos.length > 2); // 1==Anno 0==ajcITD + assertEquals("LAnno;", annos[0].getTypeSignature()); + assertEquals("LAnno2;", annos[2].getTypeSignature()); + } + + public void testTwoItdsOnTarget() throws Exception { + runTest("two itds on target"); + // Aspect X gets the field, aspect Y gets a mangled one + checkForField("TwoItdsOnTarget", Modifier.PRIVATE, "x"); + checkForField("TwoItdsOnTarget", Modifier.PUBLIC, "ajc$interField$Y$x"); + } + + public void testTwoItdsOnTargetThatAlreadyHasIt() throws Exception { + runTest("two itds on target that already has it"); + // Aspect X gets the field, aspect Y gets a mangled one + checkForField("TwoItdsOnTargetHasAlready", Modifier.PUBLIC, "ajc$interField$X$x"); + checkForField("TwoItdsOnTargetHasAlready", Modifier.PUBLIC, "ajc$interField$Y$x"); + } + + public void testInteractingOldAndNew() throws Exception { + runTest("interacting old and new"); + int SYNTHETIC = 0x00001000; // 4096 + checkForField("InteractingOldAndNew", Modifier.PRIVATE, "i"); + checkForField("InteractingOldAndNew", Modifier.PUBLIC, "ajc$interField$Y$i"); + checkForMethod("InteractingOldAndNew", Modifier.PUBLIC | Modifier.STATIC, "main"); + checkForMethod("InteractingOldAndNew", Modifier.PUBLIC | Modifier.STATIC | SYNTHETIC, "ajc$get$i"); + checkForMethod("InteractingOldAndNew", Modifier.PUBLIC | Modifier.STATIC | SYNTHETIC, "ajc$set$i"); + checkForMethod("InteractingOldAndNew", Modifier.PUBLIC, "getI1"); + checkForMethod("InteractingOldAndNew", Modifier.PUBLIC, "getI2"); + checkForMethod("InteractingOldAndNew", Modifier.PUBLIC, "setI1"); + checkForMethod("InteractingOldAndNew", Modifier.PUBLIC, "setI2"); + } + + public void testPrivateGenerics() throws Exception { + runTest("generics - private"); + Field f = checkForField("Generics", Modifier.PRIVATE, "listOfString"); + assertEquals("Ljava/util/List;", f.getGenericSignature()); + f = checkForField("Generics", Modifier.PRIVATE, "thing"); + assertEquals("TX;", f.getGenericSignature()); + } + + // --- + + private Field checkForField(String clazzname, int modifiers, String name) throws Exception { + JavaClass jc = getClassFrom(ajc.getSandboxDirectory(), clazzname); + Field[] fs = jc.getFields(); + StringBuffer fields = new StringBuffer(); + for (Field f : fs) { + fields.append(f.getName()).append(" "); + if (f.getName().equals(name)) { + if (f.getModifiers() != modifiers) { + fail("Found field " + name + " in " + clazzname + " but modifiers were wrong, they were " + f.getModifiers()); + } + return f; + } + } + fail("Did not find field " + name + " in class " + clazzname + ". Found fields: " + fields.toString()); + return null; + } + + private Method checkForMethod(String clazzname, int modifiers, String name) throws Exception { + JavaClass jc = getClassFrom(ajc.getSandboxDirectory(), clazzname); + Method[] fs = jc.getMethods(); + StringBuffer methods = new StringBuffer(); + methods.append("\n"); + for (Method f : fs) { + methods.append(f.getName()).append("\n"); + if (f.getName().equals(name)) { + if (f.getModifiers() != modifiers) { + fail("Found method " + name + " in " + clazzname + " but modifiers were wrong, they were " + f.getModifiers()); + } + return f; + } + System.out.println(f.getGenericSignature()); + } + fail("Did not find method " + name + " in class " + clazzname + ". Found methods: " + methods.toString()); + return null; + } + + // public itd onto a target that already has a field of that name + // just to check what goes wrong and who checks it + public void testPublicClash() throws Exception { + runTest("two"); + } + + public void testPrivateClash() throws Exception { + runTest("three"); + + JavaClass jc = getClassFrom(ajc.getSandboxDirectory(), "Three"); + Field[] fs = jc.getFields(); + for (Field f : fs) { + System.out.println(f); + } + + // public int ajc$interField$X$xPrivate [RuntimeVisibleAnnotations] + // public Integer ajc$interField$$yDefault [RuntimeVisibleAnnotations] + // public String zPublic [RuntimeVisibleAnnotations] + + } + + // -- + + public SyntheticRepository createRepos(File cpentry) { + ClassPath cp = new ClassPath(cpentry + File.pathSeparator + System.getProperty("java.class.path")); + return SyntheticRepository.getInstance(cp); + } + + protected JavaClass getClassFrom(File where, String clazzname) throws ClassNotFoundException { + SyntheticRepository repos = createRepos(where); + return repos.loadClass(clazzname); + } + + public static Test suite() { + return XMLBasedAjcTestCase.loadSuite(TransparentWeavingTests.class); + } + + @Override + protected File getSpecFile() { + return new File("../tests/src/org/aspectj/systemtest/ajc169/transparentweaving.xml"); + } + +} \ No newline at end of file diff --git a/tests/src/org/aspectj/systemtest/ajc169/transparentweaving.xml b/tests/src/org/aspectj/systemtest/ajc169/transparentweaving.xml new file mode 100644 index 000000000..10351bdc4 --- /dev/null +++ b/tests/src/org/aspectj/systemtest/ajc169/transparentweaving.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file -- 2.39.5