You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ss...@apache.org on 2014/10/29 23:46:38 UTC

svn commit: r1635325 - in /sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl: ./ model/

Author: sseifert
Date: Wed Oct 29 22:46:38 2014
New Revision: 1635325

URL: http://svn.apache.org/r1635325
Log:
SLING-4112 refactor to cache most of reflection inspection tasks

Added:
    sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/model/ModelClassConstructor.java   (with props)
    sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/model/ParameterCountInjectComparator.java
      - copied, changed from r1635287, sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/ParameterCountInjectComparator.java
Removed:
    sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/ParameterCountInjectComparator.java
Modified:
    sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java
    sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/model/ModelClass.java

Modified: sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java?rev=1635325&r1=1635324&r2=1635325&view=diff
==============================================================================
--- sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java (original)
+++ sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java Wed Oct 29 22:46:38 2014
@@ -19,7 +19,6 @@ package org.apache.sling.models.impl;
 import java.lang.ref.PhantomReference;
 import java.lang.ref.ReferenceQueue;
 import java.lang.reflect.AnnotatedElement;
-import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.InvocationTargetException;
@@ -44,7 +43,6 @@ import java.util.concurrent.ConcurrentHa
 import java.util.concurrent.ConcurrentMap;
 
 import javax.annotation.PostConstruct;
-import javax.inject.Inject;
 import javax.inject.Named;
 
 import org.apache.commons.beanutils.PropertyUtils;
@@ -78,6 +76,7 @@ import org.apache.sling.models.impl.mode
 import org.apache.sling.models.impl.model.InjectableField;
 import org.apache.sling.models.impl.model.InjectableMethod;
 import org.apache.sling.models.impl.model.ModelClass;
+import org.apache.sling.models.impl.model.ModelClassConstructor;
 import org.apache.sling.models.spi.AcceptsNullName;
 import org.apache.sling.models.spi.DisposalCallback;
 import org.apache.sling.models.spi.DisposalCallbackRegistry;
