KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > system > server > profileservice > ServerImpl


1 /*
2  * JBoss, Home of Professional Open Source
3  * Copyright 2005, JBoss Inc., and individual contributors as indicated
4  * by the @authors tag. See the copyright.txt in the distribution for a
5  * full listing of individual contributors.
6  *
7  * This is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * This software is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this software; if not, write to the Free
19  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21  */

22
23 package org.jboss.system.server.profileservice;
24
25 import java.io.File JavaDoc;
26 import java.net.URL JavaDoc;
27 import java.util.Date JavaDoc;
28 import java.util.Properties JavaDoc;
29
30 import javax.management.Notification JavaDoc;
31 import javax.management.NotificationBroadcasterSupport JavaDoc;
32 import javax.management.NotificationEmitter JavaDoc;
33
34 import org.jboss.Version;
35 import org.jboss.deployers.spi.deployment.MainDeployer;
36 import org.jboss.kernel.Kernel;
37 import org.jboss.kernel.plugins.deployment.BasicKernelDeployer;
38 import org.jboss.kernel.spi.event.KernelEvent;
39 import org.jboss.logging.Logger;
40 import org.jboss.net.protocol.URLStreamHandlerFactory;
41 import org.jboss.system.server.Server;
42 import org.jboss.system.server.ServerConfig;
43 import org.jboss.system.server.BaseServerConfig;
44 import org.jboss.util.StopWatch;
45
46
47 /**
48  * A Server implementation that uses the deployer-beans.xml and ProfileService
49  * to boot the server.
50  *
51  * @author Scott.Stark@jboss.org
52  * @author <a HREF="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
53  * @version $Revision$
54  */

