[jboss-cvs] JBossAS SVN: r67782 - branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Mon Dec 3 11:49:43 EST 2007


Author: bdecoste
Date: 2007-12-03 11:49:43 -0500 (Mon, 03 Dec 2007)
New Revision: 67782

Modified:
   branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/ProxyFactoryHelper.java
Log:
[JBPAPP-478] merged fix for [EJBTHREE-785] [EJBTHREE-1062]

Modified: branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/ProxyFactoryHelper.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/ProxyFactoryHelper.java	2007-12-03 16:47:32 UTC (rev 67781)
+++ branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/ProxyFactoryHelper.java	2007-12-03 16:49:43 UTC (rev 67782)
@@ -21,17 +21,15 @@
  */
 package org.jboss.ejb3;
 
-import org.jboss.annotation.ejb.LocalHomeBinding;
-import org.jboss.annotation.ejb.RemoteHomeBinding;
-import org.jboss.annotation.ejb.LocalBinding;
-import org.jboss.annotation.ejb.RemoteBinding;
-import org.jboss.annotation.ejb.RemoteBindings;
-import org.jboss.aop.Advisor;
-import org.jboss.ejb.LocalImpl;
-import org.jboss.ejb.RemoteImpl;
-import org.jboss.logging.Logger;
-import org.jboss.ejb3.remoting.RemoteProxyFactory;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
 
+import javax.ejb.EJBLocalObject;
+import javax.ejb.EJBObject;
 import javax.ejb.Local;
 import javax.ejb.LocalHome;
 import javax.ejb.Remote;
@@ -41,10 +39,17 @@
 import javax.naming.Context;
 import javax.naming.NameNotFoundException;
 import javax.naming.NamingException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
 
