[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