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 2006, Red Hat Middleware LLC, and individual contributors
    4    * as indicated by the @author tags. See the copyright.txt file in the
    5    * distribution for a 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.InvocationTargetException;
   25   import java.lang.reflect.Method;
   26   import java.net.URL;
   27   import java.rmi.MarshalException;
   28   import java.security.AccessController;
   29   import java.security.Policy;
   30   import java.security.Principal;
   31   import java.security.PrivilegedActionException;
   32   import java.security.PrivilegedExceptionAction;
   33   import java.util.HashMap;
   34   import java.util.HashSet;
   35   import java.util.Iterator;
   36   import java.util.Map;
   37   import java.util.Set;
   38   
   39   import javax.ejb.EJBException;
   40   import javax.ejb.EJBObject;
   41   import javax.ejb.TimedObject;
   42   import javax.ejb.Timer;
   43   import javax.ejb.TimerService;
   44   import javax.ejb.spi.HandleDelegate;
   45   import javax.management.MBeanException;
   46   import javax.management.MalformedObjectNameException;
   47   import javax.management.ObjectName;
   48   import javax.naming.Context;
   49   import javax.naming.InitialContext;
   50   import javax.naming.LinkRef;
   51   import javax.naming.NamingException;
   52   import javax.naming.Reference;
   53   import javax.naming.StringRefAddr;
   54   import javax.transaction.TransactionManager;
   55   import javax.xml.soap.SOAPMessage;
   56   
   57   import org.jboss.deployers.vfs.spi.structure.VFSDeploymentUnit;
   58   import org.jboss.deployment.DeploymentException;
   59   import org.jboss.deployment.DeploymentInfo;
   60   import org.jboss.ejb.plugins.local.BaseLocalProxyFactory;
   61   import org.jboss.ejb.txtimer.EJBTimerService;
   62   import org.jboss.ejb.txtimer.EJBTimerServiceImpl;
   63   import org.jboss.invocation.Invocation;
   64   import org.jboss.invocation.InvocationKey;
   65   import org.jboss.invocation.InvocationStatistics;
   66   import org.jboss.invocation.InvocationType;
   67   import org.jboss.invocation.JBossLazyUnmarshallingException;
   68   import org.jboss.invocation.MarshalledInvocation;
   69   import org.jboss.logging.Logger;
   70   import org.jboss.metadata.ApplicationMetaData;
   71   import org.jboss.metadata.BeanMetaData;
   72   import org.jboss.metadata.EjbLocalRefMetaData;
   73   import org.jboss.metadata.EjbRefMetaData;
   74   import org.jboss.metadata.EnvEntryBinder;
   75   import org.jboss.metadata.EnvEntryMetaData;
   76   import org.jboss.metadata.MessageDestinationRefMetaData;
   77   import org.jboss.metadata.ResourceEnvRefMetaData;
   78   import org.jboss.metadata.ResourceRefMetaData;
   79   import org.jboss.metadata.javaee.spec.MessageDestinationMetaData;
   80   import org.jboss.metadata.javaee.spec.ServiceReferenceMetaData;
   81   import org.jboss.metadata.serviceref.ServiceReferenceHandler;
   82   import org.jboss.metadata.serviceref.VirtualFileAdaptor;
   83   import org.jboss.mx.util.ObjectNameConverter;
   84   import org.jboss.mx.util.ObjectNameFactory;
   85   import org.jboss.naming.ENCFactory;
   86   import org.jboss.naming.ENCThreadLocalKey;
   87   import org.jboss.naming.NonSerializableFactory;
   88   import org.jboss.naming.Util;
   89   import org.jboss.security.AnybodyPrincipal;
   90   import org.jboss.security.AuthenticationManager;
   91   import org.jboss.security.ISecurityManagement;
   92   import org.jboss.security.authorization.PolicyRegistration;
   93   import org.jboss.security.RealmMapping;
   94   import org.jboss.security.SimplePrincipal;
   95   import org.jboss.system.ServiceMBeanSupport;
   96   import org.jboss.util.NestedError;
   97   import org.jboss.util.NestedRuntimeException;
   98   import org.jboss.wsf.spi.deployment.UnifiedVirtualFile;
   99   import org.omg.CORBA.ORB;
  100   
  101   /**
  102    * This is the base class for all EJB-containers in JBoss. A Container
  103    * functions as the central hub of all metadata and plugins. Through this
  104    * the container plugins can get hold of the other plugins and any metadata
  105    * they need.
  106    *
  107    * <p>The EJBDeployer creates instances of subclasses of this class
  108    *    and calls the appropriate initialization methods.
  109    *
  110    * <p>A Container does not perform any significant work, but instead delegates
  111    *    to the plugins to provide for all kinds of algorithmic functionality.
  112    *
  113    * @see EJBDeployer
  114    *
  115    * @author <a href="mailto:rickard.oberg@jboss.org">Rickard Oberg</a>
  116    * @author <a href="mailto:marc.fleury@jboss.org">Marc Fleury</a>
  117    * @author <a href="mailto:Scott.Stark@jboss.org">Scott Stark</a>.
  118    * @author <a href="bill@burkecentral.com">Bill Burke</a>
  119    * @author <a href="mailto:d_jencks@users.sourceforge.net">David Jencks</a>
  120    * @author <a href="mailto:christoph.jung@infor.de">Christoph G. Jung</a>
  121    * @author <a href="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
  122    * @author adrian@jboss.org
  123    * @author anil.saldhana@jboss.org
  124    * @version $Revision: 74152 $
  125    *
  126    * @jmx.mbean extends="org.jboss.system.ServiceMBean"
  127    */
  128   public abstract class Container extends ServiceMBeanSupport implements ContainerMBean, AllowedOperationsFlags
  129   {
  130      public final static String BASE_EJB_CONTAINER_NAME = "jboss.j2ee:service=EJB";
  131   
  132      public final static ObjectName ORB_NAME = ObjectNameFactory.create("jboss:service=CorbaORB");
  133   
  134      public final static ObjectName EJB_CONTAINER_QUERY_NAME = ObjectNameFactory.create(BASE_EJB_CONTAINER_NAME + ",*");
  135   
  136      protected static final Method EJBOBJECT_REMOVE;
  137   
  138      /** A reference to {@link javax.ejb.TimedObject#ejbTimeout}. */
  139      protected static final Method EJB_TIMEOUT;
  140   
  141      /** This is the application that this container is a part of */
  142      protected EjbModule ejbModule;
  143   
  144      /**
  145       * This is the classloader of this container. All classes and resources that
  146       * the bean uses will be loaded from here. By doing this we make the bean
  147       * re-deployable
  148       */
  149      protected ClassLoader classLoader;
  150   
  151      /** The class loader for remote dynamic classloading */
  152      protected ClassLoader webClassLoader;
  153   
  154      /**
  155       * Externally supplied configuration data
  156       */
  157      private VFSDeploymentUnit unit;
  158   
  159      /**
  160       * This is the new metadata. it includes information from both ejb-jar and
  161       * jboss.xml the metadata for the application can be accessed trough
  162       * metaData.getApplicationMetaData()
  163       */
  164      protected BeanMetaData metaData;
  165   
  166      /** This is the EnterpriseBean class */
  167      protected Class beanClass;
  168   
  169      /** This is the Home interface class */
  170      protected Class homeInterface;
  171   
  172      /** This is the Remote interface class */
  173      protected Class remoteInterface;
  174   
  175      /** The local home interface class */
  176      protected Class localHomeInterface;
  177   
  178      /** The local inteface class */
  179      protected Class localInterface;
  180   
  181      /** This is the TransactionManager */
  182      protected TransactionManager tm;
  183   
  184      /** The Security Context FQN */
  185      protected String securityContextClassName;
  186   
  187      /** Security Domain to fall back on **/
  188      protected String defaultSecurityDomain;
  189   
  190      /** SecurityManagement Instance - holder of all security managers */
  191      protected ISecurityManagement securityManagement;
  192      
  193      /** PolicyRegistration - Holds Authorization Policies */
  194      protected PolicyRegistration policyRegistration;
  195   
  196      /** This is the SecurityManager */
  197      protected AuthenticationManager sm;
  198   
  199      /** This is the realm mapping */
  200      protected RealmMapping rm;
  201   
  202      /** The custom security proxy used by the SecurityInterceptor */
  203      protected Object securityProxy;
  204   
  205      /** This is the bean lock manager that is to be used */
  206      protected BeanLockManager lockManager;
  207   
  208      /** ??? */
  209      protected LocalProxyFactory localProxyFactory = new BaseLocalProxyFactory();
  210   
  211      /** This is a cache for method permissions */
  212      private HashMap<Method, Set<Principal>> methodPermissionsCache = new HashMap<Method, Set<Principal>>();
  213   
  214      /** Maps for MarshalledInvocation mapping */
  215      protected Map marshalledInvocationMapping = new HashMap();
  216   
  217      /** ObjectName of Container */
  218      private ObjectName jmxName;
  219   
  220      /** HashMap<String, EJBProxyFactory> for the invoker bindings */
  221      protected HashMap proxyFactories = new HashMap();
  222   
  223      /** A priviledged actions for MBeanServer.invoke when running with sec mgr */
  224      private MBeanServerAction serverAction = new MBeanServerAction();
  225   
  226      /**
  227       * The Proxy factory is set in the Invocation.  This TL is used
  228       * for methods that do not have access to the Invocation.
  229       */
  230      protected ThreadLocal proxyFactoryTL = new ThreadLocal();
  231   
  232      /** The number of create invocations that have been made */
  233      protected long createCount;
  234   
  235      /** The number of create invocations that have been made */
  236      protected long removeCount;
  237   
  238      /** Time statistics for the invoke(Invocation) methods */
  239      protected InvocationStatistics invokeStats = new InvocationStatistics();
  240   
  241      /** The JACC context id for the container */
  242      protected String jaccContextID;
  243   
  244      /** 
  245       * Flag to denote whether a JACC configuration has been fitted for authorization 
  246       */
  247      protected boolean isJaccEnabled = false;
  248   
  249      protected EJBTimerService timerService;
  250   
  251      static
  252      {
  253         try
  254         {
  255            EJBOBJECT_REMOVE = EJBObject.class.getMethod("remove", new Class[0]);
  256            EJB_TIMEOUT = TimedObject.class.getMethod("ejbTimeout", new Class[] { Timer.class });
  257         }
  258         catch (Throwable t)
  259         {
  260            throw new NestedRuntimeException(t);
  261         }
  262      }
  263   
  264      // Public --------------------------------------------------------
  265   
  266      public Class getLocalClass()
  267      {
  268         return localInterface;
  269      }
  270   
  271      public Class getLocalHomeClass()
  272      {
  273         return localHomeInterface;
  274      }
  275   
  276      public Class getRemoteClass()
  277      {
  278         return remoteInterface;
  279      }
  280   
  281      /**
  282       * this actually should be called remotehome, but for interface compliance purposes
  283       * we keep it like that
  284       */
  285      public Class getHomeClass()
  286      {
  287         return homeInterface;
  288      }
  289   
  290      /**
  291       * Whether the bean is call by value
  292       * 
  293       * @return true for call by value
  294       */
  295      public boolean isCallByValue()
  296      {
  297         if (ejbModule.isCallByValue())
  298            return true;
  299         return metaData.isCallByValue();
  300      }
  301   
  302      /**
  303       * Sets a transaction manager for this container.
  304       *
  305       * @see javax.transaction.TransactionManager
  306       *
  307       * @param tm
  308       */
  309      public void setTransactionManager(final TransactionManager tm)
  310      {
  311         this.tm = tm;
  312      }
  313   
  314      /**
  315       * Returns this container's transaction manager.
  316       *
  317       * @return A concrete instance of javax.transaction.TransactionManager
  318       */
  319      public TransactionManager getTransactionManager()
  320      {
  321         return tm;
  322      }
  323   
  324      public void setSecurityManager(AuthenticationManager sm)
  325      {
  326         this.sm = sm;
  327      }
  328   
  329      public AuthenticationManager getSecurityManager()
  330      {
  331         return sm;
  332      }
  333   
  334      public ISecurityManagement getSecurityManagement()
  335      {
  336         return securityManagement;
  337      }
  338   
  339      public void setSecurityManagement(ISecurityManagement securityManagement)
  340      {
  341         this.securityManagement = securityManagement;
  342      } 
  343   
  344      public PolicyRegistration getPolicyRegistration()
  345      {
  346         return policyRegistration;
  347      }
  348   
  349      public void setPolicyRegistration(PolicyRegistration policyRegistration)
  350      {
  351         this.policyRegistration = policyRegistration;
  352      }
  353   
  354      public String getDefaultSecurityDomain()
  355      {
  356         return defaultSecurityDomain;
  357      }
  358   
  359      public void setDefaultSecurityDomain(String defaultSecurityDomain)
  360      {
  361         this.defaultSecurityDomain = defaultSecurityDomain;
  362      }
  363   
  364      public String getSecurityContextClassName()
  365      {
  366         return securityContextClassName;
  367      }
  368   
  369      public void setSecurityContextClassName(String securityContextClassName)
  370      {
  371         this.securityContextClassName = securityContextClassName;
  372      }
  373   
  374      public BeanLockManager getLockManager()
  375      {
  376         return lockManager;
  377      }
  378   
  379      public void setLockManager(final BeanLockManager lockManager)
  380      {
  381         this.lockManager = lockManager;
  382         lockManager.setContainer(this);
  383      }
  384   
  385      public void addProxyFactory(String invokerBinding, EJBProxyFactory factory)
  386      {
  387         proxyFactories.put(invokerBinding, factory);
  388      }
  389   
  390      public void setRealmMapping(final RealmMapping rm)
  391      {
  392         this.rm = rm;
  393      }
  394   
  395      public RealmMapping getRealmMapping()
  396      {
  397         return rm;
  398      }
  399   
  400      public void setSecurityProxy(Object proxy)
  401      {
  402         this.securityProxy = proxy;
  403      }
  404   
  405      public Object getSecurityProxy()
  406      {
  407         return securityProxy;
  408      }
  409   
  410      public EJBProxyFactory getProxyFactory()
  411      {
  412         EJBProxyFactory factory = (EJBProxyFactory)proxyFactoryTL.get();
  413         // There's no factory thread local which means this is probably
  414         // a local invocation. Just use the first (usually only)
  415         // proxy factory.
  416         // TODO: define a default factory in the meta data or 
  417         //       even better, let the return over the original transport
  418         //       plugin the transport layer for the generated proxy
  419         if (factory == null && remoteInterface != null)
  420         {
  421            Iterator i = proxyFactories.values().iterator();
  422            if (i.hasNext())
  423               factory = (EJBProxyFactory)i.next();
  424         }
  425         return factory;
  426      }
  427   
  428      public void setProxyFactory(Object factory)
  429      {
  430         proxyFactoryTL.set(factory);
  431      }
  432   
  433      public EJBProxyFactory lookupProxyFactory(String binding)
  434      {
  435         return (EJBProxyFactory)proxyFactories.get(binding);
  436      }
  437   
  438      /**
  439       * Gets the DeploymentInfo for this Container
  440       * @deprecated use DeploymentUnit accessors
  441       * @return The DeploymentInfo for this Container
  442       */
  443      public final DeploymentInfo getDeploymentInfo()
  444      {
  445         return null;
  446      }
  447   
  448      /**
  449       * Sets the DeploymentInfo of this Container
  450       * @deprecated use DeploymentUnit accessors
  451       * @param di The new DeploymentInfo to be used
  452       */
  453      public final void setDeploymentInfo(DeploymentInfo di)
  454      {
  455      }
  456   
  457      public final VFSDeploymentUnit getDeploymentUnit()
  458      {
  459         return unit;
  460      }
  461   
  462      public final void setDeploymentUnit(VFSDeploymentUnit di)
  463      {
  464         this.unit = di;
  465      }
  466   
  467      /**
  468       * Sets the application deployment unit for this container. All the bean
  469       * containers within the same application unit share the same instance.
  470       *
  471       * @param   app     application for this container
  472       */
  473      public void setEjbModule(EjbModule app)
  474      {
  475         ejbModule = app;
  476      }
  477   
  478      public String getJaccContextID()
  479      {
  480         return jaccContextID;
  481      }
  482   
  483      public void setJaccContextID(String id)
  484      {
  485         jaccContextID = id;
  486      }
  487   
  488      public EJBTimerService getTimerService()
  489      {
  490         return timerService;
  491      }
  492   
  493      public void setTimerService(EJBTimerService timerService)
  494      {
  495         this.timerService = timerService;
  496      }
  497   
  498      /** 
  499       * Get the flag whether JACC is enabled  
  500       * @return 
  501       */
  502      public boolean isJaccEnabled()
  503      {
  504         return isJaccEnabled;
  505      }
  506   
  507      /**
  508       * Set the flag that JACC is enabled 
  509       *  
  510       * @param isJaccEnabled 
  511       */
  512      public void setJaccEnabled(boolean isJaccEnabled)
  513      {
  514         this.isJaccEnabled = isJaccEnabled;
  515      }
  516   
  517      /**
  518       * Gets the application deployment unit for this container. All the bean
  519       * containers within the same application unit share the same instance.
  520       * @jmx.managed-attribute
  521       */
  522      public EjbModule getEjbModule()
  523      {
  524         return ejbModule;
  525      }
  526   
  527      /**
  528       * Gets the number of create invocations that have been made
  529       * @jmx.managed-attribute
  530       */
  531      public long getCreateCount()
  532      {
  533         return createCount;
  534      }
  535   
  536      /**
  537       * Gets the number of remove invocations that have been made
  538       * @jmx.managed-attribute
  539       */
  540      public long getRemoveCount()
  541      {
  542         return removeCount;
  543      }
  544   
  545      /** Gets the invocation statistics collection
  546       * @jmx.managed-attribute
  547       */
  548      public InvocationStatistics getInvokeStats()
  549      {
  550         return invokeStats;
  551      }
  552   
  553      /**
  554       * Sets the class loader for this container. All the classes and resources
  555       * used by the bean in this container will use this classloader.
  556       *
  557       * @param   cl
  558       */
  559      public void setClassLoader(ClassLoader cl)
  560      {
  561         this.classLoader = cl;
  562      }
  563   
  564      /**
  565       * Returns the classloader for this container.
  566       *
  567       * @return
  568       */
  569      public ClassLoader getClassLoader()
  570      {
  571         return classLoader;
  572      }
  573   
  574      /** Get the class loader for dynamic class loading via http.
  575       */
  576      public ClassLoader getWebClassLoader()
  577      {
  578         return webClassLoader;
  579      }
  580   
  581      /** Set the class loader for dynamic class loading via http.
  582       */
  583      public void setWebClassLoader(final ClassLoader webClassLoader)
  584      {
  585         this.webClassLoader = webClassLoader;
  586      }
  587   
  588      /**
  589       * Sets the meta data for this container. The meta data consists of the
  590       * properties found in the XML descriptors.
  591       *
  592       * @param metaData
  593       */
  594      public void setBeanMetaData(final BeanMetaData metaData)
  595      {
  596         this.metaData = metaData;
  597      }
  598   
  599      /**
  600       * push the ENC onto the stack so that java:comp works
  601       *
  602       */
  603      public void pushENC()
  604      {
  605         ENCFactory.pushContextId(getJmxName());
  606      }
  607   
  608      public void popENC()
  609      {
  610         ENCFactory.popContextId();
  611      }
  612   
  613      /**
  614       * cleanup ENC on shutdown
  615       *
  616       */
  617      public void cleanENC()
  618      {
  619         ENCFactory.getEncById().remove(getJmxName());
  620      }
  621   
  622      /** Get the components environment context
  623       * @jmx.managed-attribute
  624       * @return Environment Context
  625       */
  626      public Context getEnvContext() throws NamingException
  627      {
  628         pushENC();
  629         try
  630         {
  631            return (Context)new InitialContext().lookup("java:comp/env");
  632         }
  633         finally
  634         {
  635            popENC();
  636         }
  637      }
  638   
  639      /**
  640       * Returns the metadata of this container.
  641       *
  642       * @jmx.managed-attribute
  643       * @return metaData;
  644       */
  645      public BeanMetaData getBeanMetaData()
  646      {
  647         return metaData;
  648      }
  649   
  650      /**
  651       * Returns the permissions for a method. (a set of roles)
  652       *
  653       * @return assemblyDescriptor;
  654       */
  655      public Set<Principal> getMethodPermissions(Method m, InvocationType iface)
  656      {
  657         Set<Principal> permissions;
  658   
  659         if (methodPermissionsCache.containsKey(m))
  660         {
  661            permissions = (Set)methodPermissionsCache.get(m);
  662         }
  663         else if (m.equals(EJB_TIMEOUT))
  664         {
  665            // No role is required to access the ejbTimeout as this is 
  666            permissions = new HashSet<Principal>();
  667            permissions.add(AnybodyPrincipal.ANYBODY_PRINCIPAL);
  668            methodPermissionsCache.put(m, permissions);
  669         }
  670         else
  671         {
  672            String name = m.getName();
  673            Class[] sig = m.getParameterTypes();
  674            Set<String> roles = getBeanMetaData().getMethodPermissions(name, sig, iface);
  675            permissions = new HashSet<Principal>();
  676            if (roles != null)
  677            {
  678               for (String role : roles)
  679                  permissions.add(new SimplePrincipal(role));
  680            } 
  681            methodPermissionsCache.put(m, permissions);
  682         }
  683   
  684         return permissions;
  685      }
  686   
  687      /**
  688       * Returns the bean class instance of this container.
  689       *
  690       * @return    instance of the Enterprise bean class.
  691       */
  692      public Class getBeanClass()
  693      {
  694         return beanClass;
  695      }
  696   
  697      /**
  698       * Returns a new instance of the bean class or a subclass of the bean class.
  699       * This factory style method is speciffically used by a container to supply
  700       * an implementation of the abstract accessors in EJB2.0, but could be
  701       * usefull in other situations. This method should ALWAYS be used instead
  702       * of getBeanClass().newInstance();
  703       *
  704       * @return    the new instance
  705       *
  706       * @see java.lang.Class#newInstance
  707       */
  708      public Object createBeanClassInstance() throws Exception
  709      {
  710         return getBeanClass().newInstance();
  711      }
  712   
  713      /**
  714       * Sets the codebase of this container.
  715       *
  716       * @param   codebase a possibly empty, but non null String with
  717       *                   a sequence of URLs separated by spaces
  718       * /
  719       public void setCodebase(final String codebase)
  720       {
  721       if (codebase != null)
  722       this.codebase = codebase;
  723       }
  724       */
  725      /**
  726       * Gets the codebase of this container.
  727       *
  728       * @return    this container's codebase String, a sequence of URLs
  729       *            separated by spaces
  730       * /
  731       public String getCodebase()
  732       {
  733       return codebase;
  734       }
  735       */
  736   
  737      /** Build a JMX name using the pattern jboss.j2ee:service=EJB,jndiName=[jndiName]
  738       where the [jndiName] is either the bean remote home JNDI binding, or
  739       the local home JNDI binding if the bean has no remote interfaces.
  740       */
  741      public ObjectName getJmxName()
  742      {
  743         if (jmxName == null)
  744         {
  745            BeanMetaData beanMetaData = getBeanMetaData();
  746            if (beanMetaData == null)
  747            {
  748               throw new IllegalStateException("Container metaData is null");
  749            }
  750   
  751            String jndiName = beanMetaData.getContainerObjectNameJndiName();
  752            if (jndiName == null)
  753            {
  754               throw new IllegalStateException("Container jndiName is null");
  755            }
  756   
  757            // The name must be escaped since the jndiName may be arbitrary
  758            String name = BASE_EJB_CONTAINER_NAME + ",jndiName=" + jndiName;
  759            try
  760            {
  761               jmxName = ObjectNameConverter.convert(name);
  762            }
  763            catch (MalformedObjectNameException e)
  764            {
  765               throw new RuntimeException("Failed to create ObjectName, msg=" + e.getMessage());
  766            }
  767         }
  768         return jmxName;
  769      }
  770   
  771      /**
  772       * Creates the single Timer Service for this container if not already created
  773       *
  774       * @param pKey Bean id
  775       * @return Container Timer Service
  776       * @throws IllegalStateException If the type of EJB is not allowed to use the
  777       * timer service, or the bean class does not implement javax.ejb.TimedObject
  778       *
  779       * @see javax.ejb.EJBContext#getTimerService
  780       *
  781       * @jmx.managed-operation
  782       **/
  783      public TimerService getTimerService(Object pKey) throws IllegalStateException
  784      {
  785         if (this instanceof StatefulSessionContainer)
  786            throw new IllegalStateException("Statefull Session Beans are not allowed to access the TimerService");
  787   
  788         // Validate that the bean implements the TimedObject interface
  789         if (TimedObject.class.isAssignableFrom(beanClass) == false)
  790         {
  791            // jbcts-381
  792            return EJBTimerServiceImpl.FOR_NON_TIMED_OBJECT;
  793         }
  794   
  795         TimerService timerService = null;
  796         try
  797         {
  798            timerService = this.timerService.createTimerService(getJmxName(), pKey, this);
  799         }
  800         catch (Exception e)
  801         {
  802            throw new EJBException("Could not create timer service", e);
  803         }
  804         return timerService;
  805      }
  806   
  807      /**
  808       * Removes Timer Service for this container
  809       *
  810       * @param pKey Bean id
  811       * @throws IllegalStateException If the type of EJB is not allowed to use the timer service
  812       *
  813       * @jmx.managed-operation
  814       **/
  815      public void removeTimerService(Object pKey) throws IllegalStateException
  816      {
  817         try
  818         {
  819            if (pKey != null)
  820            {
  821               // entity bean->remove()
  822               timerService.removeTimerService(getJmxName(), pKey);
  823            }
  824            else
  825            {
  826               // container stop, we choose whether active timers
  827               // should be persisted (default), or not (legacy)
  828               timerService.removeTimerService(getJmxName(), getBeanMetaData().getTimerPersistence());
  829            }
  830         }
  831         catch (Exception e)
  832         {
  833            log.error("Could not remove timer service", e);
  834         }
  835      }
  836   
  837      /**
  838       * Restore any timers previously persisted for this container
  839       */
  840      protected void restoreTimers()
  841      {
  842         try
  843         {
  844            // TODO: this name needs to be externalized
  845            // pass to the ejb timer service the container ObjectName
  846            timerService.restoreTimers(getServiceName(), getClassLoader());
  847         }
  848         catch (Exception e)
  849         {
  850            log.warn("Could not restore ejb timers", e);
  851         }
  852      }
  853   
  854      /**
  855       * The EJBDeployer calls this method.  The EJBDeployer has set
  856       * all the plugins and interceptors that this bean requires and now proceeds
  857       * to initialize the chain.  The method looks for the standard classes in
  858       * the URL, sets up the naming environment of the bean. The concrete
  859       * container classes should override this method to introduce
  860       * implementation specific initialization behaviour.
  861       *
  862       * @throws Exception    if loading the bean class failed
  863       *                      (ClassNotFoundException) or setting up "java:"
  864       *                      naming environment failed (DeploymentException)
  865       */
  866      protected void createService() throws Exception
  867      {
  868         // Acquire classes from CL
  869         beanClass = classLoader.loadClass(metaData.getEjbClass());
  870   
  871         if (metaData.getLocalHome() != null)
  872            localHomeInterface = classLoader.loadClass(metaData.getLocalHome());
  873         if (metaData.getLocal() != null)
  874            localInterface = classLoader.loadClass(metaData.getLocal());
  875   
  876         localProxyFactory.setContainer(this);
  877         localProxyFactory.create();
  878         if (localHomeInterface != null)
  879            ejbModule.addLocalHome(this, localProxyFactory.getEJBLocalHome());
  880         ejbModule.createMissingPermissions(this, metaData);
  881         // Allow the policy to incorporate the policy configs
  882         Policy.getPolicy().refresh();
  883      }
  884   
  885      /**
  886       * A default implementation of starting the container service.
  887       * The container registers it's dynamic MBean interface in the JMX base.
  888       *
  889       * The concrete container classes should override this method to introduce
  890       * implementation specific start behaviour.
  891       *
  892       * todo implement the service lifecycle methods in an xmbean interceptor so
  893       * non lifecycle managed ops are blocked when mbean is not started.
  894       *
  895       * @throws Exception    An exception that occured during start
  896       */
  897      protected void startService() throws Exception
  898      {
  899         // Setup "java:comp/env" namespace
  900         setupEnvironment();
  901   
  902         localProxyFactory.start();
  903      }
  904   
  905      /**
  906       * A default implementation of stopping the container service (no-op). The
  907       * concrete container classes should override this method to introduce
  908       * implementation specific stop behaviour.
  909       */
  910      protected void stopService() throws Exception
  911      {
  912         localProxyFactory.stop();
  913         removeTimerService(null);
  914         teardownEnvironment();
  915      }
  916   
  917      /**
  918       * A default implementation of destroying the container service (no-op).
  919       * The concrete container classes should override this method to introduce
  920       * implementation specific destroy behaviour.
  921       */
  922      protected void destroyService() throws Exception
  923      {
  924         cleanENC();
  925         localProxyFactory.destroy();
  926         ejbModule.removeLocalHome(this);
  927   
  928         beanClass = null;
  929         homeInterface = null;
  930         remoteInterface = null;
  931         localHomeInterface = null;
  932         localInterface = null;
  933         methodPermissionsCache.clear();
  934         // InvocationStatistics holds refs to Methods from
  935         // application classes, so to avoid a classloader
  936         // leak, lets not just resetStats() but also replace
  937         // the object
  938         invokeStats.resetStats(); // in case someone else has a ref
  939         invokeStats = new InvocationStatistics();
  940         marshalledInvocationMapping.clear();
  941      }
  942   
  943      /**
  944       * This method is called when a method call comes
  945       * in on the Home object.  The Container forwards this call to the
  946       * interceptor chain for further processing.
  947       *
  948       * @param mi   the object holding all info about this invocation
  949       * @return     the result of the home invocation
  950       *
  951       * @throws Exception
  952       */
  953      public abstract Object internalInvokeHome(Invocation mi) throws Exception;
  954   
  955      /**
  956       * This method is called when a method call comes
  957       * in on an EJBObject.  The Container forwards this call to the interceptor
  958       * chain for further processing.
  959       */
  960      public abstract Object internalInvoke(Invocation mi) throws Exception;
  961   
  962      abstract Interceptor createContainerInterceptor();
  963   
  964      public abstract void addInterceptor(Interceptor in);
  965   
  966      /** The detached invoker operation.
  967       * 
  968       * @jmx.managed-operation
  969       *
  970       * @param mi - the method invocation context
  971       * @return the value of the ejb invocation
  972       * @throws Exception on error
  973       */
  974      public Object invoke(Invocation mi) throws Exception
  975      {
  976         ClassLoader callerClassLoader = SecurityActions.getContextClassLoader();
  977         long start = System.currentTimeMillis();
  978         Method m = null;
  979   
  980         Object type = null;
  981         String contextID = getJaccContextID();
  982         try
  983         {
  984            pushENC();
  985   
  986            // JBAS-3732 - Remove classloader.equals optimization
  987            SecurityActions.setContextClassLoader(this.classLoader);
  988   
  989            // Set the JACC context id
  990            mi.setValue(InvocationKey.JACC_CONTEXT_ID, contextID);
  991            contextID = SecurityActions.setContextID(contextID);
  992            // Set the standard JACC policy context handler data is not a SEI msg
  993            if (mi.getType() != InvocationType.SERVICE_ENDPOINT)
  994            {
  995               EJBArgsPolicyContextHandler.setArgs(mi.getArguments());
  996            }
  997            else
  998            {
  999               SOAPMessage msg = (SOAPMessage)mi.getValue(InvocationKey.SOAP_MESSAGE);
 1000               SOAPMsgPolicyContextHandler.setMessage(msg);
 1001            }
 1002            // Set custom JACC policy handlers
 1003            BeanMetaDataPolicyContextHandler.setMetaData(this.getBeanMetaData());
 1004   
 1005            // Check against home, remote, localHome, local, getHome,
 1006            // getRemote, getLocalHome, getLocal
 1007            type = mi.getType();
 1008   
 1009            // stat gathering: concurrent calls
 1010            this.invokeStats.callIn();
 1011   
 1012            if (type == InvocationType.REMOTE || type == InvocationType.LOCAL ||
 1013            // web service calls come in as "ordinary" application invocations
 1014                  type == InvocationType.SERVICE_ENDPOINT)
 1015            {
 1016               if (mi instanceof MarshalledInvocation)
 1017               {
 1018                  ((MarshalledInvocation)mi).setMethodMap(marshalledInvocationMapping);
 1019   
 1020                  if (log.isTraceEnabled())
 1021                  {
 1022                     log.trace("METHOD REMOTE INVOKE " + mi.getObjectName() + "||" + mi.getMethod().getName() + "||");
 1023                  }
 1024               }
 1025   
 1026               m = mi.getMethod();
 1027   
 1028               Object obj = internalInvoke(mi);
 1029               return obj;
 1030            }
 1031            else if (type == InvocationType.HOME || type == InvocationType.LOCALHOME)
 1032            {
 1033               if (mi instanceof MarshalledInvocation)
 1034               {
 1035   
 1036                  ((MarshalledInvocation)mi).setMethodMap(marshalledInvocationMapping);
 1037   
 1038                  if (log.isTraceEnabled())
 1039                  {
 1040                     log.trace("METHOD HOME INVOKE " + mi.getObjectName() + "||" + mi.getMethod().getName() + "||" + mi.getArguments().toString());
 1041                  }
 1042               }
 1043               m = mi.getMethod();
 1044   
 1045               Object obj = internalInvokeHome(mi);
 1046               return obj;
 1047            }
 1048            else
 1049            {
 1050               throw new MBeanException(new IllegalArgumentException("Unknown invocation type: " + type));
 1051            }
 1052         }
 1053         /**
 1054          * Having to catch this exception here in case can not
 1055          * unmarshall arguments, values, etc.  Then, convert to
 1056          * UnmarshalException as defined by spec (JBAS-2999)
 1057          */
 1058         catch (JBossLazyUnmarshallingException e)
 1059         {
 1060            InvocationType calltype = mi.getType();
 1061            boolean isLocal = calltype == InvocationType.LOCAL || calltype == InvocationType.LOCALHOME;
 1062   
 1063            // handle unmarshalling exception which should only come if problem unmarshalling
 1064            // invocation payload, arguments, or value on remote end.
 1065            if (isLocal)
 1066            {
 1067               throw new EJBException("UnmarshalException", e);
 1068            }
 1069            else
 1070            {
 1071               throw new MarshalException("MarshalException", e);
 1072            }
 1073         }
 1074         finally
 1075         {
 1076            if (m != null)
 1077            {
 1078               long end = System.currentTimeMillis();
 1079               long elapsed = end - start;
 1080               this.invokeStats.updateStats(m, elapsed);
 1081            }
 1082   
 1083            // stat gathering: concurrent calls
 1084            this.invokeStats.callOut();
 1085   
 1086            popENC();
 1087   
 1088            // Restore the incoming class loader
 1089            SecurityActions.setContextClassLoader(callerClassLoader);
 1090   
 1091            // Restore the incoming context id
 1092            contextID = SecurityActions.setContextID(contextID);
 1093   
 1094            if (mi.getType() == InvocationType.SERVICE_ENDPOINT)
 1095            {
 1096               // Remove msg from ThreadLocal to prevent leakage into the thread pool
 1097               SOAPMsgPolicyContextHandler.setMessage(null);
 1098            }
 1099            else
 1100            {
 1101               // Remove args from ThreadLocal to prevent leakage into the thread pool
 1102               EJBArgsPolicyContextHandler.setArgs(null);
 1103            }
 1104   
 1105            // Remove metadata from ThreadLocal to prevent leakage into the thread pool
 1106            BeanMetaDataPolicyContextHandler.setMetaData(null);
 1107         }
 1108      }
 1109   
 1110      // Private -------------------------------------------------------
 1111   
 1112      /**
 1113       * This method sets up the naming environment of the bean.
 1114       * We create the java:comp/env namespace with properties, EJB-References,
 1115       * and DataSource ressources.
 1116       */
 1117      private void setupEnvironment() throws Exception
 1118      {
 1119         BeanMetaData beanMetaData = getBeanMetaData();
 1120   
 1121         // debug
 1122         log.debug("Begin java:comp/env for EJB: " + beanMetaData.getEjbName());
 1123         ClassLoader tcl = SecurityActions.getContextClassLoader();
 1124         log.debug("TCL: " + tcl);
 1125   
 1126         ORB orb = null;
 1127         HandleDelegate hd = null;
 1128         try
 1129         {
 1130            orb = (ORB)server.getAttribute(ORB_NAME, "ORB");
 1131            hd = (HandleDelegate)server.getAttribute(ORB_NAME, "HandleDelegate");
 1132         }
 1133         catch (Throwable t)
 1134         {
 1135            log.debug("Unable to retrieve orb" + t.toString());
 1136         }
 1137   
 1138         // Since the BCL is already associated with this thread we can start
 1139         // using the java: namespace directly
 1140         Context ctx = (Context)new InitialContext().lookup("java:comp");
 1141         Object id = ENCFactory.getCurrentId();
 1142         log.debug("Using java:comp using id=" + id);
 1143   
 1144         // Bind the orb
 1145         if (orb != null)
 1146         {
 1147            NonSerializableFactory.rebind(ctx, "ORB", orb);
 1148            log.debug("Bound java:comp/ORB for EJB: " + getBeanMetaData().getEjbName());
 1149   
 1150            NonSerializableFactory.rebind(ctx, "HandleDelegate", hd);
 1151            log.debug("Bound java:comp/HandleDelegate for EJB: " + getBeanMetaData().getEjbName());
 1152         }
 1153   
 1154         // JTA links
 1155         ctx.bind("TransactionSynchronizationRegistry", new LinkRef("java:TransactionSynchronizationRegistry"));
 1156         log.debug("Linked java:comp/TransactionSynchronizationRegistry to JNDI name: java:TransactionSynchronizationRegistry");
 1157   
 1158         Context envCtx = ctx.createSubcontext("env");
 1159   
 1160         // Bind environment properties
 1161         {
 1162            Iterator i = beanMetaData.getEnvironmentEntries();
 1163            while (i.hasNext())
 1164            {
 1165               EnvEntryMetaData entry = (EnvEntryMetaData)i.next();
 1166               log.debug("Binding env-entry: " + entry.getName() + " of type: " + entry.getType() + " to value:" + entry.getValue());
 1167   
 1168               EnvEntryBinder.bindEnvEntry(envCtx, entry);
 1169            }
 1170         }
 1171   
 1172         // Bind EJB references
 1173         {
 1174            Iterator i = beanMetaData.getEjbReferences();
 1175            while (i.hasNext())
 1176            {
 1177               EjbRefMetaData ref = (EjbRefMetaData)i.next();
 1178               log.debug("Binding an EJBReference " + ref.getName());
 1179   
 1180               if (ref.getLink() != null)
 1181               {
 1182                  // Internal link
 1183                  String linkName = ref.getLink();
 1184                  String jndiName = ref.getJndiName();
 1185                  log.debug("Binding " + ref.getName() + " to ejb-link: " + linkName + " -> " + jndiName);
 1186   
 1187                  if (jndiName == null)
 1188                  {
 1189                     String msg = "Failed to resolve ejb-link: " + linkName + " from ejb-ref: " + ref.getName() + " in ejb: " + beanMetaData.getEjbName();
 1190                     throw new DeploymentException(msg);
 1191                  }
 1192   
 1193                  Util.bind(envCtx, ref.getName(), new LinkRef(jndiName));
 1194   
 1195               }
 1196               else
 1197               {
 1198                  // Get the invoker specific ejb-ref mappings
 1199                  Iterator it = beanMetaData.getInvokerBindings();
 1200                  Reference reference = null;
 1201                  while (it.hasNext())
 1202                  {
 1203                     String invokerBinding = (String)it.next();
 1204                     // Check for an invoker level jndi-name
 1205                     String name = ref.getInvokerBinding(invokerBinding);
 1206                     // Check for an global jndi-name
 1207                     if (name == null)
 1208                        name = ref.getJndiName();
 1209                     if (name == null)
 1210                     {
 1211                        throw new DeploymentException("ejb-ref " + ref.getName() + ", expected either ejb-link in ejb-jar.xml or " + "jndi-name in jboss.xml");
 1212                     }
 1213   
 1214                     StringRefAddr addr = new StringRefAddr(invokerBinding, name);
 1215                     log.debug("adding " + invokerBinding + ":" + name + " to Reference");
 1216   
 1217                     if (reference == null)
 1218                     {
 1219                        reference = new Reference("javax.naming.LinkRef", ENCThreadLocalKey.class.getName(), null);
 1220                     }
 1221                     reference.add(addr);
 1222                  }
 1223   
 1224                  // If there were invoker bindings create bind the reference
 1225                  if (reference != null)
 1226                  {
 1227                     if (ref.getJndiName() != null)
 1228                     {
 1229                        // Add default for the bean level ejb-ref/jndi-name
 1230                        StringRefAddr addr = new StringRefAddr("default", ref.getJndiName());
 1231                        reference.add(addr);
 1232                     }
 1233                     if (reference.size() == 1 && reference.get("default") == null)
 1234                     {
 1235                        /* There is only one invoker binding and its not default so
 1236                         create a default binding to allow the link to have a value
 1237                         when accessed without an invoker active.
 1238                         */
 1239                        StringRefAddr addr = (StringRefAddr)reference.get(0);
 1240                        String target = (String)addr.getContent();
 1241                        StringRefAddr addr1 = new StringRefAddr("default", target);
 1242                        reference.add(addr1);
 1243                     }
 1244                     Util.bind(envCtx, ref.getName(), reference);
 1245                  }
 1246                  else
 1247                  {
 1248                     // Bind the bean level ejb-ref/jndi-name
 1249                     if (ref.getJndiName() == null)
 1250                     {
 1251                        throw new DeploymentException("ejb-ref " + ref.getName() + ", expected either ejb-link in ejb-jar.xml " + "or jndi-name in jboss.xml");
 1252                     }
 1253                     Util.bind(envCtx, ref.getName(), new LinkRef(ref.getJndiName()));
 1254                  }
 1255               }
 1256            }
 1257         }
 1258   
 1259         // Bind Local EJB references
 1260         {
 1261            Iterator i = beanMetaData.getEjbLocalReferences();
 1262            while (i.hasNext())
 1263            {
 1264               EjbLocalRefMetaData ref = (EjbLocalRefMetaData)i.next();
 1265               String refName = ref.getName();
 1266               log.debug("Binding an EJBLocalReference " + ref.getName());
 1267   
 1268               if (ref.getLink() != null)
 1269               {
 1270                  // Internal link
 1271                  log.debug("Binding " + refName + " to bean source: " + ref.getLink());
 1272   
 1273                  String jndiName = ref.getJndiName();
 1274   
 1275                  Util.bind(envCtx, ref.getName(), new LinkRef(jndiName));
 1276               }
 1277               else
 1278               {
 1279                  // Bind the bean level ejb-local-ref/local-jndi-name
 1280                  if (ref.getJndiName() == null)
 1281                  {
 1282                     throw new DeploymentException("ejb-local-ref " + ref.getName() + ", expected either ejb-link in ejb-jar.xml " + "or local-jndi-name in jboss.xml");
 1283                  }
 1284                  Util.bind(envCtx, ref.getName(), new LinkRef(ref.getJndiName()));
 1285               }
 1286            }
 1287         }
 1288   
 1289         // Bind service references
 1290         {
 1291            ClassLoader loader = unit.getClassLoader();
 1292            UnifiedVirtualFile vfsRoot = new VirtualFileAdaptor(unit.getRoot());
 1293            Iterator<ServiceReferenceMetaData> serviceReferences = beanMetaData.getServiceReferences();
 1294            if (serviceReferences != null)
 1295            {
 1296               while (serviceReferences.hasNext())
 1297               {
 1298                  ServiceReferenceMetaData sref = serviceReferences.next();
 1299                  String refName = sref.getServiceRefName();
 1300                  new ServiceReferenceHandler().bindServiceRef(envCtx, refName, vfsRoot, loader, sref);
 1301               }
 1302            }
 1303         }
 1304   
 1305         // Bind resource references
 1306         {
 1307            Iterator i = beanMetaData.getResourceReferences();
 1308   
 1309            // let's play guess the cast game ;)  New metadata should fix this.
 1310            ApplicationMetaData application = beanMetaData.getApplicationMetaData();
 1311   
 1312            while (i.hasNext())
 1313            {
 1314               ResourceRefMetaData ref = (ResourceRefMetaData)i.next();
 1315   
 1316               String resourceName = ref.getResourceName();
 1317               String finalName = application.getResourceByName(resourceName);
 1318               String resType = ref.getType();
 1319               // If there was no resource-manager specified then an immeadiate
 1320               // jndi-name or res-url name should have been given
 1321               if (finalName == null)
 1322                  finalName = ref.getJndiName();
 1323   
 1324               if (finalName == null && resType.equals("java.net.URL") == false)
 1325               {
 1326                  // the application assembler did not provide a resource manager
 1327                  // if the type is javax.sql.Datasoure use the default one
 1328   
 1329                  if (ref.getType().equals("javax.sql.DataSource"))
 1330                  {
 1331                     // Go through JNDI and look for DataSource - use the first one
 1332                     Context dsCtx = new InitialContext();
 1333                     try
 1334                     {
 1335                        // Check if it is available in JNDI
 1336                        dsCtx.lookup("java:/DefaultDS");
 1337                        finalName = "java:/DefaultDS";
 1338                     }
 1339                     catch (Exception e)
 1340                     {
 1341                        log.debug("failed to lookup DefaultDS; ignoring", e);
 1342                     }
 1343                     finally
 1344                     {
 1345                        dsCtx.close();
 1346                     }
 1347                  }
 1348   
 1349                  // Default failed? Warn user and move on
 1350                  // POTENTIALLY DANGEROUS: should this be a critical error?
 1351                  if (finalName == null)
 1352                  {
 1353                     log.warn("No resource manager found for " + ref.getResourceName());
 1354                     continue;
 1355                  }
 1356               }
 1357   
 1358               if (resType.equals("java.net.URL"))
 1359               {
 1360                  // URL bindings
 1361                  if (ref.getResURL() != null)
 1362                  {
 1363                     // The URL string was given by the res-url
 1364                     log.debug("Binding URL: " + ref.getRefName() + " to JDNI ENC as: " + ref.getResURL());
 1365                     URL resURL = new URL(ref.getResURL());
 1366                     Util.bind(envCtx, ref.getRefName(), resURL);
 1367                  }
 1368                  else
 1369                  {
 1370                     log.debug("Binding URL: " + ref.getRefName() + " to: " + finalName);
 1371                     Object bind = null;
 1372                     if (ref.getJndiName() != null)
 1373                     {
 1374                        // Was the url given as a jndi-name reference to link to it
 1375                        bind = new LinkRef(finalName);
 1376                     }
 1377                     else
 1378                     {
 1379                        // The url string was given via a resource-name mapping
 1380                        bind = new URL(finalName);
 1381                     }
 1382                     Util.bind(envCtx, ref.getRefName(), bind);
 1383                  }
 1384               }
 1385               else
 1386               {
 1387                  // Resource Manager bindings, should validate the type...
 1388                  log.debug("Binding resource manager: " + ref.getRefName() + " to JDNI ENC as: " + finalName);
 1389                  Util.bind(envCtx, ref.getRefName(), new LinkRef(finalName));
 1390               }
 1391            }
 1392         }
 1393   
 1394         // Bind resource env references
 1395         {
 1396            Iterator i = beanMetaData.getResourceEnvReferences();
 1397            while (i.hasNext())
 1398            {
 1399               ResourceEnvRefMetaData resRef = (ResourceEnvRefMetaData)i.next();
 1400               String encName = resRef.getRefName();
 1401               String jndiName = resRef.getJndiName();
 1402               // Should validate the type...
 1403               log.debug("Binding env resource: " + encName + " to JDNI ENC as: " + jndiName);
 1404               Util.bind(envCtx, encName, new LinkRef(jndiName));
 1405            }
 1406         }
 1407   
 1408         // Bind message destination references
 1409         {
 1410            Iterator i = beanMetaData.getMessageDestinationReferences();
 1411   
 1412            while (i.hasNext())
 1413            {
 1414               MessageDestinationRefMetaData ref = (MessageDestinationRefMetaData)i.next();
 1415   
 1416               String refName = ref.getRefName();
 1417               String jndiName = ref.getJNDIName();
 1418               String link = ref.getLink();
 1419               if (link != null)
 1420               {
 1421                  if (jndiName == null)
 1422                  {
 1423                     MessageDestinationMetaData messageDestination = getMessageDestination(link);
 1424                     if (messageDestination == null)
 1425                        throw new DeploymentException("message-destination-ref '" + refName + "' message-destination-link '" + link
 1426                              + "' not found and no jndi-name in jboss.xml");
 1427                     else
 1428                     {
 1429                        String linkJNDIName = messageDestination.getJndiName();
 1430                        if (linkJNDIName == null)
 1431                           log.warn("message-destination '" + link + "' has no jndi-name in jboss.xml");
 1432                        else
 1433                           jndiName = linkJNDIName;
 1434                     }
 1435                  }
 1436                  else
 1437                     log.warn("message-destination-ref '" + refName + "' ignoring message-destination-link '" + link + "' because it has a jndi-name in jboss.xml");
 1438               }
 1439               else if (jndiName == null)
 1440                  throw new DeploymentException("message-destination-ref '" + refName + "' has no message-destination-link in ejb-jar.xml and no jndi-name in jboss.xml");
 1441               Util.bind(envCtx, refName, new LinkRef(jndiName));
 1442            }
 1443         }
 1444   
 1445         // Create a java:comp/env/security/security-domain link to the container
 1446         // or application security-domain if one exists so that access to the
 1447         // security manager can be made without knowing the global jndi name.
 1448   
 1449         String securityDomain = metaData.getContainerConfiguration().getSecurityDomain();
 1450         if (securityDomain == null)
 1451            securityDomain = metaData.getApplicationMetaData().getSecurityDomain();
 1452         if (securityDomain != null)
 1453         {
 1454            log.debug("Binding securityDomain: " + securityDomain + " to JDNI ENC as: security/security-domain");
 1455   
 1456            Util.bind(envCtx, "security/security-domain", new LinkRef(securityDomain));
 1457            Util.bind(envCtx, "security/subject", new LinkRef(securityDomain + "/subject"));
 1458            Util.bind(envCtx, "security/realmMapping", new LinkRef(securityDomain + "/realmMapping"));
 1459            Util.bind(envCtx, "security/authorizationMgr", new LinkRef(securityDomain + "/authorizationMgr"));
 1460         }
 1461   
 1462         log.debug("End java:comp/env for EJB: " + beanMetaData.getEjbName());
 1463      }
 1464   
 1465      public MessageDestinationMetaData getMessageDestination(String link)
 1466      {
 1467         return EjbUtil50.findMessageDestination(null, unit, link);
 1468      }
 1469   
 1470      /**
 1471       *The <code>teardownEnvironment</code> method unbinds everything from
 1472       * the comp/env context.  It would be better do destroy the env context
 1473       * but destroyContext is not currently implemented..
 1474       *
 1475       * @exception Exception if an error occurs
 1476       */
 1477      private void teardownEnvironment() throws Exception
 1478      {
 1479         Context ctx = (Context)new InitialContext().lookup("java:comp");
 1480         ctx.unbind("env");
 1481         log.debug("Removed bindings from java:comp/env for EJB: " + getBeanMetaData().getEjbName());
 1482         ctx.unbind("TransactionSynchronizationRegistry");
 1483         log.debug("Unbound java:comp/TransactionSynchronizationRegistry for EJB: " + getBeanMetaData().getEjbName());
 1484         try
 1485         {
 1486            NonSerializableFactory.unbind("ORB");
 1487            log.debug("Unbound java:comp/ORB for EJB: " + getBeanMetaData().getEjbName());
 1488   
 1489            NonSerializableFactory.unbind("HandleDelegate");
 1490            log.debug("Unbound java:comp/HandleDelegate for EJB: " + getBeanMetaData().getEjbName());
 1491         }
 1492         catch (NamingException ignored)
 1493         {
 1494         }
 1495      }
 1496   
 1497      /**
 1498       * The base class for container interceptors.
 1499       *
 1500       * <p>
 1501       * All container interceptors perform the same basic functionality
 1502       * and only differ slightly.
 1503       */
 1504      protected abstract class AbstractContainerInterceptor implements Interceptor
 1505      {
 1506         protected final Logger log = Logger.getLogger(this.getClass());
 1507   
 1508         public void setContainer(Container con)
 1509         {
 1510         }
 1511   
 1512         public void setNext(Interceptor interceptor)
 1513         {
 1514         }
 1515   
 1516         public Interceptor getNext()
 1517         {
 1518            return null;
 1519         }
 1520   
 1521         public void create()
 1522         {
 1523         }
 1524   
 1525         public void start()
 1526         {
 1527         }
 1528   
 1529         public void stop()
 1530         {
 1531         }
 1532   
 1533         public void destroy()
 1534         {
 1535         }
 1536   
 1537         protected void rethrow(Exception e) throws Exception
 1538         {
 1539            if (e instanceof IllegalAccessException)
 1540            {
 1541               // Throw this as a bean exception...(?)
 1542               throw new EJBException(e);
 1543            }
 1544            else if (e instanceof InvocationTargetException)
 1545            {
 1546               Throwable t = ((InvocationTargetException)e).getTargetException();
 1547   
 1548               if (t instanceof EJBException)
 1549               {
 1550                  throw (EJBException)t;
 1551               }
 1552               else if (t instanceof Exception)
 1553               {
 1554                  throw (Exception)t;
 1555               }
 1556               else if (t instanceof Error)
 1557               {
 1558                  throw (Error)t;
 1559               }
 1560               else
 1561               {
 1562                  throw new NestedError("Unexpected Throwable", t);
 1563               }
 1564            }
 1565   
 1566            throw e;
 1567         }
 1568   
 1569         // Monitorable implementation ------------------------------------
 1570   
 1571         public void sample(Object s)
 1572         {
 1573            // Just here to because Monitorable request it but will be removed soon
 1574         }
 1575   
 1576         public Map retrieveStatistic()
 1577         {
 1578            return null;
 1579         }
 1580   
 1581         public void resetStatistic()
 1582         {
 1583         }
 1584      }
 1585   
 1586      /** Perform the MBeanServer.invoke op in a PrivilegedExceptionAction if
 1587       * running with a security manager.
 1588       */
 1589      class MBeanServerAction implements PrivilegedExceptionAction
 1590      {
 1591         private ObjectName target;
 1592         String method;
 1593         Object[] args;
 1594         String[] sig;
 1595   
 1596         MBeanServerAction()
 1597         {
 1598         }
 1599   
 1600         MBeanServerAction(ObjectName target, String method, Object[] args, String[] sig)
 1601         {
 1602            this.target = target;
 1603            this.method = method;
 1604            this.args = args;
 1605            this.sig = sig;
 1606         }
 1607   
 1608         public Object run() throws Exception
 1609         {
 1610            Object rtnValue = server.invoke(target, method, args, sig);
 1611            return rtnValue;
 1612         }
 1613   
 1614         Object invoke(ObjectName target, String method, Object[] args, String[] sig) throws Exception
 1615         {
 1616            SecurityManager sm = System.getSecurityManager();
 1617            Object rtnValue = null;
 1618            if (sm == null)
 1619            {
 1620               // Direct invocation on MBeanServer
 1621               rtnValue = server.invoke(target, method, args, sig);
 1622            }
 1623            else
 1624            {
 1625               try
 1626               {
 1627                  // Encapsulate the invocation in a PrivilegedExceptionAction
 1628                  MBeanServerAction action = new MBeanServerAction(target, method, args, sig);
 1629                  rtnValue = AccessController.doPrivileged(action);
 1630               }
 1631               catch (PrivilegedActionException e)
 1632               {
 1633                  Exception ex = e.getException();
 1634                  throw ex;
 1635               }
 1636            }
 1637            return rtnValue;
 1638         }
 1639      }
 1640   }

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