[seam-commits] Seam SVN: r8481 - trunk/src/wicket/org/jboss/seam/wicket/ioc.
seam-commits at lists.jboss.org
seam-commits at lists.jboss.org
Sat Jul 19 08:43:18 EDT 2008
Author: pete.muir at jboss.org
Date: 2008-07-19 08:43:17 -0400 (Sat, 19 Jul 2008)
New Revision: 8481
Added:
trunk/src/wicket/org/jboss/seam/wicket/ioc/Interceptor.java
Removed:
trunk/src/wicket/org/jboss/seam/wicket/ioc/RootInterceptor.java
Modified:
trunk/src/wicket/org/jboss/seam/wicket/ioc/BijectionInterceptor.java
trunk/src/wicket/org/jboss/seam/wicket/ioc/InvocationContext.java
trunk/src/wicket/org/jboss/seam/wicket/ioc/JavassistInstrumentor.java
trunk/src/wicket/org/jboss/seam/wicket/ioc/WicketHandler.java
Log:
Add support for intercepting exceptions
Modified: trunk/src/wicket/org/jboss/seam/wicket/ioc/BijectionInterceptor.java
===================================================================
--- trunk/src/wicket/org/jboss/seam/wicket/ioc/BijectionInterceptor.java 2008-07-17 18:49:20 UTC (rev 8480)
+++ trunk/src/wicket/org/jboss/seam/wicket/ioc/BijectionInterceptor.java 2008-07-19 12:43:17 UTC (rev 8481)
@@ -3,18 +3,17 @@
import org.jboss.seam.wicket.WicketComponent;
-public class BijectionInterceptor<T> extends RootInterceptor<T>
+public class BijectionInterceptor<T> implements Interceptor<T>
{
- @Override
- public void afterInvoke(InvocationContext<T> invocationContext)
+ public Object afterInvoke(InvocationContext<T> invocationContext, Object result)
{
invocationContext.getComponent().outject(invocationContext.getBean());
invocationContext.getComponent().disinject(invocationContext.getBean());
disinjectEnclosingInstances(invocationContext);
+ return result;
}
- @Override
public void beforeInvoke(InvocationContext<T> invocationContext)
{
try
@@ -28,12 +27,17 @@
}
}
+ public Exception handleException(InvocationContext<T> invocationContext, Exception exception)
+ {
+ return exception;
+ }
+
private static <T> void injectEnclosingInstances(InvocationContext<T> invocationContext)
{
InstrumentedComponent enclosingInstance = invocationContext.getInstrumentedComponent().getEnclosingInstance();
while (enclosingInstance != null)
{
- if (!enclosingInstance.getHandler().isCallInProgress())
+ if (!enclosingInstance.getHandler().isReentrant())
{
WicketComponent.getInstance(enclosingInstance.getClass()).inject(enclosingInstance);
enclosingInstance = enclosingInstance.getEnclosingInstance();
@@ -50,7 +54,7 @@
InstrumentedComponent enclosingInstance = invocationContext.getInstrumentedComponent().getEnclosingInstance();
while (enclosingInstance != null)
{
- if (!enclosingInstance.getHandler().isCallInProgress())
+ if (!enclosingInstance.getHandler().isReentrant())
{
WicketComponent.getInstance(enclosingInstance.getClass()).disinject(enclosingInstance);
enclosingInstance = enclosingInstance.getEnclosingInstance();
Copied: trunk/src/wicket/org/jboss/seam/wicket/ioc/Interceptor.java (from rev 8477, trunk/src/wicket/org/jboss/seam/wicket/ioc/RootInterceptor.java)
===================================================================
--- trunk/src/wicket/org/jboss/seam/wicket/ioc/Interceptor.java (rev 0)
+++ trunk/src/wicket/org/jboss/seam/wicket/ioc/Interceptor.java 2008-07-19 12:43:17 UTC (rev 8481)
@@ -0,0 +1,15 @@
+package org.jboss.seam.wicket.ioc;
+
+import java.io.Serializable;
+
+
+public interface Interceptor<T> extends Serializable
+{
+
+ public void beforeInvoke(InvocationContext<T> invocationContext);
+
+ public Object afterInvoke(InvocationContext<T> invocationContext, Object result);
+
+ public Exception handleException(InvocationContext<T> invocationContext, Exception exception);
+
+}
Modified: trunk/src/wicket/org/jboss/seam/wicket/ioc/InvocationContext.java
===================================================================
--- trunk/src/wicket/org/jboss/seam/wicket/ioc/InvocationContext.java 2008-07-17 18:49:20 UTC (rev 8480)
+++ trunk/src/wicket/org/jboss/seam/wicket/ioc/InvocationContext.java 2008-07-19 12:43:17 UTC (rev 8481)
@@ -20,7 +20,7 @@
this.component = component;
}
- public InvocationContext(T bean, WicketComponent<T> component)
+ public InvocationContext(Constructor<T> constructor, T bean, WicketComponent<T> component)
{
// TODO Write the constructor discovery code
this.constructor = constructor;
Modified: trunk/src/wicket/org/jboss/seam/wicket/ioc/JavassistInstrumentor.java
===================================================================
--- trunk/src/wicket/org/jboss/seam/wicket/ioc/JavassistInstrumentor.java 2008-07-17 18:49:20 UTC (rev 8480)
+++ trunk/src/wicket/org/jboss/seam/wicket/ioc/JavassistInstrumentor.java 2008-07-19 12:43:17 UTC (rev 8481)
@@ -6,10 +6,12 @@
import javassist.CannotCompileException;
import javassist.ClassPool;
+import javassist.CtBehavior;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtField;
import javassist.CtMethod;
+import javassist.CtNewConstructor;
import javassist.CtNewMethod;
import javassist.LoaderClassPath;
import javassist.Modifier;
@@ -131,6 +133,8 @@
Initializer handlerInitializer = Initializer.byCall(handlerClass, "create");
implementation.addField(handlerField, handlerInitializer);
+ CtClass exception = classPool.get(Exception.class.getName());
+
CtClass instrumentedComponent = classPool.get(InstrumentedComponent.class.getName());
implementation.addInterface(instrumentedComponent);
CtMethod getHandlerMethod = CtNewMethod.getter("getHandler", handlerField);
@@ -142,34 +146,13 @@
{
if (!Modifier.isStatic(method.getModifiers()))
{
- String methodName = method.getName();
if (!("getHandler".equals(method.getName()) || "getEnclosingInstance".equals(method.getName())))
- {
- String methodSignature = "";
- for (int i = 0; i < method.getParameterTypes().length; i++)
- {
- if (i > 0)
- {
- methodSignature += ",";
- }
- methodSignature += method.getParameterTypes()[i].getName() + ".class";
- }
- String methodCall = "this.getClass().getDeclaredMethod(\""+ methodName + "\", methodParameters)";
- String methodParameters;
- if (methodSignature.length() > 0)
- {
- methodParameters = "Class[] methodParameters = {" + methodSignature + "};";
- }
- else
- {
- methodParameters = "Class[] methodParameters = new Class[0];";
- }
- log.trace("Method call: " + methodCall);
+ {
+ String newName = implementation.makeUniqueName(method.getName());
- method.insertBefore(methodParameters + "handler.beforeInvoke(this, " + methodCall + ");");
- method.insertBefore("handler.setCallInProgress(true);");
- method.insertAfter(methodParameters + "handler.afterInvoke(this, " + methodCall + ");");
- method.insertAfter("handler.setCallInProgress(false);", true);
+ CtMethod newMethod = CtNewMethod.copy(method, newName, implementation, null);
+ implementation.addMethod(newMethod);
+ method.setBody(createBody(implementation, newMethod));
log.trace("instrumented method " + method.getName());
}
}
@@ -178,21 +161,85 @@
{
if (constructor.isConstructor())
{
- constructor.insertBeforeBody("handler.beforeInvoke(this);");
- constructor.insertBeforeBody("handler.setCallInProgress(true);");
- constructor.insertAfter("handler.afterInvoke(this);");
- constructor.insertAfter("handler.setCallInProgress(false);");
- log.trace("instrumented constructor " + constructor.getName());
+ {
+ String constructorObject = createConstructorObject(constructor);
+ constructor.insertBeforeBody(constructorObject + "handler.beforeInvoke(this, constructor);");
+ constructor.addCatch("{" + constructorObject + "throw new RuntimeException(handler.handleException(this, constructor, e));}", exception, "e");
+ constructor.insertAfter(constructorObject + "handler.afterInvoke(this, constructor);");
+ log.trace("instrumented constructor " + constructor.getName());
+ }
}
}
}
classes.add(implementation.getName());
+
}
public ClassLoader getClassLoader()
{
return classLoader;
}
+
+ private static String createBody(CtClass clazz, CtMethod method) throws NotFoundException
+ {
+ String src = "{" + createMethodObject(method) + "handler.beforeInvoke(this, method);" + createMethodDelegation(method) + "return ($r) handler.afterInvoke(this, method, ($w) result);}";
+ log.trace("Creating method " + clazz.getName() + "." + method.getName() + "(" + method.getSignature() + ")" + src);
+ return src;
+ }
+
+ private static String createMethodDelegation(CtMethod method) throws NotFoundException
+ {
+ CtClass returnType = method.getReturnType();
+ if (returnType.equals(CtClass.voidType))
+ {
+ return "Object result = null; " + wrapInExceptionHandler(method.getName() + "($$);");
+ }
+ else
+ {
+ String src = returnType.getName() + " result;";
+ src += wrapInExceptionHandler("result = " + method.getName() + "($$);");
+ return src;
+ }
+ }
+
+ private static String wrapInExceptionHandler(String src)
+ {
+ return "try {" + src + "} catch (Exception e) { throw new RuntimeException(handler.handleException(this, method, e)); }";
+ }
+
+ private static String createParameterTypesArray(CtBehavior behavior) throws NotFoundException
+ {
+ String src = "Class[] parameterTypes = new Class[" + behavior.getParameterTypes().length + "];";
+ for (int i = 0; i < behavior.getParameterTypes().length; i++)
+ {
+ src += "parameterTypes[" + i + "] = " + behavior.getParameterTypes()[i].getName() + ".class;";
+ }
+ return src;
+ }
+
+ private static String createMethodObject(CtMethod method) throws NotFoundException
+ {
+ String src = createParameterTypesArray(method);
+ src += "java.lang.reflect.Method method = this.getClass().getDeclaredMethod(\""+ method.getName() + "\", parameterTypes);";
+ return src;
+ }
+
+ private static String createConstructorObject(CtConstructor constructor) throws NotFoundException
+ {
+ String src = createParameterTypesArray(constructor);
+ src += "java.lang.reflect.Constructor constructor = this.getClass().getDeclaredConstructor(parameterTypes);";
+ return src;
+ }
+
+ private static String createParametersArray(CtBehavior behavior) throws NotFoundException
+ {
+ String src = "Object[] parameters = new Object[" + behavior.getParameterTypes().length + "];";
+ for (int i = 0; i < behavior.getParameterTypes().length; i++)
+ {
+ src += "parameters[" + i + "] = $" + i + ";";
+ }
+ return src;
+ }
private static boolean isInstrumentable(CtClass clazz)
{
Deleted: trunk/src/wicket/org/jboss/seam/wicket/ioc/RootInterceptor.java
===================================================================
--- trunk/src/wicket/org/jboss/seam/wicket/ioc/RootInterceptor.java 2008-07-17 18:49:20 UTC (rev 8480)
+++ trunk/src/wicket/org/jboss/seam/wicket/ioc/RootInterceptor.java 2008-07-19 12:43:17 UTC (rev 8481)
@@ -1,13 +0,0 @@
-package org.jboss.seam.wicket.ioc;
-
-import java.io.Serializable;
-
-
-public abstract class RootInterceptor<T> implements Serializable
-{
-
- public abstract void beforeInvoke(InvocationContext<T> invocationContext);
-
- public abstract void afterInvoke(InvocationContext<T> invocationContext);
-
-}
Modified: trunk/src/wicket/org/jboss/seam/wicket/ioc/WicketHandler.java
===================================================================
--- trunk/src/wicket/org/jboss/seam/wicket/ioc/WicketHandler.java 2008-07-17 18:49:20 UTC (rev 8480)
+++ trunk/src/wicket/org/jboss/seam/wicket/ioc/WicketHandler.java 2008-07-19 12:43:17 UTC (rev 8481)
@@ -23,7 +23,7 @@
this.type = type;
}
- private List<RootInterceptor> interceptors;
+ private List<Interceptor> interceptors;
private Class<?> type;
private transient WicketComponent component;
private boolean callInProgress;
@@ -38,11 +38,11 @@
return component;
}
- private List<RootInterceptor> getInterceptors()
+ private List<Interceptor> getInterceptors()
{
if (interceptors == null)
{
- interceptors = new ArrayList<RootInterceptor>();
+ interceptors = new ArrayList<Interceptor>();
interceptors.add(new BijectionInterceptor());
}
return interceptors;
@@ -50,30 +50,30 @@
public void beforeInvoke(Object target, Method calledMethod)
{
- beforeInvoke(new InvocationContext(calledMethod, target, getComponent()));
+ doBeforeInvoke(new InvocationContext(calledMethod, target, getComponent()));
}
- public void afterInvoke(Object target, Method calledMethod)
+ public Object afterInvoke(Object target, Method calledMethod, Object result)
{
- afterInvoke(new InvocationContext(calledMethod, target, getComponent()));
+ return doAfterInvoke(new InvocationContext(calledMethod, target, getComponent()), result);
}
- public void beforeInvoke(Object target)
+ public void beforeInvoke(Object target, Constructor constructor)
{
getComponent().initialize(target);
- beforeInvoke(new InvocationContext(target, getComponent()));
+ doBeforeInvoke(new InvocationContext(constructor, target, getComponent()));
}
- public void afterInvoke(Object target)
+ public void afterInvoke(Object target, Constructor constructor)
{
- afterInvoke(new InvocationContext(target, getComponent()));
+ doAfterInvoke(new InvocationContext(constructor, target, getComponent()), null);
}
- private void beforeInvoke(InvocationContext invocationContext)
+ private void doBeforeInvoke(InvocationContext invocationContext)
{
- if (reentrant ==0)
+ if (reentrant == 0)
{
- for (RootInterceptor interceptor : getInterceptors())
+ for (Interceptor interceptor : getInterceptors())
{
interceptor.beforeInvoke(invocationContext);
}
@@ -81,30 +81,44 @@
reentrant++;
}
- private void afterInvoke(InvocationContext invocationContext)
+ public Exception handleException(Object target, Method method, Exception exception)
{
- reentrant--;
+ return doHandleException(new InvocationContext(method, target, getComponent()), exception);
+ }
+
+ public Exception handleException(Object target, Constructor constructor, Exception exception)
+ {
+ return doHandleException(new InvocationContext(constructor, target, getComponent()), exception);
+ }
+
+ private Exception doHandleException(InvocationContext invocationContext, Exception exception)
+ {
if (reentrant == 0)
{
- for (RootInterceptor interceptor : getInterceptors())
+ for (Interceptor interceptor : getInterceptors())
{
- interceptor.afterInvoke(invocationContext);
+ exception = interceptor.handleException(invocationContext, exception);
}
}
+ return exception;
}
-
- public boolean isCallInProgress()
+
+ private Object doAfterInvoke(InvocationContext invocationContext, Object result)
{
- if (callInProgress == false)
+ reentrant--;
+ if (reentrant == 0)
{
- reentrant = 0;
+ for (int i = interceptors.size() - 1; i >= 0; i--)
+ {
+ result = interceptors.get(i).afterInvoke(invocationContext, result);
+ }
}
- return callInProgress;
+ return result;
}
-
- public void setCallInProgress(boolean callInProgress)
+
+ public boolean isReentrant()
{
- this.callInProgress = callInProgress;
+ return reentrant > 0;
}
public static InstrumentedComponent getEnclosingInstance(Object bean, int level)
More information about the seam-commits
mailing list