Save This Page
Home » jboss-5.0.0.CR1-src » org » jboss » ejb » [javadoc | source]
    1   /*
    2   * JBoss, Home of Professional Open Source
    3   * Copyright 2005, JBoss Inc., and individual contributors as indicated
    4   * by the @authors tag. See the copyright.txt in the distribution for a
    5   * full listing of individual contributors.
    6   *
    7   * This is free software; you can redistribute it and/or modify it
    8   * under the terms of the GNU Lesser General Public License as
    9   * published by the Free Software Foundation; either version 2.1 of
   10   * the License, or (at your option) any later version.
   11   *
   12   * This software is distributed in the hope that it will be useful,
   13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   15   * Lesser General Public License for more details.
   16   *
   17   * You should have received a copy of the GNU Lesser General Public
   18   * License along with this software; if not, write to the Free
   19   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
   20   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
   21   */
   22   package org.jboss.ejb;
   23   
   24   // $Id: SessionContainer.java 62680 2007-05-01 04:23:04Z anil.saldhana@jboss.com $
   25   
   26   import java.lang.reflect.Method;
   27   import java.rmi.RemoteException;
   28   import java.util.HashMap;
   29   import java.util.Hashtable;
   30   import java.util.Iterator;
   31   import java.util.Map;
   32   
   33   import javax.ejb.EJBHome;
   34   import javax.ejb.EJBLocalHome;
   35   import javax.ejb.EJBMetaData;
   36   import javax.ejb.EJBObject;
   37   import javax.ejb.Handle;
   38   import javax.ejb.HomeHandle;
   39   import javax.ejb.RemoveException;
   40   import javax.ejb.TimedObject;
   41   import javax.ejb.Timer;
   42   import javax.management.ObjectName;
   43    
   44   import org.jboss.invocation.Invocation;
   45   import org.jboss.invocation.MarshalledInvocation;
   46   import org.jboss.metadata.SessionMetaData;
   47   
   48   /**
   49    * <p>
   50    * Container dedicated to session beans. Contains factored out
   51    * redundancies between stateless and stateful treatments, because
   52    * (extending the spec) we would like to also support stateful
   53    * web services.
   54    * </p>
   55    * @author <a href="mailto:Christoph.Jung@infor.de">Christoph G. Jung</a>
   56    * @version $Revision: 62680 $
   57    * @since 30.10.2003
   58    */
   59   public abstract class SessionContainer extends Container
   60   {
   61      /**
   62       * These are the mappings between the home interface methods and the
   63       * container methods.
   64       */
   65      protected Map homeMapping;
   66   
   67      /**
   68       * These are the mappings between the remote interface methods and the
   69       * bean methods.
   70       */
   71      protected Map beanMapping;
   72   
   73      /**
   74       * This is the first interceptor in the chain. The last interceptor must
   75       * be provided by the container itself
   76       */
   77      protected Interceptor interceptor;
   78   
   79      /** this is the service endpoint class */
   80      protected Class serviceEndpoint;
   81   
   82      /** This is the instancepool that is to be used */
   83      protected InstancePool instancePool;
   84   
   85      /** set the instance pool */
   86      public void setInstancePool(InstancePool ip)
   87      {
   88         if (ip == null)
   89            throw new IllegalArgumentException("Null pool");
   90   
   91         this.instancePool = ip;
   92         ip.setContainer(this);
   93      }
   94   
   95      /** return instance pool */
   96      public InstancePool getInstancePool()
   97      {
   98         return instancePool;
   99      }
  100   
  101      /** return local proxy factory */
  102      public LocalProxyFactory getLocalProxyFactory()
  103      {
  104         return localProxyFactory;
  105      }
  106   
  107      /** add an additional interceptor to the chain */
  108      public void addInterceptor(Interceptor in)
  109      {
  110         if (interceptor == null)
  111         {
  112            interceptor = in;
  113         }
  114         else
  115         {
  116            Interceptor current = interceptor;
  117            while (current.getNext() != null)
  118            {
  119               current = current.getNext();
  120            }
  121   
  122            current.setNext(in);
  123         }
  124      }
  125   
  126      /** return first interceptor */
  127      public Interceptor getInterceptor()
  128      {
  129         return interceptor;
  130      }
  131   
  132      /** return service endpoint */
  133      public Class getServiceEndpoint()
  134      {
  135         return serviceEndpoint;
  136      }
  137   
  138      // Container stuff
  139   
  140      protected void createService() throws Exception
  141      {
  142         // Associate thread with classloader
  143         ClassLoader oldCl = SecurityActions.getContextClassLoader();
  144         SecurityActions.setContextClassLoader(getClassLoader());
  145         pushENC();
  146         try
  147         {
  148            // Acquire classes from CL
  149            if (metaData.getHome() != null)
  150               homeInterface = classLoader.loadClass(metaData.getHome());
  151            if (metaData.getRemote() != null)
  152               remoteInterface = classLoader.loadClass(metaData.getRemote());
  153            if (((SessionMetaData) metaData).getServiceEndpoint() != null)
  154            {
  155               serviceEndpoint =
  156                       classLoader.loadClass(((SessionMetaData) metaData).getServiceEndpoint());
  157            }
  158   
  159            // Call default init
  160            super.createService();
  161   
  162            // Make some additional validity checks with regards to the container configuration
  163            checkCoherency();
  164   
  165            // Map the bean methods
  166            setupBeanMapping();
  167   
  168            // Map the home methods
  169            setupHomeMapping();
  170   
  171            // Map the interfaces to Long
  172            setupMarshalledInvocationMapping();
  173   
  174            createInvokers();
  175   
  176            createInstanceCache();
  177   
  178            createInstancePool();
  179   
  180            createPersistenceManager();
  181   
  182            createInterceptors();
  183         }
  184         finally
  185         {
  186            popENC();
  187            // Reset classloader
  188            SecurityActions.setContextClassLoader(oldCl);
  189         }
  190      }
  191   
  192      /**
  193       * how home methods are treated by container
  194       */
  195      protected abstract void setupHomeMapping() throws Exception;
  196   
  197      /** loop through methods and setup mapping */
  198      protected void setUpBeanMappingImpl(Map map, Method[] methods, String declaringClass)
  199              throws NoSuchMethodException
  200      {
  201         for (int i = 0; i < methods.length; i++)
  202         {
  203            Method m = methods[i];
  204            if (m.getDeclaringClass().getName().equals(declaringClass) == false)
  205            {
  206               // Implemented by bean
  207               try
  208               {
  209                  Method beanMethod = beanClass.getMethod(m.getName(), m.getParameterTypes());
  210                  map.put(m, beanMethod);
  211               }
  212               catch (NoSuchMethodException ex)
  213               {
  214                  throw new NoSuchMethodException("Not found in bean class: " + m);
  215               }
  216   
  217               log.debug("Mapped " + m.getName() + " HASH " + m.hashCode() + "to " + map.get(m));
  218            }
  219            else
  220            {
  221               // Implemented by container
  222               try
  223               {
  224                  Method containerMethod = getClass().getMethod(m.getName(), new Class[]{Invocation.class});
  225                  map.put(m, containerMethod);
  226               }
  227               catch (NoSuchMethodException e)
  228               {
  229                  throw new NoSuchMethodException("Not found in container class: " + m);
  230               }
  231   
  232               log.debug("Mapped Container method " + m.getName() + " HASH " + m.hashCode());
  233            }
  234         }
  235      }
  236   
  237      /** build bean mappings for application logic */
  238      protected void setupBeanMapping() throws NoSuchMethodException
  239      {
  240         Map map = new HashMap();
  241   
  242         if (remoteInterface != null)
  243         {
  244            Method[] m = remoteInterface.getMethods();
  245            setUpBeanMappingImpl(map, m, "javax.ejb.EJBObject");
  246         }
  247   
  248         if (localInterface != null)
  249         {
  250            Method[] m = localInterface.getMethods();
  251            setUpBeanMappingImpl(map, m, "javax.ejb.EJBLocalObject");
  252         }
  253   
  254         if (TimedObject.class.isAssignableFrom(beanClass))
  255         {
  256            Method[] m = new Method[]{TimedObject.class.getMethod("ejbTimeout", new Class[]{Timer.class})};
  257            setUpBeanMappingImpl(map, m, "javax.ejb.Timer");
  258         }
  259   
  260         if (serviceEndpoint != null)
  261         {
  262            Method[] m = serviceEndpoint.getMethods();
  263            setUpBeanMappingImpl(map, m, "java.rmi.Remote");
  264         }
  265   
  266         beanMapping = map;
  267      }
  268   
  269      /**
  270       * sets up marshalled invocation mappings
  271       * @throws Exception
  272       */
  273   
  274      protected void setupMarshalledInvocationMapping() throws Exception
  275      {
  276         // Create method mappings for container invoker
  277         if (homeInterface != null)
  278         {
  279            Method[] m = homeInterface.getMethods();
  280            for (int i = 0; i < m.length; i++)
  281            {
  282               marshalledInvocationMapping.put(new Long(MarshalledInvocation.calculateHash(m[i])), m[i]);
  283            }
  284         }
  285   
  286         if (remoteInterface != null)
  287         {
  288            Method[] m = remoteInterface.getMethods();
  289            for (int j = 0; j < m.length; j++)
  290            {
  291               marshalledInvocationMapping.put(new Long(MarshalledInvocation.calculateHash(m[j])), m[j]);
  292            }
  293         }
  294         // Get the getEJBObjectMethod
  295         Method getEJBObjectMethod =
  296                 Class.forName("javax.ejb.Handle").getMethod("getEJBObject",
  297                         new Class[0]);
  298   
  299         // Hash it
  300         marshalledInvocationMapping.put(new Long(MarshalledInvocation.calculateHash(getEJBObjectMethod)), getEJBObjectMethod);
  301      }
  302   
  303      protected void checkCoherency() throws Exception
  304      {
  305         // Check clustering cohrency wrt metadata
  306         //
  307         if (metaData.isClustered())
  308         {
  309            boolean clusteredProxyFactoryFound = false;
  310            Iterator it = proxyFactories.keySet().iterator();
  311            while (it.hasNext())
  312            {
  313               String invokerBinding = (String) it.next();
  314               EJBProxyFactory ci = (EJBProxyFactory) proxyFactories.get(invokerBinding);
  315               if (ci instanceof org.jboss.proxy.ejb.ClusterProxyFactory)
  316                  clusteredProxyFactoryFound = true;
  317            }
  318   
  319            if (!clusteredProxyFactoryFound)
  320            {
  321               log.warn("*** EJB '"
  322                       + this.metaData.getEjbName()
  323                       + "' deployed as CLUSTERED but not a single clustered-invoker is bound to container ***");
  324            }
  325         }
  326      }
  327   
  328      /** creates a new instance pool */
  329      protected void createInstancePool() throws Exception
  330      {
  331   
  332         // Try to register the instance pool as an MBean
  333         try
  334         {
  335            ObjectName containerName = super.getJmxName();
  336            Hashtable props = containerName.getKeyPropertyList();
  337            props.put("plugin", "pool");
  338            ObjectName poolName = new ObjectName(containerName.getDomain(), props);
  339            server.registerMBean(instancePool, poolName);
  340         }
  341         catch (Throwable t)
  342         {
  343            log.debug("Failed to register pool as mbean", t);
  344         }
  345         // Initialize pool
  346         instancePool.create();
  347      }
  348   
  349      /**
  350       * no instance cache per default
  351       */
  352      protected void createInstanceCache() throws Exception
  353      {
  354      }
  355   
  356      /** creates the invokers */
  357      protected void createInvokers() throws Exception
  358      {
  359         // Init container invoker
  360         for (Iterator it = proxyFactories.keySet().iterator(); it.hasNext();)
  361         {
  362            String invokerBinding = (String) it.next();
  363            EJBProxyFactory ci = (EJBProxyFactory) proxyFactories.get(invokerBinding);
  364            ci.create();
  365         }
  366      }
  367   
  368      /** Initialize the interceptors by calling the chain */
  369      protected void createInterceptors() throws Exception
  370      {
  371         Interceptor in = interceptor;
  372         while (in != null)
  373         {
  374            in.setContainer(this);
  375            in.create();
  376            in = in.getNext();
  377         }
  378      }
  379   
  380      /**
  381       * no persistence manager per default
  382       */
  383      protected void createPersistenceManager() throws Exception
  384      {
  385      }
  386   
  387      protected void startService() throws Exception
  388      {
  389         // Associate thread with classloader
  390         ClassLoader oldCl = SecurityActions.getContextClassLoader();
  391         SecurityActions.setContextClassLoader(getClassLoader());
  392         pushENC();
  393         try
  394         {
  395            // Call default start
  396            super.startService();
  397   
  398            startInvokers();
  399   
  400            startInstanceCache();
  401   
  402            startInstancePool();
  403   
  404            startPersistenceManager();
  405   
  406            startInterceptors();
  407            
  408            // Restore persisted ejb timers
  409            restoreTimers();         
  410         }
  411         finally
  412         {
  413            popENC();
  414            // Reset classloader
  415            SecurityActions.setContextClassLoader(oldCl);
  416         }
  417      }
  418   
  419      /**
  420       * no persistence manager per default
  421       */
  422      protected void startPersistenceManager() throws Exception
  423      {
  424      }
  425   
  426      /**
  427       * no instance cache per default
  428       */
  429      protected void startInstanceCache() throws Exception
  430      {
  431      }
  432   
  433      /** Start container invokers */
  434      protected void startInvokers() throws Exception
  435      {
  436         for (Iterator it = proxyFactories.keySet().iterator(); it.hasNext();)
  437         {
  438            String invokerBinding = (String) it.next();
  439            EJBProxyFactory ci = (EJBProxyFactory) proxyFactories.get(invokerBinding);
  440            ci.start();
  441         }
  442      }
  443   
  444      /** Start pool */
  445      protected void startInstancePool() throws Exception
  446      {
  447         instancePool.start();
  448      }
  449   
  450      /** Start all interceptors in the chain **/
  451      protected void startInterceptors() throws Exception
  452      {
  453         Interceptor in = interceptor;
  454         while (in != null)
  455         {
  456            in.start();
  457            in = in.getNext();
  458         }
  459      }
  460   
  461      protected void stopService() throws Exception
  462      {
  463         // Associate thread with classloader
  464         ClassLoader oldCl = SecurityActions.getContextClassLoader();
  465         SecurityActions.setContextClassLoader(getClassLoader());
  466         pushENC();
  467         try
  468         {
  469            // Call default stop
  470            super.stopService();
  471   
  472            stopInvokers();
  473   
  474            stopInstanceCache();
  475   
  476            stopInstancePool();
  477   
  478            stopPersistenceManager();
  479   
  480            stopInterceptors();
  481         }
  482         finally
  483         {
  484            popENC();
  485            // Reset classloader
  486            SecurityActions.setContextClassLoader(oldCl);
  487         }
  488      }
  489   
  490      /** Stop all interceptors in the chain */
  491      protected void stopInterceptors()
  492      {
  493         Interceptor in = interceptor;
  494         while (in != null)
  495         {
  496            in.stop();
  497            in = in.getNext();
  498         }
  499      }
  500   
  501      /** no persistence */
  502      protected void stopPersistenceManager()
  503      {
  504      }
  505   
  506      /** Stop pool */
  507      protected void stopInstancePool()
  508      {
  509         instancePool.stop();
  510      }
  511   
  512      /** no instance cache */
  513      protected void stopInstanceCache()
  514      {
  515      }
  516   
  517      /** Stop container invoker */
  518      protected void stopInvokers()
  519      {
  520         for (Iterator it = proxyFactories.keySet().iterator(); it.hasNext();)
  521         {
  522            String invokerBinding = (String) it.next();
  523            EJBProxyFactory ci = (EJBProxyFactory) proxyFactories.get(invokerBinding);
  524            ci.stop();
  525         }
  526      }
  527   
  528      protected void destroyService() throws Exception
  529      {
  530         // Associate thread with classloader
  531         ClassLoader oldCl = SecurityActions.getContextClassLoader();
  532         SecurityActions.setContextClassLoader(getClassLoader());
  533         pushENC();
  534         try
  535         {
  536            destroyInvokers();
  537   
  538            destroyInstanceCache();
  539   
  540            destroyInstancePool();
  541   
  542            destroyPersistenceManager();
  543   
  544            destroyInterceptors();
  545   
  546            destroyMarshalledInvocationMapping();
  547   
  548            homeInterface = null;
  549            remoteInterface = null;
  550            serviceEndpoint = null;
  551            beanMapping.clear();
  552            
  553            // Call default destroy
  554            super.destroyService();
  555         }
  556         finally
  557         {
  558            popENC();
  559            // Reset classloader
  560            SecurityActions.setContextClassLoader(oldCl);
  561         }
  562      }
  563   
  564      protected void destroyMarshalledInvocationMapping()
  565      {
  566         MarshalledInvocation.removeHashes(homeInterface);
  567         MarshalledInvocation.removeHashes(remoteInterface);
  568      }
  569   
  570      protected void destroyInterceptors()
  571      {
  572         // Destroy all the interceptors in the chain
  573         Interceptor in = interceptor;
  574         while (in != null)
  575         {
  576            in.destroy();
  577            in.setContainer(null);
  578            in = in.getNext();
  579         }
  580      }
  581   
  582      protected void destroyPersistenceManager()
  583      {
  584      }
  585   
  586      protected void destroyInstancePool()
  587      {
  588         // Destroy pool
  589         instancePool.destroy();
  590         instancePool.setContainer(null);
  591         try
  592         {
  593            ObjectName containerName = super.getJmxName();
  594            Hashtable props = containerName.getKeyPropertyList();
  595            props.put("plugin", "pool");
  596            ObjectName poolName = new ObjectName(containerName.getDomain(), props);
  597            server.unregisterMBean(poolName);
  598         }
  599         catch (Throwable ignore)
  600         {
  601         }
  602      }
  603   
  604      protected void destroyInstanceCache()
  605      {
  606      }
  607   
  608      protected void destroyInvokers()
  609      {
  610         // Destroy container invoker
  611         for (Iterator it = proxyFactories.keySet().iterator(); it.hasNext();)
  612         {
  613            String invokerBinding = (String) it.next();
  614            EJBProxyFactory ci = (EJBProxyFactory) proxyFactories.get(invokerBinding);
  615            ci.destroy();
  616            ci.setContainer(null);
  617         }
  618      }
  619   
  620      public Object internalInvokeHome(Invocation mi) throws Exception
  621      {
  622         Method method = mi.getMethod();
  623         if (method != null && method.getName().equals("remove"))
  624         {
  625            // Handle or primary key?
  626            Object arg = mi.getArguments()[0];
  627            if (arg instanceof Handle)
  628            {
  629               if (arg == null)
  630                  throw new RemoteException("Null handle");
  631               Handle handle = (Handle) arg;
  632               EJBObject ejbObject = handle.getEJBObject();
  633               ejbObject.remove();
  634               return null;
  635            }
  636            else
  637               throw new RemoveException("EJBHome.remove(Object) not allowed for session beans");
  638         } 
  639         // Invoke through interceptors
  640         return getInterceptor().invokeHome(mi);
  641      }
  642   
  643      /**
  644       * This method does invocation interpositioning of tx and security,
  645       * retrieves the instance from an object table, and invokes the method
  646       * on the particular instance
  647       */
  648      public Object internalInvoke(Invocation mi) throws Exception
  649      { 
  650         // Invoke through interceptors
  651         return getInterceptor().invoke(mi);
  652      }
  653   
  654      // EJBObject implementation --------------------------------------
  655   
  656      /**
  657       * While the following methods are implemented in the client in the case
  658       * of JRMP we would need to implement them to fully support other transport
  659       * protocols
  660       *
  661       * @return  Always null
  662       */
  663      public Handle getHandle(Invocation mi) throws RemoteException
  664      {
  665         
  666         // TODO
  667         return null;
  668      }
  669   
  670      public Object getPrimaryKey(Invocation mi) throws RemoteException
  671      {
  672         return getPrimaryKey();
  673      }
  674   
  675      public Object getPrimaryKey() throws RemoteException
  676      {
  677         throw new RemoteException("Call to getPrimaryKey not allowed on session bean");
  678      }
  679      
  680      public EJBHome getEJBHome(Invocation mi) throws RemoteException
  681      {
  682         EJBProxyFactory ci = getProxyFactory();
  683         if (ci == null)
  684         {
  685            String msg = "No ProxyFactory, check for ProxyFactoryFinderInterceptor";
  686            throw new IllegalStateException(msg);
  687         }
  688   
  689         return (EJBHome) ci.getEJBHome();
  690      }
  691   
  692      /**
  693       * @return   Always false
  694       */
  695      public boolean isIdentical(Invocation mi) throws RemoteException
  696      {
  697         EJBProxyFactory ci = getProxyFactory();
  698         if (ci == null)
  699         {
  700            String msg = "No ProxyFactory, check for ProxyFactoryFinderInterceptor";
  701            throw new IllegalStateException(msg);
  702         }
  703   
  704         return ci.isIdentical(this, mi);
  705      }
  706   
  707      public EJBMetaData getEJBMetaDataHome(Invocation mi) throws RemoteException
  708      {
  709         return getEJBMetaDataHome();
  710      }
  711      
  712      public EJBMetaData getEJBMetaDataHome() throws RemoteException
  713      {
  714         EJBProxyFactory ci = getProxyFactory();
  715         if (ci == null)
  716         {
  717            String msg = "No ProxyFactory, check for ProxyFactoryFinderInterceptor";
  718            throw new IllegalStateException(msg);
  719         }
  720   
  721         return ci.getEJBMetaData();
  722      }
  723      
  724      public HomeHandle getHomeHandleHome(Invocation mi) throws RemoteException
  725      {
  726         return getHomeHandleHome();
  727      }
  728      
  729      public HomeHandle getHomeHandleHome() throws RemoteException
  730      {
  731         EJBProxyFactory ci = getProxyFactory();
  732         if (ci == null)
  733         {
  734            String msg = "No ProxyFactory, check for ProxyFactoryFinderInterceptor";
  735            throw new IllegalStateException(msg);
  736         }
  737   
  738         EJBHome home = (EJBHome) ci.getEJBHome();
  739         return home.getHomeHandle();
  740      }
  741   
  742      // Home interface implementation ---------------------------------
  743   
  744      // local object interface implementation
  745   
  746      public EJBLocalHome getEJBLocalHome(Invocation mi)
  747      {
  748         return localProxyFactory.getEJBLocalHome();
  749      }
  750   
  751      /**
  752       * needed for sub-inner-class access (old jdk compiler bug)
  753       * @return
  754       */
  755      protected Map getHomeMapping()
  756      {
  757         return homeMapping;
  758      }
  759   
  760      /**
  761       * needed for sub-inner-class access (old jdk compiler bug)
  762       * @return
  763       */
  764      protected Map getBeanMapping()
  765      {
  766         return beanMapping;
  767      }
  768   
  769   }

Save This Page
Home » jboss-5.0.0.CR1-src » org » jboss » ejb » [javadoc | source]