Skip to content

Instantly share code, notes, and snippets.

@rmannibucau
Created January 21, 2013 11:27
Show Gist options
  • Select an option

  • Save rmannibucau/4585407 to your computer and use it in GitHub Desktop.

Select an option

Save rmannibucau/4585407 to your computer and use it in GitHub Desktop.
Index: webbeans-impl/src/main/java/org/apache/webbeans/container/BeanManagerImpl.java
===================================================================
--- webbeans-impl/src/main/java/org/apache/webbeans/container/BeanManagerImpl.java (revision 1436220)
+++ webbeans-impl/src/main/java/org/apache/webbeans/container/BeanManagerImpl.java (working copy)
@@ -91,6 +91,8 @@
import org.apache.webbeans.util.WebBeansUtil;
import org.apache.webbeans.xml.WebBeansXMLConfigurator;
+import static org.apache.webbeans.util.InjectionExceptionUtil.throwAmbiguousResolutionException;
+
/**
* Implementation of the {@link BeanManager} contract of the web beans
* container.
Index: webbeans-impl/src/main/java/org/apache/webbeans/container/BeanCacheKey.java
===================================================================
--- webbeans-impl/src/main/java/org/apache/webbeans/container/BeanCacheKey.java (revision 1436220)
+++ webbeans-impl/src/main/java/org/apache/webbeans/container/BeanCacheKey.java (working copy)
@@ -18,48 +18,22 @@
*/
package org.apache.webbeans.container;
-import org.apache.webbeans.util.AnnotationUtil;
+import org.apache.webbeans.inject.instance.InstanceCacheKey;
-import javax.enterprise.util.Nonbinding;
import java.lang.annotation.Annotation;
-import java.lang.reflect.Array;
-import java.lang.reflect.Method;
import java.lang.reflect.Type;
-import java.util.Arrays;
-import java.util.Comparator;
-public final class BeanCacheKey
+public final class BeanCacheKey extends InstanceCacheKey
{
private final Type type;
private final String path;
- private final Annotation qualifier;
- private final Annotation qualifiers[];
private final int hashCode;
- private static final Comparator<Annotation> ANNOTATION_COMPARATOR = new AnnotationComparator();
public BeanCacheKey( Type type, String path, Annotation... qualifiers )
{
+ super(qualifiers);
this.type = type;
this.path = path;
- final int length = qualifiers != null ? qualifiers.length : 0;
- if (length == 0)
- {
- this.qualifier = null;
- this.qualifiers = null;
- }
- else if (length == 1)
- {
- this.qualifier = qualifiers[0];
- this.qualifiers = null;
- }
- else
- {
- this.qualifier = null;
- // to save array creations, we only create an array, if we have more than one annotation
- this.qualifiers = new Annotation[length];
- System.arraycopy(qualifiers, 0, this.qualifiers, 0, length);
- Arrays.sort(this.qualifiers, ANNOTATION_COMPARATOR);
- }
// this class is directly used in ConcurrentHashMap.get() so simply init the hasCode here
hashCode = computeHashCode();
@@ -83,14 +57,10 @@
{
return false;
}
- if (qualifier != null ? !qualifierEquals(qualifier, cacheKey.qualifier) : cacheKey.qualifier != null)
+ if (!super.equals(cacheKey))
{
return false;
}
- if (!qualifierArrayEquals(qualifiers, cacheKey.qualifiers))
- {
- return false;
- }
if (path != null ? !path.equals(cacheKey.path) : cacheKey.path != null)
{
return false;
@@ -99,33 +69,6 @@
return true;
}
- private boolean qualifierArrayEquals(Annotation[] qualifiers1, Annotation[] qualifiers2)
- {
- if (qualifiers1 == qualifiers2)
- {
- return true;
- }
- else if (qualifiers1 == null || qualifiers2 == null)
- {
- return false;
- }
- if (qualifiers1.length != qualifiers2.length)
- {
- return false;
- }
- for (int i = 0; i < qualifiers1.length; i++)
- {
- Annotation a1 = qualifiers1[i];
- Annotation a2 = qualifiers2[i];
- if (a1 == null ? a2 != null : !qualifierEquals(a1, a2))
- {
- return false;
- }
- }
-
- return true;
- }
-
@Override
public int hashCode()
{
@@ -133,177 +76,19 @@
}
/**
- * We need this method as some weird JVMs return 0 as hashCode for classes.
- * In that case we return the hashCode of the String.
- */
- private int getTypeHashCode(Type type)
- {
- int typeHash = type.hashCode();
- if (typeHash == 0 && type instanceof Class)
- {
- return ((Class)type).getName().hashCode();
- // the type.toString() is always the same: "java.lang.Class@<hexid>"
- // was: return type.toString().hashCode();
- }
-
- return typeHash;
- }
-
- /**
* Compute the HashCode. This should be called only in the constructor.
*/
private int computeHashCode()
{
int computedHashCode = 31 * getTypeHashCode(type) + (path != null ? path.hashCode() : 0);
- if (qualifier != null)
+ if (hasQualifiers())
{
- computedHashCode = 31 * computedHashCode + getQualifierHashCode(qualifier);
+ computedHashCode = 31 * computedHashCode + super.hashCode();
}
- if (qualifiers != null)
- {
- for (int i = 0; i < qualifiers.length; i++)
- {
- computedHashCode = 31 * computedHashCode + getQualifierHashCode(qualifiers[i]);
- }
- }
return computedHashCode;
}
/**
- * Calculate the hashCode() of a qualifier, which ignores {@link Nonbinding} members.
- */
- private int getQualifierHashCode(Annotation a)
- {
- Class annotationClass = getAnnotationClass(a.getClass());
-
- if (annotationClass == null)
- {
- return getTypeHashCode(a.getClass());
- }
-
- // the hashCode of an Annotation is calculated solely via the hashCodes
- // of it's members. If there are no members, it is 0.
- // thus we first need to get the annotation-class hashCode
- int hashCode = getTypeHashCode(annotationClass);
-
- // and now add the hashCode of all it's Nonbinding members
- // the following algorithm is defined by the Annotation class definition
- // see the JavaDoc for Annotation!
- // we only change it so far that we skip evaluating @Nonbinding members
- final Method[] members = annotationClass.getDeclaredMethods();
-
- for (Method member : members)
- {
- if (member.isAnnotationPresent(Nonbinding.class))
- {
- // ignore the non binding
- continue;
- }
-
- // Member value
- final Object object = callMethod(a, member);
- final int value;
- if(object.getClass().isArray())
- {
- Class<?> type = object.getClass().getComponentType();
- if(type.isPrimitive())
- {
- if(Long.TYPE == type)
- {
- value = Arrays.hashCode((long[]) object);
- }
- else if(Integer.TYPE == type)
- {
- value = Arrays.hashCode((int[])object);
- }
- else if(Short.TYPE == type)
- {
- value = Arrays.hashCode((short[])object);
- }
- else if(Double.TYPE == type)
- {
- value = Arrays.hashCode((double[])object);
- }
- else if(Float.TYPE == type)
- {
- value = Arrays.hashCode((float[])object);
- }
- else if(Boolean.TYPE == type)
- {
- value = Arrays.hashCode((boolean[])object);
- }
- else if(Byte.TYPE == type)
- {
- value = Arrays.hashCode((byte[])object);
- }
- else if(Character.TYPE == type)
- {
- value = Arrays.hashCode((char[])object);
- }
- else
- {
- value = 0;
- }
- }
- else
- {
- value = Arrays.hashCode((Object[])object);
- }
- }
- else
- {
- value = object.hashCode();
- }
-
- hashCode = 29 * hashCode + value;
- hashCode = 29 * hashCode + member.getName().hashCode();
- }
-
- return hashCode;
- }
-
- /**
- * Implements the equals() method for qualifiers, which ignores {@link Nonbinding} members.
- */
- private boolean qualifierEquals(Annotation qualifier1, Annotation qualifier2)
- {
- return ANNOTATION_COMPARATOR.compare(qualifier1, qualifier2) == 0;
- }
-
- private static Class getAnnotationClass(Class a)
- {
- for (Class i : a.getInterfaces())
- {
- if (i.isAnnotation())
- {
- return i;
- }
- }
- return null;
- }
-
- /**
- * Helper method for calculating the hashCode of an annotation.
- */
- private static Object callMethod(Object instance, Method method)
- {
- try
- {
- if (!method.isAccessible())
- {
- method.setAccessible(true);
- }
-
- return method.invoke(instance, AnnotationUtil.EMPTY_OBJECT_ARRAY);
- }
- catch (Exception e)
- {
- throw new RuntimeException("Exception in method call : " + method.getName(), e);
- }
-
- }
-
- /**
* for debugging ...
*/
@Override
@@ -311,118 +96,6 @@
{
return "BeanCacheKey{" + "type=" + type + ", path='" + path + '\''
+ ", qualifiers="
- + (qualifiers == null ? qualifier : Arrays.asList(qualifiers)) + ", hashCode=" + hashCode + '}';
+ + super.toString() + ", hashCode=" + hashCode + '}';
}
-
- /**
- * to keep the annotations ordered.
- */
- private static class AnnotationComparator implements Comparator<Annotation>
- {
-
- // Notice: Sorting is a bit costly, but the use of this code is very rar.
- public int compare(Annotation annotation1, Annotation annotation2)
- {
- final Class<? extends Annotation> type1 = annotation1.annotationType();
- final Class<? extends Annotation> type2 = annotation2.annotationType();
- final int temp = type1.getName().compareTo(type2.getName());
- if (temp != 0)
- {
- return temp;
- }
- final Method[] member1 = type1.getDeclaredMethods();
- final Method[] member2 = type2.getDeclaredMethods();
-
- // TBD: the order of the list of members seems to be deterministic
-
- int i = 0;
- int j = 0;
- final int length1 = member1.length;
- final int length2 = member2.length;
-
- // find next nonbinding
- for (;; i++, j++)
- {
- while (i < length1 && member1[i].isAnnotationPresent(Nonbinding.class))
- {
- i++;
- }
- while (j < length2 && member2[j].isAnnotationPresent(Nonbinding.class))
- {
- j++;
- }
- if (i >= length1 && j >= length2)
- { // both ended
- return 0;
- }
- else if (i >= length1)
- { // #1 ended
- return 1;
- }
- else if (j >= length2)
- { // #2 ended
- return -1;
- }
- else
- { // not ended
- int c = member1[i].getName().compareTo(member2[j].getName());
- if (c != 0)
- {
- return c;
- }
- final Object value1 = callMethod(annotation1, member1[i]);
- final Object value2 = callMethod(annotation2, member2[j]);
- assert value1.getClass().equals(value2.getClass());
-
- if (value1 instanceof Comparable)
- {
- c = ((Comparable)value1).compareTo(value2);
- if (c != 0)
- {
- return c;
- }
- }
- else if (value1.getClass().isArray())
- {
- c = value1.getClass().getComponentType().getName()
- .compareTo(value2.getClass().getComponentType().getName());
- if (c != 0)
- {
- return c;
- }
-
- final int length = Array.getLength(value1);
- c = length - Array.getLength(value2);
- if (c != 0)
- {
- return c;
- }
- for (int k = 0; k < length; k++)
- {
- c = ((Comparable)Array.get(value1, k)).compareTo(Array.get(value2, k));
- if (c != 0)
- {
- return c;
- }
- }
-
- }
- else if (value1 instanceof Class)
- {
-
- c = ((Class)value1).getName().compareTo(((Class) value2).getName());
- if (c != 0)
- {
- return c;
- }
- }
- else
- {
- // valid types for members are only Comparable, Arrays, or Class
- assert false;
- }
- }
- }
- }
- }
}
Index: webbeans-impl/src/main/java/org/apache/webbeans/container/InjectionResolver.java
===================================================================
--- webbeans-impl/src/main/java/org/apache/webbeans/container/InjectionResolver.java (revision 1436220)
+++ webbeans-impl/src/main/java/org/apache/webbeans/container/InjectionResolver.java (working copy)
@@ -423,15 +423,12 @@
return beansXMLScanner.getBeansXml(injectionPointBeanClass);
}
- /**
- * Resolution by type.
- *
- * @param injectionPointType injection point api type
- * @param qualifiers qualifiers of the injection point
- * @return set of resolved beans
- */
public Set<Bean<?>> implResolveByType(Type injectionPointType, Class<?> injectinPointClass, Annotation... qualifiers)
{
+ return implResolveByType(null, injectionPointType, injectinPointClass, qualifiers);
+ }
+
+ public BeanCacheKey computeKey(Type injectionPointType, Class<?> injectinPointClass, Annotation... qualifiers) {
ScannerService scannerService = webBeansContext.getScannerService();
String bdaBeansXMLFilePath = null;
if (scannerService.isBDABeansXmlScanningEnabled())
@@ -448,6 +445,28 @@
bdaBeansXMLFilePath = getBDABeansXMLPath(injectinPointClass);
}
+ return new BeanCacheKey(injectionPointType, bdaBeansXMLFilePath, qualifiers);
+ }
+
+ /**
+ * Resolution by type.
+ *
+ * @param injectionPointType injection point api type
+ * @param qualifiers qualifiers of the injection point
+ * @return set of resolved beans
+ */
+ public Set<Bean<?>> implResolveByType(BeanCacheKey cacheKey, Type injectionPointType, Class<?> injectinPointClass, Annotation... qualifiers)
+ {
+ if (cacheKey == null) {
+ cacheKey = computeKey(injectionPointType, injectinPointClass, qualifiers);
+ }
+
+ Set<Bean<?>> resolvedComponents = resolvedBeansByType.get(cacheKey);
+ if (resolvedComponents != null)
+ {
+ return resolvedComponents;
+ }
+
boolean currentQualifier = false;
if (isInstanceOrEventInjection(injectionPointType))
@@ -463,14 +482,6 @@
}
}
- BeanCacheKey cacheKey = new BeanCacheKey(injectionPointType, bdaBeansXMLFilePath, qualifiers);
-
- Set<Bean<?>> resolvedComponents = resolvedBeansByType.get(cacheKey);
- if (resolvedComponents != null)
- {
- return resolvedComponents;
- }
-
resolvedComponents = new HashSet<Bean<?>>();
boolean returnAll = false;
Index: webbeans-impl/src/main/java/org/apache/webbeans/inject/instance/InstanceCacheKey.java
===================================================================
--- webbeans-impl/src/main/java/org/apache/webbeans/inject/instance/InstanceCacheKey.java (revision 0)
+++ webbeans-impl/src/main/java/org/apache/webbeans/inject/instance/InstanceCacheKey.java (working copy)
@@ -0,0 +1,400 @@
+/*
+ * 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.webbeans.inject.instance;
+
+import org.apache.webbeans.util.AnnotationUtil;
+
+import javax.enterprise.util.Nonbinding;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.Comparator;
+
+public class InstanceCacheKey {
+ private static final Comparator<Annotation> ANNOTATION_COMPARATOR = new AnnotationComparator();
+
+ private final Annotation qualifier;
+ private final Annotation qualifiers[];
+ private final int hashCode;
+
+ public InstanceCacheKey(final Annotation[] qualifiers) {
+ final int length = qualifiers != null ? qualifiers.length : 0;
+ if (length == 0)
+ {
+ this.qualifier = null;
+ this.qualifiers = null;
+ }
+ else if (length == 1)
+ {
+ this.qualifier = qualifiers[0];
+ this.qualifiers = null;
+ }
+ else
+ {
+ this.qualifier = null;
+ // to save array creations, we only create an array, if we have more than one annotation
+ this.qualifiers = new Annotation[length];
+ System.arraycopy(qualifiers, 0, this.qualifiers, 0, length);
+ Arrays.sort(this.qualifiers, ANNOTATION_COMPARATOR);
+ }
+
+ hashCode = computeHashCode();
+ }
+
+ private int computeHashCode() {
+ int computedHashCode = 0;
+ if (qualifier != null)
+ {
+ computedHashCode = 31 * computedHashCode + getQualifierHashCode(qualifier);
+ }
+ if (qualifiers != null)
+ {
+ for (Annotation qualifier1 : qualifiers) {
+ computedHashCode = 31 * computedHashCode + getQualifierHashCode(qualifier1);
+ }
+ }
+ return computedHashCode;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof InstanceCacheKey)) return false;
+
+ InstanceCacheKey that = (InstanceCacheKey) o;
+
+ if (qualifier != null ? !qualifierEquals(qualifier, that.qualifier) : that.qualifier != null)
+ {
+ return false;
+ }
+ if (!qualifierArrayEquals(qualifiers, that.qualifiers))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return hashCode;
+ }
+
+ /**
+ * Implements the equals() method for qualifiers, which ignores {@link javax.enterprise.util.Nonbinding} members.
+ */
+ private boolean qualifierEquals(Annotation qualifier1, Annotation qualifier2)
+ {
+ return ANNOTATION_COMPARATOR.compare(qualifier1, qualifier2) == 0;
+ }
+
+ @Override // for debugging
+ public String toString()
+ {
+ return "" + (qualifiers == null ? qualifier : Arrays.asList(qualifiers));
+ }
+
+ private boolean qualifierArrayEquals(Annotation[] qualifiers1, Annotation[] qualifiers2)
+ {
+ if (qualifiers1 == qualifiers2)
+ {
+ return true;
+ }
+ else if (qualifiers1 == null || qualifiers2 == null)
+ {
+ return false;
+ }
+ if (qualifiers1.length != qualifiers2.length)
+ {
+ return false;
+ }
+ for (int i = 0; i < qualifiers1.length; i++)
+ {
+ Annotation a1 = qualifiers1[i];
+ Annotation a2 = qualifiers2[i];
+ if (a1 == null ? a2 != null : !qualifierEquals(a1, a2))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static Class getAnnotationClass(Class a)
+ {
+ for (Class i : a.getInterfaces())
+ {
+ if (i.isAnnotation())
+ {
+ return i;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Helper method for calculating the hashCode of an annotation.
+ */
+ private static Object callMethod(Object instance, Method method)
+ {
+ try
+ {
+ if (!method.isAccessible())
+ {
+ method.setAccessible(true);
+ }
+
+ return method.invoke(instance, AnnotationUtil.EMPTY_OBJECT_ARRAY);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Exception in method call : " + method.getName(), e);
+ }
+
+ }
+
+ protected boolean hasQualifiers() {
+ return qualifier != null || qualifiers != null;
+ }
+
+ /**
+ * Calculate the hashCode() of a qualifier, which ignores {@link Nonbinding} members.
+ */
+ private int getQualifierHashCode(Annotation a)
+ {
+ Class annotationClass = getAnnotationClass(a.getClass());
+
+ if (annotationClass == null)
+ {
+ return getTypeHashCode(a.getClass());
+ }
+
+ // the hashCode of an Annotation is calculated solely via the hashCodes
+ // of it's members. If there are no members, it is 0.
+ // thus we first need to get the annotation-class hashCode
+ int hashCode = getTypeHashCode(annotationClass);
+
+ // and now add the hashCode of all it's Nonbinding members
+ // the following algorithm is defined by the Annotation class definition
+ // see the JavaDoc for Annotation!
+ // we only change it so far that we skip evaluating @Nonbinding members
+ final Method[] members = annotationClass.getDeclaredMethods();
+
+ for (Method member : members)
+ {
+ if (member.isAnnotationPresent(Nonbinding.class))
+ {
+ // ignore the non binding
+ continue;
+ }
+
+ // Member value
+ final Object object = callMethod(a, member);
+ final int value;
+ if(object.getClass().isArray())
+ {
+ Class<?> type = object.getClass().getComponentType();
+ if(type.isPrimitive())
+ {
+ if(Long.TYPE == type)
+ {
+ value = Arrays.hashCode((long[]) object);
+ }
+ else if(Integer.TYPE == type)
+ {
+ value = Arrays.hashCode((int[])object);
+ }
+ else if(Short.TYPE == type)
+ {
+ value = Arrays.hashCode((short[])object);
+ }
+ else if(Double.TYPE == type)
+ {
+ value = Arrays.hashCode((double[])object);
+ }
+ else if(Float.TYPE == type)
+ {
+ value = Arrays.hashCode((float[])object);
+ }
+ else if(Boolean.TYPE == type)
+ {
+ value = Arrays.hashCode((boolean[])object);
+ }
+ else if(Byte.TYPE == type)
+ {
+ value = Arrays.hashCode((byte[])object);
+ }
+ else if(Character.TYPE == type)
+ {
+ value = Arrays.hashCode((char[])object);
+ }
+ else
+ {
+ value = 0;
+ }
+ }
+ else
+ {
+ value = Arrays.hashCode((Object[])object);
+ }
+ }
+ else
+ {
+ value = object.hashCode();
+ }
+
+ hashCode = 29 * hashCode + value;
+ hashCode = 29 * hashCode + member.getName().hashCode();
+ }
+
+ return hashCode;
+ }
+
+ /**
+ * We need this method as some weird JVMs return 0 as hashCode for classes.
+ * In that case we return the hashCode of the String.
+ */
+ protected int getTypeHashCode(Type type)
+ {
+ int typeHash = type.hashCode();
+ if (typeHash == 0 && type instanceof Class)
+ {
+ return ((Class)type).getName().hashCode();
+ // the type.toString() is always the same: "java.lang.Class@<hexid>"
+ // was: return type.toString().hashCode();
+ }
+
+ return typeHash;
+ }
+
+ /**
+ * to keep the annotations ordered.
+ */
+ private static class AnnotationComparator implements Comparator<Annotation>
+ {
+
+ // Notice: Sorting is a bit costly, but the use of this code is very rar.
+ public int compare(Annotation annotation1, Annotation annotation2)
+ {
+ final Class<? extends Annotation> type1 = annotation1.annotationType();
+ final Class<? extends Annotation> type2 = annotation2.annotationType();
+ final int temp = type1.getName().compareTo(type2.getName());
+ if (temp != 0)
+ {
+ return temp;
+ }
+ final Method[] member1 = type1.getDeclaredMethods();
+ final Method[] member2 = type2.getDeclaredMethods();
+
+ // TBD: the order of the list of members seems to be deterministic
+
+ int i = 0;
+ int j = 0;
+ final int length1 = member1.length;
+ final int length2 = member2.length;
+
+ // find next nonbinding
+ for (;; i++, j++)
+ {
+ while (i < length1 && member1[i].isAnnotationPresent(Nonbinding.class))
+ {
+ i++;
+ }
+ while (j < length2 && member2[j].isAnnotationPresent(Nonbinding.class))
+ {
+ j++;
+ }
+ if (i >= length1 && j >= length2)
+ { // both ended
+ return 0;
+ }
+ else if (i >= length1)
+ { // #1 ended
+ return 1;
+ }
+ else if (j >= length2)
+ { // #2 ended
+ return -1;
+ }
+ else
+ { // not ended
+ int c = member1[i].getName().compareTo(member2[j].getName());
+ if (c != 0)
+ {
+ return c;
+ }
+ final Object value1 = callMethod(annotation1, member1[i]);
+ final Object value2 = callMethod(annotation2, member2[j]);
+ assert value1.getClass().equals(value2.getClass());
+
+ if (value1 instanceof Comparable)
+ {
+ c = ((Comparable)value1).compareTo(value2);
+ if (c != 0)
+ {
+ return c;
+ }
+ }
+ else if (value1.getClass().isArray())
+ {
+ c = value1.getClass().getComponentType().getName()
+ .compareTo(value2.getClass().getComponentType().getName());
+ if (c != 0)
+ {
+ return c;
+ }
+
+ final int length = Array.getLength(value1);
+ c = length - Array.getLength(value2);
+ if (c != 0)
+ {
+ return c;
+ }
+ for (int k = 0; k < length; k++)
+ {
+ c = ((Comparable)Array.get(value1, k)).compareTo(Array.get(value2, k));
+ if (c != 0)
+ {
+ return c;
+ }
+ }
+
+ }
+ else if (value1 instanceof Class)
+ {
+
+ c = ((Class)value1).getName().compareTo(((Class) value2).getName());
+ if (c != 0)
+ {
+ return c;
+ }
+ }
+ else
+ {
+ // valid types for members are only Comparable, Arrays, or Class
+ assert false;
+ }
+ }
+ }
+ }
+ }
+}
Index: webbeans-impl/src/main/java/org/apache/webbeans/inject/instance/InstanceImpl.java
===================================================================
--- webbeans-impl/src/main/java/org/apache/webbeans/inject/instance/InstanceImpl.java (revision 1436220)
+++ webbeans-impl/src/main/java/org/apache/webbeans/inject/instance/InstanceImpl.java (working copy)
@@ -18,32 +18,38 @@
*/
package org.apache.webbeans.inject.instance;
+import org.apache.webbeans.config.WebBeansContext;
+import org.apache.webbeans.container.BeanCacheKey;
+import org.apache.webbeans.container.BeanManagerImpl;
+import org.apache.webbeans.container.InjectionResolver;
+import org.apache.webbeans.context.creational.CreationalContextImpl;
+import org.apache.webbeans.portable.InjectionPointProducer;
+import org.apache.webbeans.util.ClassUtil;
+import org.apache.webbeans.util.InjectionExceptionUtil;
+import org.apache.webbeans.util.OwbCustomObjectInputStream;
+import org.apache.webbeans.util.WebBeansUtil;
+
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.Instance;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.util.TypeLiteral;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
-import javax.enterprise.context.spi.CreationalContext;
-import javax.enterprise.inject.Instance;
-import javax.enterprise.inject.spi.Bean;
-import javax.enterprise.inject.spi.InjectionPoint;
-import javax.enterprise.util.TypeLiteral;
+import static org.apache.webbeans.util.InjectionExceptionUtil.throwAmbiguousResolutionException;
-import org.apache.webbeans.config.WebBeansContext;
-import org.apache.webbeans.container.BeanManagerImpl;
-import org.apache.webbeans.container.InjectionResolver;
-import org.apache.webbeans.context.creational.CreationalContextImpl;
-import org.apache.webbeans.portable.InjectionPointProducer;
-import org.apache.webbeans.util.ClassUtil;
-import org.apache.webbeans.util.InjectionExceptionUtil;
-import org.apache.webbeans.util.OwbCustomObjectInputStream;
-import org.apache.webbeans.util.WebBeansUtil;
-
/**
* Implements the {@link Instance} interface.
*
@@ -62,12 +68,17 @@
private InjectionPoint injectionPoint;
/** Qualifier annotations appeared on the injection point */
- private Set<Annotation> qualifierAnnotations = new HashSet<Annotation>();
+ private Annotation[] anns;
private WebBeansContext webBeansContext;
private CreationalContext<?> parentCreationalContext;
+ // cache for perfs, transient is useless since we manage the serial ourself byt just for doc purpose
+ private transient BeanCacheKey cacheKey = null;
+ private transient Set<Bean<?>> beans = null;
+ private transient final ConcurrentMap<InstanceCacheKey, InstanceImpl<T>> instancesCache = new ConcurrentHashMap<InstanceCacheKey, InstanceImpl<T>>();
+
/**
* Creates new instance.
*
@@ -75,7 +86,6 @@
* @param injectionPoint null or injection point
* @param webBeansContext
* @param creationalContext will get used for creating &#064;Dependent beans
- * @param ownerInstance the object the current Instance got injected into
* @param annotations qualifier annotations
*/
public InstanceImpl(Type injectionClazz, InjectionPoint injectionPoint, WebBeansContext webBeansContext,
@@ -85,13 +95,43 @@
this.injectionPoint = injectionPoint;
this.parentCreationalContext = creationalContext;
- for (Annotation ann : annotations)
+ final Set<Annotation> qualifierAnnotations = new HashSet<Annotation>();
+ Collections.addAll(qualifierAnnotations, annotations);
+ anns = new Annotation[qualifierAnnotations.size()];
+ anns = qualifierAnnotations.toArray(anns);
+
+ this.webBeansContext = webBeansContext;
+
+ init();
+ }
+
+ private void computeCacheKey() {
+ InjectionResolver injectionResolver = webBeansContext.getBeanManagerImpl().getInjectionResolver();
+
+ Bean<?> injectionPointBean = injectionPoint.getBean();
+ Class<?> injectionPointClass = null;
+ if (injectionPointBean != null)
{
- qualifierAnnotations.add(ann);
+ injectionPointClass = injectionPointBean.getBeanClass();
}
- this.webBeansContext = webBeansContext;
+
+ cacheKey = injectionResolver.computeKey(injectionClazz, injectionPointClass, anns);
}
+ private static Bean<?> quickResolve(final Set<Bean<?>> set) { // we already did resolveAll() so no need to redo it
+ if (set.isEmpty())
+ {
+ return null;
+ }
+
+ if(set.size() > 1)
+ {
+ throwAmbiguousResolutionException(set);
+ }
+
+ return set.iterator().next();
+ }
+
/**
* Returns the bean instance with given qualifier annotations.
*
@@ -105,14 +145,9 @@
InjectionPointProducer.setThreadLocal(injectionPoint);
try
{
- Annotation[] anns = new Annotation[qualifierAnnotations.size()];
- anns = qualifierAnnotations.toArray(anns);
-
- Set<Bean<?>> beans = resolveBeans();
-
BeanManagerImpl beanManager = webBeansContext.getBeanManagerImpl();
- Bean<?> bean = beanManager.resolve(beans);
+ Bean<?> bean = quickResolve(beans);
if (bean == null)
{
@@ -150,22 +185,19 @@
*
* @return set of resolved beans
*/
- private Set<Bean<?>> resolveBeans()
+ private void resolveBeans()
{
- Annotation[] anns = new Annotation[qualifierAnnotations.size()];
- anns = qualifierAnnotations.toArray(anns);
-
InjectionResolver injectionResolver = webBeansContext.getBeanManagerImpl().getInjectionResolver();
- InjectionResolver resolver = injectionResolver;
Bean<?> injectionPointBean = injectionPoint.getBean();
Class<?> injectionPointClass = null;
if (injectionPointBean != null)
{
injectionPointClass = injectionPointBean.getBeanClass();
}
- Set<Bean<?>> beans = resolver.implResolveByType(injectionClazz, injectionPointClass, anns);
- return resolver.resolveAll(beans);
+
+ Set<Bean<?>> beanSet = injectionResolver.implResolveByType(cacheKey, injectionClazz, injectionPointClass, anns);
+ beans = injectionResolver.resolveAll(beanSet);
}
/**
@@ -173,9 +205,7 @@
*/
public boolean isAmbiguous()
{
- Set<Bean<?>> beans = resolveBeans();
-
- return beans.size() > 1 ? true : false;
+ return beans.size() > 1;
}
/**
@@ -183,9 +213,7 @@
*/
public boolean isUnsatisfied()
{
- Set<Bean<?>> beans = resolveBeans();
-
- return beans.size() == 0 ? true : false;
+ return beans.isEmpty();
}
/**
@@ -193,10 +221,23 @@
*/
public Instance<T> select(Annotation... qualifiers)
{
- Annotation[] newQualifiersArray = getAdditionalQualifiers(qualifiers);
- InstanceImpl<T> newInstance = new InstanceImpl<T>(injectionClazz, injectionPoint, webBeansContext, parentCreationalContext, newQualifiersArray);
+ final InstanceCacheKey key = new InstanceCacheKey(qualifiers);
- return newInstance;
+ InstanceImpl<T> instance = instancesCache.get(key);
+ if (instance != null) {
+ return instance;
+ }
+
+ final Annotation[] newQualifiersArray = getAdditionalQualifiers(qualifiers);
+
+ instance = new InstanceImpl<T>(injectionClazz, injectionPoint, webBeansContext, parentCreationalContext, newQualifiersArray);
+ InstanceImpl<T> old = instancesCache.putIfAbsent(key, instance);
+ if (old != null)
+ {
+ instance = old;
+ }
+
+ return instance;
}
/**
@@ -208,7 +249,7 @@
private Annotation[] getAdditionalQualifiers(Annotation[] qualifiers)
{
webBeansContext.getAnnotationManager().checkQualifierConditions(qualifiers);
- Set<Annotation> newQualifiers = new HashSet<Annotation>(qualifierAnnotations);
+ Set<Annotation> newQualifiers = new HashSet<Annotation>(Arrays.asList(anns));
if (qualifiers != null && qualifiers.length > 0)
{
@@ -225,7 +266,7 @@
Annotation[] newQualifiersArray = new Annotation[newQualifiers.size()];
newQualifiersArray = newQualifiers.toArray(newQualifiersArray);
-
+
return newQualifiersArray;
}
@@ -245,9 +286,7 @@
Annotation[] newQualifiers = getAdditionalQualifiers(qualifiers);
- InstanceImpl<U> newInstance = new InstanceImpl(sub, injectionPoint, webBeansContext, parentCreationalContext, newQualifiers);
-
- return newInstance;
+ return new InstanceImpl(sub, injectionPoint, webBeansContext, parentCreationalContext, newQualifiers);
}
/**
@@ -264,7 +303,6 @@
@SuppressWarnings("unchecked")
public Iterator<T> iterator()
{
- Set<Bean<?>> beans = resolveBeans();
Set<T> instances = new HashSet<T>();
InjectionPointProducer.setThreadLocal(injectionPoint);
try
@@ -287,7 +325,7 @@
{
ObjectOutputStream oos = new ObjectOutputStream(op);
oos.writeObject(injectionClazz);
- oos.writeObject(qualifierAnnotations);
+ oos.writeObject(anns);
oos.writeObject(injectionPoint);
oos.flush();
@@ -298,11 +336,18 @@
webBeansContext = WebBeansContext.currentInstance();
final ObjectInputStream inputStream = new OwbCustomObjectInputStream(in, WebBeansUtil.getCurrentClassLoader());
injectionClazz = (Type)inputStream.readObject();
- qualifierAnnotations = (Set<Annotation>)inputStream.readObject();
+ anns = (Annotation[])inputStream.readObject();
injectionPoint = (InjectionPoint) inputStream.readObject();
+
+ init();
}
-
+ private void init() {
+ computeCacheKey();
+ resolveBeans();
+ }
+
+
public String toString()
{
StringBuilder builder = new StringBuilder();
@@ -312,7 +357,7 @@
builder.append(",with qualifier annotations {");
int i = 0;
- for (Annotation qualifier : qualifierAnnotations)
+ for (Annotation qualifier : anns)
{
if (i != 0)
{
@@ -320,11 +365,11 @@
}
builder.append(qualifier.toString());
+ i++;
}
builder.append("}");
return builder.toString();
}
-
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment