Save This Page
Home » jboss-5.0.0.CR1-src » org » jboss » [javadoc | source]
    1   /*
    2    * JBoss, Home of Professional Open Source
    3    * Copyright 2005, JBoss Inc., and individual contributors as indicated
    4    * by the @authors tag. See the copyright.txt in the distribution for a
    5    * full listing of individual contributors.
    6    *
    7    * This is free software; you can redistribute it and/or modify it
    8    * under the terms of the GNU Lesser General Public License as
    9    * published by the Free Software Foundation; either version 2.1 of
   10    * the License, or (at your option) any later version.
   11    *
   12    * This software is distributed in the hope that it will be useful,
   13    * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   15    * Lesser General Public License for more details.
   16    *
   17    * You should have received a copy of the GNU Lesser General Public
   18    * License along with this software; if not, write to the Free
   19    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
   20    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
   21    */
   22   package org.jboss;
   23   
   24   import gnu.getopt.Getopt;
   25   import gnu.getopt.LongOpt;
   26   
   27   import java.io.File;
   28   import java.io.FilenameFilter;
   29   import java.net.MalformedURLException;
   30   import java.net.URL;
   31   import java.net.URLDecoder;
   32   import java.util.LinkedList;
   33   import java.util.List;
   34   import java.util.Properties;
   35   
   36   import org.jboss.system.server.Server;
   37   import org.jboss.system.server.ServerConfig;
   38   import org.jboss.system.server.ServerConfigUtil;
   39   import org.jboss.system.server.ServerLoader;
   40   
   41   /**
   42    * Provides a command line interface to start the JBoss server.
   43    *
   44    * <p>
   45    * To enable debug or trace messages durring boot change the Log4j
   46    * configuration to use either <tt>log4j-debug.properties</tt>
   47    * <tt>log4j-trace.properties</tt> by setting the system property
   48    * <tt>log4j.configuration</tt>:
   49    *
   50    * <pre>
   51    *   ./run.sh -Dlog4j.configuration=log4j-debug.properties
   52    * </pre>
   53    * TODO: Should jdk logging be the default
   54    *
   55    * @author <a href="mailto:marc.fleury@jboss.org">Marc Fleury</a>
   56    * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
   57    * @author <a href="mailto:adrian.brock@happeningtimes.com">Adrian Brock</a>
   58    * @author <a href="mailto:scott.stark@jboss.org">Scott Stark</a>
   59    * @author <a href="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
   60    * @version $Revision: 63730 $
   61    */
   62   public class Main
   63   {
   64      /** EDU.oswego.cs.dl.util.concurrent */
   65      private String concurrentLib = "concurrent.jar";
   66   
   67      /** A URL for obtaining microkernel patches */
   68      private URL bootURL;
   69      
   70      /** Extra jars from the /lib location that are added to the start of the boot
   71       classpath. This can be used to override jboss /lib boot classes.
   72       */
   73      private List<String> bootLibraries = new LinkedList<String>();
   74   
   75      /** Extra libraries to load the server with .*/
   76      private List<String> extraLibraries = new LinkedList<String>();
   77   
   78      /** Extra classpath URLS to load the server with .*/
   79      private List<URL> extraClasspath = new LinkedList<URL>();
   80   
   81      /**
   82       * Server properties.  This object holds all of the required
   83       * information to get the server up and running. Use System
   84       * properties for defaults.
   85       */
   86      private Properties props = new Properties(System.getProperties());
   87      
   88      /** The booted server instance */
   89      private Server server;
   90   
   91      /**
   92       * Explicit constructor.
   93       */
   94      public Main()
   95      {
   96         super();
   97      }
   98   
   99      /**
  100       * Access the booted server.
  101       * @return the Server instance.
  102       */
  103      public Server getServer()
  104      {
  105         return server;
  106      }
  107   
  108      /**
  109       * Boot up JBoss.
  110       *
  111       * @param args   The command line arguments.
  112       *
  113       * @throws Exception    Failed to boot.
  114       */
  115      public void boot(final String[] args) throws Exception
  116      {
  117         // First process the command line to pickup custom props/settings
  118         processCommandLine(args);
  119   
  120         // Auto set HOME_DIR to ../bin/run.jar if not set
  121         String homeDir = props.getProperty(ServerConfig.HOME_DIR);
  122         if (homeDir == null)
  123         {
  124            String path = Main.class.getProtectionDomain().getCodeSource().getLocation().getFile();
  125            /* The 1.4 JDK munges the code source file with URL encoding so run
  126             * this path through the decoder so that is JBoss starts in a path with
  127             * spaces we don't come crashing down.
  128            */
  129            path = URLDecoder.decode(path, "UTF-8");
  130            File runJar = new File(path);
  131            File homeFile = runJar.getParentFile().getParentFile();
  132            homeDir = homeFile.getCanonicalPath();
  133         }
  134         props.setProperty(ServerConfig.HOME_DIR, homeDir);
  135   
  136         // Setup HOME_URL too, ServerLoader needs this
  137         String homeURL = props.getProperty(ServerConfig.HOME_URL);
  138         if (homeURL == null)
  139         {
  140            File file = new File(homeDir);
  141            homeURL = file.toURL().toString();
  142            props.setProperty(ServerConfig.HOME_URL, homeURL);
  143         }
  144   
  145         // Load the server instance
  146         ServerLoader loader = new ServerLoader(props);
  147   
  148         /* If there is a patch dir specified make it the first element of the
  149         loader bootstrap classpath. If its a file url pointing to a dir, then
  150         add the dir and its contents.
  151         */
  152         if (bootURL != null)
  153         {
  154            if (bootURL.getProtocol().equals("file"))
  155            {
  156               File dir = new File(bootURL.getFile());
  157               if (dir.exists())
  158               {
  159                  // Add the local file patch directory
  160                  loader.addURL(dir.toURL());
  161   
  162                  // Add the contents of the directory too
  163                  File[] jars = dir.listFiles(new JarFilter());
  164   
  165                  for (int j = 0; jars != null && j < jars.length; j++)
  166                  {
  167                     loader.addURL(jars[j].getCanonicalFile().toURL());
  168                  }
  169               }
  170            }
  171            else
  172            {
  173               loader.addURL(bootURL);
  174            }
  175         }
  176   
  177         // Add any extra libraries
  178         for (int i = 0; i < bootLibraries.size(); i++)
  179         {
  180            loader.addLibrary(bootLibraries.get(i));
  181         }
  182   
  183         // Add the jars from the endorsed dir
  184         loader.addEndorsedJars();
  185   
  186         // jmx UnifiedLoaderRepository needs a concurrent class...
  187         loader.addLibrary(concurrentLib);
  188   
  189         // Add any extra libraries after the boot libs
  190         for (int i = 0; i < extraLibraries.size(); i++)
  191         {
  192            loader.addLibrary(extraLibraries.get(i));
  193         }
  194   
  195         // Add any extra classapth URLs
  196         for (int i = 0; i < extraClasspath.size(); i++)
  197         {
  198            loader.addURL(extraClasspath.get(i));
  199         }
  200   
  201         // Load the server
  202         ClassLoader parentCL = Thread.currentThread().getContextClassLoader();
  203         server = loader.load(parentCL);
  204   
  205         // Initialize the server
  206         server.init(props);
  207   
  208         // Start 'er up mate!
  209         server.start();
  210      }
  211   
  212      /**
  213       * Shutdown the booted Server instance.
  214       *
  215       */
  216      public void shutdown()
  217      {
  218         server.shutdown();
  219      }
  220   
  221      private URL makeURL(String urlspec) throws MalformedURLException
  222      {
  223         urlspec = urlspec.trim();
  224   
  225         URL url;
  226   
  227         try
  228         {
  229            url = new URL(urlspec);
  230            if (url.getProtocol().equals("file"))
  231            {
  232               // make sure the file is absolute & canonical file url
  233               File file = new File(url.getFile()).getCanonicalFile();
  234               url = file.toURL();
  235            }
  236         }
  237         catch (Exception e)
  238         {
  239            // make sure we have a absolute & canonical file url
  240            try
  241            {
  242               File file = new File(urlspec).getCanonicalFile();
  243               url = file.toURL();
  244            }
  245            catch (Exception n)
  246            {
  247               throw new MalformedURLException(n.toString());
  248            }
  249         }
  250   
  251         return url;
  252      }
  253   
  254      /** Process the command line... */
  255      private void processCommandLine(final String[] args) throws Exception
  256      {
  257         // set this from a system property or default to jboss
  258         String programName = System.getProperty("program.name", "jboss");
  259         String sopts = "-:hD:d:p:n:c:Vj::B:L:C:P:b:g:u:m:l:";
  260         LongOpt[] lopts =
  261         {
  262            new LongOpt("help", LongOpt.NO_ARGUMENT, null, 'h'),
  263            new LongOpt("bootdir", LongOpt.REQUIRED_ARGUMENT, null, 'd'),
  264            new LongOpt("patchdir", LongOpt.REQUIRED_ARGUMENT, null, 'p'),
  265            new LongOpt("netboot", LongOpt.REQUIRED_ARGUMENT, null, 'n'),
  266            new LongOpt("configuration", LongOpt.REQUIRED_ARGUMENT, null, 'c'),
  267            new LongOpt("version", LongOpt.NO_ARGUMENT, null, 'V'),
  268            new LongOpt("jaxp", LongOpt.REQUIRED_ARGUMENT, null, 'j'),
  269            new LongOpt("bootlib", LongOpt.REQUIRED_ARGUMENT, null, 'B'),
  270            new LongOpt("library", LongOpt.REQUIRED_ARGUMENT, null, 'L'),
  271            new LongOpt("classpath", LongOpt.REQUIRED_ARGUMENT, null, 'C'),
  272            new LongOpt("properties", LongOpt.REQUIRED_ARGUMENT, null, 'P'),
  273            new LongOpt("host", LongOpt.REQUIRED_ARGUMENT, null, 'b'),
  274            new LongOpt("partition", LongOpt.REQUIRED_ARGUMENT, null, 'g'),
  275            new LongOpt("udp", LongOpt.REQUIRED_ARGUMENT, null, 'u'),
  276            new LongOpt("mcast_port", LongOpt.REQUIRED_ARGUMENT, null, 'm'),
  277            new LongOpt("log", LongOpt.REQUIRED_ARGUMENT, null, 'l'),
  278         };
  279   
  280         Getopt getopt = new Getopt(programName, args, sopts, lopts);
  281         int code;
  282         String arg;
  283         props.setProperty(ServerConfig.SERVER_BIND_ADDRESS, "127.0.0.1");
  284         System.setProperty(ServerConfig.SERVER_BIND_ADDRESS, "127.0.0.1");
  285         while ((code = getopt.getopt()) != -1)
  286         {
  287            switch (code)
  288            {
  289               case ':':
  290               case '?':
  291                  // for now both of these should exit with error status
  292                  System.exit(1);
  293                  break; // for completeness
  294   
  295               case 1:
  296                  // this will catch non-option arguments
  297                  // (which we don't currently care about)
  298                  System.err.println(programName +
  299                                     ": unused non-option argument: " +
  300                                     getopt.getOptarg());
  301                  break; // for completeness
  302   
  303               case 'h':
  304                  // show command line help
  305                  System.out.println("usage: " + programName + " [options]");
  306                  System.out.println();
  307                  System.out.println("options:");
  308                  System.out.println("    -h, --help                    Show this help message");
  309                  System.out.println("    -V, --version                 Show version information");
  310                  System.out.println("    --                            Stop processing options");
  311                  System.out.println("    -D<name>[=<value>]            Set a system property");
  312                  System.out.println("    -d, --bootdir=<dir>           Set the boot patch directory; Must be absolute or url");
  313                  System.out.println("    -p, --patchdir=<dir>          Set the patch directory; Must be absolute or url");
  314                  System.out.println("    -n, --netboot=<url>           Boot from net with the given url as base");
  315                  System.out.println("    -c, --configuration=<name>    Set the server configuration name");
  316                  System.out.println("    -B, --bootlib=<filename>      Add an extra library to the front bootclasspath");
  317                  System.out.println("    -L, --library=<filename>      Add an extra library to the loaders classpath");
  318                  System.out.println("    -C, --classpath=<url>         Add an extra url to the loaders classpath");
  319                  System.out.println("    -P, --properties=<url>        Load system properties from the given url");
  320                  System.out.println("    -b, --host=<host or ip>       Bind address for all JBoss services");
  321                  System.out.println("    -g, --partition=<name>        HA Partition name (default=DefaultDomain)");
  322                  System.out.println("    -m, --mcast_port=<ip>         UDP multicast port; Only used by JGroups multiplexer");
  323                  System.out.println("    -u, --udp=<ip>                UDP multicast address");
  324                  System.out.println("    -l, --log=<log4j|jdk>         Specify the logger plugin type");
  325                  System.out.println();
  326                  System.exit(0);
  327                  break; // for completeness
  328   
  329               case 'D':
  330               {
  331                  // set a system property
  332                  arg = getopt.getOptarg();
  333                  String name, value;
  334                  int i = arg.indexOf("=");
  335                  if (i == -1)
  336                  {
  337                     name = arg;
  338                     value = "true";
  339                  }
  340                  else
  341                  {
  342                     name = arg.substring(0, i);
  343                     value = arg.substring(i + 1, arg.length());
  344                  }
  345                  System.setProperty(name, value);
  346                  // Ensure setting the old bind.address property also sets the new
  347                  // jgroups.bind_addr property, otherwise jgroups may ignore it
  348                  if ("bind.address".equals(name))
  349                  {
  350                     // Wildcard address is not valid for JGroups
  351                     String addr = ServerConfigUtil.fixRemoteAddress(value);
  352                     System.setProperty("jgroups.bind_addr", addr);
  353                  }
  354                  else if ("jgroups.bind_addr".equals(name))
  355                  {
  356                     // Wildcard address is not valid for JGroups
  357                     String addr = ServerConfigUtil.fixRemoteAddress(value);
  358                     System.setProperty("jgroups.bind_addr", addr);
  359                  }
  360                  break;
  361               }
  362   
  363               case 'd':
  364                  // set the boot patch URL
  365                  bootURL = makeURL(getopt.getOptarg());
  366                  break;
  367   
  368               case 'p':
  369               {
  370                  // set the patch URL
  371                  URL patchURL = makeURL(getopt.getOptarg());
  372                  props.put(ServerConfig.PATCH_URL, patchURL.toString());
  373   
  374                  break;
  375               }
  376   
  377               case 'n':
  378                  // set the net boot url
  379                  arg = getopt.getOptarg();
  380   
  381                  // make sure there is a trailing '/'
  382                  if (!arg.endsWith("/")) arg += "/";
  383   
  384                  props.put(ServerConfig.HOME_URL, new URL(arg).toString());
  385                  break;
  386   
  387               case 'c':
  388                  // set the server name
  389                  arg = getopt.getOptarg();
  390                  props.put(ServerConfig.SERVER_NAME, arg);
  391                  break;
  392   
  393               case 'V':
  394               {
  395                  // Package information for org.jboss
  396                  Package jbossPackage = Package.getPackage("org.jboss");
  397   
  398                  // show version information
  399                  System.out.println("JBoss " + jbossPackage.getImplementationVersion());
  400                  System.out.println();
  401                  System.out.println("Distributable under LGPL license.");
  402                  System.out.println("See terms of license at gnu.org.");
  403                  System.out.println();
  404                  System.exit(0);
  405                  break; // for completness
  406               }
  407   
  408               case 'j':
  409                  // Show an error and exit
  410                  System.err.println(programName + ": option '-j, --jaxp' no longer supported");
  411                  System.exit(1);
  412                  break; // for completness
  413   
  414               case 'B':
  415                  arg = getopt.getOptarg();
  416                  bootLibraries.add(arg);
  417                  break;
  418   
  419               case 'L':
  420                  arg = getopt.getOptarg();
  421                  extraLibraries.add(arg);
  422                  break;
  423   
  424               case 'C':
  425               {
  426                  URL url = makeURL(getopt.getOptarg());
  427                  extraClasspath.add(url);
  428                  break;
  429               }
  430   
  431               case 'P':
  432               {
  433                  // Set system properties from url/file
  434                  URL url = makeURL(getopt.getOptarg());
  435                  Properties props = System.getProperties();
  436                  props.load(url.openConnection().getInputStream());
  437                  break;
  438               }
  439               case 'b':
  440                  arg = getopt.getOptarg();
  441                  props.put(ServerConfig.SERVER_BIND_ADDRESS, arg);
  442                  System.setProperty(ServerConfig.SERVER_BIND_ADDRESS, arg);
  443                  // used by JGroups; only set if not set via -D so users
  444                  // can use a different interface for cluster communication
  445                  // There are 2 versions of this property, deprecated bind.address
  446                  // and the new version, jgroups.bind_addr
  447                  String bindAddress = System.getProperty("bind.address");
  448                  if (bindAddress == null)
  449                  {
  450                     // Wildcard address is not valid for JGroups
  451                     bindAddress = ServerConfigUtil.fixRemoteAddress(arg);
  452                     System.setProperty("bind.address", bindAddress);
  453                  }
  454                  bindAddress = System.getProperty("jgroups.bind_addr");
  455                  if (bindAddress == null)
  456                  {
  457                     // Wildcard address is not valid for JGroups
  458                     bindAddress = ServerConfigUtil.fixRemoteAddress(arg);
  459                     System.setProperty("jgroups.bind_addr", bindAddress);
  460                  }
  461                  
  462                  // Set the java.rmi.server.hostname if not set
  463                  String rmiHost = System.getProperty("java.rmi.server.hostname");
  464                  if( rmiHost == null )
  465                  {
  466                     rmiHost = ServerConfigUtil.fixRemoteAddress(arg);
  467                     System.setProperty("java.rmi.server.hostname", rmiHost);
  468                  }
  469                  break;
  470                  
  471               case 'g':
  472                  arg = getopt.getOptarg();
  473                  props.put(ServerConfig.PARTITION_NAME_PROPERTY, arg);
  474                  System.setProperty(ServerConfig.PARTITION_NAME_PROPERTY, arg);
  475                  break;
  476                  
  477               case 'u':
  478                  arg = getopt.getOptarg();
  479                  props.put(ServerConfig.PARTITION_UDP_PROPERTY, arg);
  480                  System.setProperty(ServerConfig.PARTITION_UDP_PROPERTY, arg);
  481                  // the new jgroups property name
  482                  System.setProperty("jgroups.udp.mcast_addr", arg);
  483                  break;
  484                  
  485               case 'm':
  486                  arg = getopt.getOptarg();
  487                  props.put(ServerConfig.PARTITION_UDP_PORT_PROPERTY, arg);
  488                  System.setProperty(ServerConfig.PARTITION_UDP_PORT_PROPERTY, arg);
  489                  break;
  490                  
  491               case 'l':
  492               {
  493                  arg = getopt.getOptarg();
  494                  String logPlugin = arg;
  495                  if( arg.equalsIgnoreCase("log4j") )
  496                     logPlugin = "org.jboss.logging.Log4jLoggerPlugin";
  497                  else if( arg.equalsIgnoreCase("jdk") )
  498                  {
  499                     logPlugin = "org.jboss.logging.JDK14LoggerPlugin";
  500                     // Also override the jdk LogManager
  501                     System.setProperty("java.util.logging.manager",
  502                        "org.jboss.logging.jdk.JDKLogManager");
  503                  }
  504                  System.setProperty("org.jboss.logging.Logger.pluginClass", logPlugin);
  505                  break;
  506               }
  507               
  508               default:
  509                  // this should not happen,
  510                  // if it does throw an error so we know about it
  511                  throw new Error("unhandled option code: " + code);
  512            }
  513         }
  514   
  515         // Fix up other bind addresses
  516         String bindAddress = System.getProperty(ServerConfig.SERVER_BIND_ADDRESS);
  517         if (System.getProperty("java.rmi.server.hostname") == null)
  518            System.setProperty("java.rmi.server.hostname", bindAddress);
  519         if (System.getProperty("jgroups.bind_addr") == null)
  520            System.setProperty("jgroups.bind_addr", bindAddress);
  521         
  522         // Enable jboss.vfs.forceCopy by default, if unspecified
  523         if (System.getProperty("jboss.vfs.forceCopy") == null)
  524            System.setProperty("jboss.vfs.forceCopy", "true");
  525      }
  526   
  527      /**
  528       * This is where the magic begins.
  529       *
  530       * <P>Starts up inside of a "jboss" thread group to allow better
  531       *    identification of JBoss threads.
  532       *
  533       * @param args    The command line arguments.
  534       * @throws Exception for any error
  535       */
  536      public static void main(final String[] args) throws Exception
  537      {
  538         Runnable worker = new Runnable() {
  539               public void run()
  540               {
  541                  try
  542                  {
  543                     Main main = new Main();
  544                     main.boot(args);
  545                  }
  546                  catch (Exception e)
  547                  {
  548                     System.err.println("Failed to boot JBoss:");
  549                     e.printStackTrace();
  550                  }
  551               }
  552   
  553            };
  554   
  555         ThreadGroup threads = new ThreadGroup("jboss");
  556         new Thread(threads, worker, "main").start();
  557      }
  558   
  559      /**
  560       * This method is here so that if JBoss is running under
  561       * Alexandria (An NT Service Installer), Alexandria can shutdown
  562       * the system down correctly.
  563       * 
  564       * @param argv the arguments
  565       */
  566      public static void systemExit(String argv[])
  567      {
  568         System.exit(0);
  569      }
  570   
  571      static class JarFilter implements FilenameFilter
  572      {
  573         public boolean accept(File dir, String name)
  574         {
  575            return name.endsWith(".jar");
  576         }
  577      }
  578   }

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