Save This Page
Home » JBoss-5.1.0 » org » jboss » system » server » [javadoc | source]
    1   /***************************************
    2    *                                     *
    3    *  JBoss: The OpenSource J2EE WebOS   *
    4    *                                     *
    5    *  Distributable under LGPL license.  *
    6    *  See terms of license at gnu.org.   *
    7    *                                     *
    8    ***************************************/
    9   
   10   package org.jboss.system.server;
   11   
   12   import java.io.File;
   13   import java.net.URL;
   14   
   15   import java.util.List;
   16   import java.util.ArrayList;
   17   import java.util.Date;
   18   import java.util.Iterator;
   19   import java.util.Properties;
   20   
   21   import javax.management.Attribute;
   22   import javax.management.MBeanServer;
   23   import javax.management.MBeanServerFactory;
   24   import javax.management.NotificationBroadcasterSupport;
   25   import javax.management.ObjectName;
   26   import javax.management.Notification;
   27   import javax.management.NotificationListener;
   28   import javax.management.NotificationFilter;
   29   import javax.management.ListenerNotFoundException;
   30   import javax.management.MBeanNotificationInfo;
   31   import javax.management.NotificationBroadcaster;
   32   
   33   import org.jboss.Version;
   34   import org.jboss.deployment.MainDeployerMBean;
   35   import org.jboss.deployment.IncompleteDeploymentException;
   36   import org.jboss.logging.Logger;
   37   import org.jboss.mx.loading.UnifiedClassLoader;
   38   import org.jboss.mx.server.ServerConstants;
   39   import org.jboss.net.protocol.URLStreamHandlerFactory;
   40   import org.jboss.util.StopWatch;
   41   import org.jboss.util.file.Files;
   42   import org.jboss.util.file.FileSuffixFilter;
   43   import org.jboss.mx.util.JMXExceptionDecoder;
   44   import org.jboss.mx.util.ObjectNameFactory;
   45   import org.jboss.mx.util.MBeanProxyExt;
   46   import org.jboss.system.ServiceControllerMBean;
   47   
   48   
   49   /**
   50    * The main container component of a JBoss server instance.
   51    *
   52    * <h3>Concurrency</h3>
   53    * This class is <b>not</b> thread-safe.
   54    *
   55    * @jmx:mbean name="jboss.system:type=Server"
   56    *
   57    * @author <a href="mailto:marc.fleury@jboss.org">Marc Fleury</a>
   58    * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
   59    * @author Scott.Stark@jboss.org
   60    * @version $Revision: 1.25.2.17 $
   61    */
   62   public class ServerImpl
   63      implements Server, ServerImplMBean, NotificationBroadcaster
   64   {
   65      private final static ObjectName DEFAULT_LOADER_NAME =
   66         ObjectNameFactory.create(ServerConstants.DEFAULT_LOADER_NAME);
   67   
   68      /** Instance logger. */
   69      private Logger log;
   70   
   71      /** Container for version information. */
   72      private final Version version = Version.getInstance();
   73   
   74      /** Package information for org.jboss */
   75      private final Package jbossPackage = Package.getPackage("org.jboss");
   76   
   77      /** The basic configuration for the server. */
   78      private ServerConfigImpl config;
   79   
   80      /** The JMX MBeanServer which will serve as our communication bus. */
   81      private MBeanServer server;
   82   
   83      /** When the server was started. */
   84      private Date startDate;
   85   
   86      /** Flag to indicate if we are started. */
   87      private boolean started;
   88   
   89      /** The JVM shutdown hook */
   90      private ShutdownHook shutdownHook;
   91   
   92      /** The JBoss Life Thread */
   93      private LifeThread lifeThread;
   94   
   95      /** The NotificationBroadcaster implementation delegate */
   96      private NotificationBroadcasterSupport broadcasterSupport;
   97   
   98      /**
   99       * No-arg constructor for {@link ServerLoader}.
  100       */
  101      public ServerImpl()
  102      {
  103      }
  104   
  105      /**
  106       * Initialize the Server instance.
  107       *
  108       * @param props     The configuration properties for the server.
  109       * @return          Typed server configuration object.
  110       *
  111       * @throws IllegalStateException    Already initialized.
  112       * @throws Exception                Failed to initialize.
  113       */
  114      public void init(final Properties props) throws IllegalStateException, Exception
  115      {
  116         if (props == null)
  117            throw new IllegalArgumentException("props is null");
  118         if (config != null)
  119            throw new IllegalStateException("already initialized");
  120   
  121         ClassLoader oldCL = Thread.currentThread().getContextClassLoader();
  122   
  123         try
  124         {
  125            Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
  126            doInit(props);
  127         }
  128         finally
  129         {
  130            Thread.currentThread().setContextClassLoader(oldCL);
  131         }
  132      }
  133   
  134      /** Actually does the init'ing... */
  135      private void doInit(final Properties props) throws Exception
  136      {
  137         // Create a new config object from the give properties
  138         this.config = new ServerConfigImpl(props);
  139   
  140         // Create the NotificationBroadcaster delegate
  141         broadcasterSupport = new NotificationBroadcasterSupport();
  142   
  143         // Set the VM temp directory to the server tmp dir
  144         boolean overrideTmpDir = Boolean.getBoolean("jboss.server.temp.dir.overrideJavaTmpDir");
  145         if( overrideTmpDir )
  146         {
  147            File serverTmpDir = config.getServerTempDir();
  148            System.setProperty("java.io.tmpdir", serverTmpDir.getCanonicalPath());
  149         }
  150   
  151         // masqurade as Server.class (cause Impl is not really important)
  152         log = Logger.getLogger(Server.class);
  153   
  154         // Setup URL handlers - do this before initializing the ServerConfig
  155         initURLHandlers();
  156         config.initURLs();
  157   
  158         log.info("Starting JBoss (MX MicroKernel)...");
  159   
  160         // Show what release this is...
  161         log.info("Release ID: " +
  162                  jbossPackage.getImplementationTitle() + " " +
  163                  jbossPackage.getImplementationVersion());
  164   
  165         log.debug("Using config: " + config);
  166   
  167         // make sure our impl type is exposed
  168         log.debug("Server type: " + getClass());
  169   
  170         // Log the basic configuration elements
  171         log.info("Home Dir: " + config.getHomeDir());
  172         log.info("Home URL: " + config.getHomeURL());
  173         log.info("Library URL: " + config.getLibraryURL());
  174         log.info("Patch URL: " + config.getPatchURL());
  175         log.info("Server Name: " + config.getServerName());
  176         log.info("Server Home Dir: " + config.getServerHomeDir());
  177         log.info("Server Home URL: " + config.getServerHomeURL());
  178         log.info("Server Data Dir: " + config.getServerDataDir());
  179         log.info("Server Temp Dir: " + config.getServerTempDir());
  180         log.info("Server Config URL: " + config.getServerConfigURL());
  181         log.info("Server Library URL: " + config.getServerLibraryURL());
  182         log.info("Root Deployemnt Filename: " + config.getRootDeploymentFilename());
  183      }
  184   
  185      /**
  186       * The <code>initURLHandlers</code> method calls
  187       * internalInitURLHandlers.  if requireJBossURLStreamHandlers is
  188       * false, any exceptions are logged and ignored.
  189       *
  190       */
  191      private void initURLHandlers()
  192      {
  193         if (config.getRequireJBossURLStreamHandlerFactory())
  194         {
  195            internalInitURLHandlers();
  196         } // end of if ()
  197         else
  198         {
  199            try
  200            {
  201               internalInitURLHandlers();
  202            }
  203            catch (SecurityException e)
  204            {
  205               log.warn("You do not have permissions to set URLStreamHandlerFactory", e);
  206            } // end of try-catch
  207            catch (Error e)
  208            {
  209               log.warn("URLStreamHandlerFactory already set", e);
  210            } // end of catch
  211         } // end of else
  212      }
  213   
  214      /**
  215       * Set up our only URLStreamHandlerFactory.
  216       * This is needed to ensure Sun's version is not used (as it leaves files
  217       * locked on Win2K/WinXP platforms.
  218       */
  219      private void internalInitURLHandlers()
  220      {
  221         // Install a URLStreamHandlerFactory that uses the TCL
  222         URL.setURLStreamHandlerFactory(new URLStreamHandlerFactory());
  223   
  224         // Preload JBoss URL handlers
  225         URLStreamHandlerFactory.preload();
  226   
  227         // Include the default JBoss protocol handler package
  228         String handlerPkgs = System.getProperty("java.protocol.handler.pkgs");
  229         if (handlerPkgs != null)
  230         {
  231            handlerPkgs += "|org.jboss.net.protocol";
  232         }
  233         else
  234         {
  235            handlerPkgs = "org.jboss.net.protocol";
  236         }
  237         System.setProperty("java.protocol.handler.pkgs", handlerPkgs);
  238      }
  239   
  240      /**
  241       * Get the typed server configuration object which the
  242       * server has been initalized to use.
  243       *
  244       * @return          Typed server configuration object.
  245       *
  246       * @throws IllegalStateException    Not initialized.
  247       */
  248      public ServerConfig getConfig() throws IllegalStateException
  249      {
  250         if (config == null)
  251            throw new IllegalStateException("not initialized");
  252   
  253         return config;
  254      }
  255   
  256      /**
  257       * Check if the server is started.
  258       *
  259       * @return   True if the server is started, else false.
  260       * @jmx:managed-attribute
  261       */
  262      public boolean isStarted()
  263      {
  264         return started;
  265      }
  266   
  267      /**
  268       * Start the Server instance.
  269       *
  270       * @throws IllegalStateException    Already started or not initialized.
  271       * @throws Exception                Failed to start.
  272       */
  273      public void start() throws IllegalStateException, Exception
  274      {
  275         // make sure we are initialized
  276         getConfig();
  277   
  278         // make sure we aren't started yet
  279         if (started)
  280            throw new IllegalStateException("already started");
  281   
  282         ClassLoader oldCL = Thread.currentThread().getContextClassLoader();
  283   
  284         try
  285         {
  286            Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
  287   
  288            // Deal with those pesky JMX throwables
  289            try
  290            {
  291               doStart();
  292            }
  293            catch (Exception e)
  294            {
  295               JMXExceptionDecoder.rethrow(e);
  296            }
  297         }
  298         catch (Throwable t)
  299         {
  300            log.debug("Failed to start", t);
  301   
  302            if (t instanceof Exception)
  303               throw (Exception)t;
  304            if (t instanceof Error)
  305               throw (Error)t;
  306   
  307            throw new org.jboss.util.UnexpectedThrowable(t);
  308         }
  309         finally
  310         {
  311            Thread.currentThread().setContextClassLoader(oldCL);
  312         }
  313      }
  314   
  315      /** Actually does the starting... */
  316      private void doStart() throws Exception
  317      {
  318         // See how long it takes us to start up
  319         StopWatch watch = new StopWatch(true);
  320   
  321         // remeber when we we started
  322         startDate = new Date();
  323   
  324         log.info("Starting General Purpose Architecture (GPA)...");
  325   
  326         // Create the MBeanServer
  327         server = MBeanServerFactory.createMBeanServer("jboss");
  328         log.debug("Created MBeanServer: " + server);
  329   
  330         // Register server components
  331         server.registerMBean(this, ServerImplMBean.OBJECT_NAME);
  332         server.registerMBean(config, ServerConfigImplMBean.OBJECT_NAME);
  333   
  334         // Initialize spine boot libraries
  335         UnifiedClassLoader ucl = initBootLibraries();
  336   
  337         // Set ServiceClassLoader as classloader for the construction of
  338         // the basic system
  339         Thread.currentThread().setContextClassLoader(ucl);
  340   
  341         // General Purpose Architecture information
  342         createMBean("org.jboss.system.server.ServerInfo");
  343   
  344         // Service Controller
  345         ObjectName controller = createMBean("org.jboss.system.ServiceController");
  346   
  347         // Main Deployer
  348         ObjectName mainDeployer = startBootService(controller, "org.jboss.deployment.MainDeployer");
  349         server.setAttribute(mainDeployer,
  350                             new Attribute("ServiceController", controller));
  351   
  352         // Install the shutdown hook
  353         shutdownHook = new ShutdownHook(controller, mainDeployer);
  354         shutdownHook.setDaemon(true);
  355   
  356         try
  357         {
  358            Runtime.getRuntime().addShutdownHook(shutdownHook);
  359            log.debug("Shutdown hook added");
  360         }
  361         catch (Exception e)
  362         {
  363            log.warn("Failed to add shutdown hook; ignoring", e);
  364         }
  365   
  366         // JARDeployer, required to process <classpath>
  367         startBootService(controller, "org.jboss.deployment.JARDeployer");
  368   
  369         // SARDeployer, required to process *-service.xml
  370         startBootService(controller, "org.jboss.deployment.SARDeployer");
  371   
  372         log.info("Core system initialized");
  373   
  374         // TODO: Split up init (ie. create) from start ops so we can expose more control
  375         //       to embeded clients.
  376   
  377         // Ok, now deploy the root deployable to finish the job
  378   
  379         MainDeployerMBean md = (MainDeployerMBean)
  380            MBeanProxyExt.create(MainDeployerMBean.class, mainDeployer, server);
  381   
  382         try
  383         {
  384            md.deploy(config.getServerConfigURL() + config.getRootDeploymentFilename());
  385         }
  386         catch (IncompleteDeploymentException e) {
  387            log.error("Root deployment has missing dependencies; continuing", e);
  388         }
  389   
  390         lifeThread = new LifeThread();
  391         lifeThread.start();
  392   
  393         watch.stop();
  394         // Tell the world how fast it was =)
  395         log.info("JBoss (MX MicroKernel) [" + jbossPackage.getImplementationVersion() +
  396                  "] Started in " + watch);
  397         started = true;
  398   
  399         // Send a notification that the startup is complete
  400         Notification msg = new Notification(START_NOTIFICATION_TYPE, this, 1);
  401         msg.setUserData(new Long(watch.getLapTime()));
  402         sendNotification(msg);
  403      }
  404   
  405      /**
  406       * Instantiate and register a service for the given classname into the MBean server.
  407       */
  408      private ObjectName createMBean(final String classname)
  409         throws Exception
  410      {
  411         ObjectName name = server.createMBean(classname, null).getObjectName();
  412         log.debug("Created system MBean: " + name);
  413   
  414         return name;
  415      }
  416   
  417      /**
  418       * Instantiate/register, create and start a service for the given classname.
  419       */
  420      private ObjectName startBootService(final ObjectName controllerName, final String classname)
  421         throws Exception
  422      {
  423         ObjectName name = createMBean(classname);
  424   
  425         // now go through the create/start sequence on the new service
  426   
  427         Object[] args = { name };
  428         String[] sig = { ObjectName.class.getName() };
  429   
  430         server.invoke(controllerName, "create", args, sig);
  431         server.invoke(controllerName, "start", args, sig);
  432   
  433         return name;
  434      }
  435   
  436      /**
  437       * Initialize the boot libraries.
  438       */
  439      private UnifiedClassLoader initBootLibraries() throws Exception
  440      {
  441         boolean debug = log.isDebugEnabled();
  442   
  443         // Build the list of URL for the spine to boot
  444         List list = new ArrayList();
  445   
  446         // Add the patch URL.  If the url protocol is file, then
  447         // add the contents of the directory it points to
  448         URL patchURL = config.getPatchURL();
  449         if (patchURL != null)
  450         {
  451            if (patchURL.getProtocol().equals("file"))
  452            {
  453               File dir = new File(patchURL.getFile());
  454               if (dir.exists())
  455               {
  456                  // Add the local file patch directory
  457                  list.add(dir.toURL());
  458   
  459                  // Add the contents of the directory too
  460                  File[] jars = dir.listFiles(new FileSuffixFilter(new String[] { ".jar", ".zip" }, true));
  461   
  462                  for (int j = 0; jars != null && j < jars.length; j++)
  463                  {
  464                     list.add(jars[j].getCanonicalFile().toURL());
  465                  }
  466               }
  467            }
  468            else
  469            {
  470               list.add(patchURL);
  471            }
  472         }
  473   
  474         // Add the server configuration directory to be able to load config files as resources
  475         list.add(config.getServerConfigURL());
  476   
  477         // Not needed, ServerImpl will have the basics on its classpath from ServerLoader
  478         // may want to bring this back at some point if we want to have reloadable core
  479         // components...
  480   
  481         // URL libraryURL = config.getLibraryURL();
  482         // list.add(new URL(libraryURL, "jboss-spine.jar"));
  483   
  484         log.debug("Boot url list: " + list);
  485   
  486         // Create loaders for each URL
  487         UnifiedClassLoader loader = null;
  488         for (Iterator iter = list.iterator(); iter.hasNext();)
  489         {
  490            URL url = (URL)iter.next();
  491            if (debug)
  492            {
  493               log.debug("Creating loader for URL: " + url);
  494            }
  495   
  496            // This is a boot URL, so key it on itself.
  497            Object[] args = {url, Boolean.TRUE};
  498            String[] sig = {"java.net.URL", "boolean"};
  499            loader = (UnifiedClassLoader) server.invoke(DEFAULT_LOADER_NAME, "newClassLoader", args, sig);
  500         }
  501         return loader;
  502      }
  503   
  504      /**
  505       * Shutdown the Server instance and run shutdown hooks.
  506       *
  507       * <p>If the exit on shutdown flag is true, then {@link #exit}
  508       *    is called, else only the shutdown hook is run.
  509       *
  510       * @jmx:managed-operation
  511       *
  512       * @throws IllegalStateException    No started.
  513       */
  514      public void shutdown() throws IllegalStateException
  515      {
  516         if (!started)
  517            throw new IllegalStateException("not started");
  518   
  519         final ServerImpl server = this;
  520   
  521         log.info("Shutting down");
  522   
  523         boolean exitOnShutdown = config.getExitOnShutdown();
  524         boolean blockingShutdown = config.getBlockingShutdown();
  525         if (log.isDebugEnabled())
  526         {
  527            log.debug("exitOnShutdown: " + exitOnShutdown);
  528            log.debug("blockingShutdown: " + blockingShutdown);
  529         }
  530   
  531         lifeThread.interrupt();
  532   
  533         if (exitOnShutdown)
  534         {
  535            server.exit(0);
  536         }
  537         else if (blockingShutdown)
  538         {
  539            shutdownHook.shutdown();
  540         } // end of if ()
  541         else
  542         {
  543            // start in new thread to give positive
  544            // feedback to requesting client of success.
  545            new Thread()
  546            {
  547               public void run()
  548               {
  549                  // just run the hook, don't call System.exit, as we may
  550                  // be embeded in a vm that would not like that very much
  551                  shutdownHook.shutdown();
  552               }
  553            }.start();
  554         }
  555      }
  556   
  557      /**
  558       * Shutdown the server, the JVM and run shutdown hooks.
  559       *
  560       * @jmx:managed-operation
  561       *
  562       * @param exitcode   The exit code returned to the operating system.
  563       */
  564      public void exit(final int exitcode)
  565      {
  566         // start in new thread so that we might have a chance to give positive
  567         // feed back to requesting client of success.
  568         new Thread()
  569         {
  570            public void run()
  571            {
  572               log.info("Shutting down the JVM now!");
  573               Runtime.getRuntime().exit(exitcode);
  574            }
  575         }.start();
  576      }
  577   
  578      /**
  579       * Shutdown the server, the JVM and run shutdown hooks.  Exits with
  580       * code 1.
  581       *
  582       * @jmx:managed-operation
  583       */
  584      public void exit()
  585      {
  586         exit(1);
  587      }
  588   
  589      /**
  590       * Forcibly terminates the currently running Java virtual machine.
  591       *
  592       * @param exitcode   The exit code returned to the operating system.
  593       *
  594       * @jmx:managed-operation
  595       */
  596      public void halt(final int exitcode)
  597      {
  598         // Send a notification that the startup is complete
  599         Notification msg = new Notification(STOP_NOTIFICATION_TYPE, this, 2);
  600         sendNotification(msg);
  601   
  602         // start in new thread so that we might have a chance to give positive
  603         // feed back to requesting client of success.
  604         new Thread()
  605         {
  606            public void run()
  607            {
  608               System.err.println("Halting the system now!");
  609               Runtime.getRuntime().halt(exitcode);
  610            }
  611         }.start();
  612      }
  613   
  614      /**
  615       * Forcibly terminates the currently running Java virtual machine.
  616       * Exits with code 1.
  617       *
  618       * @jmx:managed-operation
  619       */
  620      public void halt()
  621      {
  622         halt(1);
  623      }
  624   
  625   
  626      ///////////////////////////////////////////////////////////////////////////
  627      //                            Runtime Access                             //
  628      ///////////////////////////////////////////////////////////////////////////
  629   
  630      /** A simple helper used to log the Runtime memory information. */
  631      private void logMemoryUsage(final Runtime rt)
  632      {
  633         log.info("Total/free memory: " + rt.totalMemory() + "/" + rt.freeMemory());
  634      }
  635   
  636      /**
  637       * Hint to the JVM to run the garbage collector.
  638       *
  639       * @jmx:managed-operation
  640       */
  641      public void runGarbageCollector()
  642      {
  643         Runtime rt = Runtime.getRuntime();
  644   
  645         logMemoryUsage(rt);
  646         rt.gc();
  647         log.info("Hinted to the JVM to run garbage collection");
  648         logMemoryUsage(rt);
  649      }
  650   
  651      /**
  652       * Hint to the JVM to run any pending object finailizations.
  653       *
  654       * @jmx:managed-operation
  655       */
  656      public void runFinalization()
  657      {
  658         Runtime.getRuntime().runFinalization();
  659         log.info("Hinted to the JVM to run any pending object finalizations");
  660      }
  661   
  662      /**
  663       * Enable or disable tracing method calls at the Runtime level.
  664       *
  665       * @jmx:managed-operation
  666       */
  667      public void traceMethodCalls(final Boolean flag)
  668      {
  669         Runtime.getRuntime().traceMethodCalls(flag.booleanValue());
  670      }
  671   
  672      /**
  673       * Enable or disable tracing instructions the Runtime level.
  674       *
  675       * @jmx:managed-operation
  676       */
  677      public void traceInstructions(final Boolean flag)
  678      {
  679         Runtime.getRuntime().traceInstructions(flag.booleanValue());
  680      }
  681   
  682   
  683      ///////////////////////////////////////////////////////////////////////////
  684      //                          Server Information                           //
  685      ///////////////////////////////////////////////////////////////////////////
  686   
  687      /**
  688       * @jmx:managed-attribute
  689       */
  690      public Date getStartDate()
  691      {
  692         return startDate;
  693      }
  694   
  695      /**
  696       * @jmx:managed-attribute
  697       */
  698      public String getVersion()
  699      {
  700         return version.toString();
  701      }
  702   
  703      /**
  704       * @jmx:managed-attribute
  705       */
  706      public String getVersionName()
  707      {
  708         return version.getName();
  709      }
  710   
  711      /**
  712       * @jmx:managed-attribute
  713       */
  714      public String getBuildNumber()
  715      {
  716         return version.getBuildNumber();
  717      }
  718   
  719      /**
  720       * @jmx:managed-attribute
  721       */
  722      public String getBuildID()
  723      {
  724         return version.getBuildID();
  725      }
  726   
  727      /**
  728       * @jmx:managed-attribute
  729       */
  730      public String getBuildDate()
  731      {
  732         return version.getBuildDate();
  733      }
  734   
  735   // Begin NotificationBroadcaster interface methods
  736      public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback)
  737      {
  738         broadcasterSupport.addNotificationListener(listener, filter, handback);
  739      }
  740   
  741      public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException
  742      {
  743         broadcasterSupport.removeNotificationListener(listener);
  744      }
  745   
  746      public MBeanNotificationInfo[] getNotificationInfo()
  747      {
  748         return broadcasterSupport.getNotificationInfo();
  749      }
  750   
  751      public void sendNotification(Notification notification)
  752      {
  753         broadcasterSupport.sendNotification(notification);
  754      }
  755   // End NotificationBroadcaster interface methods
  756   
  757      ///////////////////////////////////////////////////////////////////////////
  758      //                             Life Thread                               //
  759      ///////////////////////////////////////////////////////////////////////////
  760   
  761      private class LifeThread
  762         extends Thread
  763      {
  764         Object lock = new Object();
  765   
  766         public void run()
  767         {
  768            synchronized (lock)
  769            {
  770               try
  771               {
  772                  lock.wait();
  773               }
  774               catch (InterruptedException ignore)
  775               {
  776               }
  777            }
  778            log.info("LifeThread.run exits!");
  779         }
  780      }
  781   
  782      ///////////////////////////////////////////////////////////////////////////
  783      //                             Shutdown Hook                             //
  784      ///////////////////////////////////////////////////////////////////////////
  785   
  786      private class ShutdownHook
  787         extends Thread
  788      {
  789         /** The ServiceController which we will ask to shut things down with. */
  790         private ObjectName controller;
  791   
  792         /** The MainDeployer which we will ask to undeploy everything. */
  793         private ObjectName mainDeployer;
  794   
  795         private boolean forceHalt = true;
  796   
  797         public ShutdownHook(final ObjectName controller, final ObjectName mainDeployer)
  798         {
  799            super("JBoss Shutdown Hook");
  800   
  801            this.controller = controller;
  802            this.mainDeployer = mainDeployer;
  803   
  804            String value = System.getProperty("jboss.shutdown.forceHalt", null);
  805            if (value != null) {
  806               forceHalt = new Boolean(value).booleanValue();
  807            }
  808         }
  809   
  810         public void run()
  811         {
  812            shutdown();
  813   
  814            // later bitch
  815            if (forceHalt) {
  816               System.out.println("Halting VM");
  817               Runtime.getRuntime().halt(0);
  818            }
  819         }
  820   
  821         public void shutdown()
  822         {
  823            log.info("JBoss SHUTDOWN: Undeploying all packages");
  824            shutdownDeployments();
  825   
  826            log.info("Shutting down all services");
  827            System.out.println("Shutting down");
  828   
  829            // Make sure all services are down properly
  830            shutdownServices();
  831   
  832            // Make sure all mbeans are unregistered
  833            removeMBeans();
  834   
  835            log.debug("Deleting server tmp/deploy directory");
  836            File tmp = config.getServerTempDir();
  837            File tmpDeploy = new File(tmp, "deploy");
  838            Files.delete(tmpDeploy);
  839   
  840            log.info("Shutdown complete");
  841            System.out.println("Shutdown complete");
  842         }
  843   
  844         protected void shutdownDeployments()
  845         {
  846            try
  847            {
  848               // get the deployed objects from ServiceController
  849               server.invoke(mainDeployer,
  850                             "shutdown",
  851                             new Object[0],
  852                             new String[0]);
  853            }
  854            catch (Exception e)
  855            {
  856               Throwable t = JMXExceptionDecoder.decode(e);
  857               log.error("Failed to shutdown deployer", t);
  858            }
  859         }
  860   
  861         /**
  862          * The <code>shutdownServices</code> method calls the one and only
  863          * ServiceController to shut down all the mbeans registered with it.
  864          */
  865         protected void shutdownServices()
  866         {
  867            try
  868            {
  869               // get the deployed objects from ServiceController
  870               server.invoke(controller,
  871                             "shutdown",
  872                             new Object[0],
  873                             new String[0]);
  874            }
  875            catch (Exception e)
  876            {
  877               Throwable t = JMXExceptionDecoder.decode(e);
  878               log.error("Failed to shutdown services", t);
  879            }
  880         }
  881   
  882         /**
  883          * The <code>removeMBeans</code> method uses the mbean server to unregister
  884          * all the mbeans registered here.
  885          */
  886         protected void removeMBeans()
  887         {
  888            try
  889            {
  890               server.unregisterMBean(ServiceControllerMBean.OBJECT_NAME);
  891               server.unregisterMBean(ServerConfigImplMBean.OBJECT_NAME);
  892               server.unregisterMBean(ServerImplMBean.OBJECT_NAME);
  893            }
  894            catch (Exception e)
  895            {
  896               Throwable t = JMXExceptionDecoder.decode(e);
  897               log.error("Failed to unregister mbeans", t);
  898            }
  899            try
  900            {
  901               MBeanServerFactory.releaseMBeanServer(server);
  902            }
  903            catch (Exception e)
  904            {
  905               Throwable t = JMXExceptionDecoder.decode(e);
  906               log.error("Failed to release mbean server", t);
  907            }
  908         }
  909      }
  910   }

Save This Page
Home » JBoss-5.1.0 » org » jboss » system » server » [javadoc | source]