org.mule.MuleServer Maven / Gradle / Ivy
/*
* $Id: MuleServer.java 22252 2011-06-23 06:15:55Z dirk.olmes $
* --------------------------------------------------------------------------------------
* Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com
*
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule;
import org.mule.api.DefaultMuleException;
import org.mule.api.MuleContext;
import org.mule.api.MuleException;
import org.mule.api.config.ConfigurationBuilder;
import org.mule.api.config.ConfigurationException;
import org.mule.api.config.MuleConfiguration;
import org.mule.api.context.MuleContextBuilder;
import org.mule.api.context.MuleContextFactory;
import org.mule.config.ExceptionHelper;
import org.mule.config.PropertiesMuleConfigurationFactory;
import org.mule.config.StartupContext;
import org.mule.config.builders.SimpleConfigurationBuilder;
import org.mule.config.i18n.CoreMessages;
import org.mule.config.i18n.Message;
import org.mule.context.DefaultMuleContextBuilder;
import org.mule.context.DefaultMuleContextFactory;
import org.mule.util.ClassUtils;
import org.mule.util.IOUtils;
import org.mule.util.MuleUrlStreamHandlerFactory;
import org.mule.util.PropertiesUtils;
import org.mule.util.StringMessageUtils;
import org.mule.util.SystemUtils;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* MuleServer
is a simple application that represents a local Mule
* Server daemon. It is initialised with a mule-config.xml file.
*/
public class MuleServer implements Runnable
{
public static final String CLI_OPTIONS[][] = {
{"builder", "true", "Configuration Builder Type"},
{"config", "true", "Configuration File"},
{"appconfig", "true", "Application configuration File"},
{"idle", "false", "Whether to run in idle (unconfigured) mode"},
{"main", "true", "Main Class"},
{"mode", "true", "Run Mode"},
{"props", "true", "Startup Properties"},
{"production", "false", "Production Mode"},
{"debug", "false", "Configure Mule for JPDA remote debugging."}
};
/**
* Don't use a class object so the core doesn't depend on mule-module-spring-config.
*/
protected static final String CLASSNAME_DEFAULT_CONFIG_BUILDER = "org.mule.config.builders.AutoConfigurationBuilder";
/**
* This builder sets up the configuration for an idle Mule node - a node that
* doesn't do anything initially but is fed configuration during runtime
*/
protected static final String CLASSNAME_DEFAULT_IDLE_CONFIG_BUILDER = "org.mule.config.builders.MuleIdleConfigurationBuilder";
/**
* Required to support the '-config spring' shortcut. Don't use a class object so
* the core doesn't depend on mule-module-spring.
* for Mule 2.x
*/
protected static final String CLASSNAME_SPRING_CONFIG_BUILDER = "org.mule.config.spring.SpringXmlConfigurationBuilder";
/**
* If the annotations module is on the classpath, also enable annotations config builder
*/
public static final String CLASSNAME_ANNOTATIONS_CONFIG_BUILDER = "org.mule.config.AnnotationsConfigurationBuilder";
/**
* If the iBeans module is on the classpath, this config builder can be used to scan for iBeans annotations.
*/
public static final String CLASSNAME_IBEANS_CONFIG_BUILDER = "org.mule.module.ibeans.config.IBeanHolderConfigurationBuilder";
/**
* logger used by this class
*/
private static final Log logger = LogFactory.getLog(MuleServer.class);
public static final String DEFAULT_CONFIGURATION = "mule-config.xml";
public static final String DEFAULT_APP_CONFIGURATION = "mule-app.properties";
/**
* one or more configuration urls or filenames separated by commas
*/
private String configurationResources = null;
private String appConfigurationResource = null;
/**
* A FQN of the #configBuilder class, required in case MuleServer is
* reinitialised.
*/
private static String configBuilderClassName = null;
/**
* A properties file to be read at startup. This can be useful for setting
* properties which depend on the run-time environment (dev, test, production).
*/
private static String startupPropertiesFile = null;
/**
* The Runtime shutdown thread used to dispose this server
*/
private static MuleShutdownHook muleShutdownHook;
/**
* The MuleContext should contain anything which does not belong in the Registry.
* There is one MuleContext per Mule instance. Assuming it has been created, a
* handle to the local MuleContext can be obtained from anywhere by calling
* MuleServer.getMuleContext()
*/
protected static MuleContext muleContext = null;
/**
* Application entry point.
*
* @param args command-line args
* @throws Exception if there is an exception creating the MuleServer
*/
public static void main(String[] args) throws Exception
{
MuleServer server = new MuleServer(args);
server.start(false, true);
}
public MuleServer()
{
init(new String[]{});
}
public MuleServer(String configResources)
{
// setConfigurationResources(configResources);
init(new String[]{"-config", configResources});
}
/**
* Configure the server with command-line arguments.
* @param args Command line args passed in from the {@link #main(String[])} method
* @throws IllegalArgumentException if an argument is passed in that is not recognised by the Mule Server
*/
public MuleServer(String[] args) throws IllegalArgumentException
{
init(args);
}
protected void init(String[] args) throws IllegalArgumentException
{
Map commandlineOptions;
try
{
commandlineOptions = SystemUtils.getCommandLineOptions(args, CLI_OPTIONS);
}
catch (DefaultMuleException me)
{
throw new IllegalArgumentException(me.toString());
}
// set our own UrlStreamHandlerFactory to become more independent of system
// properties
MuleUrlStreamHandlerFactory.installUrlStreamHandlerFactory();
String config = (String) commandlineOptions.get("config");
// Try default if no config file was given.
if (config == null && !commandlineOptions.containsKey("idle"))
{
logger.warn("A configuration file was not set, using default: " + DEFAULT_CONFIGURATION);
// try to load the config as a file as well
URL configUrl = IOUtils.getResourceAsUrl(DEFAULT_CONFIGURATION, MuleServer.class, true, false);
if (configUrl != null)
{
config = configUrl.toExternalForm();
}
else
{
System.out.println(CoreMessages.configNotFoundUsage());
System.exit(-1);
}
}
if (config != null)
{
setConfigurationResources(config);
}
String appconfig = (String) commandlineOptions.get("appconfig");
this.appConfigurationResource = appconfig;
// Configuration builder
String cfgBuilderClassName = (String) commandlineOptions.get("builder");
if (commandlineOptions.containsKey("idle"))
{
setConfigurationResources("IDLE");
cfgBuilderClassName = CLASSNAME_DEFAULT_IDLE_CONFIG_BUILDER;
}
// Configuration builder
if (cfgBuilderClassName != null)
{
try
{
// Provide a shortcut for Spring: "-builder spring"
if (cfgBuilderClassName.equalsIgnoreCase("spring"))
{
cfgBuilderClassName = CLASSNAME_SPRING_CONFIG_BUILDER;
}
setConfigBuilderClassName(cfgBuilderClassName);
}
catch (Exception e)
{
logger.fatal(e);
final Message message = CoreMessages.failedToLoad("Builder: " + cfgBuilderClassName);
System.err.println(StringMessageUtils.getBoilerPlate("FATAL: " + message.toString()));
System.exit(1);
}
}
// Startup properties
String propertiesFile = (String) commandlineOptions.get("props");
if (propertiesFile != null)
{
setStartupPropertiesFile(propertiesFile);
}
StartupContext.get().setStartupOptions(commandlineOptions);
}
/**
* Start the mule server
*
* @param ownThread determines if the server will run in its own daemon thread or
* the current calling thread
* @param registerShutdownHook whether to register the default Mule Server shutdown hock. this will shut down mule cleanly if
* the JVM is shutdown. The only reason not to register this hook is to override it with a custom version
*/
public void start(boolean ownThread, boolean registerShutdownHook)
{
if (registerShutdownHook)
{
registerShutdownHook();
}
if (ownThread)
{
Thread serverThread = new Thread(this, "MuleServer");
serverThread.setDaemon(true);
serverThread.start();
}
else
{
run();
}
}
/**
* Overloaded the [main] thread run method. This calls initialise and shuts down
* if an exception occurs
*/
public void run()
{
try
{
logger.info("Mule Server initializing...");
initialize();
logger.info("Mule Server starting...");
muleContext.start();
}
catch (Throwable e)
{
shutdown(e);
}
}
/**
* Sets the configuration builder to use for this server. Note that if a builder
* is not set and the server's start method is called the default is an instance
* of SpringXmlConfigurationBuilder
.
*
* @param builderClassName the configuration builder FQN to use
* @throws ClassNotFoundException if the class with the given name can not be
* loaded
*/
public static void setConfigBuilderClassName(String builderClassName) throws ClassNotFoundException
{
if (builderClassName != null)
{
Class> cls = ClassUtils.loadClass(builderClassName, MuleServer.class);
if (ConfigurationBuilder.class.isAssignableFrom(cls))
{
MuleServer.configBuilderClassName = builderClassName;
}
else
{
throw new IllegalArgumentException("Not a usable ConfigurationBuilder class: "
+ builderClassName);
}
}
else
{
MuleServer.configBuilderClassName = null;
}
}
/**
* Returns the class name of the configuration builder used to create this
* MuleServer.
*
* @return FQN of the current config builder
*/
public static String getConfigBuilderClassName()
{
if (configBuilderClassName != null)
{
return configBuilderClassName;
}
else
{
return CLASSNAME_DEFAULT_CONFIG_BUILDER;
}
}
/**
* Initializes this daemon. Derived classes could add some extra behaviour if
* they wish.
*
* @throws Exception if failed to initialize
*/
public void initialize() throws Exception
{
if (configurationResources == null)
{
logger.warn("A configuration file was not set, using default: " + DEFAULT_CONFIGURATION);
configurationResources = DEFAULT_CONFIGURATION;
}
// create a new ConfigurationBuilder that is disposed afterwards
ConfigurationBuilder cfgBuilder = createConfigurationBuilder();
if (!cfgBuilder.isConfigured())
{
List configBuilders = new ArrayList(3);
// need to add the annotations config builder before Spring so we can use Mule
// annotations in Spring
addAnnotationsConfigBuilder(configBuilders);
addStartupPropertiesConfigBuilder(configBuilders);
configBuilders.add(cfgBuilder);
MuleConfiguration configuration = createMuleConfiguration();
MuleContextBuilder contextBuilder = new DefaultMuleContextBuilder();
contextBuilder.setMuleConfiguration(configuration);
MuleContextFactory contextFactory = new DefaultMuleContextFactory();
muleContext = contextFactory.createMuleContext(configBuilders, contextBuilder);
}
}
protected ConfigurationBuilder createConfigurationBuilder() throws ConfigurationException
{
try
{
return (ConfigurationBuilder) ClassUtils.instanciateClass(getConfigBuilderClassName(),
new Object[]{ configurationResources }, MuleServer.class);
}
catch (Exception e)
{
throw new ConfigurationException(CoreMessages.failedToLoad(getConfigBuilderClassName()), e);
}
}
/**
* If the annotations module is on the classpath, add the annotations config builder to the
* list. This will enable annotations config for this instance.
*/
protected void addAnnotationsConfigBuilder(List builders) throws Exception
{
if (ClassUtils.isClassOnPath(CLASSNAME_ANNOTATIONS_CONFIG_BUILDER, getClass()))
{
Object configBuilder = ClassUtils.instanciateClass(CLASSNAME_ANNOTATIONS_CONFIG_BUILDER,
ClassUtils.NO_ARGS, getClass());
builders.add((ConfigurationBuilder) configBuilder);
}
}
protected void addStartupPropertiesConfigBuilder(List builders) throws IOException
{
Properties startupProperties = null;
if (getStartupPropertiesFile() != null)
{
startupProperties = PropertiesUtils.loadProperties(getStartupPropertiesFile(), getClass());
}
builders.add(new SimpleConfigurationBuilder(startupProperties));
}
protected MuleConfiguration createMuleConfiguration()
{
String appPropertiesFile = null;
if (this.appConfigurationResource == null)
{
appPropertiesFile = PropertiesMuleConfigurationFactory.getMuleAppConfiguration(this.configurationResources);
}
else
{
appPropertiesFile = this.appConfigurationResource;
}
return new PropertiesMuleConfigurationFactory(appPropertiesFile).createConfiguration();
}
/**
* Will shut down the server displaying the cause and time of the shutdown
*
* @param e the exception that caused the shutdown
*/
public void shutdown(Throwable e)
{
doShutdown();
unregisterShutdownHook();
Message msg = CoreMessages.fatalErrorWhileRunning();
MuleException muleException = ExceptionHelper.getRootMuleException(e);
int exitCode = 1;
if (muleException != null)
{
logger.fatal(muleException.getDetailedMessage());
exitCode = muleException.getExceptionCode();
}
else
{
logger.fatal(msg.toString() + " " + e.getMessage(), e);
}
List msgs = new ArrayList();
msgs.add(msg.getMessage());
Throwable root = ExceptionHelper.getRootException(e);
msgs.add(root.getMessage() + " (" + root.getClass().getName() + ")");
msgs.add(" ");
msgs.add(CoreMessages.fatalErrorInShutdown().getMessage());
String shutdownMessage = StringMessageUtils.getBoilerPlate(msgs, '*', 80);
logger.fatal(shutdownMessage);
System.exit(exitCode);
}
/**
* shutdown the server. This just displays the time the server shut down
*/
public void shutdown()
{
logger.info("Mule server shutting down due to normal shutdown request");
unregisterShutdownHook();
doShutdown();
System.exit(0);
}
protected void doShutdown()
{
if (muleContext != null)
{
muleContext.dispose();
muleContext = null;
}
}
public Log getLogger()
{
return logger;
}
public void registerShutdownHook()
{
if (muleShutdownHook == null)
{
muleShutdownHook = new MuleShutdownHook();
}
else
{
Runtime.getRuntime().removeShutdownHook(muleShutdownHook);
}
Runtime.getRuntime().addShutdownHook(muleShutdownHook);
}
public void unregisterShutdownHook()
{
if (muleShutdownHook != null)
{
Runtime.getRuntime().removeShutdownHook(muleShutdownHook);
}
}
// /////////////////////////////////////////////////////////////////
// Getters and setters
// /////////////////////////////////////////////////////////////////
/**
* Getter for property messengerURL.
*
* @return Value of property messengerURL.
*/
public String getConfigurationResources()
{
return configurationResources;
}
/**
* Setter for property configurationResources.
*
* @param configurationResources New value of property configurationResources.
*/
public void setConfigurationResources(String configurationResources)
{
this.configurationResources = configurationResources;
}
public static String getStartupPropertiesFile()
{
return startupPropertiesFile;
}
public static void setStartupPropertiesFile(String startupPropertiesFile)
{
MuleServer.startupPropertiesFile = startupPropertiesFile;
}
public MuleContext getMuleContext()
{
return muleContext;
}
/**
* This class is installed only for MuleServer running as commandline app. A
* clean Mule shutdown can be achieved by disposing the
* {@link org.mule.DefaultMuleContext}.
*/
private class MuleShutdownHook extends Thread
{
public MuleShutdownHook()
{
super();
}
@Override
public void run()
{
doShutdown();
System.exit(0);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy