Author: rmannibucau
Date: Tue Jan  1 20:21:15 2013
New Revision: 1427549

URL: http://svn.apache.org/viewvc?rev=1427549&view=rev
Log:
some caching - on isdebugenabled on our logger + method resolution in jaxws 
invocation + skipping reflection to get threadname in tomee from ContextBindings

Modified:
    
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonContainer.java
    
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
    
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/Logger.java
    
openejb/trunk/openejb/server/openejb-cxf/src/main/java/org/apache/openejb/server/cxf/ejb/EjbMethodInvoker.java
    
openejb/trunk/openejb/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatThreadContextListener.java

Modified: 
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonContainer.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonContainer.java?rev=1427549&r1=1427548&r2=1427549&view=diff
==============================================================================
--- 
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonContainer.java
 (original)
+++ 
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonContainer.java
 Tue Jan  1 20:21:15 2013
@@ -34,8 +34,6 @@ import org.apache.openejb.core.webservic
 import org.apache.openejb.monitoring.StatsInterceptor;
 import org.apache.openejb.spi.SecurityService;
 import org.apache.openejb.util.Duration;
-import org.apache.openejb.util.LogCategory;
-import org.apache.openejb.util.Logger;
 import org.apache.xbean.finder.ClassFinder;
 
 import javax.ejb.ConcurrentAccessTimeoutException;
@@ -46,10 +44,10 @@ import javax.ejb.EJBLocalObject;
 import javax.ejb.EJBObject;
 import javax.interceptor.AroundInvoke;
 import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.locks.Lock;
 
 import static org.apache.openejb.core.transaction.EjbTransactionUtil.*;
@@ -63,6 +61,8 @@ public class SingletonContainer implemen
 
     private HashMap<String, BeanContext> deploymentRegistry = new 
HashMap<String, BeanContext>();
 
+    private final ConcurrentMap<Class<?>, List<Method>> interceptorCache = new 
ConcurrentHashMap<Class<?>, List<Method>>();
+
     private Object containerID = null;
     private SecurityService securityService;
     private Duration accessTimeout;
@@ -331,19 +331,33 @@ public class SingletonContainer implemen
 
         if (interceptor == null) throw new 
IllegalArgumentException("Interceptor instance is null.");
 
+        final Class<?> interceptorClass = interceptor.getClass();
+
         //  Add the webservice interceptor to the list of interceptor instances
         Map<String, Object> interceptors = new HashMap<String, 
Object>(instance.interceptors);
         {
-            interceptors.put(interceptor.getClass().getName(), interceptor);
+            interceptors.put(interceptorClass.getName(), interceptor);
         }
 
         //  Create an InterceptorData for the webservice interceptor to the 
list of interceptorDatas for this method
         List<InterceptorData> interceptorDatas = new 
ArrayList<InterceptorData>();
         {
-            InterceptorData providerData = new 
InterceptorData(interceptor.getClass());
-            ClassFinder finder = new ClassFinder(interceptor.getClass());
-            
providerData.getAroundInvoke().addAll(finder.findAnnotatedMethods(AroundInvoke.class));
-            interceptorDatas.add(providerData);
+            final InterceptorData providerData = new 
InterceptorData(interceptorClass);
+
+            List<Method> aroundInvokes = 
interceptorCache.get(interceptorClass);
+            if (aroundInvokes == null) {
+                aroundInvokes = new 
ClassFinder(interceptorClass).findAnnotatedMethods(AroundInvoke.class);
+                if (SingletonContainer.class.getClassLoader() == 
interceptorClass.getClassLoader()) { // use cache only for server classes
+                    final List<Method> value = new 
CopyOnWriteArrayList<Method>(aroundInvokes);
+                    aroundInvokes = 
interceptorCache.putIfAbsent(interceptorClass, value); // ensure it to be 
thread safe
+                    if (aroundInvokes == null) {
+                        aroundInvokes = value;
+                    }
+                }
+            }
+
+            providerData.getAroundInvoke().addAll(aroundInvokes);
+            interceptorDatas.add(0, providerData);
             
interceptorDatas.addAll(beanContext.getMethodInterceptors(runMethod));
         }
 

Modified: 
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java?rev=1427549&r1=1427548&r2=1427549&view=diff
==============================================================================
--- 
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
 (original)
+++ 
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
 Tue Jan  1 20:21:15 2013
