aboutsummaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authoraclement <aclement>2005-04-19 11:52:17 +0000
committeraclement <aclement>2005-04-19 11:52:17 +0000
commit2fcbc5bda7a0e1a6103eba2913e769fe891e4da2 (patch)
tree48186a483c3c220fab4e147f3cb953e5cee9cfc2 /runtime
parent11ddbca0fd1d44048332e3649967d82d03a78014 (diff)
downloadaspectj-2fcbc5bda7a0e1a6103eba2913e769fe891e4da2.tar.gz
aspectj-2fcbc5bda7a0e1a6103eba2913e769fe891e4da2.zip
From branch: Changes to runtime for @AJ
Diffstat (limited to 'runtime')
-rw-r--r--runtime/src/org/aspectj/lang/Aspects.java93
-rw-r--r--runtime/src/org/aspectj/lang/ProceedingJoinPoint.java54
-rw-r--r--runtime/src/org/aspectj/runtime/internal/AroundClosure.java28
-rw-r--r--runtime/src/org/aspectj/runtime/reflect/Factory.java17
-rw-r--r--runtime/src/org/aspectj/runtime/reflect/JoinPointImpl.java47
5 files changed, 229 insertions, 10 deletions
diff --git a/runtime/src/org/aspectj/lang/Aspects.java b/runtime/src/org/aspectj/lang/Aspects.java
new file mode 100644
index 000000000..d907fce59
--- /dev/null
+++ b/runtime/src/org/aspectj/lang/Aspects.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2005 Contributors
+ * 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:
+ * initial implementation Jonas Bonér, Alexandre Vasseur
+ *******************************************************************************/
+package org.aspectj.lang;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ * Handles generic aspectOf method when those are not available in the aspects but added later on
+ * thru load time weaving.
+ * <p/>
+ * Aspects.aspectOf(..) is doing reflective calls to the aspect aspectOf, so for better performance
+ * consider using preparation of the aspects.
+ *
+ * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
+ */
+public class Aspects {
+
+ private final static Class[] EMPTY_CLASS_ARRAY = new Class[0];
+ private final static Class[] PEROBJECT_CLASS_ARRAY = new Class[]{Object.class};
+ private final static Object[] EMPTY_OBJECT_ARRAY = new Object[0];
+ private final static String ASPECTOF = "aspectOf";
+
+ /**
+ * Returns the singleton aspect
+ *
+ * @param aspectClass
+ * @return
+ * @throws NoAspectBoundException if no such aspect
+ */
+ public static Object aspectOf(Class aspectClass) throws NoAspectBoundException {
+ try {
+ return getSingletonAspectOf(aspectClass).invoke(null, EMPTY_OBJECT_ARRAY);
+ } catch (Exception e) {
+ throw new NoAspectBoundException(aspectClass.getName(), e);
+ }
+ }
+
+ /**
+ * Returns the perthis / pertarget aspect
+ * @param aspectClass
+ * @param perObject
+ * @return
+ * @throws NoAspectBoundException if no such aspect, or no aspect bound
+ */
+ public static Object aspectOf(Class aspectClass, Object perObject) throws NoAspectBoundException {
+ try {
+ return getPerObjectAspectOf(aspectClass).invoke(null, new Object[]{perObject});
+ } catch (Exception e) {
+ throw new NoAspectBoundException(aspectClass.getName(), e);
+ }
+ }
+
+ public static Object aspectOf(Class aspectClass, Thread perThread) throws NoAspectBoundException {
+ //TODO - how to know it s a real per Thread ?
+ // if it is actually a singleton one, we will have it as well...
+ try {
+ return getSingletonAspectOf(aspectClass).invoke(null, EMPTY_OBJECT_ARRAY);
+ } catch (Exception e) {
+ throw new NoAspectBoundException(aspectClass.getName(), e);
+ }
+ }
+
+ private static Method getSingletonAspectOf(Class aspectClass) throws NoSuchMethodException {
+ Method method = aspectClass.getDeclaredMethod(ASPECTOF, EMPTY_CLASS_ARRAY);
+ method.setAccessible(true);
+ if (!method.isAccessible()
+ || !Modifier.isPublic(method.getModifiers())
+ || !Modifier.isStatic(method.getModifiers())) {
+ throw new RuntimeException(aspectClass.getName(), new Exception("aspectOf is not public static"));
+ }
+ return method;
+ }
+
+ private static Method getPerObjectAspectOf(Class aspectClass) throws NoSuchMethodException {
+ Method method = aspectClass.getDeclaredMethod(ASPECTOF, PEROBJECT_CLASS_ARRAY);
+ method.setAccessible(true);
+ if (!method.isAccessible()
+ || !Modifier.isPublic(method.getModifiers())
+ || !Modifier.isStatic(method.getModifiers())) {
+ throw new RuntimeException(aspectClass.getName(), new Exception("aspectOf is not public static"));
+ }
+ return method;
+ }
+}
diff --git a/runtime/src/org/aspectj/lang/ProceedingJoinPoint.java b/runtime/src/org/aspectj/lang/ProceedingJoinPoint.java
new file mode 100644
index 000000000..2a54d407b
--- /dev/null
+++ b/runtime/src/org/aspectj/lang/ProceedingJoinPoint.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2005 Contributors
+ * 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:
+ * initial implementation Jonas Bonér, Alexandre Vasseur
+ *******************************************************************************/
+package org.aspectj.lang;
+
+import org.aspectj.runtime.internal.AroundClosure;
+
+/**
+ * ProceedingJoinPoint exposes the proceed(..) method in order to support around advice in @AJ aspects
+ *
+ * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
+ */
+public interface ProceedingJoinPoint extends JoinPoint {
+
+ /**
+ * The joinpoint needs to know about its closure so that proceed can delegate to closure.run()
+ * <p/>
+ * This internal method should not be called directly, and won't be visible to the end-user when
+ * packed in a jar (synthetic method)
+ *
+ * @param arc
+ */
+ void set$AroundClosure(AroundClosure arc);
+
+ /**
+ * Proceed with the next advice or target method invocation
+ *
+ * @return
+ * @throws Throwable
+ */
+ public Object proceed() throws Throwable;
+
+ /**
+ * Proceed with the next advice or target method invocation
+ * <p/>
+ * The given args Object[] must be in the same order and size as the advice signature but
+ * without the actual joinpoint instance
+ *
+ * @param args
+ * @return
+ * @throws Throwable
+ */
+ public Object proceed(Object[] args) throws Throwable;
+
+}
+
+
diff --git a/runtime/src/org/aspectj/runtime/internal/AroundClosure.java b/runtime/src/org/aspectj/runtime/internal/AroundClosure.java
index 1d5ad810a..f47921688 100644
--- a/runtime/src/org/aspectj/runtime/internal/AroundClosure.java
+++ b/runtime/src/org/aspectj/runtime/internal/AroundClosure.java
@@ -9,24 +9,31 @@
*
* Contributors:
* Xerox/PARC initial implementation
+ * Alex Vasseur wired up for @AJ proceeding
* ******************************************************************/
package org.aspectj.runtime.internal;
+import org.aspectj.lang.ProceedingJoinPoint;
+
public abstract class AroundClosure {
- //private Object[] state;
+ private Object[] state;
+ protected Object[] preInitializationState;
- public AroundClosure(/* Object[] state */) {
- // this.state = state;
+ public AroundClosure() {
}
- protected Object[] state;
- protected Object[] preInitializationState;
public AroundClosure(Object[] state) {
this.state = state;
}
+
+
+ public Object[] getState() {
+ return state;
+ }
+
public Object[] getPreInitializationState() {
return preInitializationState;
}
@@ -36,4 +43,15 @@ public abstract class AroundClosure {
* call in the around advice (with primitives coerced to Object types)
*/
public abstract Object run(Object[] args) throws Throwable;
+
+ /**
+ * This method is called to implicitly associate the closure with the joinpoint
+ * as required for @AJ aspect proceed()
+ */
+ public ProceedingJoinPoint linkClosureAndJoinPoint() {
+ //TODO is this cast safe ?
+ ProceedingJoinPoint jp = (ProceedingJoinPoint)state[state.length-1];
+ jp.set$AroundClosure(this);
+ return jp;
+ }
}
diff --git a/runtime/src/org/aspectj/runtime/reflect/Factory.java b/runtime/src/org/aspectj/runtime/reflect/Factory.java
index 3ee924f99..c3e662874 100644
--- a/runtime/src/org/aspectj/runtime/reflect/Factory.java
+++ b/runtime/src/org/aspectj/runtime/reflect/Factory.java
@@ -9,6 +9,7 @@
*
* Contributors:
* Xerox/PARC initial implementation
+ * Alex Vasseur new factory methods for variants of JP
* ******************************************************************/
@@ -43,7 +44,19 @@ public final class Factory {
public JoinPoint.StaticPart makeSJP(String kind, Signature sig, int l) {
return new JoinPointImpl.StaticPartImpl(kind, sig, makeSourceLoc(l, -1));
}
-
+
+ public JoinPoint.EnclosingStaticPart makeESJP(String kind, Signature sig, SourceLocation loc) {
+ return new JoinPointImpl.EnclosingStaticPartImpl(kind, sig, loc);
+ }
+
+ public JoinPoint.EnclosingStaticPart makeESJP(String kind, Signature sig, int l, int c) {
+ return new JoinPointImpl.EnclosingStaticPartImpl(kind, sig, makeSourceLoc(l, c));
+ }
+
+ public JoinPoint.EnclosingStaticPart makeESJP(String kind, Signature sig, int l) {
+ return new JoinPointImpl.EnclosingStaticPartImpl(kind, sig, makeSourceLoc(l, -1));
+ }
+
public static JoinPoint.StaticPart makeEncSJP(Member member) {
Signature sig = null;
String kind = null;
@@ -64,7 +77,7 @@ public final class Factory {
} else {
throw new IllegalArgumentException("member must be either a method or constructor");
}
- return new JoinPointImpl.StaticPartImpl(kind,sig,null);
+ return new JoinPointImpl.EnclosingStaticPartImpl(kind,sig,null);
}
private static Object[] NO_ARGS = new Object[0];
diff --git a/runtime/src/org/aspectj/runtime/reflect/JoinPointImpl.java b/runtime/src/org/aspectj/runtime/reflect/JoinPointImpl.java
index 430f36a42..34d5b469c 100644
--- a/runtime/src/org/aspectj/runtime/reflect/JoinPointImpl.java
+++ b/runtime/src/org/aspectj/runtime/reflect/JoinPointImpl.java
@@ -14,11 +14,13 @@
package org.aspectj.runtime.reflect;
-import org.aspectj.lang.*;
-
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.SourceLocation;
+import org.aspectj.runtime.internal.AroundClosure;
-class JoinPointImpl implements JoinPoint {
+class JoinPointImpl implements ProceedingJoinPoint {
static class StaticPartImpl implements JoinPoint.StaticPart {
String kind;
Signature signature;
@@ -48,6 +50,12 @@ class JoinPointImpl implements JoinPoint {
public final String toLongString() { return toString(StringMaker.longStringMaker); }
}
+ static class EnclosingStaticPartImpl extends StaticPartImpl implements EnclosingStaticPart {
+ public EnclosingStaticPartImpl(String kind, Signature signature, SourceLocation sourceLocation) {
+ super(kind, signature, sourceLocation);
+ }
+ }
+
Object _this;
Object target;
Object[] args;
@@ -78,4 +86,37 @@ class JoinPointImpl implements JoinPoint {
public final String toString() { return staticPart.toString(); }
public final String toShortString() { return staticPart.toShortString(); }
public final String toLongString() { return staticPart.toLongString(); }
+
+ // To proceed we need a closure to proceed on
+ private AroundClosure arc;
+ public void set$AroundClosure(AroundClosure arc) {
+ this.arc = arc;
+ }
+
+ public Object proceed() throws Throwable {
+ // when called from a before advice, but be a no-op
+ if (arc == null)
+ return null;
+ else
+ return arc.run(arc.getState());
+ }
+
+ public Object proceed(Object[] adviceBindings) throws Throwable {
+ // when called from a before advice, but be a no-op
+ if (arc == null)
+ return null;
+ else {
+ // state is always consistent with caller?,callee?,formals...,jp
+ Object[] state = arc.getState();
+ for (int i = state.length-2; i >= 0; i--) {
+ int formalIndex = (adviceBindings.length - 1) - (state.length-2) + i;
+ if (formalIndex >= 0 && formalIndex < adviceBindings.length) {
+ state[i] = adviceBindings[formalIndex];
+ }
+ }
+ return arc.run(state);
+ }
+ }
+
+
}