+import org.jboss.annotation.ejb.LocalBinding;
+import org.jboss.annotation.ejb.LocalHomeBinding;
+import org.jboss.annotation.ejb.RemoteBinding;
+import org.jboss.annotation.ejb.RemoteBindings;
+import org.jboss.annotation.ejb.RemoteHomeBinding;
+import org.jboss.aop.Advisor;
+import org.jboss.ejb.LocalImpl;
+import org.jboss.ejb.RemoteImpl;
+import org.jboss.ejb3.remoting.RemoteProxyFactory;
+import org.jboss.logging.Logger;
 /**
  * Comment
  *
@@ -80,38 +85,109 @@
 
    }
 
-   public static Class[] getLocalInterfaces(Container container)
+   public static Class<?>[] getLocalInterfaces(Container container)
    {
-      Local li = (javax.ejb.Local) ((EJBContainer) container).resolveAnnotation(javax.ejb.Local.class);
+      // Obtain @Local
+      Local localAnnotation = (Local)((EJBContainer) container).resolveAnnotation(javax.ejb.Local.class);
 
-      if (li != null)
+      // Obtain @Remote
+      Remote remoteAnnotation = (Remote)((EJBContainer) container).resolveAnnotation(Remote.class);
+
+      // Obtain all business interfaces
+      List<Class<?>> businessInterfaces = getBusinessInterfaces(container.getBeanClass());
+
+      // JIRA EJBTHREE-1062
+      // EJB 3 4.6.6
+      // If no @Local is defined on the bean class, and the bean class implements a single interface, 
+      // this interface is a local business interface unless denoted otherwise
+      if (localAnnotation == null && container.getBeanClass().getInterfaces().length == 1)
       {
-         if (li.value().length > 0) return li.value();
+         // Obtain the implemented interface
+         Class<?> singleInterface =  container.getBeanClass().getInterfaces()[0];
+         
+         // If not explicitly marked as @Remote, and is a valid business interface
+         if (remoteAnnotation==null
+               && businessInterfaces.contains(singleInterface))
+         {
+            // Return the implemented interface  
+            return container.getBeanClass().getInterfaces();            
+         }
+      }
 
-         // We have an emtpy @Local annotated bean class
+      // If @Local is present
+      if (localAnnotation != null)
+      {
+         // If @Local.value is defined
+         if (localAnnotation.value().length > 0)
+         {
+            // Return the value array defined
+            return localAnnotation.value();
+         }
+  
+         // If @Local is defined with no value and there are no business interfaces
+         if (businessInterfaces.size() == 0){
+            throw new RuntimeException("Use of empty @Local on bean class and there are no valid business interfaces: " + container.getEjbName());            
+         }
+         // If @Local is defined with no value and there is more than one business interface 
+         else if (businessInterfaces.size() > 0)
+         {
+            // Define list to hold all interfaces implemented directly by bean class that are valid business interfaces
+            List<Class<?>> beanClassBusinessInterfaces = new ArrayList<Class<?>>();
+            // All business interfaces
+            for(Class<?> businessInterface : businessInterfaces)
+            {
+               // All interfaces directly implemented by bean class
+               for(Class<?> beanClassInterface : container.getBeanClass().getInterfaces())
+               {
+                  // If interface directly implemented by bean class is business interface
+                  if(businessInterface.equals(beanClassInterface))
+                  {
+                     // Add to list
+                     beanClassBusinessInterfaces.add(businessInterface);
+                  }
+               }
+            }
+            
+            // If more than one business interface is directly implemented by the bean class
+            if(beanClassBusinessInterfaces.size()>1)
+            {
+               throw new RuntimeException("Use of empty @Local on bean class and there are more than one default interface: " + container.getEjbName());
+            }
+            // JIRA EJBTHREE-1062
+            // EJB 3 4.6.6
+            // If the bean class implements only one business interface, that 
+            //interface is exposed as local business if not denoted as @Remote
+            else
+            {
+               // If not explicitly marked as @Remote
+               if (remoteAnnotation == null)
+               {
+                  // Return the implemented interface  
+                  return beanClassBusinessInterfaces.toArray(new Class<?>[]
+                  {});
+               }
 
-         ArrayList list = getBusinessInterfaces(container.getBeanClass());
-         if (list.size() == 0)
-            throw new RuntimeException("Use of empty @Local on bean class and there are no valid business interfaces: " + container.getEjbName());
-         if (list.size() > 1)
-            throw new RuntimeException("Use of empty @Local on bean class and there are more than one default interface: " + container.getEjbName());
-         Class[] rtn = {(Class) list.get(0)};
-         li = new LocalImpl(rtn);
-         ((EJBContainer) container).getAnnotations().addClassAnnotation(javax.ejb.Local.class, li);
+            }
+         }
+         
+         Class[] rtn = {(Class) businessInterfaces.get(0)};
+         localAnnotation = new LocalImpl(rtn);
+         ((EJBContainer) container).getAnnotations().addClassAnnotation(javax.ejb.Local.class, localAnnotation);
          return rtn;
       }
 
       Class beanClass = container.getBeanClass();
       String endpoint = getEndpointInterface(container);
-      Class[] ri = getRemoteInterfaces(container);
+      Class[] remoteInterfaces = getRemoteInterfaces(container);
 
-      if (li == null && ri == null && endpoint == null && (beanClass.getInterfaces() == null || beanClass.getInterfaces().length == 0))
+      if (localAnnotation == null && (remoteInterfaces != null && remoteInterfaces.length == 0) && endpoint == null
+            && (beanClass.getInterfaces() == null || beanClass.getInterfaces().length == 0))
          throw new RuntimeException("bean class has no local, webservice, or remote interfaces defined and does not implement at least one business interface: " + container.getEjbName());
 
       // introspect implemented interfaces.
-      if (li == null)
+      if (localAnnotation == null)
       {
-         Class[] intfs = beanClass.getInterfaces();
+         List<Class<?>> intfs = getBusinessInterfaces(beanClass);
          ArrayList<Class> locals = new ArrayList<Class>();
          for (Class clazz : intfs)
          {
@@ -122,23 +198,22 @@
          }
          if (locals.size() > 0)
          {
-            intfs = locals.toArray(new Class[locals.size()]);
-            li = new LocalImpl(intfs);
-            ((Advisor) container).getAnnotations().addClassAnnotation(javax.ejb.Local.class, li);
+            localAnnotation = new LocalImpl(locals.toArray(new Class[]{}));
+            ((Advisor) container).getAnnotations().addClassAnnotation(javax.ejb.Local.class, localAnnotation);
             //return li.value(); ALR Removed (EJBTHREE-751)
          }
       }
       // no @Local interfaces implemented
-      if (li == null)
+      if (localAnnotation == null)
       {
          // search for default
-         ArrayList<Class> interfaces = getBusinessInterfaces(beanClass);
+         List<Class<?>> interfaces = getBusinessInterfaces(beanClass);
          if (interfaces.size() != 1) return null; // indeterminate
 
          Class intf = interfaces.get(0);
-         if (ri != null)
+         if (remoteInterfaces != null)
          {
-            for (Class rintf : ri)
+            for (Class rintf : remoteInterfaces)
             {
                if (intf.getName().equals(rintf.getName()))
                {
@@ -149,19 +224,19 @@
          if (intf.getName().equals(endpoint)) return null;
 
          Class[] rtn = {intf};
-         li = new LocalImpl(rtn);
-         ((EJBContainer) container).getAnnotations().addClassAnnotation(javax.ejb.Local.class, li);
+         localAnnotation = new LocalImpl(rtn);
+         ((EJBContainer) container).getAnnotations().addClassAnnotation(javax.ejb.Local.class, localAnnotation);
          return rtn;
       }
       
 
       // Check to ensure @Local and @Remote are not defined on the same interface
       // JIRA EJBTHREE-751
-      if(ri != null)
+      if (remoteInterfaces != null)
       {
-         for (Class remoteInterface : ri)
+         for (Class<?> remoteInterface : remoteInterfaces)
          {
-            for (Class localInterface : li.value())
+            for (Class<?> localInterface : localAnnotation.value())
             {
                if (localInterface.equals(remoteInterface))
                {
@@ -172,22 +247,61 @@
          }
       }
       
-      return li.value();
+      return localAnnotation.value();
    }
+   
+   /**
+    * Resolve the potential business interfaces on an enterprise bean.
+    * Returns all interfaces implemented by this class and it's supers which
+    * are potentially a business interface.
+    *
+    * Note: for normal operation call container.getBusinessInterfaces().
+    *
+    * @param    beanClass   the EJB implementation class
+    * @return   a list of potential business interfaces
+    * @see      org.jboss.ejb3.EJBContainer#getBusinessInterfaces()
+    */
+   public static List<Class<?>> getBusinessInterfaces(Class<?> beanClass)
+   {
+      // Obtain all business interfaces implemented by this bean class and its superclasses
+      return getBusinessInterfaces(beanClass, new ArrayList<Class<?>>()); 
+   }
 