55 public class ServerImpl extends NotificationBroadcasterSupport JavaDoc
56    implements Server, NotificationEmitter JavaDoc
57 {
58    /** Instance logger. */
59    private Logger log;
60
61    /** Container for version information. */
62    private final Version version = Version.getInstance();
63
64    /** Package information for org.jboss */
65    private final Package JavaDoc jbossPackage = Package.getPackage("org.jboss");
66
67    /** The kernel bootstrap */
68    private ProfileServiceBootstrap bootstrap;
69    /** A resource prefix */
70    private String JavaDoc deployerBeansPrefix;
71
72    /** The basic configuration for the server. */
73    private BaseServerConfig config;
74
75    /** When the server was started. */
76    private Date JavaDoc startDate;
77
78    /** Flag to indicate if we are started. */
79    private boolean started;
80    /** A flag indicating if start has been called */
81    private boolean isInStart;
82    /** A flag indicating if shutdown has been called */
83    private boolean isInShutdown;
84
85    /** The JVM shutdown hook */
86    private ShutdownHook shutdownHook;
87
88    /** The JBoss Life Thread */
89    private LifeThread lifeThread;
90
91    /**
92     * No-arg constructor for ServerImpl
93     */

94    public ServerImpl()
95    {
96    }
97
98    /**
99     * Initialize the Server instance.
100     *
101     * @param props - The configuration properties for the server.
102     *
103     * @throws IllegalStateException Already initialized.
104     * @throws Exception Failed to initialize.
105     */

106    public void init(final Properties JavaDoc props)
107       throws IllegalStateException JavaDoc, Exception JavaDoc
108    {
109       if (props == null)
110          throw new IllegalArgumentException JavaDoc("props is null");
111       if (config != null)
112          throw new IllegalStateException JavaDoc("already initialized");
113
114       ClassLoader JavaDoc oldCL = Thread.currentThread().getContextClassLoader();
115
116       try
117       {
118          Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
119          doInit(props);
120       }
121       finally
122       {
123          Thread.currentThread().setContextClassLoader(oldCL);
124       }
125    }
126
127    /**
128     * Initialize server configuration and jvm settings.
129     * @param props
130     * @throws Exception
131     */

132    private void doInit(final Properties JavaDoc props) throws Exception JavaDoc
133    {
134       // Create a new config object from the give properties
135
this.config = new BaseServerConfig(props);
136       this.deployerBeansPrefix = props.getProperty("jboss.server.deployerBeansPrefix");
137
138       // Set the VM temp directory to the server tmp dir
139
boolean overrideTmpDir = Boolean.getBoolean("jboss.server.temp.dir.overrideJavaTmpDir");
140       if( overrideTmpDir )
141       {
142          File JavaDoc serverTmpDir = config.getServerTempDir();
143          System.setProperty("java.io.tmpdir", serverTmpDir.getCanonicalPath());
144       }
145
146       /* Initialize the logging layer using the ServerImpl class. The server log
147       directory is initialized prior to this to ensure the jboss.server.log.dir
148       system property is set in case its used by the logging configs.
149       */

150       config.getServerLogDir();
151       log = Logger.getLogger(getClass());
152
153       // Setup URL handlers - do this before initializing the ServerConfig
154
initURLHandlers();
155       config.initURLs();
156
157       log.info("Starting JBoss (Microcontainer)...");
158
159       if (jbossPackage != null)
160       {
161          // Show what release this is...
162
log.info("Release ID: " +
163                   jbossPackage.getImplementationTitle() + " " +
164                   jbossPackage.getImplementationVersion());
165       }
166       else
167       {
168          log.warn("could not get package info to display release, either the " +
169             "jar manifest in jboss-system.jar has been mangled or you're " +
170             "running unit tests from ant outside of JBoss itself.");
171       }
172
173       log.debug("Using config: " + config);
174
175       // make sure our impl type is exposed
176
log.debug("Server type: " + getClass());
177
178       // Log the basic configuration elements
179
log.info("Home Dir: " + config.getHomeDir());
180       log.info("Home URL: " + config.getHomeURL());
181       log.info("Library URL: " + config.getLibraryURL());
182       log.info("Patch URL: " + config.getPatchURL());
183       log.info("Server Name: " + config.getServerName());
184       log.info("Server Home Dir: " + config.getServerHomeDir());
185       log.info("Server Home URL: " + config.getServerHomeURL());
186       log.info("Server Data Dir: " + config.getServerDataDir());
187       log.info("Server Temp Dir: " + config.getServerTempDir());
188       log.info("Server Config URL: " + config.getServerConfigURL());
189       log.info("Server Library URL: " + config.getServerLibraryURL());
190       log.info("Root Deployment Filename: " + config.getRootDeploymentFilename());
191    }
192
193    /**
194     * The <code>initURLHandlers</code> method calls
195     * internalInitURLHandlers. if requireJBossURLStreamHandlers is
196     * false, any exceptions are logged and ignored.
197     *
198     */

199    private void initURLHandlers()
200    {
201       if (config.getRequireJBossURLStreamHandlerFactory())
202       {
203          internalInitURLHandlers();
204       } // end of if ()
205
else
206       {
207          try
208          {
209             internalInitURLHandlers();
210          }
211          catch (SecurityException JavaDoc e)
212          {
213             log.warn("You do not have permissions to set URLStreamHandlerFactory", e);
214          } // end of try-catch
215
catch (Error JavaDoc e)
216          {
217             log.warn("URLStreamHandlerFactory already set", e);
218          } // end of catch
219
} // end of else
220
}
221
222    /**
223     * Set up our only URLStreamHandlerFactory.
224     * This is needed to ensure Sun's version is not used (as it leaves files
225     * locked on Win2K/WinXP platforms.
226     */

227    private void internalInitURLHandlers()
228    {
229       try
230       {
231          // Install a URLStreamHandlerFactory that uses the TCL
232
URL.setURLStreamHandlerFactory(new URLStreamHandlerFactory());
233    
234          // Preload JBoss URL handlers
235
URLStreamHandlerFactory.preload();
236       }
237       catch (Error JavaDoc error)
238       { //very naughty but we HAVE to do this or
239
//we'll fail if we ever try to do this again
240
log.warn("Caught Throwable Error, this probably means " +
241             "we've already set the URLStreamHAndlerFactory before");
242       }
243
244       // Include the default JBoss protocol handler package
245
String JavaDoc handlerPkgs = System.getProperty("java.protocol.handler.pkgs");
246       if (handlerPkgs != null)
247       {
248          handlerPkgs += "|org.jboss.net.protocol";
249       }
250       else
251       {
252          handlerPkgs = "org.jboss.net.protocol";
253       }
254       System.setProperty("java.protocol.handler.pkgs", handlerPkgs);
255    }
256
257    /**
258     * Get the typed server configuration object which the
259     * server has been initalized to use.
260     *
261     * @return Typed server configuration object.
262     *
263     * @throws IllegalStateException Not initialized.
264     */

265    public ServerConfig getConfig() throws IllegalStateException JavaDoc
266    {
267       if (config == null)
268          throw new IllegalStateException JavaDoc("not initialized");
269
270       return config;
271    }
272
273    /**
274     * Check if the server is started.
275     *
276     * @return True if the server is started, else false.
277     */

278    public boolean isStarted()
279    {
280       return started;
281    }
282
283    /**
284     Check if the shutdown operation has been called/is in progress.
285
286     @return true if shutdown has been called, false otherwise
287     */

288    public boolean isInShutdown()
289    {
290       return isInShutdown;
291    }
292
293    /**
294     * Start the Server instance.
295     *
296     * @throws IllegalStateException Already started or not initialized.
297     * @throws Exception Failed to start.
298     */

299    public void start() throws IllegalStateException JavaDoc, Exception JavaDoc
300    {
301       synchronized( this )
302       {
303          if( isInStart == false )
304          {
305             isInStart = true;
306          }
307          else
308          {
309             log.debug("Already in start, ignoring duplicate start");
310             return;
311          }
312       }
313
314       // make sure we are initialized
315
getConfig();
316
317       // make sure we aren't started yet
318
if (started)
319          throw new IllegalStateException JavaDoc("already started");
320
321       ClassLoader JavaDoc oldCL = Thread.currentThread().getContextClassLoader();
322
323       try
324       {
325          ClassLoader JavaDoc myCL = getClass().getClassLoader();
326          /*
327          URL libURL = config.getLibraryURL();
328          // Hack to add the jmx jars until the mc/legacy jmx integration is cleaned up
329          URL[] jmxJars = {
330                new URL(libURL, "dom4j.jar"),
331                new URL(libURL, "jboss-j2se.jar"),
332                new URL(libURL, "jboss-jmx.jar"),
333                new URL(libURL, "jboss-mbeans.jar"),
334                new URL(libURL, "jboss-system-jmx.jar")
335          };
336          NoAnnotationURLClassLoader jmxLoader = new NoAnnotationURLClassLoader(jmxJars, myCL);
337          Thread.currentThread().setContextClassLoader(jmxLoader);
338          */

339          Thread.currentThread().setContextClassLoader(myCL);
340          doStart();
341       }
342       catch (Throwable JavaDoc t)
343       {
344          log.debug("Failed to start", t);
345
346          if (t instanceof Exception JavaDoc)
347             throw (Exception JavaDoc)t;
348          if (t instanceof Error JavaDoc)
349             throw (Error JavaDoc)t;
350
351          throw new org.jboss.util.UnexpectedThrowable(t);
352       }
353       finally
354       {
355          Thread.currentThread().setContextClassLoader(oldCL);
356          isInStart = false;
357       }
358    }
359
360    /**
361     * Start the server by booting the kernel, loading deployers, and loading
362     * the profile deployments.
363     *
364     * @throws Throwable for any error
365     */

366    private void doStart() throws Throwable JavaDoc
367    {
368       // See how long it takes us to start up
369
StopWatch watch = new StopWatch(true);
370
371       // remeber when we we started
372
startDate = new Date JavaDoc();
373
374       bootstrap = new ProfileServiceBootstrap(config.getServerName(), this);
375       if( deployerBeansPrefix != null )
376       {
377          bootstrap.setDeployerBeansPrefix(deployerBeansPrefix);
378          log.info("Starting Microcontainer, deployerBeansPrefix="+deployerBeansPrefix);
379       }
380       else
381       {
382          URL JavaDoc configURL = config.getServerConfigURL();
383          URL JavaDoc bootstrapURL = new URL JavaDoc(configURL, ProfileServiceBootstrap.BOOTSTRAP_XML_NAME);
384          log.info("Starting Microcontainer, bootstrapURL="+bootstrapURL);
385          bootstrap.setBootstrapURL(bootstrapURL);
386       }
387
388       // Install the shutdown hook
389
shutdownHook = new ShutdownHook();
390       shutdownHook.setDaemon(true);
391       try
392       {
393          Runtime.getRuntime().addShutdownHook(shutdownHook);
394          log.debug("Shutdown hook added");
395       }
396       catch (Exception JavaDoc e)
397       {
398          log.warn("Failed to add shutdown hook; ignoring", e);
399       }
400
401       bootstrap.run();
402
403       lifeThread = new LifeThread();
404       lifeThread.start();
405
406       started = true;
407
408       // Send a notification that the startup is complete
409
KernelEvent startEvent = bootstrap.createEvent(START_NOTIFICATION_TYPE, new Long JavaDoc(watch.getLapTime()));
410       bootstrap.fireKernelEvent(startEvent);
411       // Send a JMX notification that the startup is complete
412
Notification JavaDoc msg = new Notification JavaDoc(START_NOTIFICATION_TYPE, this, 1);
413       msg.setUserData(new Long JavaDoc(watch.getLapTime()));
414       sendNotification(msg);
415
416       watch.stop();
417
418       if (jbossPackage != null)
419       {
420          // Tell the world how fast it was =)
421
log.info("JBoss (Microcontainer) [" + jbossPackage.getImplementationVersion() +
422                   "] Started in " + watch);
423       }
424       else
425       {
426          log.warn("could not get package info to display release, either the " +
427             "jar manifest in run.jar has been mangled or you're " +
428             "running unit tests from ant outside of JBoss itself.");
429       }
430    }
431
432    /**
433     * Shutdown the Server instance and run shutdown hooks.
434     *
435     * <p>If the exit on shutdown flag is true, then {@link #exit()}
436     * is called, else only the shutdown hook is run.
437     *
438     * @throws IllegalStateException No started.
439     */

440    public void shutdown() throws IllegalStateException JavaDoc
441    {
442       if (!started)
443          throw new IllegalStateException JavaDoc("not started");
444
445       final ServerImpl server = this;
446
447       log.debug("Shutting down");
448
449       isInShutdown = true;
450       boolean exitOnShutdown = config.getExitOnShutdown();
451       boolean blockingShutdown = config.getBlockingShutdown();
452
453       log.debug("exitOnShutdown: " + exitOnShutdown);
454       log.debug("blockingShutdown: " + blockingShutdown);
455
456       lifeThread.interrupt();
457
458       if (exitOnShutdown)
459       {
460          server.exit(0);
461       }
462       else if (blockingShutdown)
463       {
464          shutdownHook.shutdown();
465       } // end of if ()
466
else
467       {
468          // start in new thread to give positive
469
// feedback to requesting client of success.
470
new Thread JavaDoc()
471          {
472             public void run()
473             {
474                // just run the hook, don't call System.exit, as we may
475
// be embeded in a vm that would not like that very much
476
shutdownHook.shutdown();
477             }
478          }.start();
479       }
480    }
481
482    /**
483     * Shutdown the server, the JVM and run shutdown hooks.
484     *
485     * @param exitcode The exit code returned to the operating system.
486     */

487    public void exit(final int exitcode)
488    {
489       // start in new thread so that we might have a chance to give positive
490
// feed back to requesting client of success.
491
new Thread JavaDoc()
492       {
493          public void run()
494          {
495             log.info("Shutting down the JVM now!");
496             Runtime.getRuntime().exit(exitcode);
497          }
498       }.start();
499    }
500
501    /**
502     * Shutdown the server, the JVM and run shutdown hooks. Exits with
503     * code 1.
504     */

505    public void exit()
506    {
507       exit(1);
508    }
509
510    /**
511     * Forcibly terminates the currently running Java virtual machine.
512     *
513     * @param exitcode The exit code returned to the operating system.
514     */

515    public void halt(final int exitcode)
516    {
517       // Send a stop event msg
518
KernelEvent stopEvent = bootstrap.createEvent(STOP_NOTIFICATION_TYPE, null);
519       bootstrap.fireKernelEvent(stopEvent);
520
521       // start in new thread so that we might have a chance to give positive
522
// feed back to requesting client of success.
523
new Thread JavaDoc()
524       {
525          public void run()
526          {
527             System.err.println("Halting the system now!");
528             Runtime.getRuntime().halt(exitcode);
529          }
530       }.start();
531    }
532
533    /**
534     * Forcibly terminates the currently running Java virtual machine.
535     * Exits with code 1.
536     */

537    public void halt()
538    {
539       halt(1);
540    }
541
542
543    ///////////////////////////////////////////////////////////////////////////
544
// Runtime Access //
545
///////////////////////////////////////////////////////////////////////////
546

547    /**
548     * A simple helper used to log the Runtime memory information.
549     *
550     * @param rt the runtime
551     */

552    private void logMemoryUsage(final Runtime JavaDoc rt)
553    {
554       log.info("Total/free memory: " + rt.totalMemory() + "/" + rt.freeMemory());
555    }
556
557    /**
558     * Hint to the JVM to run the garbage collector.
559     */

560    public void runGarbageCollector()
561    {
562       Runtime JavaDoc rt = Runtime.getRuntime();
563
564       logMemoryUsage(rt);
565       rt.gc();
566       log.info("Hinted to the JVM to run garbage collection");
567       logMemoryUsage(rt);
568    }
569
570    /**
571     * Hint to the JVM to run any pending object finalizations.
572     */

573    public void runFinalization()
574    {
575       Runtime.getRuntime().runFinalization();
576       log.info("Hinted to the JVM to run any pending object finalizations");
577    }
578
579    /**
580     * Enable or disable tracing method calls at the Runtime level.
581     *
582     * @param flag whether to enable trace
583     */

584    public void traceMethodCalls(final Boolean JavaDoc flag)
585    {
586       Runtime.getRuntime().traceMethodCalls(flag.booleanValue());
587    }
588
589    /**
590     * Enable or disable tracing instructions the Runtime level.
591     *
592     * @param flag whether to enable trace
593     */

594    public void traceInstructions(final Boolean JavaDoc flag)
595    {
596       Runtime.getRuntime().traceInstructions(flag.booleanValue());
597    }
598
599
600    ///////////////////////////////////////////////////////////////////////////
601
// Server Information //
602
///////////////////////////////////////////////////////////////////////////
603

604    public Date JavaDoc getStartDate()
605    {
606       return startDate;
607    }
608
609    public String JavaDoc getVersion()
610    {
611       return version.toString();
612    }
613
614    public String JavaDoc getVersionName()
615    {
616       return version.getName();
617    }
618
619    public String JavaDoc getBuildNumber()
620    {
621       return version.getBuildNumber();
622    }
623
624    public String JavaDoc getBuildJVM()
625    {
626       return version.getBuildJVM();
627    }
628
629    public String JavaDoc getBuildOS()
630    {
631       return version.getBuildOS();
632    }
633
634    public String JavaDoc getBuildID()
635    {
636       return version.getBuildID();
637    }
638
639    /**
640     * The server build date
641     * @return server build date
642     */

643    public String JavaDoc getBuildDate()
644    {
645       return version.getBuildDate();
646    }
647
648    /**
649     * The server kernel.
650     * @return server kernel.
651     */

652    public Kernel getKernel()
653    {
654       return bootstrap.getKernel();
655    }
656
657    /** A simple thread that keeps the vm alive in the event there are no
658     * other threads started.
659     */

660    private class LifeThread
661       extends Thread JavaDoc
662    {
663       Object JavaDoc lock = new Object JavaDoc();
664       LifeThread()
665       {
666          super("JBossLifeThread");
667       }
668       public void run()
669       {
670          synchronized (lock)
671          {
672             try
673             {
674                lock.wait();
675             }
676             catch (InterruptedException JavaDoc ignore)
677             {
678             }
679          }
680          log.info("LifeThread.run exits!");
681       }
682    }
683
684    ///////////////////////////////////////////////////////////////////////////
685
// Shutdown Hook //
686
///////////////////////////////////////////////////////////////////////////
687

688    private class ShutdownHook
689       extends Thread JavaDoc
690    {
691       private boolean forceHalt = true;
692
693       public ShutdownHook()
694       {
695          super("JBoss Shutdown Hook");
696
697          String JavaDoc value = SecurityActions.getSystemProperty("jboss.shutdown.forceHalt", null);
698          if (value != null)
699          {
700             forceHalt = new Boolean JavaDoc(value).booleanValue();
701          }
702       }
703
704       public void run()
705       {
706          shutdown();
707          if (forceHalt)
708          {
709             System.out.println("Halting VM");
710             Runtime.getRuntime().halt(0);
711          }
712       }
713
714       public void shutdown()
715       {
716          // Send a notification that mbeanServer stop is initiated
717
log.info("JBoss SHUTDOWN");
718          Notification JavaDoc msg = new Notification JavaDoc(Server.STOP_NOTIFICATION_TYPE, this, 2);
719          sendNotification(msg);
720          log.info("Undeploying all packages");
721          shutdownDeployments();
722
723          log.debug("Shutting down Microcontainer");
724          System.out.println("Shutting down Microcontainer");
725
726          // Shutdown the core kernel
727
shutdownKernel();
728
729          log.info("Shutdown complete");
730          System.out.println("Shutdown complete");
731       }
732
733       protected void shutdownDeployments()
734       {
735          try
736          {
737             MainDeployer deployer = bootstrap.getMainDeployer();
738             if (deployer != null)
739                deployer.shutdown();
740          }
741          catch (Exception JavaDoc e)
742          {
743             log.error("Failed to shutdown deployer", e);
744          }
745       }
746
747       /**
748        * The <code>shutdownServices</code> method calls the one and only
749        * ServiceController to shut down all the mbeans registered with it.
750        */

751       protected void shutdownKernel()
752       {
753          try
754          {
755             BasicKernelDeployer deployer = bootstrap.getKernelDeployer();
756             if (deployer != null)
757                deployer.shutdown();
758          }
759          catch (Exception JavaDoc e)
760          {
761             log.error("Failed to shutdown services", e);
762          }
763       }
764
765    }
766 }
767
Popular Tags