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