@@ -26,6 +26,9 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArrayList;
 import javax.ejb.EJBAccessException;
 import javax.ejb.EJBHome;
 import javax.ejb.EJBLocalHome;
@@ -49,8 +52,6 @@ import org.apache.openejb.core.timer.Ejb
 import org.apache.openejb.core.transaction.TransactionPolicy;
 import org.apache.openejb.core.webservices.AddressingSupport;
 import org.apache.openejb.core.webservices.NoAddressingSupport;
-import org.apache.openejb.monitoring.LocalMBeanServer;
-import org.apache.openejb.monitoring.ManagedMBean;
 import org.apache.openejb.monitoring.StatsInterceptor;
 import org.apache.openejb.spi.SecurityService;
 import org.apache.openejb.util.Duration;
@@ -61,6 +62,7 @@ import org.apache.xbean.finder.ClassFind
  * @org.apache.xbean.XBean element="statelessContainer"
  */
 public class StatelessContainer implements org.apache.openejb.RpcContainer {
+    private final ConcurrentMap<Class<?>, List<Method>> interceptorCache = new 
ConcurrentHashMap<Class<?>, List<Method>>();
 
     private StatelessInstanceManager instanceManager;
 
@@ -284,6 +286,8 @@ public class StatelessContainer implemen
         // of our stack.
         Object interceptor = args[1];
 
+        final Class<?> interceptorClass = interceptor.getClass();
+
 
         //  Add the webservice interceptor to the list of interceptor instances
         Map<String, Object> interceptors = new HashMap<String, 
Object>(instance.interceptors);
@@ -294,10 +298,21 @@ public class StatelessContainer implemen
         //  Create an InterceptorData for the webservice interceptor to the 
list of interceptorDatas for this method
         List<InterceptorData> interceptorDatas = new 
ArrayList<InterceptorData>();
         {
-            InterceptorData providerData = new 
InterceptorData(interceptor.getClass());
-            ClassFinder finder = new ClassFinder(interceptor.getClass());
-            
providerData.getAroundInvoke().addAll(finder.findAnnotatedMethods(AroundInvoke.class));
-//            interceptorDatas.add(providerData);
+            final InterceptorData providerData = new 
InterceptorData(interceptorClass);
+
+            List<Method> aroundInvokes = 
interceptorCache.get(interceptorClass);
+            if (aroundInvokes == null) {
+                aroundInvokes = new 
ClassFinder(interceptorClass).findAnnotatedMethods(AroundInvoke.class);
+                if (StatelessContainer.class.getClassLoader() == 
interceptorClass.getClassLoader()) { // use cache only for server classes
+                    final List<Method> value = new 
CopyOnWriteArrayList<Method>(aroundInvokes);
+                    aroundInvokes = 
interceptorCache.putIfAbsent(interceptorClass, aroundInvokes); // ensure it to 
be thread safe
+                    if (aroundInvokes == null) {
+                        aroundInvokes = value;
+                    }
+                }
+            }
+
+            providerData.getAroundInvoke().addAll(aroundInvokes);
             interceptorDatas.add(0, providerData);
             
interceptorDatas.addAll(beanContext.getMethodInterceptors(runMethod));
         }

Modified: 
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/Logger.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/Logger.java?rev=1427549&r1=1427548&r2=1427549&view=diff
==============================================================================
--- 
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/Logger.java
 (original)
+++ 
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/Logger.java
 Tue Jan  1 20:21:15 2013
@@ -249,11 +249,13 @@ public class Logger {
     private final LogCategory category;
     private final LogStream logStream;
     private final String baseName;
+    private final boolean debug;
 
     public Logger(final LogCategory category, final LogStream logStream, final 
String baseName) {
         this.category = category;
         this.logStream = logStream;
         this.baseName = baseName;
+        this.debug = logStream.isDebugEnabled(); // commonly used and can be 
slow so cache it
     }
 
     public static Logger getInstance(final LogCategory category, final Class 
clazz) {
@@ -344,7 +346,7 @@ public class Logger {
     }
 
     public boolean isDebugEnabled() {
-        return logStream.isDebugEnabled();
+        return debug;
     }
 
     public boolean isErrorEnabled() {

Modified: 
openejb/trunk/openejb/server/openejb-cxf/src/main/java/org/apache/openejb/server/cxf/ejb/EjbMethodInvoker.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb/server/openejb-cxf/src/main/java/org/apache/openejb/server/cxf/ejb/EjbMethodInvoker.java?rev=1427549&r1=1427548&r2=1427549&view=diff
==============================================================================
--- 
openejb/trunk/openejb/server/openejb-cxf/src/main/java/org/apache/openejb/server/cxf/ejb/EjbMethodInvoker.java
 (original)
+++ 
openejb/trunk/openejb/server/openejb-cxf/src/main/java/org/apache/openejb/server/cxf/ejb/EjbMethodInvoker.java
 Tue Jan  1 20:21:15 2013
@@ -17,14 +17,6 @@
  */
 package org.apache.openejb.server.cxf.ejb;
 
-import java.lang.reflect.Method;
-import java.util.List;
-import java.util.Map;
-
-import javax.interceptor.InvocationContext;
-import javax.xml.ws.WebFault;
-import javax.xml.ws.handler.MessageContext.Scope;
-
 import org.apache.cxf.Bus;
 import org.apache.cxf.jaxws.AbstractJAXWSMethodInvoker;
 import org.apache.cxf.jaxws.context.WebServiceContextImpl;
@@ -39,6 +31,15 @@ import org.apache.openejb.RpcContainer;
 import org.apache.openejb.util.LogCategory;
 import org.apache.openejb.util.Logger;
 
+import javax.interceptor.InvocationContext;
+import javax.xml.ws.WebFault;
+import javax.xml.ws.handler.MessageContext.Scope;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
 public class EjbMethodInvoker extends AbstractJAXWSMethodInvoker {
 
     private static final Logger log = Logger.getInstance(LogCategory.CXF, 
EjbMethodInvoker.class);
@@ -115,7 +116,7 @@ public class EjbMethodInvoker extends Ab
 
             Class callInterface = this.beanContext
                     .getServiceEndpointInterface();
-            method = getMostSpecificMethod(method, callInterface);
+            method = getMostSpecificMethod(beanContext, method, callInterface);
             Object res = container.invoke(
                     this.beanContext.getDeploymentID(),
                     InterfaceType.SERVICE_ENDPOINT, callInterface, method,
@@ -162,6 +163,31 @@ public class EjbMethodInvoker extends Ab
         }
     }
 
+    // seems the cxf impl is slow so caching it in BeanContext
+    private Method getMostSpecificMethod(final BeanContext beanContext, final 
Method method, final Class callInterface) {
+        MostSpecificMethodCache cache = 
beanContext.get(MostSpecificMethodCache.class);
+
+        if (cache == null) {
+            synchronized (beanContext) { // no need to use a lock IMO here
+                cache = beanContext.get(MostSpecificMethodCache.class);
+                if (cache == null) {
+                    cache = new MostSpecificMethodCache();
+                    beanContext.set(MostSpecificMethodCache.class, cache);
+                }
+            }
+        }
+
+        final MostSpecificMethodKey key = new 
MostSpecificMethodKey(callInterface, method);
+
+        Method m = cache.methods.get(key);
+        if (m == null) { // no need of more synchro since Method will be 
resolved to the same instance
+            m = getMostSpecificMethod(method, callInterface);
+            cache.methods.putIfAbsent(key, m);
+        }
+
+        return m;
+    }
+
     public Object directEjbInvoke(Exchange exchange, Method m,
             List<Object> params) throws Exception {
         Object[] paramArray;
@@ -172,4 +198,48 @@ public class EjbMethodInvoker extends Ab
         }
         return performInvocation(exchange, null, m, paramArray);
     }
+
+    public static class MostSpecificMethodCache { // just a wrapper to put in 
BeanContext without conflict
+        public final ConcurrentMap<MostSpecificMethodKey, Method> methods = 
new ConcurrentHashMap<MostSpecificMethodKey, Method>();
+    }
+
+    public static class MostSpecificMethodKey {
+        public final Class<?> ejbInterface;
+        public final Method method;
+        private int hashCode;
+
+        public MostSpecificMethodKey(final Class<?> ejbInterface, final Method 
method) {
+            this.ejbInterface = ejbInterface;
+            this.method = method;
+
+            // this class exists for map usage so simply precalculate hashcode
+            hashCode = ejbInterface != null ? ejbInterface.hashCode() : 0;
+            hashCode = 31 * hashCode + (method != null ? method.hashCode() : 
0);
+        }
+
+        @Override
+        public boolean equals(final Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+
+            final MostSpecificMethodKey that = (MostSpecificMethodKey) o;
+
+            if (!(ejbInterface != null ? 
!ejbInterface.equals(that.ejbInterface) : that.ejbInterface != null)) {
+                if (!(method != null ? !method.equals(that.method) : 
that.method != null)) {
+                    return true;
+                }
+            }
+            return false;
+
+        }
+
+        @Override
+        public int hashCode() {
+            return hashCode;
+        }
+    }
 }
\ No newline at end of file

Modified: 
openejb/trunk/openejb/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatThreadContextListener.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatThreadContextListener.java?rev=1427549&r1=1427548&r2=1427549&view=diff
==============================================================================
--- 
openejb/trunk/openejb/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatThreadContextListener.java
 (original)
+++ 
openejb/trunk/openejb/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatThreadContextListener.java
 Tue Jan  1 20:21:15 2013
@@ -24,8 +24,10 @@ import org.apache.openejb.util.LogCatego
 import org.apache.openejb.util.Logger;
 
 import javax.naming.NamingException;
+import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.Hashtable;
 
 /**
  * Tomcat thread context listener.
@@ -48,24 +50,23 @@ public class TomcatThreadContextListener
      * getThreadName method in class ContextBindings
      */
     protected Method method;
+    private Hashtable<Thread, Object> threadNameBindings;
 
     /**
      * Creates a new instance.
      */
     public TomcatThreadContextListener() {
         ContextBindings.bindContext(OPENEJB_CONTEXT, new OpenEJBContext());
-        boolean accessible = false;
         try {
             // someone decided to make the getThreadName package protected so 
we have to use reflection
             method = ContextBindings.class.getDeclaredMethod("getThreadName");
-//            accessible = method.isAccessible();
             method.setAccessible(true);
-        } catch (NoSuchMethodException e) {
+
+            final Field threadNameBindingsField = 
ContextBindings.class.getDeclaredField("threadNameBindings");
+            threadNameBindingsField.setAccessible(true);
+            threadNameBindings = (Hashtable<Thread, Object>) 
threadNameBindingsField.get(null);
+        } catch (Exception e) {
             logger.error("Expected ContextBinding to have the method 
getThreadName()");
-//        } finally {
-//            if (!accessible) {
-//                method.setAccessible(accessible);
-//            }
         }
     }
 
@@ -78,13 +79,14 @@ public class TomcatThreadContextListener
             Data data = new Data(getThreadName());
             newContext.set(Data.class, data);
         } catch (NamingException ignored) {
+            // no-op
         }
 
         // set the new context
         try {
-            ContextBindings.bindThread(OPENEJB_CONTEXT);
+            ContextBindings.bindThread(OPENEJB_CONTEXT, null);
         } catch (NamingException e) {
-            ContextBindings.unbindContext(OPENEJB_CONTEXT);
+            ContextBindings.unbindContext(OPENEJB_CONTEXT, null);
             throw new IllegalArgumentException("Unable to bind OpenEJB enc");
         }
     }
@@ -94,13 +96,13 @@ public class TomcatThreadContextListener
      */
     public void contextExited(ThreadContext exitedContext, ThreadContext 
reenteredContext) {
         // unbind the new context
-        ContextBindings.unbindThread(OPENEJB_CONTEXT);
+        ContextBindings.unbindThread(OPENEJB_CONTEXT, null);
 
         // attempt to restore the old context
         Data data = exitedContext.get(Data.class);
         if (data != null && data.oldContextName != null) {
             try {
-                ContextBindings.bindThread(data.oldContextName);
+                ContextBindings.bindThread(data.oldContextName, null);
             } catch (NamingException e) {
                 logger.error("Exception in method contextExited", e);
             }
@@ -115,8 +117,14 @@ public class TomcatThreadContextListener
      */
     private Object getThreadName() throws NamingException {
         try {
-            Object threadName = method.invoke(null);
-            return threadName;
+            return threadNameBindings.get(Thread.currentThread());
+        } catch (Exception e) {
+            // no-op: try the old implementation
+        }
+
+        // this implementation is probably better but slower
+        try {
+            return method.invoke(null);
 
         } catch (InvocationTargetException e) {
             // if it's a naming exception, it should be treated by the caller


Reply via email to