Преглед на файлове

From branch: Changes to runtime for @AJ

tags/PRE_ANDY
aclement преди 19 години
родител
ревизия
2fcbc5bda7

+ 93
- 0
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;
}
}

+ 54
- 0
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;

}



+ 23
- 5
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;
}
}

+ 15
- 2
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];

+ 44
- 3
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);
}
}


}

Loading…
Отказ
Запис