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   import java.lang.reflect.Method;
   25   import java.net.URL;
   26   import java.security.Policy;
   27   import java.util.ArrayList;
   28   import java.util.Collection;
   29   import java.util.Collections;
   30   import java.util.HashMap;
   31   import java.util.HashSet;
   32   import java.util.Iterator;
   33   import java.util.LinkedList;
   34   import java.util.ListIterator;
   35   import java.util.Map;
   36   
   37   import javax.ejb.EJBLocalHome;
   38   import javax.management.MalformedObjectNameException;
   39   import javax.management.ObjectName;
   40   import javax.naming.InitialContext;
   41   import javax.naming.NamingException;
   42   import javax.security.jacc.EJBMethodPermission;
   43   import javax.security.jacc.PolicyConfiguration;
   44   import javax.security.jacc.PolicyConfigurationFactory;
   45   import javax.security.jacc.PolicyContextException;
   46   import javax.transaction.TransactionManager;
   47   
   48   import org.jboss.classloading.spi.RealClassLoader;
   49   import org.jboss.deployers.structure.spi.DeploymentUnit;
   50   import org.jboss.deployers.vfs.spi.structure.VFSDeploymentUnit;
   51   import org.jboss.deployment.DeploymentException;
   52   import org.jboss.deployment.DeploymentInfo;
   53   import org.jboss.ejb.plugins.SecurityProxyInterceptor;
   54   import org.jboss.ejb.plugins.StatefulSessionInstancePool;
   55   import org.jboss.ejb.txtimer.EJBTimerService;
   56   import org.jboss.invocation.InvocationType;
   57   import org.jboss.logging.Logger;
   58   import org.jboss.metadata.ApplicationMetaData;
   59   import org.jboss.metadata.BeanMetaData;
   60   import org.jboss.metadata.ConfigurationMetaData;
   61   import org.jboss.metadata.EntityMetaData;
   62   import org.jboss.metadata.InvokerProxyBindingMetaData;
   63   import org.jboss.metadata.MetaData;
   64   import org.jboss.metadata.SessionMetaData;
   65   import org.jboss.metadata.XmlLoadable;
   66   import org.jboss.mx.util.MBeanProxyExt;
   67   import org.jboss.mx.util.ObjectNameFactory;
   68   import org.jboss.security.AuthenticationManager;
   69   import org.jboss.security.ISecurityManagement;
   70   import org.jboss.security.RealmMapping;
   71   import org.jboss.security.SecurityConstants;
   72   import org.jboss.security.SecurityUtil;
   73   import org.jboss.security.authorization.PolicyRegistration;
   74   import org.jboss.security.plugins.SecurityDomainContext;
   75   import org.jboss.system.Registry;
   76   import org.jboss.system.ServiceControllerMBean;
   77   import org.jboss.system.ServiceMBeanSupport;
   78   import org.jboss.tm.TransactionManagerFactory;
   79   import org.jboss.util.loading.DelegatingClassLoader;
   80   import org.jboss.virtual.VirtualFile;
   81   import org.jboss.web.WebClassLoader;
   82   import org.jboss.web.WebClassLoaderFactory;
   83   import org.jboss.web.WebServiceMBean;
   84   import org.w3c.dom.Element;
   85   
   86   /**
   87    * An EjbModule represents a collection of beans that are deployed as a
   88    * unit.
   89    *
   90    * <p>The beans may use the EjbModule to access other beans within the same
   91    *    deployment unit.
   92    *
   93    * @see Container
   94    * @see EJBDeployer
   95    *
   96    * @author <a href="mailto:rickard.oberg@telkel.com">Rickard Oberg</a>
   97    * @author <a href="mailto:d_jencks@users.sourceforge.net">David Jencks</a>
   98    * @author <a href="mailto:reverbel@ime.usp.br">Francisco Reverbel</a>
   99    * @author <a href="mailto:Adrian.Brock@HappeningTimes.com">Adrian.Brock</a>
  100    * @author <a href="mailto:Scott.Stark@jboss.org">Scott Stark</a>
  101    * @author <a href="mailto:Anil.Saldhana@jboss.org">Anil Saldhana</a>
  102    * @version $Revision: 73334 $
  103    */
  104   @SuppressWarnings("deprecation")
  105   public class EjbModule
  106      extends ServiceMBeanSupport
  107      implements EjbModuleMBean
  108   {
  109      public static final String BASE_EJB_MODULE_NAME = "jboss.j2ee:service=EjbModule";
  110   
  111      public static final ObjectName EJB_MODULE_QUERY_NAME = ObjectNameFactory.create(BASE_EJB_MODULE_NAME + ",*");
  112   
  113      public static String DEFAULT_STATELESS_CONFIGURATION = "Default Stateless SessionBean";
  114      public static String DEFAULT_STATEFUL_CONFIGURATION = "Default Stateful SessionBean";
  115      public static String DEFAULT_ENTITY_BMP_CONFIGURATION = "Default BMP EntityBean";
  116      public static String DEFAULT_ENTITY_CMP_CONFIGURATION = "Default CMP EntityBean";
  117      public static String DEFAULT_MESSAGEDRIVEN_CONFIGURATION = "Default MesageDriven Bean";
  118   
  119      // Constants uses with container interceptor configurations
  120      public static final int BMT = 1;
  121      public static final int CMT = 2;
  122      public static final int ANY = 3;
  123   
  124      static final String BMT_VALUE = "Bean";
  125      static final String CMT_VALUE = "Container";
  126      static final String ANY_VALUE = "Both";
  127    
  128      /** The security management */
  129      private ISecurityManagement securityManagement;
  130   
  131      /** Class logger. */
  132      private static final Logger log = Logger.getLogger(EjbModule.class);
  133   
  134      // Constants -----------------------------------------------------
  135   
  136      // Attributes ----------------------------------------------------
  137   
  138      /** HashMap<ejbName, Container> the containers for this deployment unit. */
  139      HashMap containers = new HashMap();
  140      /** The containers in their ApplicationMetaData ordering */
  141      LinkedList containerOrdering = new LinkedList();
  142      /** HashMap<ejbName, EJBLocalHome> of local homes */
  143      HashMap localHomes = new HashMap();
  144   
  145      /** Class loader of this deployment unit. */
  146      ClassLoader classLoader = null;
  147   
  148      /** Name of this deployment unit, url it was deployed from */
  149      final String name;
  150   
  151      private VFSDeploymentUnit deploymentUnit;
  152   
  153      private ServiceControllerMBean serviceController;
  154   
  155      private final Map moduleData =
  156         Collections.synchronizedMap(new HashMap());
  157   
  158      private ObjectName webServiceName;
  159   
  160      private TransactionManagerFactory tmFactory;
  161      private EJBTimerService timerService;
  162   
  163      /** Whether we are call by value */
  164      private boolean callByValue;
  165      private ApplicationMetaData appMetaData;
  166   
  167      /**
  168       * Policy Registration Bean (Holder of Authorization Policies)
  169       */
  170      private PolicyRegistration policyRegistration = null; 
  171   
  172      public EjbModule(final VFSDeploymentUnit unit, ApplicationMetaData metaData)
  173      {
  174         this.appMetaData = metaData;
  175         this.deploymentUnit = unit;
  176         String name = deploymentUnit.getName();
  177         if (name.endsWith("/"))
  178         {
  179            name = name.substring(0, name.length() - 1);
  180         }
  181         this.name = name;
  182   
  183         // FIXME all this deployment unit access should be replaced with deployers processing updating the metadata
  184         //Ask the ejb deployer whether we are call by value
  185         Boolean flag = unit.getAttachment("EJB.callByValue", Boolean.class);
  186         DeploymentUnit temp = unit;
  187         while (flag == null && temp != null)
  188         {
  189            //Ask the ear deployer whether we are call by value
  190            flag = temp.getAttachment("EAR.callByValue", Boolean.class);
  191            if (flag != null)
  192               break;
  193            temp = temp.getParent();
  194         }
  195         if (flag != null )
  196               callByValue = flag.booleanValue();
  197   
  198         //Set the unauthenticated identity on the metadata if absent
  199         if(metaData.getUnauthenticatedPrincipal() == null)
  200         {
  201            String unauthenticatedPrincipal = unit.getAttachment("EJB.unauthenticatedIdentity", String.class);
  202            if(unauthenticatedPrincipal == null)
  203               unauthenticatedPrincipal = unit.getAttachment("EAR.unauthenticatedIdentity", String.class);
  204            metaData.getJBossMetaData().setUnauthenticatedPrincipal(unauthenticatedPrincipal);
  205         }
  206         // Add the ApplicationMetaData for the jbossws ejb21 deployer to pickup later
  207         if (unit.getAttachment(ApplicationMetaData.class) == null)
  208            unit.addAttachment(ApplicationMetaData.class, metaData);
  209      }
  210      
  211      /**
  212       * @deprecated DeploymentInfo is obsolete
  213       */
  214      public EjbModule(final DeploymentInfo di, TransactionManager tm,
  215            ObjectName webServiceName)
  216      {
  217         this.name = "deprecated";
  218      }
  219   
  220      public void setTransactionManagerFactory(TransactionManagerFactory tm)
  221      {
  222         this.tmFactory = tm;
  223      }
  224   
  225      public void setSecurityManagement(ISecurityManagement sm)
  226      {
  227         this.securityManagement = sm;
  228      }
  229      
  230      public void setPolicyRegistration(PolicyRegistration policyRegistration)
  231      {
  232         this.policyRegistration = policyRegistration;
  233      }
  234   
  235      public EJBTimerService getTimerService()
  236      {
  237         return timerService;
  238      }
  239   
  240      public void setTimerService(EJBTimerService timerService)
  241      {
  242         this.timerService = timerService;
  243      }
  244   
  245      public ObjectName getWebServiceName()
  246      {
  247         return webServiceName;
  248      }
  249      public void setWebServiceName(ObjectName webServiceName)
  250      {
  251         this.webServiceName = webServiceName;
  252      }
  253   
  254      public Map getModuleDataMap()
  255      {
  256         return moduleData;
  257      }
  258   
  259      public Object getModuleData(Object key)
  260      {
  261         return moduleData.get(key);
  262      }
  263   
  264      public void putModuleData(Object key, Object value)
  265      {
  266         moduleData.put(key, value);
  267      }
  268   
  269      public void removeModuleData(Object key)
  270      {
  271         moduleData.remove(key);
  272      }
  273   
  274      /**
  275       * Add a container to this deployment unit.
  276       *
  277       * @param   con
  278       */
  279      private void addContainer(Container con)
  280         throws DeploymentException
  281      {
  282         String ejbName = con.getBeanMetaData().getEjbName();
  283         if (containers.containsKey(ejbName))
  284            throw new DeploymentException("Duplicate ejb-name. Container for "
  285               + ejbName + " already exists.");
  286         containers.put(ejbName, con);
  287         containerOrdering.add(con);
  288         con.setEjbModule(this);
  289      }
  290   
  291      /**
  292       * Remove a container from this deployment unit.
  293       *
  294       * @param   con
  295       */
  296      public void removeContainer(Container con)
  297      {
  298         containers.remove(con.getBeanMetaData().getEjbName());
  299         containerOrdering.remove(con);
  300      }
  301   
  302      public void addLocalHome(Container con, EJBLocalHome localHome)
  303      {
  304         localHomes.put(con.getBeanMetaData().getEjbName(), localHome);
  305      }
  306   
  307      public void removeLocalHome(Container con)
  308      {
  309         localHomes.remove(con.getBeanMetaData().getEjbName());
  310      }
  311   
  312      public EJBLocalHome getLocalHome(Container con)
  313      {
  314         return (EJBLocalHome) localHomes.get(con.getBeanMetaData().getEjbName());
  315      }
  316   
  317      /**
  318       * Whether the container is call by value
  319       * 
  320       * @return true for call by value
  321       */
  322      public boolean isCallByValue()
  323      {
  324         return callByValue;
  325      }
  326      
  327      /**
  328       * Get a container from this deployment unit that corresponds to a given name
  329       *
  330       * @param   name  ejb-name name defined in ejb-jar.xml
  331       *
  332       * @return  container for the named bean, or null if the container was
  333       *          not found
  334       */
  335      public Container getContainer(String name)
  336      {
  337         return (Container) containers.get(name);
  338      }
  339   
  340      /**
  341       * Get all containers in this deployment unit.
  342       *
  343       * @return  a collection of containers for each enterprise bean in this
  344       *          deployment unit.
  345       * @jmx:managed-attribute
  346       */
  347      public Collection getContainers()
  348      {
  349         return containerOrdering;
  350      }
  351   
  352      /**
  353       * Get the class loader of this deployment unit.
  354       *
  355       * @return
  356       */
  357      public ClassLoader getClassLoader()
  358      {
  359         return classLoader;
  360      }
  361   
  362      /**
  363       * Set the class loader of this deployment unit
  364       *
  365       * @param   cl
  366       */
  367      public void setClassLoader(ClassLoader cl)
  368      {
  369         this.classLoader = cl;
  370      }
  371   
  372      /**
  373       * Get the URL from which this deployment unit was deployed
  374       *
  375       * @return    The URL from which this Application was deployed.
  376       */
  377      public URL getURL()
  378      {
  379         return appMetaData.getUrl();
  380      }
  381    
  382      // Service implementation ----------------------------------------
  383   
  384      protected void createService() throws Exception
  385      {
  386         serviceController = (ServiceControllerMBean)
  387            MBeanProxyExt.create(ServiceControllerMBean.class,
  388                                 ServiceControllerMBean.OBJECT_NAME,
  389                                 server);
  390   
  391         log.debug("createService, begin");
  392   
  393         //Set up the beans in this module.
  394         try
  395         {
  396            Iterator beans = appMetaData.getEnterpriseBeans();
  397            String contextID = appMetaData.getJaccContextID();
  398            if( contextID == null )
  399               contextID = deploymentUnit.getSimpleName(); 
  400            //appMetaData.gsetJaccContextID(contextID);
  401            /*PolicyConfiguration pc = null; */
  402            while (beans.hasNext())
  403            {
  404               BeanMetaData bean = (BeanMetaData) beans.next();
  405               log.info("Deploying " + bean.getEjbName());
  406               Container con = createContainer(bean, deploymentUnit);
  407               addContainer(con);
  408               //@todo support overriding the context id via metadata is needed
  409               con.setJaccContextID(contextID); 
  410            } 
  411   
  412            //only one iteration should be necessary, but we won't sweat it.
  413            //2 iterations are needed by cmp...jdbc/bridge/JDBCCMRFieldBridge which
  414            //assumes persistence managers are all set up for every
  415            //bean in the relationship!
  416            ListIterator iter = containerOrdering.listIterator();
  417            while( iter.hasNext() )
  418            {
  419               Container con = (Container) iter.next();
  420               ObjectName jmxName = con.getJmxName();
  421               /* Add the container mbean to the deployment mbeans so the state
  422                  of the deployment can be tracked.
  423               */
  424               server.registerMBean(con, jmxName);
  425               //deploymentUnit.mbeans.add(jmxName);
  426               BeanMetaData metaData = con.getBeanMetaData();
  427               Collection<ObjectName> depends = new ArrayList<ObjectName>();
  428               for(String dependsName : metaData.getDepends())
  429               {
  430                  depends.add(ObjectName.getInstance(dependsName));
  431               }
  432               Iterator<String> invokerBindings = metaData.getInvokerBindings();
  433               while (invokerBindings != null && invokerBindings.hasNext())
  434               {
  435                  String invokerBindingName = invokerBindings.next();
  436                  InvokerProxyBindingMetaData ipbmd = appMetaData.getInvokerProxyBindingMetaDataByName(invokerBindingName);
  437                  if (ipbmd != null)
  438                  {
  439                     String invokerName = ipbmd.getInvokerMBean();
  440                     if (invokerName != null)
  441                     {
  442                        try
  443                        {
  444                           ObjectName invokerMBean = ObjectName.getInstance(invokerName);
  445                           if (depends.contains(invokerMBean) == false)
  446                              depends.add(invokerMBean);
  447                        }
  448                        catch (MalformedObjectNameException e)
  449                        {
  450                           log.trace("Ignored malformed invoker mbean '" + invokerName + "' " + e.toString());
  451                        }
  452                     }
  453                  }
  454               }
  455               serviceController.create(jmxName, depends);
  456               // We keep the hashCode around for fast creation of proxies
  457               int jmxHash = jmxName.hashCode();
  458               Registry.bind(new Integer(jmxHash), jmxName);
  459               log.debug("Bound jmxName=" + jmxName + ", hash=" + jmxHash + "into Registry");
  460            }
  461   
  462            //Register any available XACML Policies
  463            String securityDomain = SecurityUtil.unprefixSecurityDomain(appMetaData.getSecurityDomain()); 
  464            if(securityDomain == null)
  465               securityDomain = SecurityConstants.DEFAULT_EJB_APPLICATION_POLICY; //Fallback
  466            VirtualFile xacmlFile = deploymentUnit.getMetaDataFile("jboss-xacml-policy.xml");
  467            if(xacmlFile != null)
  468            {  
  469               if(policyRegistration != null)
  470               {
  471                  policyRegistration.registerPolicy(contextID, PolicyRegistration.XACML, 
  472                        xacmlFile.toURL());
  473               } 
  474            }
  475         }
  476         catch (Exception e)
  477         {
  478            destroyService();
  479            throw e;
  480         } // end of try-catch
  481   
  482      }
  483   
  484      /**
  485       * The mbean Service interface <code>start</code> method calls
  486       * the start method on each contatiner, then the init method on each
  487       * container.  Conversion to a different registration system with one-phase
  488       * startup is conceivable.
  489       *
  490       * @exception Exception if an error occurs
  491       */
  492      protected void startService() throws Exception
  493      {
  494         // before EntityContainer returns from the startService, its PM should be usable
  495         ListIterator iter = containerOrdering.listIterator();
  496         while( iter.hasNext() )
  497         {
  498            Container con = (Container) iter.next();
  499            if(con.getBeanMetaData().isEntity())
  500            {
  501               ClassLoader oldCl = SecurityActions.getContextClassLoader();
  502               SecurityActions.setContextClassLoader(con.getClassLoader());
  503               con.pushENC();
  504               try
  505               {
  506                  ((EntityContainer)con).getPersistenceManager().start();
  507               }
  508               finally
  509               {
  510                  con.popENC();
  511                  // Reset classloader
  512                  SecurityActions.setContextClassLoader(oldCl);
  513               }
  514            }
  515         }
  516   
  517         iter = containerOrdering.listIterator();
  518         while( iter.hasNext() )
  519         {
  520            Container con = (Container) iter.next();
  521            log.debug("startService, starting container: " + con.getBeanMetaData().getEjbName());
  522            serviceController.start(con.getJmxName());
  523         }
  524      }
  525   
  526      /**
  527       * Stops all the containers of this application.
  528       */
  529      protected void stopService() throws Exception
  530      {
  531         ListIterator iter = containerOrdering.listIterator(containerOrdering.size());
  532         while( iter.hasPrevious() )
  533         {
  534            Container con = (Container) iter.previous();
  535            try
  536            {
  537               ObjectName jmxName = con.getJmxName();
  538               // The container may already be destroyed so validate metaData
  539               BeanMetaData metaData = con.getBeanMetaData();
  540               String ejbName = metaData != null ? metaData.getEjbName() : "Unknown";
  541               log.debug("stopService, stopping container: " + ejbName);
  542   
  543               serviceController.stop(jmxName);
  544            }
  545            catch (Exception e)
  546            {
  547               log.error("unexpected exception stopping Container: " + con.getJmxName(), e);
  548            } // end of try-catch
  549         }
  550      }
  551   
  552      protected void destroyService() throws Exception
  553      {
  554         WebServiceMBean webServer = null;
  555         if (webServiceName != null)
  556         {
  557            webServer =
  558               (WebServiceMBean) MBeanProxyExt.create(WebServiceMBean.class,
  559                                                      webServiceName);
  560         }
  561         ListIterator iter = containerOrdering.listIterator(containerOrdering.size());
  562         // Unegister the permissions with the JACC layer
  563         String contextID = appMetaData.getJaccContextID(); 
  564         //Unregister any xacml policies
  565         if(this.policyRegistration != null)
  566         {
  567            policyRegistration.deRegisterPolicy(contextID, PolicyRegistration.XACML);         
  568         }
  569         
  570         while ( iter.hasPrevious() )
  571         {
  572            Container con = (Container) iter.previous();
  573            ObjectName jmxName = con.getJmxName();
  574            int conState = con.getState();
  575            boolean destroyContainer = true; 
  576            log.debug("Looking to destroy container: " + jmxName
  577               + ", state: " + con.getStateString() + ", destroy: " + destroyContainer);
  578   
  579            // always unregister from Registry
  580            int jmxHash = jmxName.hashCode();
  581            Registry.unbind(new Integer(jmxHash));
  582            
  583            // Unregister the web classloader
  584            //Removing the wcl should probably be done in stop of the container,
  585            // but I don't want to look for errors today.
  586            if (webServer != null)
  587            {
  588               ClassLoader wcl = con.getWebClassLoader();
  589               if (wcl != null)
  590               {
  591                  try
  592                  {
  593                     webServer.removeClassLoader(wcl);
  594                  }
  595                  catch (Throwable e)
  596                  {
  597                     log.warn("Failed to unregister webClassLoader", e);
  598                  }
  599               }
  600            }
  601   
  602            // Only destroy containers that have been created or started
  603            if( destroyContainer )
  604            {
  605               try
  606               {
  607                   serviceController.destroy(jmxName);
  608                   serviceController.remove(jmxName);
  609                  log.info("Undeployed " + con.getBeanMetaData().getEjbName());
  610                  if( server.isRegistered(jmxName) )
  611                  	server.unregisterMBean(jmxName);
  612               }
  613               catch (Throwable e)
  614               {
  615                  log.error("unexpected exception destroying Container: " + jmxName, e);
  616               } // end of try-catch
  617           }
  618   
  619   
  620            // cleanup container
  621            con.setBeanMetaData(null);
  622            con.setWebClassLoader(null);
  623            con.setClassLoader(null);
  624            con.setEjbModule(null);
  625            con.setDeploymentInfo(null);
  626            con.setTransactionManager(null);
  627            con.setSecurityManager(null);
  628            con.setRealmMapping(null);
  629            con.setSecurityProxy(null); 
  630            con.setSecurityManagement(null);
  631            con.setPolicyRegistration(null);
  632            con.proxyFactories.clear();
  633         }
  634   
  635         this.containers.clear();
  636         this.localHomes.clear();
  637         this.containerOrdering.clear();
  638         this.moduleData.clear();
  639         this.serviceController = null;
  640      }
  641   
  642      // ******************
  643      // Container Creation
  644      // ******************
  645   
  646      private Container createContainer(BeanMetaData bean, VFSDeploymentUnit unit)
  647         throws Exception
  648      {
  649         Container container = null;
  650         // Added message driven deployment
  651         if (bean.isMessageDriven())
  652         {
  653            container = createMessageDrivenContainer(bean, unit);
  654         }
  655         else if (bean.isSession())   // Is session?
  656         {
  657            if (((SessionMetaData) bean).isStateless())   // Is stateless?
  658            {
  659               container = createStatelessSessionContainer((SessionMetaData) bean, unit);
  660            }
  661            else   // Stateful
  662            {
  663               container = createStatefulSessionContainer((SessionMetaData) bean, unit);
  664            }
  665         }
  666         else   // Entity
  667         {
  668            container = createEntityContainer(bean, unit);
  669         }
  670   
  671         container.setDeploymentUnit(unit);
  672   
  673         return container;
  674      }
  675   
  676      private MessageDrivenContainer createMessageDrivenContainer(BeanMetaData bean,
  677                                                                  DeploymentUnit unit)
  678         throws Exception
  679      {
  680         // get the container configuration for this bean
  681         // a default configuration is now always provided
  682         ConfigurationMetaData conf = bean.getContainerConfiguration();
  683         // Stolen from Stateless deploy
  684         // Create container
  685         MessageDrivenContainer container = new MessageDrivenContainer();
  686         int transType = bean.isContainerManagedTx() ? CMT : BMT;
  687   
  688         initializeContainer(container, conf, bean, transType, unit);
  689         createProxyFactories(bean, container);
  690         container.setInstancePool(createInstancePool(conf, unit.getClassLoader()));
  691   
  692         return container;
  693      }
  694   
  695      private StatelessSessionContainer createStatelessSessionContainer(SessionMetaData bean,
  696                                                                        DeploymentUnit unit)
  697         throws Exception
  698      {
  699         // get the container configuration for this bean
  700         // a default configuration is now always provided
  701         ConfigurationMetaData conf = bean.getContainerConfiguration();
  702         // Create container
  703         StatelessSessionContainer container = new StatelessSessionContainer();
  704         int transType = bean.isContainerManagedTx() ? CMT : BMT;
  705         initializeContainer(container, conf, bean, transType, unit);
  706         if (bean.getHome() != null || bean.getServiceEndpoint()!=null)
  707         {
  708            createProxyFactories(bean, container);
  709         }
  710         container.setInstancePool(createInstancePool(conf, unit.getClassLoader()));
  711   
  712         return container;
  713      }
  714   
  715      private StatefulSessionContainer createStatefulSessionContainer(SessionMetaData bean,
  716                                                                      DeploymentUnit unit)
  717         throws Exception
  718      {
  719         // get the container configuration for this bean
  720         // a default configuration is now always provided
  721         ConfigurationMetaData conf = bean.getContainerConfiguration();
  722         // Create container
  723         StatefulSessionContainer container = new StatefulSessionContainer();
  724         int transType = bean.isContainerManagedTx() ? CMT : BMT;
  725         initializeContainer(container, conf, bean, transType, unit);
  726         if (bean.getHome() != null || bean.getServiceEndpoint()!=null)
  727         {
  728            createProxyFactories(bean, container);
  729         }
  730   
  731         ClassLoader cl = unit.getClassLoader();
  732         container.setInstanceCache(createInstanceCache(conf, cl));
  733         // No real instance pool, use the shadow class
  734         StatefulSessionInstancePool ip = new StatefulSessionInstancePool();
  735         ip.importXml(conf.getContainerPoolConf());
  736         container.setInstancePool(ip);
  737         // Set persistence manager
  738         container.setPersistenceManager((StatefulSessionPersistenceManager) cl.loadClass(conf.getPersistenceManager()).newInstance());
  739         //Set the bean Lock Manager
  740         container.setLockManager(createBeanLockManager(container, false, conf.getLockClass(), cl));
  741   
  742         return container;
  743      }
  744   
  745      private EntityContainer createEntityContainer(BeanMetaData bean,
  746                                                    DeploymentUnit unit)
  747         throws Exception
  748      {
  749         // get the container configuration for this bean
  750         // a default configuration is now always provided
  751         ConfigurationMetaData conf = bean.getContainerConfiguration();
  752         // Create container
  753         EntityContainer container = new EntityContainer();
  754         int transType = CMT;
  755         initializeContainer(container, conf, bean, transType, unit);
  756         if (bean.getHome() != null)
  757         {
  758            createProxyFactories(bean, container);
  759         }
  760   
  761         ClassLoader cl = unit.getClassLoader();
  762         container.setInstanceCache(createInstanceCache(conf, cl));
  763         container.setInstancePool(createInstancePool(conf, cl));
  764         //Set the bean Lock Manager
  765         boolean reentrant = ((EntityMetaData) bean).isReentrant();
  766         BeanLockManager lockMgr = createBeanLockManager(container, reentrant, conf.getLockClass(), cl);
  767         container.setLockManager(lockMgr);
  768   
  769         // Set persistence manager
  770         if (((EntityMetaData) bean).isBMP())
  771         {
  772            Class pmClass = cl.loadClass(conf.getPersistenceManager());
  773            EntityPersistenceManager pm = (EntityPersistenceManager) pmClass.newInstance();
  774            container.setPersistenceManager(pm);
  775         }
  776         else
  777         {
  778            // CMP takes a manager and a store
  779            org.jboss.ejb.plugins.CMPPersistenceManager persistenceManager =
  780               new org.jboss.ejb.plugins.CMPPersistenceManager();
  781   
  782            //Load the store from configuration
  783            Class pmClass = cl.loadClass(conf.getPersistenceManager());
  784            EntityPersistenceStore pm = (EntityPersistenceStore) pmClass.newInstance();
  785            persistenceManager.setPersistenceStore(pm);
  786            // Set the manager on the container
  787            container.setPersistenceManager(persistenceManager);
  788         }
  789   
  790         return container;
  791      }
  792   
  793      // **************
  794      // Helper Methods
  795      // **************
  796   
  797      /**
  798       * Perform the common steps to initializing a container.
  799       */
  800      private void initializeContainer(Container container,
  801                                       ConfigurationMetaData conf,
  802                                       BeanMetaData bean,
  803                                       int transType,
  804                                       DeploymentUnit unit)
  805         throws NamingException, DeploymentException
  806      {
  807         // Create local classloader for this container
  808         // For loading resources that must come from the local jar.  Not for loading classes!
  809         // The VFS should be used for this
  810         // container.setLocalClassLoader(new URLClassLoader(new URL[0], localCl));
  811         // Set metadata (do it *before* creating the container's WebClassLoader)
  812         container.setEjbModule(this);
  813         container.setBeanMetaData(bean);
  814   
  815         ClassLoader unitCl = unit.getClassLoader();
  816         // Create the container's WebClassLoader
  817         // and register it with the web service.
  818         String webClassLoaderName = getWebClassLoader(conf, bean);
  819         log.debug("Creating WebClassLoader of class " + webClassLoaderName);
  820         WebClassLoader wcl = null;
  821         try
  822         {
  823            Class clazz = unitCl.loadClass(webClassLoaderName);
  824            wcl = WebClassLoaderFactory.createWebClassLoader(clazz, container.getJmxName(), (RealClassLoader) unitCl);
  825         }
  826         catch (Exception e)
  827         {
  828            throw new DeploymentException(
  829               "Failed to create WebClassLoader of class "
  830               + webClassLoaderName + ": ", e);
  831         }
  832   
  833         if (webServiceName != null)
  834         {
  835            WebServiceMBean webServer =
  836               (WebServiceMBean) MBeanProxyExt.create(WebServiceMBean.class,
  837                                                      webServiceName);
  838            URL[] codebase = {webServer.addClassLoader(wcl)};
  839   
  840   
  841            wcl.setWebURLs(codebase);
  842         } // end of if ()
  843   
  844         container.setWebClassLoader(wcl);
  845         // Create classloader for this container
  846         // Only used to unique the bean ENC and does not augment class loading
  847         container.setClassLoader(new DelegatingClassLoader(wcl));
  848   
  849         // Set transaction manager
  850         InitialContext iniCtx = new InitialContext();
  851         container.setTransactionManager(tmFactory.getTransactionManager());
  852   
  853         // Set
  854         container.setTimerService(timerService);
  855   
  856         // Set security domain manager
  857         String securityDomain = bean.getApplicationMetaData().getSecurityDomain();
  858         String confSecurityDomain = conf.getSecurityDomain();
  859         // Default the config security to the application security manager
  860         if (confSecurityDomain == null)
  861            confSecurityDomain = securityDomain;
  862   
  863         // Check for an empty confSecurityDomain which signifies to disable security
  864         if (confSecurityDomain != null && confSecurityDomain.length() == 0)
  865            confSecurityDomain = null;
  866   
  867         if (confSecurityDomain != null)
  868         {   // Either the application has a security domain or the container has security setup
  869            try
  870            {
  871               String unprefixed = SecurityUtil.unprefixSecurityDomain(confSecurityDomain);
  872               log.debug("Setting security domain from: " + confSecurityDomain);
  873               String domainCtx = SecurityConstants.JAAS_CONTEXT_ROOT + "/" + unprefixed + "/domainContext";
  874               SecurityDomainContext sdc = (SecurityDomainContext) iniCtx.lookup(domainCtx);
  875               Object securityMgr = sdc.getSecurityManager();
  876               
  877               //Object securityMgr = iniCtx.lookup(confSecurityDomain);
  878               AuthenticationManager ejbS = (AuthenticationManager) securityMgr;
  879               RealmMapping rM = (RealmMapping) securityMgr;
  880               container.setSecurityManager(ejbS);
  881               container.setRealmMapping(rM);   
  882               
  883               container.setSecurityManagement(securityManagement);
  884               container.setPolicyRegistration(policyRegistration);
  885               
  886               container.setDefaultSecurityDomain((String) unit.getAttachment("EJB.defaultSecurityDomain"));
  887               container.setSecurityContextClassName((String) unit.getAttachment("EJB.securityContextClassName"));
  888            }
  889            catch (NamingException e)
  890            {
  891               throw new DeploymentException("Could not find the security-domain, name=" + confSecurityDomain, e);
  892            }
  893            catch (Exception e)
  894            {
  895               throw new DeploymentException("Invalid security-domain specified, name=" + confSecurityDomain, e);
  896            }
  897         }
  898         else
  899         {
  900            log.warn("EJB Deployment has no configured security domain. " +
  901                   "Security will be bypassed. Please verify if this is intended. Bean=" + bean.getEjbName() + " Deployment="+unit.getName());
  902         }
  903   
  904         // Load the security proxy instance if one was configured
  905         String securityProxyClassName = bean.getSecurityProxy();
  906         if (securityProxyClassName != null)
  907         {
  908            try
  909            {
  910               Class proxyClass = unitCl.loadClass(securityProxyClassName);
  911               Object proxy = proxyClass.newInstance();
  912               container.setSecurityProxy(proxy);
  913               log.debug("setSecurityProxy, " + proxy);
  914            }
  915            catch (Exception e)
  916            {
  917               throw new DeploymentException("Failed to create SecurityProxy of type: " +
  918                                             securityProxyClassName, e);
  919            }
  920         }
  921   
  922         // Install the container interceptors based on the configuration
  923         addInterceptors(container, transType, conf.getContainerInterceptorsConf());
  924      }
  925   
  926      /**
  927       * Return the name of the WebClassLoader class for this ejb.
  928       */
  929      private static String getWebClassLoader(ConfigurationMetaData conf,
  930                                              BeanMetaData bmd)
  931         throws DeploymentException
  932      {
  933         String webClassLoader = null;
  934         Iterator it = bmd.getInvokerBindings();
  935         int count = 0;
  936         while (it.hasNext())
  937         {
  938            String invoker = (String) it.next();
  939            ApplicationMetaData amd = bmd.getApplicationMetaData();
  940            InvokerProxyBindingMetaData imd =
  941               amd.getInvokerProxyBindingMetaDataByName(invoker);
  942            if (imd == null)
  943            {
  944               String msg = "Failed to find InvokerProxyBindingMetaData for: '"
  945                  + invoker + "'. Check the invoker-proxy-binding-name to "
  946                  + "invoker-proxy-binding/name mappings in jboss.xml";
  947               throw new DeploymentException(msg);
  948            }
  949   
  950            Element proxyFactoryConfig = imd.getProxyFactoryConfig();
  951            String webCL = MetaData.getOptionalChildContent(proxyFactoryConfig,
  952                                                            "web-class-loader");
  953            if (webCL != null)
  954            {
  955               log.debug("Invoker " + invoker
  956                         + " specified WebClassLoader class" + webCL);
  957               webClassLoader = webCL;
  958               count++;
  959            }
  960         }
  961         if (count > 1)
  962         {
  963            log.warn(count + " invokers have WebClassLoader specifications.");
  964            log.warn("Using the last specification seen ("
  965                     + webClassLoader + ").");
  966         }
  967         else if (count == 0)
  968         {
  969            webClassLoader = conf.getWebClassLoader();
  970            if(webClassLoader == null)
  971               webClassLoader = "org.jboss.web.WebClassLoader";
  972         }
  973         return webClassLoader;
  974      }
  975   
  976      /**
  977       * Given a container-interceptors element of a container-configuration,
  978       * add the indicated interceptors to the container depending on the container
  979       * transcation type.
  980       *
  981       * @param container   the container instance to setup.
  982       * @param transType   one of the BMT, CMT or ANY constants.
  983       * @param element     the container-interceptors element from the
  984       *                    container-configuration.
  985       */
  986      private void addInterceptors(Container container,
  987                                   int transType,
  988                                   Element element)
  989         throws DeploymentException
  990      {
  991         // Get the interceptor stack(either jboss.xml or standardjboss.xml)
  992         Iterator interceptorElements = MetaData.getChildrenByTagName(element, "interceptor");
  993         String transTypeString = stringTransactionValue(transType);
  994         ClassLoader loader = container.getClassLoader();
  995         /* First build the container interceptor stack from interceptorElements
  996            match transType values
  997         */
  998         ArrayList istack = new ArrayList();
  999         while (interceptorElements != null && interceptorElements.hasNext())
 1000         {
 1001            Element ielement = (Element) interceptorElements.next();
 1002            /* Check that the interceptor is configured for the transaction mode of the bean
 1003               by comparing its 'transaction' attribute to the string representation
 1004               of transType
 1005            */
 1006            String transAttr = ielement.getAttribute("transaction");
 1007            if (transAttr == null || transAttr.length() == 0)
 1008               transAttr = ANY_VALUE;
 1009            if (transAttr.equalsIgnoreCase(ANY_VALUE) || transAttr.equalsIgnoreCase(transTypeString))
 1010            {   // The transaction type matches the container bean trans type
 1011   
 1012               String className = null;
 1013               try
 1014               {
 1015                  className = MetaData.getFirstElementContent(ielement, null);
 1016                  Class clazz = loader.loadClass(className);
 1017                  Interceptor interceptor = (Interceptor) clazz.newInstance();
 1018                  if (interceptor instanceof XmlLoadable)
 1019                  {
 1020                     ((XmlLoadable)interceptor).importXml(ielement);
 1021                  }
 1022                  istack.add(interceptor);
 1023               }
 1024               catch (ClassNotFoundException e)
 1025               {
 1026                  log.warn("Could not load the " + className + " interceptor", e);
 1027               }
 1028               catch (Exception e)
 1029               {
 1030                  log.warn("Could not load the " + className + " interceptor for this container", e);
 1031               }
 1032            }
 1033         }
 1034   
 1035         if (istack.size() == 0)
 1036            log.warn("There are no interceptors configured. Check the standardjboss.xml file");
 1037   
 1038         // Now add the interceptors to the container
 1039         for (int i = 0; i < istack.size(); i++)
 1040         {
 1041            Interceptor interceptor = (Interceptor) istack.get(i);
 1042            container.addInterceptor(interceptor);
 1043         }
 1044   
 1045         /* If there is a security proxy associated with the container add its
 1046            interceptor just before the container interceptor
 1047         */
 1048         if (container.getSecurityProxy() != null)
 1049            container.addInterceptor(new SecurityProxyInterceptor());
 1050   
 1051         // Finally we add the last interceptor from the container
 1052         container.addInterceptor(container.createContainerInterceptor());
 1053      }
 1054   
 1055      
 1056   
 1057      /** Create any JACC permissions for the ejb methods that were not explicitly
 1058       * assigned method-permission or exclude-list mappings.
 1059       * @param con - the ejb container 
 1060       * @param bean - the bean metadata
 1061       * @throws ClassNotFoundException
 1062       * @throws PolicyContextException
 1063       */ 
 1064      void createMissingPermissions(Container con, BeanMetaData bean)
 1065         throws ClassNotFoundException, PolicyContextException
 1066      {
 1067         String contextID = con.getJaccContextID();
 1068         PolicyConfigurationFactory pcFactory = PolicyConfigurationFactory.getPolicyConfigurationFactory();
 1069         PolicyConfiguration pc = pcFactory.getPolicyConfiguration(contextID, false);
 1070         Class clazz = con.getHomeClass();
 1071         // If there is no security domain mark all methods as unchecked
 1072         boolean hasSecurityDomain = con.getSecurityManager() != null;
 1073         boolean exclude = hasSecurityDomain ? bean.isExcludeMissingMethods() : false;
 1074         
 1075         if( clazz != null )
 1076         {
 1077            addMissingMethodPermissions(bean, exclude, clazz, InvocationType.HOME, pc);
 1078         }
 1079         clazz = con.getLocalHomeClass();
 1080         if( clazz != null )
 1081         {
 1082            addMissingMethodPermissions(bean, exclude, clazz, InvocationType.LOCALHOME, pc);
 1083         }
 1084         clazz = con.getLocalClass();
 1085         if( clazz != null )
 1086         {
 1087            addMissingMethodPermissions(bean, exclude, clazz, InvocationType.LOCAL, pc);
 1088         }
 1089         clazz = con.getRemoteClass();
 1090         if( clazz != null )
 1091         {
 1092            addMissingMethodPermissions(bean, exclude, clazz, InvocationType.REMOTE, pc);
 1093         }
 1094         
 1095         if(pc.inService() == false)
 1096           pc.commit();
 1097         // Allow the policy to incorporate the policy configs
 1098         Policy.getPolicy().refresh();
 1099      }
 1100   
 1101      private void getInterfaces(Class iface, HashSet tmp)
 1102      {
 1103         tmp.add(iface);
 1104         Class[] ifaces = iface.getInterfaces();
 1105         for(int n = 0; n < ifaces.length; n ++)
 1106         {
 1107            Class iface2 = ifaces[n];
 1108            tmp.add(iface2);
 1109            getInterfaces(iface2, tmp);
 1110         }
 1111      }
 1112      private void addMissingMethodPermissions(BeanMetaData bean, boolean exclude,
 1113         Class iface, InvocationType type, PolicyConfiguration pc)
 1114         throws PolicyContextException
 1115      {
 1116         String ejbName = bean.getEjbName();
 1117         HashSet tmp = new HashSet();
 1118         getInterfaces(iface, tmp);
 1119         Class[] ifaces = new Class[tmp.size()];
 1120         tmp.toArray(ifaces);
 1121         for(int n = 0; n < ifaces.length; n ++)
 1122         {
 1123            Class c =  ifaces[n];
 1124            Method[] methods = c.getDeclaredMethods();
 1125            for(int m = 0; m < methods.length; m ++)
 1126            {
 1127               String methodName = methods[m].getName();
 1128               Class[] params = methods[m].getParameterTypes();
 1129               // See if there is a method-permission
 1130               if( bean.hasMethodPermission(methodName, params, type) )
 1131                  continue;
 1132               // Create a permission for the missing method-permission
 1133               EJBMethodPermission p = new EJBMethodPermission(ejbName,
 1134                  type.toInterfaceString(), methods[m]);
 1135               if( exclude )
 1136                  pc.addToExcludedPolicy(p);
 1137               else
 1138                  pc.addToUncheckedPolicy(p);
 1139            }
 1140         }
 1141      }
 1142   
 1143      private static String stringTransactionValue(int transType)
 1144      {
 1145         String transaction = ANY_VALUE;
 1146         switch (transType)
 1147         {
 1148         case BMT:
 1149            transaction = BMT_VALUE;
 1150            break;
 1151         case CMT:
 1152            transaction = CMT_VALUE;
 1153            break;
 1154         }
 1155         return transaction;
 1156      }
 1157   
 1158      /**
 1159       * Create all proxy factories for this ejb
 1160       */
 1161      private static void createProxyFactories(BeanMetaData conf, Container container)
 1162         throws Exception
 1163      {
 1164         ClassLoader cl = container.getClassLoader();
 1165         Iterator it = conf.getInvokerBindings();
 1166         boolean foundOne=false;
 1167         while (it.hasNext())
 1168         {
 1169            String invoker = (String) it.next();
 1170            String jndiBinding = conf.getInvokerBinding(invoker);
 1171            log.debug("creating binding for " + jndiBinding + ":" + invoker);
 1172            InvokerProxyBindingMetaData imd = conf.getApplicationMetaData().getInvokerProxyBindingMetaDataByName(invoker);
 1173            EJBProxyFactory ci = null;
 1174   
 1175            // create a ProxyFactory instance
 1176            try
 1177            {
 1178               ci = (EJBProxyFactory) cl.loadClass(imd.getProxyFactory()).newInstance();
 1179               ci.setContainer(container);
 1180               ci.setInvokerMetaData(imd);
 1181               ci.setInvokerBinding(jndiBinding);
 1182               if (ci instanceof XmlLoadable)
 1183               {
 1184                  // the container invoker can load its configuration from the jboss.xml element
 1185                  ((XmlLoadable) ci).importXml(imd.getProxyFactoryConfig());
 1186               }
 1187               container.addProxyFactory(invoker, ci);
 1188               foundOne=true;
 1189            }
 1190            catch (Exception e)
 1191            {
 1192               log.warn("The Container Invoker "+invoker+" (in jboss.xml or standardjboss.xml) could not be created because of "+e+
 1193                  " We will ignore this error, but you may miss a transport for this bean.");
 1194            }
 1195         }
 1196         if(!foundOne) {
 1197            throw new DeploymentException("Missing or invalid Container Invokers (in jboss.xml or standardjboss.xml).");
 1198         } 
 1199      }
 1200   
 1201   
 1202      private static BeanLockManager createBeanLockManager(Container container, boolean reentrant, String beanLock,
 1203                                                           ClassLoader cl)
 1204         throws Exception
 1205      {
 1206         // The bean lock manager
 1207         BeanLockManager lockManager = new BeanLockManager(container);
 1208   
 1209         Class lockClass = null;
 1210         try
 1211         {
 1212            if(beanLock == null)
 1213               beanLock = "org.jboss.ejb.plugins.lock.QueuedPessimisticEJBLock";
 1214            lockClass = cl.loadClass(beanLock);
 1215         }
 1216         catch (Exception e)
 1217         {
 1218            throw new DeploymentException("Missing or invalid lock class (in jboss.xml or standardjboss.xml): " + beanLock + " - " + e);
 1219         }
 1220   
 1221         lockManager.setLockCLass(lockClass);
 1222         lockManager.setReentrant(reentrant);
 1223   
 1224         return lockManager;
 1225      }
 1226   
 1227      private static InstancePool createInstancePool(ConfigurationMetaData conf,
 1228                                                     ClassLoader cl)
 1229         throws Exception
 1230      {
 1231         // Set instance pool
 1232         InstancePool ip = null;
 1233   
 1234         try
 1235         {
 1236            ip = (InstancePool) cl.loadClass(conf.getInstancePool()).newInstance();
 1237         }
 1238         catch (Exception e)
 1239         {
 1240            throw new DeploymentException("Missing or invalid Instance Pool (in jboss.xml or standardjboss.xml)", e);
 1241         }
 1242   
 1243         if (ip instanceof XmlLoadable)
 1244            ((XmlLoadable) ip).importXml(conf.getContainerPoolConf());
 1245   
 1246         return ip;
 1247      }
 1248   
 1249      private static InstanceCache createInstanceCache(ConfigurationMetaData conf,
 1250                                                       ClassLoader cl)
 1251         throws Exception
 1252      {
 1253         // Set instance cache
 1254         InstanceCache ic = null;
 1255   
 1256         try
 1257         {
 1258            ic = (InstanceCache) cl.loadClass(conf.getInstanceCache()).newInstance();
 1259         }
 1260         catch (Exception e)
 1261         {
 1262            throw new DeploymentException("Missing or invalid Instance Cache (in jboss.xml or standardjboss.xml)", e);
 1263         }
 1264   
 1265         if (ic instanceof XmlLoadable)
 1266            ((XmlLoadable) ic).importXml(conf.getContainerCacheConf());
 1267   
 1268         return ic;
 1269      }  
 1270   }
 1271   /*
 1272   vim:ts=3:sw=3:et
 1273   */

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