Save This Page
Home » jboss-5.0.0.CR1-src » org » jboss » ejb » [javadoc | source]
    1   /*
    2    * JBoss, the OpenSource J2EE webOS
    3    *
    4    * Distributable under LGPL license.
    5    * See terms of license at gnu.org.
    6    */
    7   
    8   package org.jboss.ejb;
    9   
   10   import java.io.File;
   11   import java.io.InputStream;
   12   import java.net.URL;
   13   import java.util.ArrayList;
   14   import java.util.HashMap;
   15   import java.util.Iterator;
   16   import javax.management.MBeanServer;
   17   import javax.management.MalformedObjectNameException;
   18   import javax.management.ObjectName;
   19   import javax.transaction.TransactionManager;
   20   
   21   import org.jboss.deployment.DeploymentInfo;
   22   import org.jboss.deployment.SubDeployerSupport;
   23   import org.jboss.deployment.DeploymentException;
   24   import org.jboss.logging.Logger;
   25   import org.jboss.system.ServiceControllerMBean;
   26   import org.jboss.metadata.ApplicationMetaData;
   27   import org.jboss.metadata.XmlFileLoader;
   28   import org.jboss.metadata.MetaData;
   29   import org.jboss.mx.loading.LoaderRepositoryFactory;
   30   import org.jboss.mx.util.MBeanProxyExt;
   31   import org.jboss.mx.util.ObjectNameConverter;
   32   import org.jboss.verifier.BeanVerifier;
   33   import org.jboss.verifier.event.VerificationEvent;
   34   import org.jboss.verifier.event.VerificationListener;
   35   import org.w3c.dom.Element;
   36   
   37   /**
   38    * A EJBDeployer is used to deploy EJB applications. It can be given a
   39    * URL to an EJB-jar or EJB-JAR XML file, which will be used to instantiate
   40    * containers and make them available for invocation.
   41    *
   42    * @jmx:mbean
   43    *      name="jboss.ejb:service=EJBDeployer"
   44    *      extends="org.jboss.deployment.SubDeployerMBean"
   45    *
   46    * @see Container
   47    *
   48    * @version <tt>$Revision: 1.23.2.13 $</tt>
   49    * @author <a href="mailto:rickard.oberg@telkel.com">Rickard Öberg</a>
   50    * @author <a href="mailto:marc.fleury@telkel.com">Marc Fleury</a>
   51    * @author <a href="mailto:jplindfo@helsinki.fi">Juha Lindfors</a>
   52    * @author <a href="mailto:sebastien.alborini@m4x.org">Sebastien Alborini</a>
   53    * @author <a href="mailto:peter.antman@tim.se">Peter Antman</a>.
   54    * @author <a href="mailto:scott.stark@jboss.org">Scott Stark</a>
   55    * @author <a href="mailto:sacha.labourey@cogito-info.ch">Sacha Labourey</a>
   56    * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
   57    */
   58   public class EJBDeployer
   59      extends SubDeployerSupport
   60      implements EJBDeployerMBean
   61   {
   62      private ServiceControllerMBean serviceController;
   63   
   64      /** A map of current deployments. */
   65      private HashMap deployments = new HashMap();
   66   
   67      /** Verify EJB-jar contents on deployments */
   68      private boolean verifyDeployments;
   69   
   70      /** Enable verbose verification. */
   71      private boolean verifierVerbose;
   72   
   73      /** Enable strict verification: deploy JAR only if Verifier reports
   74       * no problems */
   75      private boolean strictVerifier;
   76   
   77      /** Enable metrics interceptor */
   78      private boolean metricsEnabled;
   79   
   80      /** A flag indicating if deployment descriptors should be validated */
   81      private boolean validateDTDs;
   82   
   83      private ObjectName webServiceName;
   84   
   85      private ObjectName transactionManagerServiceName;
   86      private TransactionManager tm;
   87   
   88      /**
   89       * Returns the deployed applications.
   90       *
   91       * @jmx:managed-operation
   92       */
   93      public Iterator getDeployedApplications()
   94      {
   95         return deployments.values().iterator();
   96      }
   97   
   98      protected ObjectName getObjectName(MBeanServer server, ObjectName name)
   99         throws MalformedObjectNameException
  100      {
  101         return name == null ? OBJECT_NAME : name;
  102      }
  103   
  104      /**
  105       * Get a reference to the ServiceController
  106       */
  107      protected void startService() throws Exception
  108      {
  109         serviceController = (ServiceControllerMBean)
  110            MBeanProxyExt.create(ServiceControllerMBean.class,
  111                                 ServiceControllerMBean.OBJECT_NAME, server);
  112         tm = (TransactionManager)getServer().getAttribute(transactionManagerServiceName,
  113                                                           "TransactionManager");
  114   
  115         // register with MainDeployer
  116         super.startService();
  117      }
  118   
  119      /**
  120       * Implements the template method in superclass. This method stops all the
  121       * applications in this server.
  122       */
  123      protected void stopService() throws Exception
  124      {
  125   
  126         for( Iterator modules = deployments.values().iterator();
  127            modules.hasNext(); )
  128         {
  129            DeploymentInfo di = (DeploymentInfo) modules.next();
  130            stop(di);
  131         }
  132   
  133         // avoid concurrent modification exception
  134         for( Iterator modules = new ArrayList(deployments.values()).iterator();
  135            modules.hasNext(); )
  136         {
  137            DeploymentInfo di = (DeploymentInfo) modules.next();
  138            destroy(di);
  139         }
  140         deployments.clear();
  141   
  142         // deregister with MainDeployer
  143         super.stopService();
  144   
  145         serviceController = null;
  146         tm = null;
  147      }
  148   
  149      /**
  150       * Enables/disables the application bean verification upon deployment.
  151       *
  152       * @jmx:managed-attribute
  153       *
  154       * @param   verify  true to enable; false to disable
  155       */
  156      public void setVerifyDeployments( boolean verify )
  157      {
  158         verifyDeployments = verify;
  159      }
  160   
  161      /**
  162       * Returns the state of bean verifier (on/off)
  163       *
  164       * @jmx:managed-attribute
  165       *
  166       * @return   true if enabled; false otherwise
  167       */
  168      public boolean getVerifyDeployments()
  169      {
  170         return verifyDeployments;
  171      }
  172   
  173      /**
  174       * Enables/disables the verbose mode on the verifier.
  175       *
  176       * @jmx:managed-attribute
  177       *
  178       * @param   verbose  true to enable; false to disable
  179       */
  180      public void setVerifierVerbose(boolean verbose)
  181      {
  182         verifierVerbose = verbose;
  183      }
  184   
  185      /**
  186       * Returns the state of the bean verifier (verbose/non-verbose mode)
  187       *
  188       * @jmx:managed-attribute
  189       *
  190       * @return true if enabled; false otherwise
  191       */
  192      public boolean getVerifierVerbose()
  193      {
  194         return verifierVerbose;
  195      }
  196   
  197      /**
  198       * Enables/disables the strict mode on the verifier.
  199       *
  200       * @jmx:managed-attribute
  201       *
  202       * @param strictVerifier <code>true</code> to enable; <code>false</code>
  203       *   to disable
  204       */
  205      public void setStrictVerifier( boolean strictVerifier )
  206      {
  207         this.strictVerifier = strictVerifier;
  208      }
  209   
  210      /**
  211       * Returns the mode of the bean verifier (strict/non-strict mode)
  212       *
  213       * @jmx:managed-attribute
  214       *
  215       * @return <code>true</code> if the Verifier is in strict mode,
  216       *   <code>false</code> otherwise
  217       */
  218      public boolean getStrictVerifier()
  219      {
  220         return strictVerifier;
  221      }
  222   
  223   
  224      /**
  225       * Enables/disables the metrics interceptor for containers.
  226       *
  227       * @jmx:managed-attribute
  228       *
  229       * @param enable  true to enable; false to disable
  230       */
  231      public void setMetricsEnabled(boolean enable)
  232      {
  233         metricsEnabled = enable;
  234      }
  235   
  236      /**
  237       * Checks if this container factory initializes the metrics interceptor.
  238       *
  239       * @jmx:managed-attribute
  240       *
  241       * @return   true if metrics are enabled; false otherwise
  242       */
  243      public boolean isMetricsEnabled()
  244      {
  245         return metricsEnabled;
  246      }
  247   
  248      /**
  249       * Get the flag indicating that ejb-jar.dtd, jboss.dtd &amp;
  250       * jboss-web.dtd conforming documents should be validated
  251       * against the DTD.
  252       *
  253       * @jmx:managed-attribute
  254       */
  255      public boolean getValidateDTDs()
  256      {
  257         return validateDTDs;
  258      }
  259   
  260      /**
  261       * Set the flag indicating that ejb-jar.dtd, jboss.dtd &amp;
  262       * jboss-web.dtd conforming documents should be validated
  263       * against the DTD.
  264       *
  265       * @jmx:managed-attribute
  266       */
  267      public void setValidateDTDs(boolean validate)
  268      {
  269         this.validateDTDs = validate;
  270      }
  271   
  272   
  273      /**
  274       * Get the WebServiceName value.
  275       * @return the WebServiceName value.
  276       *
  277       * @jmx:managed-attribute
  278       */
  279      public ObjectName getWebServiceName()
  280      {
  281         return webServiceName;
  282      }
  283   
  284      /**
  285       * Set the WebServiceName value.
  286       * @param newWebServiceName The new WebServiceName value.
  287       *
  288       * @jmx:managed-attribute
  289       */
  290      public void setWebServiceName(ObjectName webServiceName)
  291      {
  292         this.webServiceName = webServiceName;
  293      }
  294   
  295   
  296      /**
  297       * Get the TransactionManagerServiceName value.
  298       * @return the TransactionManagerServiceName value.
  299       *
  300       * @jmx:managed-attribute
  301       */
  302      public ObjectName getTransactionManagerServiceName()
  303      {
  304         return transactionManagerServiceName;
  305      }
  306   
  307      /**
  308       * Set the TransactionManagerServiceName value.
  309       * @param transactionManagerServiceName The new TransactionManagerServiceName value.
  310       *
  311       * @jmx:managed-attribute
  312       */
  313      public void setTransactionManagerServiceName(ObjectName transactionManagerServiceName)
  314      {
  315         this.transactionManagerServiceName = transactionManagerServiceName;
  316      }
  317   
  318   
  319   
  320      public boolean accepts(DeploymentInfo di)
  321      {
  322         // To be accepted the deployment's root name must end in jar
  323         String urlStr = di.url.getFile();
  324         if( !urlStr.endsWith("jar") && !urlStr.endsWith("jar/") )
  325         {
  326            return false;
  327         }
  328   
  329         // However the jar must also contain at least one ejb-jar.xml
  330         boolean accepts = false;
  331         try
  332         {
  333            URL dd = di.localCl.findResource("META-INF/ejb-jar.xml");
  334            if (dd == null)
  335            {
  336               return false;
  337            }
  338   
  339            // If the DD url is not a subset of the urlStr then this is coming
  340            // from a jar referenced by the deployment jar manifest and the
  341            // this deployment jar it should not be treated as an ejb-jar
  342            if( di.localUrl != null )
  343            {
  344               urlStr = di.localUrl.toString();
  345            }
  346   
  347            String ddStr = dd.toString();
  348            if ( ddStr.indexOf(urlStr) >= 0 )
  349            {
  350               accepts = true;
  351            }
  352         }
  353         catch( Exception ignore )
  354         {
  355         }
  356   
  357         return accepts;
  358      }
  359   
  360      public void init(DeploymentInfo di)
  361         throws DeploymentException
  362      {
  363         try
  364         {
  365            if( di.url.getProtocol().equalsIgnoreCase("file") )
  366            {
  367               File file = new File(di.url.getFile());
  368   
  369               if( !file.isDirectory() )
  370               {
  371                  // If not directory we watch the package
  372                  di.watch = di.url;
  373               }
  374               else
  375               {
  376                  // If directory we watch the xml files
  377                  di.watch = new URL(di.url, "META-INF/ejb-jar.xml");
  378               }
  379            }
  380            else
  381            {
  382               // We watch the top only, no directory support
  383               di.watch = di.url;
  384            }
  385   
  386            // Check for a loader-repository
  387            XmlFileLoader xfl = new XmlFileLoader();
  388            InputStream in = di.localCl.getResourceAsStream("META-INF/jboss.xml");
  389            if( in != null )
  390            {
  391               Element jboss = xfl.getDocument(in, "META-INF/jboss.xml").getDocumentElement();
  392               in.close();
  393               // Check for a ejb level class loading config
  394               Element loader = MetaData.getOptionalChild(jboss, "loader-repository");
  395               if( loader != null )
  396               {
  397                  LoaderRepositoryFactory.LoaderRepositoryConfig config =
  398                        LoaderRepositoryFactory.parseRepositoryConfig(loader);
  399                  di.setRepositoryInfo(config);
  400               }
  401            }
  402   
  403         }
  404         catch (Exception e)
  405         {
  406            if (e instanceof DeploymentException)
  407               throw (DeploymentException)e;
  408            throw new DeploymentException( "failed to initialize", e );
  409         }
  410   
  411         // invoke super-class initialization
  412         super.init(di);
  413      }
  414   
  415      /** This is here as a reminder that we may not want to allow ejb jars to
  416       * have arbitrary sub deployments. Currently we do.
  417       * @param di
  418       * @throws DeploymentException
  419       */ 
  420      protected void processNestedDeployments(DeploymentInfo di)
  421         throws DeploymentException
  422      {
  423         super.processNestedDeployments(di);
  424      }
  425   
  426      public synchronized void create(DeploymentInfo di)
  427         throws DeploymentException
  428      {
  429         try
  430         {
  431            // Create a file loader with which to load the files
  432            XmlFileLoader efm = new XmlFileLoader(validateDTDs);
  433            efm.setClassLoader(di.localCl);
  434   
  435            // Load XML
  436            di.metaData = efm.load();
  437         }
  438         catch (Exception e)
  439         {
  440            if (e instanceof DeploymentException)
  441               throw (DeploymentException)e;
  442            throw new DeploymentException( "Failed to load metadata", e );
  443         }
  444   
  445         if( verifyDeployments )
  446         {
  447            // we have a positive attitude
  448            boolean allOK = true;
  449   
  450            // wrapping this into a try - catch block to prevent errors in
  451            // verifier from stopping the deployment
  452            try
  453            {
  454               BeanVerifier verifier = new BeanVerifier();
  455   
  456               // add a listener so we can log the results
  457               verifier.addVerificationListener(new VerificationListener()
  458                  {
  459                     Logger log = Logger.getLogger(EJBDeployer.class,
  460                        "verifier" );
  461   
  462                     public void beanChecked(VerificationEvent event)
  463                     {
  464                        log.debug( "Bean checked: " + event.getMessage() );
  465                     }
  466   
  467                     public void specViolation(VerificationEvent event)
  468                     {
  469                        log.warn( "EJB spec violation: " +
  470                           (verifierVerbose ? event.getVerbose() : event.getMessage()));
  471                     }
  472                  });
  473   
  474               log.debug("Verifying " + di.url);
  475               verifier.verify( di.url, (ApplicationMetaData) di.metaData,
  476                  di.ucl );
  477   
  478               allOK = verifier.getSuccess();
  479            }
  480            catch (Throwable t)
  481            {
  482               log.warn("Verify failed; continuing", t );
  483               allOK = false;
  484            }
  485   
  486            // If the verifier is in strict mode and an error/warning
  487            // was found in the Verification process, throw a Deployment
  488            // Exception
  489            if( strictVerifier && !allOK )
  490            {
  491               throw new DeploymentException( "Verification of Enterprise " +
  492                  "Beans failed, see above for error messages." );
  493            }
  494   
  495         }
  496   
  497         // Create an MBean for the EJB module
  498         try
  499         {
  500            ApplicationMetaData metadata = (ApplicationMetaData) di.metaData;
  501            EjbModule ejbModule = new EjbModule(di, tm, webServiceName);
  502            String name = metadata.getJmxName();
  503            if( name == null )
  504            {
  505               name = EjbModule.BASE_EJB_MODULE_NAME + ",module=" + di.shortName; 
  506            }
  507            // Build an escaped JMX name including deployment shortname
  508            ObjectName ejbModuleName = ObjectNameConverter.convert(name);
  509            // Check that the name is not registered
  510            if( server.isRegistered(ejbModuleName) == true )
  511            {
  512               log.debug("The EJBModule name: "+ejbModuleName
  513                  +"is already registered, adding uid="+System.identityHashCode(ejbModule));
  514               name = name + ",uid="+System.identityHashCode(ejbModule);
  515               ejbModuleName = ObjectNameConverter.convert(name);
  516            }
  517   
  518            server.registerMBean(ejbModule, ejbModuleName);
  519            di.deployedObject = ejbModuleName;
  520   
  521            log.debug( "Deploying: " + di.url );
  522            // Invoke the create life cycle method
  523            serviceController.create(di.deployedObject);
  524         }
  525         catch (Exception e)
  526         {
  527            throw new DeploymentException("Error during create of EjbModule: "
  528               + di.url, e);
  529         }
  530         super.create(di);
  531      }
  532   
  533      public synchronized void start(DeploymentInfo di)
  534         throws DeploymentException
  535      {
  536         try
  537         {
  538            // Start application
  539            log.debug( "start application, deploymentInfo: " + di +
  540                       ", short name: " + di.shortName +
  541                       ", parent short name: " +
  542                       (di.parent == null ? "null" : di.parent.shortName) );
  543   
  544            serviceController.start(di.deployedObject);
  545   
  546            log.info( "Deployed: " + di.url );
  547   
  548            // Register deployment. Use the application name in the hashtable
  549            // FIXME: this is obsolete!! (really?!)
  550            deployments.put(di.url, di);
  551         }
  552         catch (Exception e)
  553         {
  554            stop(di);
  555            destroy(di);
  556   
  557            throw new DeploymentException( "Could not deploy " + di.url, e );
  558         }
  559         super.start(di);
  560      }
  561   
  562      public void stop(DeploymentInfo di)
  563         throws DeploymentException
  564      {
  565         try
  566         {
  567            serviceController.stop(di.deployedObject);
  568         }
  569         catch (Exception e)
  570         {
  571            throw new DeploymentException( "problem stopping ejb module: " +
  572               di.url, e );
  573         }
  574         super.stop(di);
  575      }
  576   
  577      public void destroy(DeploymentInfo di)
  578         throws DeploymentException
  579      {
  580         // FIXME: If the put() is obsolete above, this is obsolete, too
  581         deployments.remove(di.url);
  582   
  583         try
  584         {
  585            serviceController.destroy( di.deployedObject );
  586            serviceController.remove( di.deployedObject );
  587         }
  588         catch (Exception e)
  589         {
  590            throw new DeploymentException( "problem destroying ejb module: " +
  591               di.url, e );
  592         }
  593         super.destroy(di);
  594      }
  595   }
  596   /*
  597   vim:ts=3:sw=3:et
  598   */

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