Author: jdonnerstag
Date: Thu Jan  1 13:06:21 2009
New Revision: 730604

URL: http://svn.apache.org/viewvc?rev=730604&view=rev
Log:
applied wicket-1763:  GuiceComponentInjector overhead for non-injectable 
Components

Added:
    
wicket/trunk/wicket-guice/src/main/java/org/apache/wicket/guice/InjectionFlagCachingGuiceComponentInjector.java

Added: 
wicket/trunk/wicket-guice/src/main/java/org/apache/wicket/guice/InjectionFlagCachingGuiceComponentInjector.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket-guice/src/main/java/org/apache/wicket/guice/InjectionFlagCachingGuiceComponentInjector.java?rev=730604&view=auto
==============================================================================
--- 
wicket/trunk/wicket-guice/src/main/java/org/apache/wicket/guice/InjectionFlagCachingGuiceComponentInjector.java
 (added)
+++ 
wicket/trunk/wicket-guice/src/main/java/org/apache/wicket/guice/InjectionFlagCachingGuiceComponentInjector.java
 Thu Jan  1 13:06:21 2009
@@ -0,0 +1,217 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.guice;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.Component;
+import org.apache.wicket.WicketRuntimeException;
+import org.apache.wicket.proxy.LazyInitProxyFactory;
+
+import com.google.inject.BindingAnnotation;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+
+/**
+ * Finding the guice annotations via reflection for each Component 
instantiation is a rather
+ * heavyweight operation (@link {...@link GuiceComponentInjector}.
+ * 
+ * This causes considerable overhead with large lists that have complicated 
component structure per
+ * row, which is totally unnecessary for stock wicket components that do not 
contain any Guice
+ * annotations.
+ * 
+ * @author Teppo Kurki (Wicket-1763)
+ */
+public class InjectionFlagCachingGuiceComponentInjector extends 
GuiceComponentInjector
+{
+       /** */
+       private final Map<Class< ? >, Boolean> classToDoInject = new 
ConcurrentHashMap<Class< ? >, Boolean>();
+
+       /**
+        * Construct.
+        * 
+        * @param app
+        * @param injector
+        */
+       public InjectionFlagCachingGuiceComponentInjector(final Application 
app, final Injector injector)
+       {
+               super(app, injector);
+       }
+
+       /**
+        * @see 
org.apache.wicket.guice.GuiceComponentInjector#inject(java.lang.Object)
+        */
+       @Override
+       public void inject(final Object object)
+       {
+               Class< ? > current = object.getClass();
+               Boolean doInject = classToDoInject.get(current);
+               if (doInject != null && !doInject.booleanValue())
+               {
+                       return;
+               }
+
+               boolean actualDoInject = false;
+
+               do
+               {
+                       Field[] currentFields = current.getDeclaredFields();
+                       for (final Field field : currentFields)
+                       {
+                               if (field.getAnnotation(Inject.class) != null)
+                               {
+                                       actualDoInject = true;
+                                       try
+                                       {
+                                               Annotation bindingAnnotation = 
findBindingAnnotation(field.getAnnotations());
+                                               Object proxy = 
LazyInitProxyFactory.createProxy(field.getType(),
+                                                               new 
GuiceProxyTargetLocator(field.getGenericType(),
+                                                                               
bindingAnnotation));
+                                               if (!field.isAccessible())
+                                               {
+                                                       
field.setAccessible(true);
+                                               }
+                                               field.set(object, proxy);
+                                       }
+                                       catch (IllegalAccessException e)
+                                       {
+                                               throw new 
WicketRuntimeException("Error Guice-injecting field " +
+                                                               field.getName() 
+ " in " + object, e);
+                                       }
+                                       catch (MoreThanOneBindingException e)
+                                       {
+                                               throw new RuntimeException(
+                                                               "Can't have 
more than one BindingAnnotation on field " +
+                                                                               
field.getName() + " of class " +
+                                                                               
object.getClass().getName());
+                                       }
+                               }
+                       }
+
+                       Method[] currentMethods = current.getDeclaredMethods();
+                       for (final Method method : currentMethods)
+                       {
+                               if (method.getAnnotation(Inject.class) != null)
+                               {
+                                       actualDoInject = true;
+                                       Annotation[][] paramAnnotations = 
method.getParameterAnnotations();
+                                       Class< ? >[] paramTypes = 
method.getParameterTypes();
+                                       Type[] genericParamTypes = 
method.getGenericParameterTypes();
+                                       Object[] args = new 
Object[paramTypes.length];
+                                       for (int i = 0; i < paramTypes.length; 
i++)
+                                       {
+                                               Type paramType;
+                                               if (genericParamTypes[i] 
instanceof ParameterizedType)
+                                               {
+                                                       paramType = 
((ParameterizedType)genericParamTypes[i]).getRawType();
+                                               }
+                                               else
+                                               {
+                                                       paramType = 
paramTypes[i];
+                                               }
+                                               try
+                                               {
+                                                       Annotation 
bindingAnnotation = findBindingAnnotation(paramAnnotations[i]);
+                                                       args[i] = 
LazyInitProxyFactory.createProxy(paramTypes[i],
+                                                                       new 
GuiceProxyTargetLocator(genericParamTypes[i],
+                                                                               
        bindingAnnotation));
+                                               }
+                                               catch 
(MoreThanOneBindingException e)
+                                               {
+                                                       throw new 
RuntimeException(
+                                                                       "Can't 
have more than one BindingAnnotation on parameter " + i +
+                                                                               
        "(" + paramType + ") of method " + method.getName() +
+                                                                               
        " of class " + object.getClass().getName());
+                                               }
+                                       }
+                                       try
+                                       {
+                                               method.invoke(object, args);
+                                       }
+                                       catch (IllegalAccessException e)
+                                       {
+                                               throw new 
WicketRuntimeException(e);
+                                       }
+                                       catch (InvocationTargetException e)
+                                       {
+                                               throw new 
WicketRuntimeException(e);
+                                       }
+                               }
+                       }
+                       current = current.getSuperclass();
+               }
+
+               // Do a null check in case Object isn't in the current 
classloader.
+               while (current != null && current != Object.class);
+               if (doInject == null)
+               {
+                       classToDoInject.put(object.getClass(), new 
Boolean(actualDoInject));
+               }
+       }
+
+       /**
+        * 
+        * @see 
org.apache.wicket.guice.GuiceComponentInjector#onInstantiation(org.apache.wicket.Component)
+        */
+       @Override
+       public void onInstantiation(final Component component)
+       {
+               inject(component);
+       }
+
+       /**
+        * 
+        * @param annotations
+        * @return
+        * @throws MoreThanOneBindingException
+        */
+       private Annotation findBindingAnnotation(final Annotation[] annotations)
+                       throws MoreThanOneBindingException
+       {
+               Annotation bindingAnnotation = null;
+
+               // Work out if we have a BindingAnnotation on this parameter.
+               for (Annotation annotation : annotations)
+               {
+                       if 
(annotation.annotationType().getAnnotation(BindingAnnotation.class) != null)
+                       {
+                               if (bindingAnnotation != null)
+                               {
+                                       throw new MoreThanOneBindingException();
+                               }
+                               bindingAnnotation = annotation;
+                       }
+               }
+               return bindingAnnotation;
+       }
+
+       /**
+        * 
+        */
+       private static class MoreThanOneBindingException extends Exception
+       {
+               private static final long serialVersionUID = 1L;
+       }
+}


Reply via email to