@@ -422,21 +421,21 @@ public class ModelAdapterFactory impleme
             throws InstantiationException, InvocationTargetException, IllegalAccessException {
         DisposalCallbackRegistryImpl registry = new DisposalCallbackRegistryImpl();
 
-        Constructor<ModelType> constructorToUse = getBestMatchingConstructor(adaptable, modelClass.getType());
+        ModelClassConstructor<ModelType> constructorToUse = getBestMatchingConstructor(adaptable, modelClass);
         if (constructorToUse == null) {
             result.addFailure(FailureType.NO_USABLE_CONSTRUCTOR, modelClass.getType());
             return null;
         }
 
         final ModelType object;
-        if (constructorToUse.getParameterTypes().length == 0) {
+        if (constructorToUse.getConstructor().getParameterTypes().length == 0) {
             // no parameters for constructor injection? instantiate it right away
-            object = constructorToUse.newInstance();
+            object = constructorToUse.getConstructor().newInstance();
         } else {
             // instantiate with constructor injection
             // if this fails, make sure resources that may be claimed by injectors are cleared up again
             try {
-                object = newInstanceWithConstructorInjection(constructorToUse, adaptable, modelClass.getType(), modelClass.getModelAnnotation(), registry, result);
+                object = newInstanceWithConstructorInjection(constructorToUse, adaptable, modelClass, registry, result);
                 if (object == null) {
                     registry.onDisposed();
                     return null;
@@ -491,57 +490,50 @@ public class ModelAdapterFactory impleme
      * @return Constructor or null if none found
      */
     @SuppressWarnings("unchecked")
-    private <ModelType> Constructor<ModelType> getBestMatchingConstructor(Object adaptable, Class<ModelType> type) {
-        Constructor<?>[] constructors = type.getConstructors();
+    private <ModelType> ModelClassConstructor<ModelType> getBestMatchingConstructor(Object adaptable, ModelClass<ModelType> type) {
+        ModelClassConstructor[] constructors = type.getConstructors();
 
-        // sort the constructor list in order from most params to least params, and constructors with @Inject annotation first
-        Arrays.sort(constructors, new ParameterCountInjectComparator());
-
-        for (Constructor<?> constructor : constructors) {
+        for (ModelClassConstructor constructor : constructors) {
             // first try to find the constructor with most parameters and @Inject annotation
-            if (constructor.isAnnotationPresent(Inject.class)) {
-                return (Constructor<ModelType>) constructor;
+            if (constructor.hasInjectAnnotation()) {
+                return constructor;
             }
             // compatibility mode for sling models implementation <= 1.0.6:
             // support constructor without @Inject if it has exactly one parameter matching the adaptable class
-            final Class<?>[] paramTypes = constructor.getParameterTypes();
+            final Class<?>[] paramTypes = constructor.getConstructor().getParameterTypes();
             if (paramTypes.length == 1) {
-                Class<?> paramType = constructor.getParameterTypes()[0];
+                Class<?> paramType = constructor.getConstructor().getParameterTypes()[0];
                 if (paramType.isInstance(adaptable)) {
-                    return (Constructor<ModelType>) constructor;
+                    return constructor;
                 }
             }
             // if no constructor for injection found use public constructor without any params
-            if (constructor.getParameterTypes().length == 0) {
-                return (Constructor<ModelType>) constructor;
+            if (constructor.getConstructor().getParameterTypes().length == 0) {
+                return constructor;
             }
         }
         return null;
     }
 
-    private <ModelType> ModelType newInstanceWithConstructorInjection(final Constructor<ModelType> constructor, final Object adaptable,
-            final Class<ModelType> type, final Model modelAnnotation, final DisposalCallbackRegistry registry,
-            final Result<ModelType> result)
+    private <ModelType> ModelType newInstanceWithConstructorInjection(final ModelClassConstructor<ModelType> constructor, final Object adaptable,
+            final ModelClass<ModelType> modelClass, final DisposalCallbackRegistry registry, final Result<ModelType> result)
             throws InstantiationException, InvocationTargetException, IllegalAccessException {
+        ConstructorParameter[] parameters = constructor.getConstructorParameters();
+
         Set<ConstructorParameter> requiredParameters = new HashSet<ConstructorParameter>();
-        Type[] parameterTypes = constructor.getGenericParameterTypes();
-        List<Object> paramValues = new ArrayList<Object>(Arrays.asList(new Object[parameterTypes.length]));
+        List<Object> paramValues = new ArrayList<Object>(Arrays.asList(new Object[parameters.length]));
         InjectCallback callback = new SetConstructorParameterCallback(paramValues);
 
-        for (int i = 0; i < parameterTypes.length; i++) {
-            Type genericType = ReflectionUtil.mapPrimitiveClasses(parameterTypes[i]);
-            boolean isPrimitive = (parameterTypes[i] != genericType);
-            ConstructorParameter constructorParameter = new ConstructorParameter(
-                    constructor.getParameterAnnotations()[i], constructor.getParameterTypes()[i], genericType, isPrimitive, i);
-            if (!injectElement(constructorParameter, adaptable, modelAnnotation, registry, callback, result)) {
-                requiredParameters.add(constructorParameter);
+        for (int i = 0; i < parameters.length; i++) {
+            if (!injectElement(parameters[i], adaptable, modelClass.getModelAnnotation(), registry, callback, result)) {
+                requiredParameters.add(parameters[i]);
             }
         }
         if (!requiredParameters.isEmpty()) {
-            result.addFailure(FailureType.MISSING_CONSTRUCTOR_PARAMS, requiredParameters, type);
+            result.addFailure(FailureType.MISSING_CONSTRUCTOR_PARAMS, requiredParameters, modelClass.getType());
             return null;
         }
-        return constructor.newInstance(paramValues.toArray(new Object[paramValues.size()]));
+        return constructor.getConstructor().newInstance(paramValues.toArray(new Object[paramValues.size()]));
     }
 
     private boolean isOptional(AnnotatedElement point, Model modelAnnotation, InjectAnnotationProcessor annotationProcessor) {

Modified: sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/model/ModelClass.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/model/ModelClass.java?rev=1635325&r1=1635324&r2=1635325&view=diff
==============================================================================
--- sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/model/ModelClass.java (original)
+++ sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/model/ModelClass.java Wed Oct 29 22:46:38 2014
@@ -18,8 +18,10 @@
  */
 package org.apache.sling.models.impl.model;
 
+import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
+import java.util.Arrays;
 import java.util.List;
 
 import org.apache.sling.models.annotations.Model;
@@ -29,24 +31,57 @@ public class ModelClass<ModelType> {
 
     private final Class<ModelType> type;
     private final Model modelAnnotation;
-    private final InjectableField[] injectableFieldsArray;
-    private final InjectableMethod[] injectableMethodsArray;
+    private final ModelClassConstructor[] constructors;
+    private final InjectableField[] injectableFields;
+    private final InjectableMethod[] injectableMethods;
 
     public ModelClass(Class<ModelType> type) {
         this.type = type;
         this.modelAnnotation = type.getAnnotation(Model.class);
+        this.constructors = getConstructors(type);
+        this.injectableFields = getInjectableFields(type);
+        this.injectableMethods = getInjectableMethods(type);
+    }
+    
+    @SuppressWarnings("unchecked")
+    private static ModelClassConstructor[] getConstructors(Class<?> type) {
+        if (type.isInterface()) {
+            return new ModelClassConstructor[0];
+        }
+        Constructor<?>[] constructors = type.getConstructors();
         
+        // sort the constructor list in order from most params to least params, and constructors with @Inject annotation first
+        Arrays.sort(constructors, new ParameterCountInjectComparator());
+
+        ModelClassConstructor[] array = new ModelClassConstructor[constructors.length];
+        for (int i=0; i<array.length; i++) {
+            array[i] = new ModelClassConstructor(constructors[i]);
+        }
+        return array;
+    }
+
+    private static InjectableField[] getInjectableFields(Class<?> type) {
+        if (type.isInterface()) {
+            return new InjectableField[0];
+        }
         List<Field> injectableFields = ReflectionUtil.collectInjectableFields(type);
-        this.injectableFieldsArray = new InjectableField[injectableFields.size()];
-        for (int i=0; i<this.injectableFieldsArray.length; i++) {
-            this.injectableFieldsArray[i] = new InjectableField(injectableFields.get(i));
+        InjectableField[] array = new InjectableField[injectableFields.size()];
+        for (int i=0; i<array.length; i++) {
+            array[i] = new InjectableField(injectableFields.get(i));
+        }
+        return array;
+    }
+
+    private static InjectableMethod[] getInjectableMethods(Class<?> type) {
+        if (!type.isInterface()) {
+            return new InjectableMethod[0];
         }
-        
         List<Method> injectableMethods = ReflectionUtil.collectInjectableMethods(type);
-        this.injectableMethodsArray = new InjectableMethod[injectableMethods.size()];
-        for (int i=0; i<this.injectableMethodsArray.length; i++) {
-            this.injectableMethodsArray[i] = new InjectableMethod(injectableMethods.get(i));
+        InjectableMethod[] array = new InjectableMethod[injectableMethods.size()];
+        for (int i=0; i<array.length; i++) {
+            array[i] = new InjectableMethod(injectableMethods.get(i));
         }
+        return array;
     }
 
     public Class<ModelType> getType() {
@@ -61,12 +96,16 @@ public class ModelClass<ModelType> {
         return this.modelAnnotation != null;
     }
     
+    public ModelClassConstructor[] getConstructors() {
+        return constructors;
+    }
+
     public InjectableField[] getInjectableFields() {
-        return this.injectableFieldsArray;
+        return this.injectableFields;
     }
 
     public InjectableMethod[] getInjectableMethods() {
-        return this.injectableMethodsArray;
+        return this.injectableMethods;
     }
 
 }

Added: sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/model/ModelClassConstructor.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/model/ModelClassConstructor.java?rev=1635325&view=auto
==============================================================================
--- sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/model/ModelClassConstructor.java (added)
+++ sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/model/ModelClassConstructor.java Wed Oct 29 22:46:38 2014
@@ -0,0 +1,61 @@
+/*
+ * 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.sling.models.impl.model;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Type;
+
+import javax.inject.Inject;
+
+import org.apache.sling.models.impl.ReflectionUtil;
+
+public class ModelClassConstructor<ModelType> {
+
+    private final Constructor<ModelType> constructor;
+    private final boolean hasInjectAnnotation;
+    private final ConstructorParameter[] constructorParametersArray;
+
+    public ModelClassConstructor(Constructor<ModelType> constructor) {
+        this.constructor = constructor;
+        this.hasInjectAnnotation = constructor.isAnnotationPresent(Inject.class);
+
+        Type[] parameterTypes = constructor.getGenericParameterTypes();
+        this.constructorParametersArray = new ConstructorParameter[parameterTypes.length];
+
+        for (int i = 0; i < parameterTypes.length; i++) {
+            Type genericType = ReflectionUtil.mapPrimitiveClasses(parameterTypes[i]);
+            boolean isPrimitive = (parameterTypes[i] != genericType);
+            this.constructorParametersArray[i] = new ConstructorParameter(
+                    constructor.getParameterAnnotations()[i], constructor.getParameterTypes()[i], genericType, isPrimitive, i);
+        }
+    }
+
+    public Constructor<ModelType> getConstructor() {
+        return constructor;
+    }
+    
+    public boolean hasInjectAnnotation() {
+        return hasInjectAnnotation;
+    }
+
+    public ConstructorParameter[] getConstructorParameters() {
+        return constructorParametersArray;
+    };
+    
+}

Propchange: sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/model/ModelClassConstructor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/model/ModelClassConstructor.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Wed Oct 29 22:46:38 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/model/ModelClassConstructor.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Copied: sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/model/ParameterCountInjectComparator.java (from r1635287, sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/ParameterCountInjectComparator.java)
URL: http://svn.apache.org/viewvc/sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/model/ParameterCountInjectComparator.java?p2=sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/model/ParameterCountInjectComparator.java&p1=sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/ParameterCountInjectComparator.java&r1=1635287&r2=1635325&rev=1635325&view=diff
==============================================================================
--- sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/ParameterCountInjectComparator.java (original)
+++ sling/whiteboard/sseifert/SLING-4112_models_tuning/impl/src/main/java/org/apache/sling/models/impl/model/ParameterCountInjectComparator.java Wed Oct 29 22:46:38 2014
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.sling.models.impl;
+package org.apache.sling.models.impl.model;
 
 import java.lang.reflect.Constructor;
 import java.util.Comparator;