]> source.dussan.org Git - aspectj.git/commitdiff
Fix and testcase for Bugzilla Bug 49657
authoraclement <aclement>
Thu, 19 Aug 2004 16:38:16 +0000 (16:38 +0000)
committeraclement <aclement>
Thu, 19 Aug 2004 16:38:16 +0000 (16:38 +0000)
   Weaver results in rt error if affected base class not exposed

14 files changed:
org.aspectj.ajdt.core/testdata/partialHierarchy/base.jar [new file with mode: 0644]
org.aspectj.ajdt.core/testdata/partialHierarchy/build.cmd [new file with mode: 0644]
org.aspectj.ajdt.core/testdata/partialHierarchy/fullBase.jar [new file with mode: 0644]
org.aspectj.ajdt.core/testdata/partialHierarchy/sample/Base.java [new file with mode: 0644]
org.aspectj.ajdt.core/testdata/partialHierarchy/sample/Derived.java [new file with mode: 0644]
org.aspectj.ajdt.core/testdata/partialHierarchy/sample/Iface.java [new file with mode: 0644]
org.aspectj.ajdt.core/testdata/partialHierarchy/sample/Trace.aj [new file with mode: 0644]
org.aspectj.ajdt.core/testdata/partialHierarchy/woven.jar [new file with mode: 0644]
org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/AjdtBatchTests.java
org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/PartiallyExposedHierarchyTestCase.java [new file with mode: 0644]
weaver/src/org/aspectj/weaver/ResolvedTypeX.java
weaver/src/org/aspectj/weaver/WeaverMessages.java
weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java
weaver/src/org/aspectj/weaver/weaver-messages.properties

