Index: impl/src/main/java/org/jboss/weld/bean/RIBean.java =================================================================== --- impl/src/main/java/org/jboss/weld/bean/RIBean.java (revision 5260) +++ impl/src/main/java/org/jboss/weld/bean/RIBean.java (working copy) @@ -116,7 +116,9 @@ if (obj instanceof RIBean) { RIBean that = (RIBean) obj; - return this.getId().equals(that.getId()); + //two beans may have the same id if they are loaded by different classloaders + //so we have to check that the classes are equal as well + return this.getBeanClass().equals(that.getBeanClass()) && this.getId().equals(that.getId()); } else { Index: impl/src/main/java/org/jboss/weld/bean/DisposalMethod.java =================================================================== --- impl/src/main/java/org/jboss/weld/bean/DisposalMethod.java (revision 5260) +++ impl/src/main/java/org/jboss/weld/bean/DisposalMethod.java (working copy) @@ -41,6 +41,7 @@ import org.jboss.weld.introspector.WeldMethod; import org.jboss.weld.introspector.WeldParameter; import org.jboss.weld.util.Beans; +import org.jboss.weld.util.reflection.AnnotatedTypeIdProvider; public class DisposalMethod extends AbstractReceiverBean { @@ -51,7 +52,9 @@ protected DisposalMethod(BeanManagerImpl manager, WeldMethod disposalMethod, AbstractClassBean declaringBean) { - super(new StringBuilder().append(DisposalMethod.class.getSimpleName()).append(BEAN_ID_SEPARATOR).append(declaringBean.getAnnotatedItem().getName()).append(disposalMethod.getSignature().toString()).toString(), declaringBean, manager); + super(new StringBuilder().append(DisposalMethod.class.getSimpleName()).append(BEAN_ID_SEPARATOR).append(AnnotatedTypeIdProvider.getAnnotatedCallableId(disposalMethod)).toString(), + declaringBean, + manager); this.disposalMethodInjectionPoint = MethodInjectionPoint.of(this, disposalMethod); initBindings(); initType(); Index: impl/src/main/java/org/jboss/weld/bean/ManagedBean.java =================================================================== --- impl/src/main/java/org/jboss/weld/bean/ManagedBean.java (revision 5260) +++ impl/src/main/java/org/jboss/weld/bean/ManagedBean.java (working copy) @@ -66,6 +66,7 @@ import org.jboss.weld.serialization.spi.helpers.SerializableContextual; import org.jboss.weld.util.Beans; import org.jboss.weld.util.Names; +import org.jboss.weld.util.reflection.AnnotatedTypeIdProvider; import org.jboss.weld.util.reflection.Reflections; import org.slf4j.cal10n.LocLogger; import org.slf4j.ext.XLogger; @@ -113,7 +114,7 @@ protected static String createId(String beanType, WeldClass clazz) { - return new StringBuilder().append(beanType).append(BEAN_ID_SEPARATOR).append(clazz.getBaseType()).toString(); + return new StringBuilder().append(beanType).append(BEAN_ID_SEPARATOR).append(AnnotatedTypeIdProvider.getAnnotatedTypeId(clazz)).toString(); } /** Index: impl/src/main/java/org/jboss/weld/bean/ProducerMethod.java =================================================================== --- impl/src/main/java/org/jboss/weld/bean/ProducerMethod.java (revision 5260) +++ impl/src/main/java/org/jboss/weld/bean/ProducerMethod.java (working copy) @@ -43,6 +43,7 @@ import org.jboss.weld.introspector.WeldMethod; import org.jboss.weld.introspector.WeldParameter; import org.jboss.weld.util.Names; +import org.jboss.weld.util.reflection.AnnotatedTypeIdProvider; /** * Represents a producer method bean @@ -82,7 +83,7 @@ initType(); initTypes(); initBindings(); - this.id = new StringBuilder().append(BEAN_ID_PREFIX).append(getClass().getSimpleName()).append(BEAN_ID_SEPARATOR).append(declaringBean.getAnnotatedItem().getName()).append(getAnnotatedItem().getSignature().toString()).toString(); + this.id = new StringBuilder().append(BEAN_ID_PREFIX).append(getClass().getSimpleName()).append(BEAN_ID_SEPARATOR).append(AnnotatedTypeIdProvider.getAnnotatedCallableId(method)).toString(); initStereotypes(); initAlternative(); initProducerMethodInjectableParameters(); Index: impl/src/main/java/org/jboss/weld/bean/ProducerField.java =================================================================== --- impl/src/main/java/org/jboss/weld/bean/ProducerField.java (revision 5260) +++ impl/src/main/java/org/jboss/weld/bean/ProducerField.java (working copy) @@ -30,6 +30,7 @@ import org.jboss.weld.bootstrap.BeanDeployerEnvironment; import org.jboss.weld.introspector.WeldField; import org.jboss.weld.util.Names; +import org.jboss.weld.util.reflection.AnnotatedTypeIdProvider; /** * Represents a producer field @@ -65,7 +66,7 @@ */ protected ProducerField(WeldField field, AbstractClassBean declaringBean, BeanManagerImpl manager) { - super(new StringBuilder().append(ProducerField.class.getSimpleName()).append(BEAN_ID_SEPARATOR).append(declaringBean.getAnnotatedItem().getName()).append(".").append(field.getName()).toString(), declaringBean, manager); + super(new StringBuilder().append(ProducerField.class.getSimpleName()).append(BEAN_ID_SEPARATOR).append(AnnotatedTypeIdProvider.getAnnotatedFieldId(field)).toString(), declaringBean, manager); this.field = field; initType(); initTypes(); Index: impl/src/main/java/org/jboss/weld/bean/NewManagedBean.java =================================================================== --- impl/src/main/java/org/jboss/weld/bean/NewManagedBean.java (revision 5260) +++ impl/src/main/java/org/jboss/weld/bean/NewManagedBean.java (working copy) @@ -45,7 +45,12 @@ { return new NewManagedBean(clazz, createId(NewManagedBean.class.getSimpleName(), clazz), manager); } - + + protected static String createId(String beanType, WeldClass clazz) + { + return new StringBuilder().append(beanType).append(BEAN_ID_SEPARATOR).append(clazz.getBaseType()).toString(); + } + private Set bindings; /** Index: impl/src/main/java/org/jboss/weld/util/reflection/AnnotatedTypeIdProvider.java =================================================================== --- impl/src/main/java/org/jboss/weld/util/reflection/AnnotatedTypeIdProvider.java (revision 0) +++ impl/src/main/java/org/jboss/weld/util/reflection/AnnotatedTypeIdProvider.java (revision 0) @@ -0,0 +1,363 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed 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.jboss.weld.util.reflection; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Set; + +import javax.enterprise.inject.spi.AnnotatedCallable; +import javax.enterprise.inject.spi.AnnotatedConstructor; +import javax.enterprise.inject.spi.AnnotatedField; +import javax.enterprise.inject.spi.AnnotatedMethod; +import javax.enterprise.inject.spi.AnnotatedParameter; +import javax.enterprise.inject.spi.AnnotatedType; + +/** + * Class that can take an AnnotatedType and return a unique + * string representation of that type + * @author Stuart Douglas + * + */ +public class AnnotatedTypeIdProvider +{ + + static final char SEPERATOR = ';'; + + /** + * generates a unique signature for an annotated type. + * members without annotations are ommited to reduce + * the length of the signature + * @param + * @param annotatedType + * @return + */ + public static String getAnnotatedTypeId(AnnotatedType annotatedType) + { + return getTypeId(annotatedType.getJavaClass(), annotatedType.getAnnotations(), annotatedType.getMethods(), annotatedType.getFields(), annotatedType.getConstructors()); + } + + /** + * generates a unique signature for a concrete class + * @param + * @param annotatedType + * @return + */ + public static String getTypeId(Class clazz, Collection annotations, Collection> methods, Collection> fields, + Collection> constructors) + { + StringBuilder builder = new StringBuilder(); + + builder.append(clazz.getName()); + builder.append(getAnnotationSetId(annotations)); + builder.append("{ "); + + //now deal with the fields + List> sortedFields = new ArrayList>(); + sortedFields.addAll(fields); + Collections.sort(sortedFields, new Comparator>() + { + public int compare(AnnotatedField arg0, AnnotatedField arg1) + { + if (arg0.getJavaMember().getName().equals(arg1.getJavaMember().getName())) + { + return arg0.getJavaMember().getDeclaringClass().getName().compareTo(arg1.getJavaMember().getDeclaringClass().getName()); + } + return arg0.getJavaMember().getName().compareTo(arg1.getJavaMember().getName()); + } + }); + for (AnnotatedField field : sortedFields) + { + if (!field.getAnnotations().isEmpty()) + { + builder.append(getAnnotatedFieldId(field)); + builder.append(SEPERATOR); + } + } + + //methods + List> sortedMethods = new ArrayList>(); + sortedMethods.addAll(methods); + Collections.sort(sortedMethods, new AnnotatedMethodComparator()); + for (AnnotatedMethod method : sortedMethods) + { + if (!method.getAnnotations().isEmpty() || hasMethodParameters(method)) + { + builder.append(getAnnotatedCallableId(method)); + builder.append(SEPERATOR); + } + } + + //constructors + List> sortedConstructors = new ArrayList>(); + sortedConstructors.addAll(constructors); + Collections.sort(sortedConstructors, new AnnotatedConstructorComparator()); + for (AnnotatedConstructor con : sortedConstructors) + { + if (!con.getAnnotations().isEmpty() || hasMethodParameters(con)) + { + builder.append(getAnnotatedCallableId(con)); + builder.append(SEPERATOR); + } + } + builder.append("}"); + + return builder.toString(); + } + + public static boolean hasMethodParameters(AnnotatedCallable callable) + { + for(AnnotatedParameter p : callable.getParameters()) + { + if (p.getAnnotations().isEmpty()) + return true; + } + return false; + } + + public static String getAnnotationSetId(Collection annotations) + { + if (annotations.isEmpty()) + return ""; + StringBuilder builder = new StringBuilder(); + builder.append('['); + + List anList = new ArrayList(annotations.size()); + anList.addAll(annotations); + Collections.sort(anList, new Comparator() + { + public int compare(Annotation arg0, Annotation arg1) + { + return arg0.annotationType().getName().compareTo(arg1.annotationType().getName()); + } + }); + for(Annotation a : anList) + { + builder.append('@'); + builder.append(a.annotationType().getName()); + builder.append('('); + Method[] decMethod = a.annotationType().getDeclaredMethods(); + List methods = new ArrayList(decMethod.length); + Collections.sort(methods, new Comparator() + { + + public int compare(Method arg0, Method arg1) + { + return arg0.getName().compareTo(arg1.getName()); + } + }); + + for (int i = 0; i < methods.size(); ++i) + { + Method m = methods.get(i); + try + { + Object value = m.invoke(a); + builder.append(m.getName()); + builder.append('='); + builder.append(value.toString()); + } + catch (NullPointerException e) + { + throw new RuntimeException("NullPointerException accessing annotation member, annotation:" + a.annotationType().getName() + " member: " + m.getName(), e); + } + catch (IllegalArgumentException e) + { + throw new RuntimeException("IllegalArgumentException accessing annotation member, annotation:" + a.annotationType().getName() + " member: " + m.getName(), e); + } + catch (IllegalAccessException e) + { + throw new RuntimeException("IllegalAccessException accessing annotation member, annotation:" + a.annotationType().getName() + " member: " + m.getName(), e); + } + catch (InvocationTargetException e) + { + throw new RuntimeException("InvocationTargetException accessing annotation member, annotation:" + a.annotationType().getName() + " member: " + m.getName(), e); + } + if (i + 1 != methods.size()) + { + builder.append(','); + } + } + builder.append(')'); + } + builder.append(']'); + return builder.toString(); + } + + public static String getAnnotatedFieldId(AnnotatedField field) + { + return getFieldId(field.getJavaMember(), field.getAnnotations()); + } + + public static String getFieldId(Field field, Collection annotations) + { + StringBuilder builder = new StringBuilder(); + builder.append(field.getDeclaringClass().getName()); + builder.append('.'); + builder.append(field.getName()); + builder.append(getAnnotationSetId(annotations)); + return builder.toString(); + } + + public static String getAnnotatedCallableId(AnnotatedCallable method) + { + StringBuilder builder = new StringBuilder(); + builder.append(method.getJavaMember().getDeclaringClass().getName()); + builder.append('.'); + builder.append(method.getJavaMember().getName()); + builder.append(getAnnotationSetId(method.getAnnotations())); + builder.append(getAnnotatatedParameterListId(method.getParameters())); + return builder.toString(); + } + + public static String getMethodId(Method method, Set annotations, List> parameters) + { + StringBuilder builder = new StringBuilder(); + builder.append(method.getDeclaringClass().getName()); + builder.append('.'); + builder.append(method.getName()); + builder.append(getAnnotationSetId(annotations)); + builder.append(getAnnotatatedParameterListId(parameters)); + return builder.toString(); + } + + public static String getConstructorId(Constructor constructor, Set annotations, List> parameters) + { + StringBuilder builder = new StringBuilder(); + builder.append(constructor.getDeclaringClass().getName()); + builder.append('.'); + builder.append(constructor.getName()); + builder.append(getAnnotationSetId(annotations)); + builder.append(getAnnotatatedParameterListId(parameters)); + return builder.toString(); + } + + public static String getAnnotatatedParameterListId(List> parameters) + { + StringBuilder builder = new StringBuilder(); + builder.append("("); + for (int i = 0; i < parameters.size(); ++i) + { + AnnotatedParameter ap = parameters.get(i); + builder.append(getAnnotatedParameterId(ap)); + if (i + 1 != parameters.size()) + { + builder.append(','); + } + } + builder.append(")"); + return builder.toString(); + } + + + public static String getAnnotatedParameterId(AnnotatedParameter annotatedParameter) + { + return getParameterId(annotatedParameter.getBaseType(), annotatedParameter.getAnnotations()); + } + + public static String getParameterId(Type type, Set annotations) + { + StringBuilder builder = new StringBuilder(); + if (type instanceof Class) + { + Class c = (Class) type; + builder.append(c.getName()); + } + else + { + builder.append(type.toString()); + } + builder.append(getAnnotationSetId(annotations)); + return builder.toString(); + } + + /** + * Does the first stage of comparing AnnoatedCallables, however it cannot compare the + * method parameters + */ + static class AnnotatedCallableComparator implements Comparator> + { + + public int compare(AnnotatedCallable arg0, AnnotatedCallable arg1) + { + //compare the names first + int res = (arg0.getJavaMember().getName().compareTo(arg1.getJavaMember().getName())); + if (res != 0) + return res; + res = arg0.getJavaMember().getDeclaringClass().getName().compareTo(arg1.getJavaMember().getDeclaringClass().getName()); + if (res != 0) + return res; + res = arg0.getParameters().size() - arg1.getParameters().size(); + return res; + } + + } + + static class AnnotatedMethodComparator implements Comparator> + { + AnnotatedCallableComparator cmp = new AnnotatedCallableComparator(); + + public int compare(AnnotatedMethod arg0, AnnotatedMethod arg1) + { + int res = cmp.compare(arg0, arg1); + if (res != 0) + return res; + for (int i = 0; i < arg0.getJavaMember().getParameterTypes().length; ++i) + { + Class p0 = arg0.getJavaMember().getParameterTypes()[i]; + Class p1 = arg1.getJavaMember().getParameterTypes()[i]; + res = p0.getName().compareTo(p1.getName()); + if (res != 0) + return res; + } + return 0; + } + + } + + static class AnnotatedConstructorComparator implements Comparator> + { + AnnotatedCallableComparator cmp = new AnnotatedCallableComparator(); + + public int compare(AnnotatedConstructor arg0, AnnotatedConstructor arg1) + { + int res = cmp.compare(arg0, arg1); + if (res != 0) + return res; + for (int i = 0; i < arg0.getJavaMember().getParameterTypes().length; ++i) + { + Class p0 = arg0.getJavaMember().getParameterTypes()[i]; + Class p1 = arg1.getJavaMember().getParameterTypes()[i]; + res = p0.getName().compareTo(p1.getName()); + if (res != 0) + return res; + } + return 0; + } + + } + +}