Coverage Report - org.mule.MuleServer
 
Classes in this File Line Coverage Branch Coverage Complexity
MuleServer
6%
8/140
0%
0/38
2.286
MuleServer$1
N/A
N/A
2.286
MuleServer$ShutdownThread
0%
0/4
0%
0/6
2.286
 
 1  
 /*
 2  
  * $Id: MuleServer.java 12269 2008-07-10 04:19:03Z dfeist $
 3  
  * --------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
 5  
  *
 6  
  * The software in this package is published under the terms of the CPAL v1.0
 7  
  * license, a copy of which has been included with this distribution in the
 8  
  * LICENSE.txt file.
 9  
  */
 10  
 
 11  
 package org.mule;
 12  
 
 13  
 import org.mule.api.DefaultMuleException;
 14  
 import org.mule.api.MuleContext;
 15  
 import org.mule.api.MuleException;
 16  
 import org.mule.api.config.ConfigurationBuilder;
 17  
 import org.mule.api.config.ConfigurationException;
 18  
 import org.mule.config.ExceptionHelper;
 19  
 import org.mule.config.i18n.CoreMessages;
 20  
 import org.mule.config.i18n.Message;
 21  
 import org.mule.context.DefaultMuleContextFactory;
 22  
 import org.mule.util.ClassUtils;
 23  
 import org.mule.util.IOUtils;
 24  
 import org.mule.util.MuleUrlStreamHandlerFactory;
 25  
 import org.mule.util.PropertiesUtils;
 26  
 import org.mule.util.StringMessageUtils;
 27  
 import org.mule.util.SystemUtils;
 28  
 
 29  
 import java.net.URL;
 30  
 import java.util.ArrayList;
 31  
 import java.util.Collections;
 32  
 import java.util.Date;
 33  
 import java.util.List;
 34  
 import java.util.Map;
 35  
 import java.util.Properties;
 36  
 
 37  
 import org.apache.commons.logging.Log;
 38  
 import org.apache.commons.logging.LogFactory;
 39  
 
 40  
 /**
 41  
  * <code>MuleServer</code> is a simple application that represents a local Mule
 42  
  * Server daemon. It is initialised with a mule-config.xml file.
 43  
  */
 44  
 public class MuleServer implements Runnable
 45  
 {
 46  2
     public static final String CLI_OPTIONS[][] = {
 47  
         {"builder", "true", "Configuration Builder Type"},
 48  
         {"config", "true", "Configuration File"},
 49  
         {"idle", "false", "Whether to run in idle (unconfigured) mode"},
 50  
         {"main", "true", "Main Class"},
 51  
         {"mode", "true", "Run Mode"},
 52  
         {"props", "true", "Startup Properties"},
 53  
         {"debug", "false", "Configure Mule for JPDA remote debugging."}
 54  
     };
 55  
 
 56  
     /**
 57  
      * Don't use a class object so the core doesn't depend on mule-module-spring-config.
 58  
      */
 59  
     protected static final String CLASSNAME_DEFAULT_CONFIG_BUILDER = "org.mule.config.builders.AutoConfigurationBuilder";
 60  
 
 61  
     /**
 62  
      * This builder sets up the configuration for an idle Mule node - a node that
 63  
      * doesn't do anything initially but is fed configuration during runtime
 64  
      */
 65  
     protected static final String CLASSNAME_DEFAULT_IDLE_CONFIG_BUILDER = "org.mule.config.builders.MuleIdleConfigurationBuilder";
 66  
 
 67  
     /**
 68  
      * Required to support the '-config spring' shortcut. Don't use a class object so
 69  
      * the core doesn't depend on mule-module-spring. TODO this may not be a problem
 70  
      * for Mule 2.x
 71  
      */
 72  
     protected static final String CLASSNAME_SPRING_CONFIG_BUILDER = "org.mule.config.spring.SpringXmlConfigurationBuilder";
 73  
 
 74  
     /**
 75  
      * logger used by this class
 76  
      */
 77  2
     private static final Log logger = LogFactory.getLog(MuleServer.class);
 78  
 
 79  
     public static final String DEFAULT_CONFIGURATION = "mule-config.xml";
 80  
 
 81  
     /**
 82  
      * one or more configuration urls or filenames separated by commas
 83  
      */
 84  0
     private String configurationResources = null;
 85  
 
 86  
     /**
 87  
      * A FQN of the #configBuilder class, required in case MuleServer is
 88  
      * reinitialised.
 89  
      */
 90  2
     private static String configBuilderClassName = null;
 91  
 
 92  
     /**
 93  
      * A properties file to be read at startup. This can be useful for setting
 94  
      * properties which depend on the run-time environment (dev, test, production).
 95  
      */
 96  2
     private static String startupPropertiesFile = null;
 97  
 
 98  
     /**
 99  
      * The Runtime shutdown thread used to dispose this server
 100  
      */
 101  
     private static MuleShutdownHook muleShutdownHook;
 102  
 
 103  0
     protected Map options = Collections.EMPTY_MAP;
 104  
 
 105  
     /**
 106  
      * The MuleContext should contain anything which does not belong in the Registry.
 107  
      * There is one MuleContext per Mule instance. Assuming it has been created, a
 108  
      * handle to the local MuleContext can be obtained from anywhere by calling
 109  
      * MuleServer.getMuleContext()
 110  
      */
 111  2
     protected static MuleContext muleContext = null;
 112  
 
 113  
     /**
 114  
      * Application entry point.
 115  
      * 
 116  
      * @param args command-line args
 117  
      */
 118  
     public static void main(String[] args) throws Exception
 119  
     {
 120  0
         MuleServer server = new MuleServer(args);
 121  0
         server.start(false, true);
 122  
 
 123  0
     }
 124  
 
 125  
     public MuleServer()
 126  0
     {
 127  0
         init(new String[]{});
 128  0
     }
 129  
 
 130  
     public MuleServer(String configResources)
 131  0
     {
 132  
         // setConfigurationResources(configResources);
 133  0
         init(new String[]{"-config", configResources});
 134  0
     }
 135  
 
 136  
     /**
 137  
      * Configure the server with command-line arguments.
 138  
      */
 139  
     public MuleServer(String[] args) throws IllegalArgumentException
 140  0
     {
 141  0
         init(args);
 142  0
     }
 143  
 
 144  
     protected void init(String[] args) throws IllegalArgumentException
 145  
     {
 146  
         Map options;
 147  
 
 148  
         try
 149  
         {
 150  0
             muleShutdownHook = new MuleShutdownHook(logger);
 151  0
             registerShutdownHook(muleShutdownHook);
 152  0
             options = SystemUtils.getCommandLineOptions(args, CLI_OPTIONS);
 153  
         }
 154  0
         catch (DefaultMuleException me)
 155  
         {
 156  0
             throw new IllegalArgumentException(me.toString());
 157  0
         }
 158  
 
 159  
         // set our own UrlStreamHandlerFactory to become more independent of system
 160  
         // properties
 161  0
         MuleUrlStreamHandlerFactory.installUrlStreamHandlerFactory();
 162  
 
 163  0
         String config = (String) options.get("config");
 164  
         // Try default if no config file was given.
 165  0
         if (config == null && !options.containsKey("idle"))
 166  
         {
 167  0
             logger.warn("A configuration file was not set, using default: " + DEFAULT_CONFIGURATION);
 168  
             // try to load the config as a file as well
 169  0
             URL configUrl = IOUtils.getResourceAsUrl(DEFAULT_CONFIGURATION, MuleServer.class, true, false);
 170  0
             if (configUrl != null)
 171  
             {
 172  0
                 config = configUrl.toExternalForm();
 173  
             }
 174  
             else
 175  
             {
 176  0
                 System.out.println(CoreMessages.configNotFoundUsage());
 177  0
                 System.exit(-1);
 178  
             }
 179  
         }
 180  
 
 181  0
         if (config != null)
 182  
         {
 183  0
             setConfigurationResources(config);
 184  
         }
 185  
 
 186  
         // Configuration builder
 187  0
         String cfgBuilderClassName = (String) options.get("builder");
 188  
 
 189  0
         if (options.containsKey("idle"))
 190  
         {
 191  0
             setConfigurationResources("IDLE");
 192  0
             cfgBuilderClassName = CLASSNAME_DEFAULT_IDLE_CONFIG_BUILDER;
 193  
         }
 194  
 
 195  
         // Configuration builder
 196  0
         if (cfgBuilderClassName != null)
 197  
         {
 198  
             try
 199  
             {
 200  
                 // Provide a shortcut for Spring: "-builder spring"
 201  0
                 if (cfgBuilderClassName.equalsIgnoreCase("spring"))
 202  
                 {
 203  0
                     cfgBuilderClassName = CLASSNAME_SPRING_CONFIG_BUILDER;
 204  
                 }
 205  0
                 setConfigBuilderClassName(cfgBuilderClassName);
 206  
             }
 207  0
             catch (Exception e)
 208  
             {
 209  0
                 logger.fatal(e);
 210  0
                 final Message message = CoreMessages.failedToLoad("Builder: " + cfgBuilderClassName);
 211  0
                 System.err.println(StringMessageUtils.getBoilerPlate("FATAL: " + message.toString()));
 212  0
                 System.exit(1);
 213  0
             }
 214  
         }
 215  
 
 216  
         // Startup properties
 217  0
         String propertiesFile = (String) options.get("props");
 218  0
         if (propertiesFile != null)
 219  
         {
 220  0
             setStartupPropertiesFile(propertiesFile);
 221  
         }
 222  0
     }
 223  
 
 224  
     /**
 225  
      * Start the mule server
 226  
      * 
 227  
      * @param ownThread determines if the server will run in its own daemon thread or
 228  
      *            the current calling thread
 229  
      */
 230  
     public void start(boolean ownThread, boolean registerShutdownHook)
 231  
     {
 232  0
         if (registerShutdownHook)
 233  
         {
 234  0
             registerShutdownHook(muleShutdownHook);
 235  
         }
 236  0
         if (ownThread)
 237  
         {
 238  0
             Thread serverThread = new Thread(this, "MuleServer");
 239  0
             serverThread.setDaemon(true);
 240  0
             serverThread.start();
 241  0
         }
 242  
         else
 243  
         {
 244  0
             run();
 245  
         }
 246  0
     }
 247  
 
 248  
     /**
 249  
      * Overloaded the [main] thread run method. This calls initialise and shuts down
 250  
      * if an exception occurs
 251  
      */
 252  
     public void run()
 253  
     {
 254  
         try
 255  
         {
 256  0
             logger.info("Mule Server initializing...");
 257  0
             initialize();
 258  0
             logger.info("Mule Server starting...");
 259  0
             muleContext.start();
 260  
         }
 261  0
         catch (Throwable e)
 262  
         {
 263  0
             shutdown(e);
 264  0
         }
 265  0
     }
 266  
 
 267  
     /**
 268  
      * Sets the configuration builder to use for this server. Note that if a builder
 269  
      * is not set and the server's start method is called the default is an instance
 270  
      * of <code>SpringXmlConfigurationBuilder</code>.
 271  
      * 
 272  
      * @param builderClassName the configuration builder FQN to use
 273  
      * @throws ClassNotFoundException if the class with the given name can not be
 274  
      *          loaded
 275  
      */
 276  
     public static void setConfigBuilderClassName(String builderClassName) throws ClassNotFoundException
 277  
     {
 278  0
         if (builderClassName != null)
 279  
         {
 280  0
             Class cls = ClassUtils.loadClass(builderClassName, MuleServer.class);
 281  0
             if (ConfigurationBuilder.class.isAssignableFrom(cls))
 282  
             {
 283  0
                 MuleServer.configBuilderClassName = builderClassName;
 284  
             }
 285  
             else
 286  
             {
 287  0
                 throw new IllegalArgumentException("Not a usable ConfigurationBuilder class: "
 288  
                                                    + builderClassName);
 289  
             }
 290  0
         }
 291  
         else
 292  
         {
 293  0
             MuleServer.configBuilderClassName = null;
 294  
         }
 295  0
     }
 296  
 
 297  
     /**
 298  
      * Returns the class name of the configuration builder used to create this
 299  
      * MuleServer.
 300  
      * 
 301  
      * @return FQN of the current config builder
 302  
      */
 303  
     public static String getConfigBuilderClassName()
 304  
     {
 305  0
         if (configBuilderClassName != null)
 306  
         {
 307  0
             return configBuilderClassName;
 308  
         }
 309  
         else
 310  
         {
 311  0
             return CLASSNAME_DEFAULT_CONFIG_BUILDER;
 312  
         }
 313  
     }
 314  
 
 315  
     /**
 316  
      * Initializes this daemon. Derived classes could add some extra behaviour if they wish.
 317  
      * 
 318  
      * @throws Exception if failed to initialize
 319  
      */
 320  
     public void initialize() throws Exception
 321  
     {
 322  0
         Runtime.getRuntime().addShutdownHook(new ShutdownThread());
 323  
 
 324  0
         if (configurationResources == null)
 325  
         {
 326  0
             logger.warn("A configuration file was not set, using default: " + DEFAULT_CONFIGURATION);
 327  0
             configurationResources = DEFAULT_CONFIGURATION;
 328  
         }
 329  
 
 330  
         ConfigurationBuilder cfgBuilder;
 331  
 
 332  
         try
 333  
         {
 334  
             // create a new ConfigurationBuilder that is disposed afterwards
 335  0
             cfgBuilder = (ConfigurationBuilder) ClassUtils.instanciateClass(getConfigBuilderClassName(),
 336  
                 new Object[]{configurationResources}, MuleServer.class);
 337  
         }
 338  0
         catch (Exception e)
 339  
         {
 340  0
             throw new ConfigurationException(CoreMessages.failedToLoad(getConfigBuilderClassName()), e);
 341  0
         }
 342  
 
 343  0
         if (!cfgBuilder.isConfigured())
 344  
         {
 345  0
             Properties startupProperties= null;
 346  0
             if (getStartupPropertiesFile() != null)
 347  
             {
 348  0
                 startupProperties = PropertiesUtils.loadProperties(getStartupPropertiesFile(), getClass());
 349  
             }
 350  0
             DefaultMuleContextFactory muleContextFactory = new DefaultMuleContextFactory();
 351  0
             muleContext = muleContextFactory.createMuleContext(cfgBuilder, startupProperties);
 352  
         }
 353  0
     }
 354  
 
 355  
     /**
 356  
      * Will shut down the server displaying the cause and time of the shutdown
 357  
      * 
 358  
      * @param e the exception that caused the shutdown
 359  
      */
 360  
     public void shutdown(Throwable e)
 361  
     {
 362  0
         Message msg = CoreMessages.fatalErrorWhileRunning();
 363  0
         MuleException muleException = ExceptionHelper.getRootMuleException(e);
 364  0
         if (muleException != null)
 365  
         {
 366  0
             logger.fatal(muleException.getDetailedMessage());
 367  
         }
 368  
         else
 369  
         {
 370  0
             logger.fatal(msg.toString() + " " + e.getMessage(), e);
 371  
         }
 372  0
         List msgs = new ArrayList();
 373  0
         msgs.add(msg.getMessage());
 374  0
         Throwable root = ExceptionHelper.getRootException(e);
 375  0
         msgs.add(root.getMessage() + " (" + root.getClass().getName() + ")");
 376  0
         msgs.add(" ");
 377  0
         msgs.add(CoreMessages.fatalErrorInShutdown());
 378  0
         if (muleContext != null)
 379  
         {
 380  0
             msgs.add(CoreMessages.serverStartedAt(muleContext.getStartDate()));
 381  
         }
 382  0
         msgs.add(CoreMessages.serverShutdownAt(new Date()));
 383  
 
 384  0
         String shutdownMessage = StringMessageUtils.getBoilerPlate(msgs, '*', 80);
 385  0
         logger.fatal(shutdownMessage);
 386  
 
 387  
         // make sure that Mule is shutdown correctly.
 388  0
         if (muleContext != null)
 389  
         {
 390  0
             muleContext.dispose();
 391  
         }
 392  0
         System.exit(0);
 393  0
     }
 394  
 
 395  
     /**
 396  
      * shutdown the server. This just displays the time the server shut down
 397  
      */
 398  
     public void shutdown()
 399  
     {
 400  0
         logger.info("Mule server shutting dow due to normal shutdown request");
 401  0
         List msgs = new ArrayList();
 402  0
         msgs.add(CoreMessages.normalShutdown());
 403  0
         msgs.add(CoreMessages.serverStartedAt(muleContext.getStartDate()).getMessage());
 404  0
         msgs.add(CoreMessages.serverShutdownAt(new Date()).getMessage());
 405  0
         String shutdownMessage = StringMessageUtils.getBoilerPlate(msgs, '*', 80);
 406  0
         logger.info(shutdownMessage);
 407  
 
 408  
         // make sure that Mule is shutdown correctly.
 409  0
         muleContext.dispose();
 410  0
         System.exit(0);
 411  0
     }
 412  
 
 413  
     public Log getLogger()
 414  
     {
 415  0
         return logger;
 416  
     }
 417  
 
 418  
     public void registerShutdownHook(MuleShutdownHook muleShutdownHook)
 419  
     {
 420  0
         Runtime.getRuntime().removeShutdownHook(muleShutdownHook);
 421  0
         Runtime.getRuntime().addShutdownHook(muleShutdownHook);
 422  0
     }
 423  
 
 424  
     // /////////////////////////////////////////////////////////////////
 425  
     // Getters and setters
 426  
     // /////////////////////////////////////////////////////////////////
 427  
 
 428  
     /**
 429  
      * Getter for property messengerURL.
 430  
      * 
 431  
      * @return Value of property messengerURL.
 432  
      */
 433  
     public String getConfigurationResources()
 434  
     {
 435  0
         return configurationResources;
 436  
     }
 437  
 
 438  
     /**
 439  
      * Setter for property configurationResources.
 440  
      * 
 441  
      * @param configurationResources New value of property configurationResources.
 442  
      */
 443  
     public void setConfigurationResources(String configurationResources)
 444  
     {
 445  0
         this.configurationResources = configurationResources;
 446  0
     }
 447  
 
 448  
     public static String getStartupPropertiesFile()
 449  
     {
 450  0
         return startupPropertiesFile;
 451  
     }
 452  
 
 453  
     public static void setStartupPropertiesFile(String startupPropertiesFile)
 454  
     {
 455  0
         MuleServer.startupPropertiesFile = startupPropertiesFile;
 456  0
     }
 457  
 
 458  
     public static MuleContext getMuleContext()
 459  
     {
 460  51970
         return muleContext;
 461  
     }
 462  
 
 463  
     public static void setMuleContext(MuleContext muleContext)
 464  
     {
 465  3754
         MuleServer.muleContext = muleContext;
 466  3754
     }
 467  
 
 468  
     /**
 469  
      * This class is installed only for MuleServer running as commandline app. A
 470  
      * clean Mule shutdown can be achieved by disposing the
 471  
      * {@link org.mule.DefaultMuleContext}.
 472  
      */
 473  0
     private static class ShutdownThread extends Thread
 474  
     {
 475  
         public void run()
 476  
         {
 477  0
             if (muleContext !=null && !muleContext.isDisposed() && !muleContext.isDisposing())
 478  
             {
 479  0
                 muleContext.dispose();
 480  
             }
 481  0
         }
 482  
     }
 483  
 }