diff --git a/org.aspectj.ajdt.core/testdata/partialHierarchy/base.jar b/org.aspectj.ajdt.core/testdata/partialHierarchy/base.jar
new file mode 100644 (file)
index 0000000..59bb333
Binary files /dev/null and b/org.aspectj.ajdt.core/testdata/partialHierarchy/base.jar differ
diff --git a/org.aspectj.ajdt.core/testdata/partialHierarchy/build.cmd b/org.aspectj.ajdt.core/testdata/partialHierarchy/build.cmd
new file mode 100644 (file)
index 0000000..74788b0
--- /dev/null
@@ -0,0 +1,8 @@
+call ajc -outjar fullBase.jar sample\Base.java sample\Derived.java sample\Iface.java\r
+jar xf fullBase.jar\r
+jar cf base.jar sample\Derived.class sample\Iface.class\r
+set XCLASSPATH=%CLASSPATH%\r
+set CLASSPATH=fullBase.jar;%CLASSPATH%\r
+call ajc -injars base.jar -outjar woven.jar sample\Trace.aj\r
+java -classpath woven.jar;%CLASSPATH%  sample.Derived\r
+set CLASSPATH=%XCLASSPATH%\r
diff --git a/org.aspectj.ajdt.core/testdata/partialHierarchy/fullBase.jar b/org.aspectj.ajdt.core/testdata/partialHierarchy/fullBase.jar
new file mode 100644 (file)
index 0000000..6231415
Binary files /dev/null and b/org.aspectj.ajdt.core/testdata/partialHierarchy/fullBase.jar differ
diff --git a/org.aspectj.ajdt.core/testdata/partialHierarchy/sample/Base.java b/org.aspectj.ajdt.core/testdata/partialHierarchy/sample/Base.java
new file mode 100644 (file)
index 0000000..f126f66
--- /dev/null
@@ -0,0 +1,9 @@
+package sample;
+
+public abstract class Base implements Iface {
+    int x;
+    Base() {
+       x=1;
+    }
+    abstract void foo();
+}
diff --git a/org.aspectj.ajdt.core/testdata/partialHierarchy/sample/Derived.java b/org.aspectj.ajdt.core/testdata/partialHierarchy/sample/Derived.java
new file mode 100644 (file)
index 0000000..cc79957
--- /dev/null
@@ -0,0 +1,15 @@
+package sample;
+
+public class Derived extends Base {
+    int y;
+    public Derived() {
+       super();
+       y = 2;
+    }
+
+    public void foo() {}
+
+    public static void main(String args[]) {
+       new Derived();
+    }
+}
diff --git a/org.aspectj.ajdt.core/testdata/partialHierarchy/sample/Iface.java b/org.aspectj.ajdt.core/testdata/partialHierarchy/sample/Iface.java
new file mode 100644 (file)
index 0000000..a295b5f
--- /dev/null
@@ -0,0 +1,4 @@
+package sample;
+
+public interface Iface {
+}
diff --git a/org.aspectj.ajdt.core/testdata/partialHierarchy/sample/Trace.aj b/org.aspectj.ajdt.core/testdata/partialHierarchy/sample/Trace.aj
new file mode 100644 (file)
index 0000000..a557782
--- /dev/null
@@ -0,0 +1,22 @@
+package sample;\r
+\r
+import java.util.logging.Logger;\r
+\r
+public aspect Trace {\r
+    public interface Traced {}\r
+    declare parents: (sample.* && !Trace) extends Traced;\r
+\r
+//    private Logger Traced.logger;\r
+    before(Traced current) : \r
+       execution(Traced+.new(..)) && !execution(Traced.new()) && this(current) {\r
+       current.getLogger().severe("entering ctor for "+thisJoinPoint);\r
+    }\r
+\r
+    public Logger Traced.getLogger() {\r
+ //       if (logger == null) {\r
+//         logger = Logger.getLogger(getClass().toString());\r
+ //       }\r
+//     return logger;\r
+return null;\r
+    }\r
+}\r
diff --git a/org.aspectj.ajdt.core/testdata/partialHierarchy/woven.jar b/org.aspectj.ajdt.core/testdata/partialHierarchy/woven.jar
new file mode 100644 (file)
index 0000000..035e2b2
Binary files /dev/null and b/org.aspectj.ajdt.core/testdata/partialHierarchy/woven.jar differ
index 5f9d266a959336c1011f2376a7b4098a12b5edec..5dcc167df74202065b2654a866342a1610bf60f9 100644 (file)
@@ -30,6 +30,7 @@ public class AjdtBatchTests extends TestCase {
         suite.addTestSuite(ImageTestCase.class); 
         suite.addTestSuite(MultipleCompileTestCase.class); 
         suite.addTestSuite(JavadocTest.class);
+        suite.addTestSuite(PartiallyExposedHierarchyTestCase.class);
         // XXX suite.addTestSuite(VerifyWeaveTestCase.class); 
         //suite.addTestSuite(WorkingCommandTestCase.class); 
         //$JUnit-END$
diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/PartiallyExposedHierarchyTestCase.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/PartiallyExposedHierarchyTestCase.java
new file mode 100644 (file)
index 0000000..de45e9e
--- /dev/null
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Matthew Webster - initial implementation
+ *******************************************************************************/
+package org.aspectj.ajdt.internal.compiler.batch;
+
+import java.io.File;
+
+import org.aspectj.tools.ajc.AjcTestCase;
+import org.aspectj.tools.ajc.CompilationResult;
+
+/**
+ * If you need to rebuild the components for this test, I'm afraid you will have
+ * to run build.cmd in the testdata/partialHierarchy directory which calls ajc and
+ * does some jar manipulation.
+ */
+public class PartiallyExposedHierarchyTestCase extends AjcTestCase {
+
+       public static final String PROJECT_DIR = "partialHierarchy";
+
+       private File baseDir;
+       
+       protected void setUp() throws Exception {
+               super.setUp();
+               baseDir = new File("../org.aspectj.ajdt.core/testdata",PROJECT_DIR);
+       }
+       
+       /**
+        * This test verifies that AspectJ behaves correctly when parts of an object
+        * hierarchy are exposed to it for weaving.  See pr49657 for all the details.
+        */
+       public void testPartiallyExposedHierarchy () {
+               Message warning = new Message(11,"no interface constructor-execution join point");
+               //TODO This line number will change to 15 (from 5) when type mungers remember where they came from!
+               Message error   = new Message(5, "type sample.Base must be accessible for weaving interface inter type declaration from aspect sample.Trace");
+               CompilationResult result = ajc(baseDir,
+                               new String[]{"-classpath","fullBase.jar",
+                                                        "-injars","base.jar",
+                                                        "sample"+File.separator+"Trace.aj"});
+//             System.err.println(result.getWarningMessages());
+//             System.err.println(result.getErrorMessages());
+//             System.err.println(result.getStandardOutput());
+               MessageSpec spec = new MessageSpec(null,newMessageList(warning),newMessageList(error));
+               assertMessages(result,spec);
+       }
+       
+
+}
index 3fbf7d5888be8de981b7978d1a2b519a8041cbf1..c9e95c5f38a4e81b7742192f1f2f3048e0d55357 100644 (file)
@@ -1307,6 +1307,25 @@ public abstract class ResolvedTypeX extends TypeX {
                return true;
        }
        
+       public ResolvedTypeX getTopmostImplementor(ResolvedTypeX interfaceType) {
+               if (isInterface()) return null;
+               if (!interfaceType.isAssignableFrom(this)) return null;
+               // Check if my super class is an implementor?
+               ResolvedTypeX higherType  = this.getSuperclass().getTopmostImplementor(interfaceType);
+               if (higherType!=null) return higherType;
+               return this;
+       }
+       
+       private ResolvedTypeX findHigher(ResolvedTypeX other) {
+        if (this == other) return this;
+     for(Iterator i = other.getDirectSupertypes(); i.hasNext(); ) {
+       ResolvedTypeX rtx = (ResolvedTypeX)i.next();
+       boolean b = this.isAssignableFrom(rtx);
+       if (b) return rtx;
+     }       
+     return null;
+       }
+       
        public List getExposedPointcuts() {
                List ret = new ArrayList();
                if (getSuperclass() != null) ret.addAll(getSuperclass().getExposedPointcuts());
index ae03329d38095ba2b27c21bcb63ba999270b2e58..8fe792f9bd22d678dfffb86b6cd5a1de14ab7a49 100644 (file)
@@ -52,6 +52,7 @@ public class WeaverMessages {
        public static final String ITD_OVERIDDING_STATIC = "overridingStatic";
        public static final String ITD_CONFLICT = "itdConflict";
        public static final String ITD_MEMBER_CONFLICT = "itdMemberConflict";
+       public static final String ITD_NON_EXPOSED_IMPLEMENTOR = "itdNonExposedImplementor";
        
        
        public static final String NON_VOID_RETURN = "nonVoidReturn";
index b490e3d2170e249ab7ea445f83c4034bd431fc69..83b179643eef54a5ad36f11a49c35857b331b30b 100644 (file)
@@ -24,6 +24,8 @@ import org.aspectj.apache.bcel.generic.InstructionFactory;
 import org.aspectj.apache.bcel.generic.InstructionList;
 import org.aspectj.apache.bcel.generic.Type;
 import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.MessageUtil;
 import org.aspectj.bridge.WeaveMessage;
 import org.aspectj.weaver.AjcMemberMaker;
 import org.aspectj.weaver.AsmRelationshipProvider;
@@ -40,6 +42,7 @@ import org.aspectj.weaver.ResolvedMember;
 import org.aspectj.weaver.ResolvedTypeMunger;
 import org.aspectj.weaver.ResolvedTypeX;
 import org.aspectj.weaver.TypeX;
+import org.aspectj.weaver.WeaverMessages;
 import org.aspectj.weaver.WeaverStateInfo;
 import org.aspectj.weaver.patterns.Pointcut;
 
@@ -414,39 +417,58 @@ public class BcelTypeMunger extends ConcreteTypeMunger {
                        addNeededSuperCallMethods(weaver, onType, munger.getSuperMethodsCalled());
                        
                return true;
-               } else if (onInterface && gen.getType().isTopmostImplementor(onType) && 
-                                               !Modifier.isAbstract(signature.getModifiers()))
-               {
-                       ResolvedMember introMethod = 
+               
+               } else if (onInterface && !Modifier.isAbstract(signature.getModifiers())) {
+                       
+                       // This means the 'gen' should be the top most implementor
+                       // - if it is *not* then something went wrong after we worked
+                       // out that it was the top most implementor (see pr49657)
+               if (!gen.getType().isTopmostImplementor(onType)) {
+                       ResolvedTypeX rtx = gen.getType().getTopmostImplementor(onType);
+                       if (!rtx.isExposedToWeaver()) {
+                               ISourceLocation sLoc = munger.getSourceLocation();
+                           weaver.getWorld().getMessageHandler().handleMessage(MessageUtil.error(
+                                       WeaverMessages.format(WeaverMessages.ITD_NON_EXPOSED_IMPLEMENTOR,rtx,getAspectType().getName()),
+                                                       (sLoc==null?getAspectType().getSourceLocation():sLoc)));
+                       } else {
+                               // XXX what does this state mean?
+                               // We have incorrectly identified what is the top most implementor and its not because
+                               // a type wasn't exposed to the weaver
+                       }
+                               return false;
+               } else {
+               
+                         ResolvedMember introMethod = 
                                        AjcMemberMaker.interMethod(signature, aspectType, false);
                        
-                       LazyMethodGen mg = makeMethodGen(gen, introMethod);
+                         LazyMethodGen mg = makeMethodGen(gen, introMethod);
                                                
-                       Type[] paramTypes = BcelWorld.makeBcelTypes(introMethod.getParameterTypes());
-                       Type returnType = BcelWorld.makeBcelType(introMethod.getReturnType());
+                         Type[] paramTypes = BcelWorld.makeBcelTypes(introMethod.getParameterTypes());
+                         Type returnType = BcelWorld.makeBcelType(introMethod.getReturnType());
                        
-                       InstructionList body = mg.getBody();
-                       InstructionFactory fact = gen.getFactory();
-                       int pos = 0;
+                         InstructionList body = mg.getBody();
+                         InstructionFactory fact = gen.getFactory();
+                         int pos = 0;
 
-                       if (!introMethod.isStatic()) {
+                         if (!introMethod.isStatic()) {
                                body.append(InstructionFactory.createThis());
                                pos++;
-                       }
-                       for (int i = 0, len = paramTypes.length; i < len; i++) {
+                         }
+                         for (int i = 0, len = paramTypes.length; i < len; i++) {
                                Type paramType = paramTypes[i];
                                body.append(InstructionFactory.createLoad(paramType, pos));
                                pos+=paramType.getSize();
-                       }
-                       body.append(Utility.createInvoke(fact, weaver.getWorld(), dispatchMethod));
-                       body.append(InstructionFactory.createReturn(returnType));
-                       mg.definingType = onType;
+                         }
+                         body.append(Utility.createInvoke(fact, weaver.getWorld(), dispatchMethod));
+                         body.append(InstructionFactory.createReturn(returnType));
+                         mg.definingType = onType;
                        
-                       weaver.addOrReplaceLazyMethodGen(mg);
+                         weaver.addOrReplaceLazyMethodGen(mg);
                        
-                       addNeededSuperCallMethods(weaver, onType, munger.getSuperMethodsCalled());
+                         addNeededSuperCallMethods(weaver, onType, munger.getSuperMethodsCalled());
                        
-                       return true;
+                         return true;
+               }
                } else {
                        return false;
                }
index 5052d27ce80a66eee9bd0887a1339b1aac2deae9..c731fb9650004302063dc6e9ea1a6a0ac0f9f47a 100644 (file)
@@ -51,6 +51,7 @@ overriddenStatic={0} cannot override {1}; overridden method is static
 overridingStatic={0} cannot override {1}; overriding method is static
 itdConflict=intertype declaration from {0} conflicts with intertype declaration: {1} from {2}
 itdMemberConflict=inter-type declaration from {0} conflicts with existing member: {1}
+itdNonExposedImplementor=type {0} must be accessible for weaving interface inter type declaration from aspect {1}
 
 # advice messages...
 nonVoidReturn=applying to join point that doesn't return void: {0}