Save This Page
Home » jboss-5.0.0.CR1-src » org » jboss » ejb » plugins » local » [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.plugins.local;
   23   
   24   import java.lang.reflect.InvocationHandler;
   25   import java.lang.reflect.Method;
   26   import java.lang.reflect.Proxy;
   27   import java.lang.reflect.Constructor;
   28   import java.rmi.AccessException;
   29   import java.rmi.NoSuchObjectException;
   30   import java.security.Principal;
   31   import java.security.PrivilegedAction;
   32   import java.security.AccessController;
   33   import java.util.ArrayList;
   34   import java.util.Collection;
   35   import java.util.Collections;
   36   import java.util.HashMap;
   37   import java.util.Iterator;
   38   import java.util.Map;
   39   import javax.ejb.AccessLocalException;
   40   import javax.ejb.EJBLocalHome;
   41   import javax.ejb.EJBLocalObject;
   42   import javax.ejb.NoSuchObjectLocalException;
   43   import javax.ejb.TransactionRequiredLocalException;
   44   import javax.ejb.TransactionRolledbackLocalException;
   45   import javax.naming.Context;
   46   import javax.naming.InitialContext; 
   47   import javax.transaction.Transaction;
   48   import javax.transaction.TransactionManager;
   49   import javax.transaction.TransactionRequiredException;
   50   import javax.transaction.TransactionRolledbackException;
   51   
   52   import org.jboss.ejb.Container;
   53   import org.jboss.ejb.EJBProxyFactoryContainer;
   54   import org.jboss.ejb.LocalProxyFactory; 
   55   import org.jboss.invocation.InvocationType;
   56   import org.jboss.invocation.MarshalledInvocation;
   57   import org.jboss.invocation.LocalEJBInvocation;
   58   import org.jboss.logging.Logger;
   59   import org.jboss.metadata.BeanMetaData;
   60   import org.jboss.naming.Util;   
   61   import org.jboss.security.SecurityContext;  
   62   import org.jboss.security.SecurityContextAssociation; 
   63   import org.jboss.util.NestedRuntimeException;
   64   import org.jboss.tm.TransactionLocal; 
   65   
   66   /**
   67    * The LocalProxyFactory implementation that handles local ejb interface
   68    * proxies.
   69    *
   70    * @author <a href="mailto:docodan@mvcsoft.com">Daniel OConnor</a>
   71    * @author <a href="mailto:scott.stark@jboss.org">Scott Stark</a>
   72    * @author <a href="mailto:dain@daingroup.com">Dain Sundstrom</a>
   73    * @author <a href="mailto:alex@jboss.org">Alexey Loubyansky</a>
   74    * @author Anil.Saldhana@redhat.com
   75    * $Revision: 72053 $
   76    */
   77   public class BaseLocalProxyFactory implements LocalProxyFactory
   78   {
   79      // Attributes ----------------------------------------------------
   80      protected static Logger log = Logger.getLogger(BaseLocalProxyFactory.class);
   81   
   82      /**
   83       * A map of the BaseLocalProxyFactory instances keyed by localJndiName
   84       */
   85      protected static Map invokerMap = Collections.synchronizedMap(new HashMap());
   86   
   87      protected Container container;
   88   
   89      /**
   90       * The JNDI name of the local home interface binding
   91       */
   92      protected String localJndiName;
   93   
   94      protected TransactionManager transactionManager;
   95   
   96      // The home can be one.
   97      protected EJBLocalHome home;
   98   
   99      // The Stateless Object can be one.
  100      protected EJBLocalObject statelessObject;
  101   
  102      protected Map beanMethodInvokerMap;
  103      protected Map homeMethodInvokerMap;
  104      protected Class localHomeClass;
  105      protected Class localClass;
  106   
  107      protected Constructor proxyClassConstructor;
  108   
  109      private final TransactionLocal cache = new TransactionLocal()
  110      {
  111         protected Object initialValue()
  112         {
  113            return new HashMap();
  114         }
  115      };
  116   
  117      // Static --------------------------------------------------------
  118   
  119      // Constructors --------------------------------------------------
  120   
  121      // Public --------------------------------------------------------
  122   
  123      // ContainerService implementation -------------------------------
  124   
  125      public void setContainer(Container con)
  126      {
  127         this.container = con;
  128      }
  129   
  130      public void create() throws Exception
  131      {
  132         BeanMetaData metaData = container.getBeanMetaData();
  133         localJndiName = metaData.getLocalJndiName();
  134      }
  135   
  136      public void start()
  137         throws Exception
  138      {
  139         BeanMetaData metaData = container.getBeanMetaData();
  140         EJBProxyFactoryContainer invokerContainer =
  141            (EJBProxyFactoryContainer) container;
  142         localHomeClass = invokerContainer.getLocalHomeClass();
  143         localClass = invokerContainer.getLocalClass();
  144         if(localHomeClass == null || localClass == null)
  145         {
  146            log.debug(metaData.getEjbName()
  147               +
  148               " cannot be Bound, doesn't " +
  149               "have local and local home interfaces");
  150            return;
  151         }
  152   
  153         // this is faster than newProxyInstance
  154         Class[] intfs = {localClass};
  155         Class proxyClass = Proxy.getProxyClass(ClassLoaderAction.UTIL.get(localClass), intfs);
  156         final Class[] constructorParams =
  157            {InvocationHandler.class};
  158   
  159         proxyClassConstructor = proxyClass.getConstructor(constructorParams);
  160   
  161         Context iniCtx = new InitialContext();
  162         String beanName = metaData.getEjbName();
  163   
  164         // Set the transaction manager and transaction propagation
  165         // context factory of the GenericProxy class
  166         transactionManager =
  167            (TransactionManager) iniCtx.lookup("java:/TransactionManager");
  168   
  169         // Create method mappings for container invoker
  170         Method[] methods = localClass.getMethods();
  171         beanMethodInvokerMap = new HashMap();
  172         for(int i = 0; i < methods.length; i++)
  173         {
  174            long hash = MarshalledInvocation.calculateHash(methods[i]);
  175            beanMethodInvokerMap.put(new Long(hash), methods[i]);
  176         }
  177   
  178         methods = localHomeClass.getMethods();
  179         homeMethodInvokerMap = new HashMap();
  180         for(int i = 0; i < methods.length; i++)
  181         {
  182            long hash = MarshalledInvocation.calculateHash(methods[i]);
  183            homeMethodInvokerMap.put(new Long(hash), methods[i]);
  184         }
  185   
  186         // bind that referance to my name
  187         Util.rebind(iniCtx, localJndiName, getEJBLocalHome());
  188         invokerMap.put(localJndiName, this);
  189         log.info("Bound EJB LocalHome '" + beanName + "' to jndi '" + localJndiName + "'");
  190      }
  191   
  192      public void stop()
  193      {
  194         // Clean up the home proxy binding
  195         try
  196         {
  197            if(invokerMap.remove(localJndiName) == this)
  198            {
  199               log.info("Unbind EJB LocalHome '" + container.getBeanMetaData().getEjbName() + "' from jndi '" + localJndiName + "'");
  200   
  201               InitialContext ctx = new InitialContext();
  202               ctx.unbind(localJndiName);
  203            }
  204         }
  205         catch(Exception ignore)
  206         {
  207         }
  208      }
  209   
  210      public void destroy()
  211      {
  212         if(beanMethodInvokerMap != null)
  213         {
  214            beanMethodInvokerMap.clear();
  215         }
  216         if(homeMethodInvokerMap != null)
  217         {
  218            homeMethodInvokerMap.clear();
  219         }
  220         MarshalledInvocation.removeHashes(localHomeClass);
  221         MarshalledInvocation.removeHashes(localClass);
  222   
  223         container = null;
  224      }
  225   
  226      public Constructor getProxyClassConstructor()
  227      {
  228         if(proxyClassConstructor == null)
  229         {
  230         }
  231         return proxyClassConstructor;
  232      }
  233   
  234      // EJBProxyFactory implementation -------------------------------
  235      public EJBLocalHome getEJBLocalHome()
  236      {
  237         if(home == null)
  238         {
  239            EJBProxyFactoryContainer cic = (EJBProxyFactoryContainer) container;
  240            InvocationHandler handler = new LocalHomeProxy(localJndiName, this);
  241            ClassLoader loader = ClassLoaderAction.UTIL.get(cic.getLocalHomeClass());
  242            Class[] interfaces = {cic.getLocalHomeClass()};
  243   
  244            home = (EJBLocalHome) Proxy.newProxyInstance(loader,
  245               interfaces,
  246               handler);
  247         }
  248         return home;
  249      }
  250   
  251      public EJBLocalObject getStatelessSessionEJBLocalObject()
  252      {
  253         if(statelessObject == null)
  254         {
  255            EJBProxyFactoryContainer cic = (EJBProxyFactoryContainer) container;
  256            InvocationHandler handler =
  257               new StatelessSessionProxy(localJndiName, this);
  258            ClassLoader loader = ClassLoaderAction.UTIL.get(cic.getLocalClass());
  259            Class[] interfaces = {cic.getLocalClass()};
  260   
  261            statelessObject = (EJBLocalObject) Proxy.newProxyInstance(loader,
  262               interfaces,
  263               handler);
  264         }
  265         return statelessObject;
  266      }
  267   
  268      public EJBLocalObject getStatefulSessionEJBLocalObject(Object id)
  269      {
  270         InvocationHandler handler =
  271            new StatefulSessionProxy(localJndiName, id, this);
  272         try
  273         {
  274            return (EJBLocalObject) proxyClassConstructor.newInstance(new Object[]{handler});
  275         }
  276         catch(Exception ex)
  277         {
  278            throw new NestedRuntimeException(ex);
  279         }
  280      }
  281   
  282      public Object getEntityEJBObject(Object id)
  283      {
  284         return getEntityEJBLocalObject(id);
  285      }
  286   
  287      public EJBLocalObject getEntityEJBLocalObject(Object id, boolean create)
  288      {
  289         EJBLocalObject result = null;
  290         if(id != null)
  291         {
  292            final Transaction tx = cache.getTransaction();
  293            if(tx == null)
  294            {
  295               result = createEJBLocalObject(id);
  296            }
  297            else
  298            {
  299               Map map = (Map) cache.get(tx);
  300               if(create)
  301               {
  302                  result = createEJBLocalObject(id);
  303                  map.put(id, result);
  304               }
  305               else
  306               {
  307                  result = (EJBLocalObject) map.get(id);
  308                  if(result == null)
  309                  {
  310                     result = createEJBLocalObject(id);
  311                     map.put(id, result);
  312                  }
  313               }
  314            }
  315         }
  316         return result;
  317      }
  318   
  319      public EJBLocalObject getEntityEJBLocalObject(Object id)
  320      {
  321         return getEntityEJBLocalObject(id, false);
  322      }
  323   
  324      public Collection getEntityLocalCollection(Collection ids)
  325      {
  326         ArrayList list = new ArrayList(ids.size());
  327         Iterator iter = ids.iterator();
  328         while(iter.hasNext())
  329         {
  330            final Object nextId = iter.next();
  331            list.add(getEntityEJBLocalObject(nextId));
  332         }
  333         return list;
  334      }
  335   
  336      /**
  337       * Invoke a Home interface method.
  338       */
  339      public Object invokeHome(Method m, Object[] args) throws Exception
  340      {
  341         // Set the right context classloader
  342         ClassLoader oldCl = TCLAction.UTIL.getContextClassLoader();
  343         boolean setCl = !oldCl.equals(container.getClassLoader());
  344         if(setCl)
  345         {
  346            TCLAction.UTIL.setContextClassLoader(container.getClassLoader());
  347         }
  348         container.pushENC();
  349   
  350         SecurityActions sa = SecurityActions.UTIL.getSecurityActions();   
  351         
  352         try
  353         {
  354            LocalEJBInvocation invocation = new LocalEJBInvocation(null,
  355               m,
  356               args,
  357               getTransaction(),
  358               sa.getPrincipal(),
  359               sa.getCredential());
  360            invocation.setType(InvocationType.LOCALHOME);  
  361    
  362            return container.invoke(invocation);
  363         }
  364         catch(AccessException ae)
  365         {
  366            throw new AccessLocalException(ae.getMessage(), ae);
  367         }
  368         catch(NoSuchObjectException nsoe)
  369         {
  370            throw new NoSuchObjectLocalException(nsoe.getMessage(), nsoe);
  371         }
  372         catch(TransactionRequiredException tre)
  373         {
  374            throw new TransactionRequiredLocalException(tre.getMessage());
  375         }
  376         catch(TransactionRolledbackException trbe)
  377         {
  378            throw new TransactionRolledbackLocalException(trbe.getMessage(), trbe);
  379         }
  380         finally
  381         {
  382            container.popENC();
  383            if(setCl)
  384            {
  385               TCLAction.UTIL.setContextClassLoader(oldCl);
  386            }  
  387         }
  388      }
  389   
  390      public String getJndiName()
  391      {
  392         return localJndiName;
  393      }
  394   
  395      /**
  396       * Return the transaction associated with the current thread.
  397       * Returns <code>null</code> if the transaction manager was never
  398       * set, or if no transaction is associated with the current thread.
  399       */
  400      Transaction getTransaction() throws javax.transaction.SystemException
  401      {
  402         if(transactionManager == null)
  403         {
  404            return null;
  405         }
  406         return transactionManager.getTransaction();
  407      }
  408   
  409      /**
  410       * Invoke a local interface method.
  411       */
  412      public Object invoke(Object id, Method m, Object[] args)
  413         throws Exception
  414      {
  415         // Set the right context classloader
  416         ClassLoader oldCl = TCLAction.UTIL.getContextClassLoader();
  417         boolean setCl = !oldCl.equals(container.getClassLoader());
  418         if(setCl)
  419         {
  420            TCLAction.UTIL.setContextClassLoader(container.getClassLoader());
  421         }
  422         container.pushENC();
  423   
  424         SecurityActions sa = SecurityActions.UTIL.getSecurityActions();  
  425         try
  426         {
  427            LocalEJBInvocation invocation = new LocalEJBInvocation(id,
  428               m,
  429               args,
  430               getTransaction(),
  431               sa.getPrincipal(),
  432               sa.getCredential());
  433            invocation.setType(InvocationType.LOCAL);  
  434            
  435            return container.invoke(invocation);
  436         }
  437         catch(AccessException ae)
  438         {
  439            throw new AccessLocalException(ae.getMessage(), ae);
  440         }
  441         catch(NoSuchObjectException nsoe)
  442         {
  443            throw new NoSuchObjectLocalException(nsoe.getMessage(), nsoe);
  444         }
  445         catch(TransactionRequiredException tre)
  446         {
  447            throw new TransactionRequiredLocalException(tre.getMessage());
  448         }
  449         catch(TransactionRolledbackException trbe)
  450         {
  451            throw new TransactionRolledbackLocalException(trbe.getMessage(), trbe);
  452         }
  453         finally
  454         {
  455            container.popENC();
  456            if(setCl)
  457            {
  458               TCLAction.UTIL.setContextClassLoader(oldCl);
  459            }  
  460         }
  461      }
  462   
  463      private EJBLocalObject createEJBLocalObject(Object id)
  464      {
  465         InvocationHandler handler = new EntityProxy(localJndiName, id, this);
  466         try
  467         {
  468            return (EJBLocalObject) proxyClassConstructor.newInstance(new Object[]{handler});
  469         }
  470         catch(Exception ex)
  471         {
  472            throw new NestedRuntimeException(ex);
  473         }
  474      }
  475       
  476   
  477      interface ClassLoaderAction
  478      {
  479         class UTIL
  480         {
  481            static ClassLoaderAction getClassLoaderAction()
  482            {
  483               return System.getSecurityManager() == null ? NON_PRIVILEGED : PRIVILEGED;
  484            }
  485   
  486            static ClassLoader get(Class clazz)
  487            {
  488               return getClassLoaderAction().get(clazz);
  489            }
  490         }
  491   
  492         ClassLoaderAction PRIVILEGED = new ClassLoaderAction()
  493         {
  494            public ClassLoader get(final Class clazz)
  495            {
  496               return (ClassLoader)AccessController.doPrivileged(
  497                  new PrivilegedAction()
  498                  {
  499                     public Object run()
  500                     {
  501                        return clazz.getClassLoader();
  502                     }
  503                  }
  504               );
  505            }
  506         };
  507   
  508         ClassLoaderAction NON_PRIVILEGED = new ClassLoaderAction()
  509         {
  510            public ClassLoader get(Class clazz)
  511            {
  512               return clazz.getClassLoader();
  513            }
  514         };
  515   
  516         ClassLoader get(Class clazz);
  517      }
  518   
  519      interface SecurityActions
  520      {
  521         class UTIL
  522         {
  523            static SecurityActions getSecurityActions()
  524            {
  525               return System.getSecurityManager() == null ? NON_PRIVILEGED : PRIVILEGED;
  526            }
  527         }
  528   
  529         SecurityActions NON_PRIVILEGED = new SecurityActions()
  530         {
  531            public Principal getPrincipal()
  532            {
  533               SecurityContext sc = getSecurityContext();
  534               if(sc == null)
  535                  return null;
  536               return sc.getUtil().getUserPrincipal();
  537            }
  538   
  539            public Object getCredential()
  540            {
  541               SecurityContext sc = getSecurityContext();
  542               if(sc == null)
  543                  return null;
  544               return sc.getUtil().getCredential();
  545            }
  546            
  547            public SecurityContext getSecurityContext()
  548            {
  549               return SecurityContextAssociation.getSecurityContext(); 
  550            }
  551             
  552         };
  553   
  554         SecurityActions PRIVILEGED = new SecurityActions()
  555         {
  556            private final PrivilegedAction getPrincipalAction = new PrivilegedAction()
  557            {
  558               public Object run()
  559               {
  560                  SecurityContext sc = getSecurityContext();
  561                  if(sc == null)
  562                     return null;
  563                  return sc.getUtil().getUserPrincipal();
  564               }
  565            };
  566   
  567            private final PrivilegedAction getCredentialAction = new PrivilegedAction()
  568            {
  569               public Object run()
  570               {
  571                  SecurityContext sc = getSecurityContext();
  572                  if(sc == null)
  573                     return null;
  574                  return sc.getUtil().getCredential();
  575               }
  576            };
  577   
  578            public Principal getPrincipal()
  579            {
  580               return (Principal)AccessController.doPrivileged(getPrincipalAction);
  581            }
  582   
  583            public Object getCredential()
  584            {
  585               return AccessController.doPrivileged(getCredentialAction);
  586            }
  587            
  588            public SecurityContext getSecurityContext()
  589            {
  590               return (SecurityContext)AccessController.doPrivileged(
  591                     new PrivilegedAction(){
  592   
  593                        public Object run()
  594                        { 
  595                           return SecurityContextAssociation.getSecurityContext();
  596                        }});
  597            } 
  598         };
  599   
  600         Principal getPrincipal();
  601   
  602         Object getCredential();
  603         SecurityContext getSecurityContext();  
  604      }
  605   
  606      interface TCLAction
  607      {
  608         class UTIL
  609         {
  610            static TCLAction getTCLAction()
  611            {
  612               return System.getSecurityManager() == null ? NON_PRIVILEGED : PRIVILEGED;
  613            }
  614   
  615            static ClassLoader getContextClassLoader()
  616            {
  617               return getTCLAction().getContextClassLoader();
  618            }
  619   
  620            static ClassLoader getContextClassLoader(Thread thread)
  621            {
  622               return getTCLAction().getContextClassLoader(thread);
  623            }
  624   
  625            static void setContextClassLoader(ClassLoader cl)
  626            {
  627               getTCLAction().setContextClassLoader(cl);
  628            }
  629   
  630            static void setContextClassLoader(Thread thread, ClassLoader cl)
  631            {
  632               getTCLAction().setContextClassLoader(thread, cl);
  633            }
  634         }
  635   
  636         TCLAction NON_PRIVILEGED = new TCLAction()
  637         {
  638            public ClassLoader getContextClassLoader()
  639            {
  640               return Thread.currentThread().getContextClassLoader();
  641            }
  642   
  643            public ClassLoader getContextClassLoader(Thread thread)
  644            {
  645               return thread.getContextClassLoader();
  646            }
  647   
  648            public void setContextClassLoader(ClassLoader cl)
  649            {
  650               Thread.currentThread().setContextClassLoader(cl);
  651            }
  652   
  653            public void setContextClassLoader(Thread thread, ClassLoader cl)
  654            {
  655               thread.setContextClassLoader(cl);
  656            }
  657         };
  658   
  659         TCLAction PRIVILEGED = new TCLAction()
  660         {
  661            private final PrivilegedAction getTCLPrivilegedAction = new PrivilegedAction()
  662            {
  663               public Object run()
  664               {
  665                  return Thread.currentThread().getContextClassLoader();
  666               }
  667            };
  668   
  669            public ClassLoader getContextClassLoader()
  670            {
  671               return (ClassLoader)AccessController.doPrivileged(getTCLPrivilegedAction);
  672            }
  673   
  674            public ClassLoader getContextClassLoader(final Thread thread)
  675            {
  676               return (ClassLoader)AccessController.doPrivileged(new PrivilegedAction()
  677               {
  678                  public Object run()
  679                  {
  680                     return thread.getContextClassLoader();
  681                  }
  682               });
  683            }
  684   
  685            public void setContextClassLoader(final ClassLoader cl)
  686            {
  687               AccessController.doPrivileged(
  688                  new PrivilegedAction()
  689                  {
  690                     public Object run()
  691                     {
  692                        Thread.currentThread().setContextClassLoader(cl);
  693                        return null;
  694                     }
  695                  }
  696               );
  697            }
  698   
  699            public void setContextClassLoader(final Thread thread, final ClassLoader cl)
  700            {
  701               AccessController.doPrivileged(
  702                  new PrivilegedAction()
  703                  {
  704                     public Object run()
  705                     {
  706                        thread.setContextClassLoader(cl);
  707                        return null;
  708                     }
  709                  }
  710               );
  711            }
  712         };
  713   
  714         ClassLoader getContextClassLoader();
  715   
  716         ClassLoader getContextClassLoader(Thread thread);
  717   
  718         void setContextClassLoader(ClassLoader cl);
  719   
  720         void setContextClassLoader(Thread thread, ClassLoader cl);
  721      }
  722   }

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