]> source.dussan.org Git - aspectj.git/commitdiff
Fix 478003: declare parents with generic itd npe
authorAndy Clement <aclement@pivotal.io>
Wed, 18 Nov 2015 22:43:41 +0000 (14:43 -0800)
committerAndy Clement <aclement@pivotal.io>
Wed, 18 Nov 2015 22:43:41 +0000 (14:43 -0800)
docs/dist/doc/README-187.html
tests/bugs188/478003/OrientDBKeyIO.java [new file with mode: 0644]
tests/src/org/aspectj/systemtest/ajc188/Ajc188Tests.java [new file with mode: 0644]
tests/src/org/aspectj/systemtest/ajc188/AllTestsAspectJ188.java [new file with mode: 0644]
tests/src/org/aspectj/systemtest/ajc188/ajc188.xml [new file with mode: 0644]
weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java

index cde9934e37215c2aa88f072a3021bce901f2e4f9..1d9b28c245210221a915b889559eba6d808e5ab0 100644 (file)
@@ -27,9 +27,106 @@ All rights reserved.
 <li>1.8.7 available 9-Sep-2015
 </ul>
 
-<!--
+
 <h2>Notable changes</h2>
--->
+
+<h3>ajdoc</h3>
+<p>The ajdoc tool has been fixed! It is now working again if run on a 1.7 JDK.</p>
+
+<h3>Dynamic weaver attachment</h3>
+<p>The AspectJ loadtime weaving agent can now be dynamically attached to a JVM after it has started 
+(you don't need to use -javaagent). This offers extra flexibility but obviously any
+classes loaded before attachment will not be woven.</p>
+
+<p>Here is a simple aspect:</p>
+<code><pre>
+public aspect Azpect {
+  before(): execution(* *(..)) {
+    System.out.println(thisJoinPointStaticPart);
+  }
+}
+</pre></code>
+
+<p>Compiled via:</p>
+
+<code><pre>ajc -1.8 Azpect.java -outxml</pre></code>
+
+<p>This produces a compiled class <tt>Azpect.class</tt> and a file <tt>META-INF/aop-ajc.xml</tt>.</p>
+
+<p>I then have this sample application (same directory):</p>
+
+<code><pre>
+import java.lang.management.ManagementFactory;
+import org.aspectj.weaver.loadtime.Agent;
+import com.sun.tools.attach.VirtualMachine;
+
+public class Application {
+
+  public static void main(String[] args) {
+    if (!isAspectJAgentLoaded())
+      System.err.println("WARNING: AspectJ weaving agent not loaded");
+    new Sample().doSomething();
+  }
+
+  public static boolean isAspectJAgentLoaded() {
+    try {
+      Agent.getInstrumentation();
+    } catch (NoClassDefFoundError e) {
+      System.out.println(e);
+      return false;
+    } catch (UnsupportedOperationException e) {
+      System.out.println(e);
+      return dynamicallyLoadAspectJAgent();
+    }
+    return true;
+  }
+
+  public static boolean dynamicallyLoadAspectJAgent() {
+    String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName();
+    int p = nameOfRunningVM.indexOf('@');
+    String pid = nameOfRunningVM.substring(0, p);
+    try {
+      VirtualMachine vm = VirtualMachine.attach(pid);
+      String jarFilePath = System.getProperty("AGENT_PATH");
+      vm.loadAgent(jarFilePath);
+      vm.detach();
+    } catch (Exception e) {
+      System.out.println(e);
+      return false;
+    }
+    return true;
+  }
+}
+</pre></code>
+
+<p>And this Sample class:</p>
+<code><pre>
+public class Sample {
+       public void doSomething() {
+               System.out.println("Do something");
+               System.out.println("Square of 7 = " + square(7));
+       }
+
+       private int square(int i) {
+               return i * i;
+       }
+}
+</pre></code>
+
+<p>Compile these with javac, <b>but you must have the aspectjweaver and the JDK tools.jar on your classpath</b>.</p>
+
+<p>Once compiled we can run it:</p>
+
+<code><pre>java -DAGENT_PATH=&lt;path-to&gt;/aspectjweaver.jar Application</pre></code>
+
+<p>What does it do? The main method calls the function that detects whether the agent is attached, if it is not then
+it programmatically attaches it using the <tt>VirtualMachine</tt> class. Then the main method accesses the
+Sample class. At this point in program execution the Sample class is loaded and because the agent has been
+attached it gets woven. Notice that the <tt>Application</tt> class itself is not woven because it was loaded prior
+to agent attachment.</p>
+
+<p>Thanks to Alexander Kriegisch for the sample code and the patch to add this behaviour to AspectJ.</p>
+
 
 <!-- ============================== -->  
 </body>
diff --git a/tests/bugs188/478003/OrientDBKeyIO.java b/tests/bugs188/478003/OrientDBKeyIO.java
new file mode 100644 (file)
index 0000000..2397ae8
--- /dev/null
@@ -0,0 +1,22 @@
+//import com.flickbay.orientdb.OrientKey;
+
+class OrientKey<T> {
+}
+
+class SimpleOrientDBValue extends OrientDBValue {}
+class OrientDBValue<T> {}
+
+public aspect OrientDBKeyIO {
+
+    public interface IO<T> {
+        OrientDBValue<T> getOrientDBValue();
+    }
+
+    declare parents : OrientKey implements IO;
+
+    public SimpleOrientDBValue OrientKey<T>.value = null;
+
+    public OrientDBValue OrientKey<T>.getOrientDBValue() { return this.value; }
+
+}
+
diff --git a/tests/src/org/aspectj/systemtest/ajc188/Ajc188Tests.java b/tests/src/org/aspectj/systemtest/ajc188/Ajc188Tests.java
new file mode 100644 (file)
index 0000000..11c503a
--- /dev/null
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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.ajc188;
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+
+import junit.framework.Test;
+
+import org.aspectj.testing.XMLBasedAjcTestCase;
+
+/**
+ * @author Andy Clement
+ */
+public class Ajc188Tests extends org.aspectj.testing.XMLBasedAjcTestCase {
+
+       public void testCompileError_478003() throws Exception {
+               runTest("compile error");
+       }
+
+       // ---
+
+       public static Test suite() {
+               return XMLBasedAjcTestCase.loadSuite(Ajc188Tests.class);
+       }
+
+       @Override
+       protected File getSpecFile() {
+               return getClassResource("ajc188.xml");
+       }
+
+}
diff --git a/tests/src/org/aspectj/systemtest/ajc188/AllTestsAspectJ188.java b/tests/src/org/aspectj/systemtest/ajc188/AllTestsAspectJ188.java
new file mode 100644 (file)
index 0000000..8867d91
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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.ajc188;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.aspectj.systemtest.apt.AptTests;
+
+public class AllTestsAspectJ188 {
+
+       public static Test suite() {
+               TestSuite suite = new TestSuite("AspectJ 1.8.8 tests");
+               // $JUnit-BEGIN$
+               suite.addTest(Ajc188Tests.suite());
+               // $JUnit-END$
+               return suite;
+       }
+}
diff --git a/tests/src/org/aspectj/systemtest/ajc188/ajc188.xml b/tests/src/org/aspectj/systemtest/ajc188/ajc188.xml
new file mode 100644 (file)
index 0000000..cc1214c
--- /dev/null
@@ -0,0 +1,9 @@
+<!DOCTYPE suite SYSTEM "../tests/ajcTestSuite.dtd"[]>
+
+<suite>
+
+<ajc-test dir="bugs188/478003" title="compile error">
+<compile files="OrientDBKeyIO.java" options="-1.8"/>
+</ajc-test>
+
+</suite>
index 7a637bb2d2fef7dd1b521aa942b3841be156fc37..8d5d26499013b4f6345f40f22fe14adba8ceddbc 100644 (file)
@@ -375,7 +375,12 @@ public class BcelTypeMunger extends ConcreteTypeMunger {
                                                                // for that type
                                                                if (m.isTargetTypeParameterized()) {
                                                                        ResolvedType genericOnType = getWorld().resolve(sig.getDeclaringType()).getGenericType();
-                                                                       m = m.parameterizedFor(newParent.discoverActualOccurrenceOfTypeInHierarchy(genericOnType));
+                                                                       ResolvedType actualOccurrence = newParent.discoverActualOccurrenceOfTypeInHierarchy(genericOnType);
+                                                                       if (actualOccurrence == null) {
+                                                                           // Handle the case where the ITD is onto the type targeted by the declare parents (PR478003)
+                                                                               actualOccurrence = newParentTarget.getType().discoverActualOccurrenceOfTypeInHierarchy(genericOnType);
+                                                                       }
+                                                                       m = m.parameterizedFor(actualOccurrence);
                                                                        // possible sig change when type parameters filled in
                                                                        sig = m.getSignature();
                                                                }