-   public static ArrayList<Class> getBusinessInterfaces(Class beanClass)
+
+   private static List<Class<?>> getBusinessInterfaces(Class<?> beanClass, List<Class<?>> interfaces)
    {
-      ArrayList<Class> interfaces = new ArrayList<Class>(Arrays.asList(beanClass.getInterfaces()));
-      interfaces.remove(java.io.Serializable.class);
-      interfaces.remove(java.io.Externalizable.class);
-      interfaces.remove(javax.ejb.SessionSynchronization.class);
-      interfaces.remove(javax.ejb.TimedObject.class);
-      Iterator<Class> it = interfaces.iterator();
-      while (it.hasNext())
+      /*
+       * 4.6.6:
+       * The following interfaces are excluded when determining whether the bean class has
+       * more than one interface: java.io.Serializable; java.io.Externaliz-
+       * able; any of the interfaces defined by the javax.ejb package.
+       */
+      for(Class<?> intf : beanClass.getInterfaces())
       {
-         if (it.next().getName().startsWith("javax.ejb")) it.remove();
+         if(intf.equals(java.io.Externalizable.class))
+            continue;
+         if(intf.equals(java.io.Serializable.class))
+            continue;
+         if(intf.getName().startsWith("javax.ejb"))
+            continue;
+         
+         // FIXME Other aop frameworks might add other interfaces, this should really be configurable
+         if(intf.getName().startsWith("org.jboss.aop"))
+            continue;
+         
+         interfaces.add(intf);
       }
-      return interfaces;
+
+      // If there's no superclass, return
+      if (beanClass.getSuperclass() == null)
+      {
+         return interfaces;
+      }
+      else
+      {
+         // Include any superclasses' interfaces
+         return getBusinessInterfaces(beanClass.getSuperclass(), interfaces);
+      }
    }
 
    public static Class getLocalHomeInterface(Container container)
@@ -361,7 +475,7 @@
       if (ri == null)
       {
          Class beanClass = container.getBeanClass();
-         Class[] intfs = beanClass.getInterfaces();
+         Class[] intfs = ProxyFactoryHelper.getBusinessInterfaces(beanClass).toArray(new Class[]{});
          ArrayList<Class> remotes = new ArrayList<Class>();
          for (Class clazz : intfs)
          {
@@ -385,7 +499,7 @@
 
       // We have an emtpy @Remote annotated bean class
 
-      ArrayList list = getBusinessInterfaces(container.getBeanClass());
+      List list = getBusinessInterfaces(container.getBeanClass());
       if (list.size() == 0)
          throw new RuntimeException("Use of empty @Remote on bean class and there are no valid business interfaces: " + container.getEjbName());
       if (list.size() > 1)




More information about the jboss-cvs-commits mailing list