Index: modules/kernel/src/com/caucho/config/reflect/AnnotatedTypeUtil.java =================================================================== --- modules/kernel/src/com/caucho/config/reflect/AnnotatedTypeUtil.java (date 1301577825000) +++ modules/kernel/src/com/caucho/config/reflect/AnnotatedTypeUtil.java (revision ) @@ -30,6 +30,8 @@ package com.caucho.config.reflect; import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; import java.util.Collection; import java.util.List; import java.util.Set; @@ -41,6 +43,7 @@ import com.caucho.config.inject.InjectManager; import com.caucho.inject.Module; +import com.stendahls.ddt.model.FileCategory; /** @@ -56,47 +59,90 @@ { return findMethod(type.getMethods(), method); } - + /** * Finds any method matching the method name and parameter types. */ public static AnnotatedMethod - findMethod(Collection> methodList, + findMethod(Collection> methodList, AnnotatedMethod method) { Method javaMethod = method.getJavaMember(); String name = javaMethod.getName(); List> paramList = (List) method.getParameters(); - + for (AnnotatedMethod testMethod : methodList) { Method testJavaMethod = testMethod.getJavaMember(); - + if (! name.equals(testJavaMethod.getName())) continue; - + List> testParamList = (List) testMethod.getParameters(); - + if (isMatch(paramList, testParamList)) { return testMethod; } } - + return null; } - + private static boolean isMatch(List> listA, List> listB) { if (listA.size() != listB.size()) return false; - + int len = listA.size(); - + for (int i = 0; i < len; i++) { - if (! listA.get(i).getBaseType().equals(listB.get(i).getBaseType())) + + Type listAType; + boolean listATypeIsGeneric = false; + if (listA.get(i).getBaseType() instanceof TypeVariable) { + listAType = ((TypeVariable) listA.get(i).getBaseType()).getBounds()[0]; + listATypeIsGeneric = true; + } + else { + listAType = listA.get(i).getBaseType(); + } + + Type listBType; + boolean listBTypeIsGeneric = false; + if (listB.get(i).getBaseType() instanceof TypeVariable) { + listBType = ((TypeVariable) listB.get(i).getBaseType()).getBounds()[0]; + listBTypeIsGeneric = true; + + } + else { + listBType = listB.get(i).getBaseType(); + } + + if (listATypeIsGeneric && listBTypeIsGeneric) { - return false; - } + return false; + } + else { + if (!listATypeIsGeneric && !listBTypeIsGeneric) { + if (!listAType.equals(listBType)) { + return false; + } + } + else { + if (listATypeIsGeneric && !listBTypeIsGeneric) { + if(!((Class) listAType).isAssignableFrom(((Class) listBType))) { + return false; + } + } - + + if (!listATypeIsGeneric && listBTypeIsGeneric) { + if (!((Class) listBType).isAssignableFrom(((Class) listAType))) { + return false; + } + } + } + } + } + return true; } /** @@ -105,7 +151,7 @@ public static AnnotatedMethod findMethod(AnnotatedType type, Method javaMethod) { - return findMethod(type, + return findMethod(type, javaMethod.getName(), javaMethod.getParameterTypes()); } @@ -118,14 +164,14 @@ { for (AnnotatedMethod annMethod : type.getMethods()) { Method method = annMethod.getJavaMember(); - + if (! method.getName().equals(methodName)) continue; - + if (isMatch(param, method.getParameterTypes())) return annMethod; } - + return null; } @@ -137,7 +183,7 @@ { return findMethod(methods, method.getName(), method.getParameterTypes()); } - + /** * Finds any method matching the method name and parameter types. */ @@ -146,17 +192,17 @@ { for (AnnotatedMethod annMethod : methods) { Method method = annMethod.getJavaMember(); - + if (! method.getName().equals(methodName)) continue; - + if (isMatch(param, method.getParameterTypes())) return annMethod; } - + return null; } - + /** * Finds any method matching the method name and parameter types. */ @@ -164,16 +210,16 @@ { if (cl == null) return null; - + for (Method method : cl.getDeclaredMethods()) { if (isMatch(method, testMethod)) return method; } - + return null; } - - + + /** * Finds any method matching the method name and parameter types. */ @@ -183,10 +229,10 @@ if (isMatch(method, testMethod)) return method; } - + return null; } - + /** * Finds any method matching the method name and parameter types. */ @@ -196,7 +242,7 @@ if (isMatch(method, testMethod)) return method; } - + return null; } @@ -210,31 +256,31 @@ return true; else if (methodA == null || methodB == null) return false; - + Method javaMethodA = methodA.getJavaMember(); Method javaMethodB = methodB.getJavaMember(); - + if (! javaMethodA.getName().equals(javaMethodB.getName())) return false; - + List> paramListA = (List) methodA.getParameters(); List> paramListB = (List) methodB.getParameters(); - + if (isMatch(paramListA, paramListB)) { return true; } - + return false; } /** * Tests if an annotated method matches a name and parameter types. */ - public static boolean isMatch(AnnotatedMethod method, + public static boolean isMatch(AnnotatedMethod method, String name, Class []param) { Method javaMethod = method.getJavaMember(); - + if (! javaMethod.getName().equals(name)) return false; @@ -268,7 +314,7 @@ return isMatch(methodA.getParameterTypes(), methodB.getParameterTypes()); } - + /** * Tests if parameters match a method's parameter types. */ @@ -276,12 +322,12 @@ { if (paramA.length != paramB.length) return false; - + for (int i = paramA.length - 1; i >= 0; i--) { if (! paramA[i].equals(paramB[i])) return false; } - + return true; } Index: modules/resin/src/com/caucho/ejb/gen/SessionGenerator.java =================================================================== --- modules/resin/src/com/caucho/ejb/gen/SessionGenerator.java (date 1301577825000) +++ modules/resin/src/com/caucho/ejb/gen/SessionGenerator.java (revision ) @@ -35,6 +35,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.List; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; @@ -59,14 +60,14 @@ @Module abstract public class SessionGenerator extends BeanGenerator { private static final L10N L = new L10N(SessionGenerator.class); - + private boolean _hasNoInterfaceView; private ArrayList> _localApi; private AnnotatedType _localBean; - + private ArrayList> _remoteApi; - + private ArrayList> _annotatedMethods = new ArrayList>(); @@ -74,14 +75,14 @@ private final NonBusinessAspectBeanFactory _nonBusinessAspectBeanFactory; - private final ArrayList> _businessMethods + private final ArrayList> _businessMethods = new ArrayList>(); - public SessionGenerator(String ejbName, + public SessionGenerator(String ejbName, AnnotatedType beanType, ArrayList> localApi, AnnotatedType localBean, - ArrayList> remoteApi, + ArrayList> remoteApi, String beanTypeName) { super(toFullClassName(ejbName, beanType.getJavaClass().getName(), beanTypeName), @@ -94,7 +95,7 @@ _remoteApi = new ArrayList>(remoteApi); - _nonBusinessAspectBeanFactory + _nonBusinessAspectBeanFactory = new NonBusinessAspectBeanFactory(getBeanType()); } @@ -104,9 +105,9 @@ StringBuilder sb = new StringBuilder(); sb.append(className); - + sb.append("__"); - + if (! className.endsWith(ejbName)) { for (int i = 0; i < ejbName.length(); i++) { char ch = ejbName.charAt(i); @@ -119,14 +120,14 @@ sb.append('_'); } } - + sb.append(beanType); sb.append("Proxy"); return sb.toString(); } - public boolean isStateless() + public boolean isStateless() { return false; } @@ -136,7 +137,7 @@ // return _hasNoInterfaceView; return getLocalBean() != null; } - + /** * Returns the local API list. */ @@ -144,7 +145,7 @@ { return _localApi; } - + public AnnotatedType getLocalBean() { return _localBean; @@ -157,7 +158,7 @@ { return _remoteApi; } - + /** * Returns the merged annotated methods */ @@ -182,36 +183,36 @@ public void introspect() { super.introspect(); - - if (getBeanType().isAnnotationPresent(LocalBean.class) + + if (getBeanType().isAnnotationPresent(LocalBean.class) && ! getBeanType().getJavaClass().isInterface()) _hasNoInterfaceView = true; - + if (_localApi.size() == 0 && _remoteApi.size() == 0) _hasNoInterfaceView = true; if (_hasNoInterfaceView) { AnnotatedType localDefault = introspectLocalDefault(); - + if (localDefault.getJavaClass().isInterface()) - _localApi.add(localDefault); + _localApi.add(localDefault); else { // we still want to introspect the methods, but don't add it as // a local api because it will be treated as an interface later introspectType(localDefault); } } - + for (AnnotatedType type : _localApi) { introspectType(type); } - + for (AnnotatedType type : _remoteApi) { introspectType(type); } - + introspectImpl(); - + // this comes after the other introspection classes because all it // does is catch private timer methods and generate aspect wrappers // that wouldn't normally be generated if the method didn't have @@ -219,24 +220,24 @@ if (isTimerSupported()) introspectTimerMethods(); } - + private void introspectType(AnnotatedType type) { for (AnnotatedMethod method : type.getMethods()) { introspectMethod(method); } } - + private void introspectMethod(AnnotatedMethod method) { - AnnotatedMethod oldMethod + AnnotatedMethod oldMethod = findMethod(_annotatedMethods, method); - + if (oldMethod != null) { // XXX: merge annotations return; } - + AnnotatedMethod baseMethod = findMethod(getBeanType().getMethods(), method); @@ -247,7 +248,7 @@ _annotatedMethods.add(baseMethod); } - + /** * Introspects the APIs methods, producing a business method for * each. @@ -258,10 +259,10 @@ // ejb/5015 introspectMethodImpl(method); } - + for (AnnotatedMethod method : getBeanType().getMethods()) { Method javaMethod = method.getJavaMember(); - + if (method.isAnnotationPresent(PostConstruct.class) && javaMethod.getParameterTypes().length == 0) { // ejb/1060 only one post construct @@ -287,70 +288,70 @@ javaMethod.getDeclaringClass(), javaMethod.getName())); } - + int modifiers = javaMethod.getModifiers(); if (! Modifier.isPublic(modifiers) && ! Modifier.isPrivate(modifiers)) addNonBusinessMethod(apiMethod); } } - + private void introspectTimerMethods() { for (AnnotatedMethod method : getAnnotatedMethods()) { introspectTimerMethod(method); - } + } } - + private void introspectTimerMethod(AnnotatedMethod apiMethod) { Method javaMethod = apiMethod.getJavaMember(); - + int modifiers = javaMethod.getModifiers(); - if (! isBusinessMethod(javaMethod) + if (! isBusinessMethod(javaMethod) && ! Modifier.isPublic(modifiers) && (javaMethod.isAnnotationPresent(Schedule.class) || javaMethod.isAnnotationPresent(Schedules.class))) { addScheduledMethod(apiMethod); } } - + protected void addBusinessMethod(AnnotatedMethod method) { AspectGenerator bizMethod = getAspectBeanFactory().create(method); - + if (bizMethod != null && ! _businessMethods.contains(bizMethod)) { _businessMethods.add(bizMethod); } } - + protected void addPostConstructMethod(AnnotatedMethod method) { if (getLifecycleAspectFactory() == null) return; - + AspectGenerator initMethod = getLifecycleAspectFactory().create(method); - + // ejb/5015 if (initMethod != null) { _businessMethods.add(initMethod); } - + /* if (initMethod != null && ! _businessMethods.contains(initMethod)) { _businessMethods.add(initMethod); } */ } - + protected void addPreDestroyMethod(AnnotatedMethod method) { if (getLifecycleAspectFactory() == null) return; - + AspectGenerator initMethod = getLifecycleAspectFactory().create(method); - + // ejb/5015 /* if (initMethod != null && ! _businessMethods.contains(initMethod)) { @@ -364,42 +365,76 @@ protected void addNonBusinessMethod(AnnotatedMethod method) { - AspectGenerator nonBizMethod + AspectGenerator nonBizMethod = _nonBusinessAspectBeanFactory.create(method); - + // XXX seems weird to add this to the _businessMethods, but the generation // is correct. if (nonBizMethod != null) _businessMethods.add(nonBizMethod); - } + } protected void addScheduledMethod(AnnotatedMethod method) { - AspectGenerator bizMethod = + AspectGenerator bizMethod = getScheduledAspectBeanFactory().create(method); - + if (bizMethod != null) _businessMethods.add(bizMethod); } - - private AnnotatedMethod + + private AnnotatedMethod findMethod(Collection> methodList, - AnnotatedMethod method) - { - for (AnnotatedMethod oldMethod : methodList) { - if (AnnotatedTypeUtil.isMatch(oldMethod, method)) { - return oldMethod; + AnnotatedMethod method) { + + List> methodCandidates = new ArrayList>(); + + for (AnnotatedMethod baseMethods : methodList) { + if (AnnotatedTypeUtil.isMatch(baseMethods, method)) { + methodCandidates.add(baseMethods); } } - + + if (methodCandidates.isEmpty()) { - return null; - } + return null; + } + else { + if (methodCandidates.size() == 1) { + return methodCandidates.get(0); + } + else { + return estimateClosestCandidate(method, methodCandidates); + } + } + } + + private AnnotatedMethod estimateClosestCandidate(AnnotatedMethod method, List> methodCandidates) { + AnnotatedMethod nominee = null; + int amountOfObjectParameters = 0; + for (AnnotatedMethod methodCandidate : methodCandidates) { + + int objectParams = 0; + for (Class parameterType : methodCandidate.getJavaMember().getParameterTypes()) { + if (parameterType.equals(Object.class)) { + objectParams++; + } + } + + if (nominee == null || objectParams < amountOfObjectParameters) { + nominee = methodCandidate; + amountOfObjectParameters = objectParams; + } + + } + return nominee; + } + - protected AnnotatedType introspectLocalDefault() + protected AnnotatedType introspectLocalDefault() { return getBeanType(); } - + protected void generateContentImpl(JavaWriter out, HashMap map) throws IOException @@ -407,7 +442,7 @@ generateBeanPrologue(out, map); generateBusinessMethods(out, map); - + generateEpilogue(out, map); generateInject(out, map); generateDelegate(out, map); @@ -416,28 +451,28 @@ } @Override - protected void generatePostConstruct(JavaWriter out, + protected void generatePostConstruct(JavaWriter out, HashMap map) throws IOException { generatePostConstructImpl(out, map); } - + protected AspectBeanFactory getScheduledAspectBeanFactory() { throw new UnsupportedOperationException(); } - + abstract protected boolean isTimerSupported(); abstract protected AspectBeanFactory getAspectBeanFactory(); - + protected AspectBeanFactory getLifecycleAspectFactory() { return null; } - + // abstract protected void generateBody(JavaWriter out) throws IOException; - + public static boolean isBusinessMethod(Method method) { if (method.getDeclaringClass().equals(Object.class)) @@ -446,15 +481,15 @@ return false; if (method.getName().startsWith("ejb")) { } - + int modifiers = method.getModifiers(); if (! Modifier.isPublic(modifiers)) return false; - + if (Modifier.isFinal(modifiers) || Modifier.isStatic(modifiers)) return false; - + return true; } }