View Javadoc
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.module.launcher;
8   
9   import org.mule.api.DefaultMuleException;
10  import org.mule.api.MuleException;
11  import org.mule.config.ExceptionHelper;
12  import org.mule.config.StartupContext;
13  import org.mule.config.i18n.CoreMessages;
14  import org.mule.config.i18n.Message;
15  import org.mule.module.launcher.log4j.ApplicationAwareRepositorySelector;
16  import org.mule.util.MuleUrlStreamHandlerFactory;
17  import org.mule.util.StringMessageUtils;
18  import org.mule.util.SystemUtils;
19  
20  import java.util.ArrayList;
21  import java.util.List;
22  import java.util.Map;
23  
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  import org.apache.log4j.LogManager;
27  
28  /**
29   *
30   */
31  public class MuleContainer
32  {
33      public static final String CLI_OPTIONS[][] = {
34          {"builder", "true", "Configuration Builder Type"},
35          {"config", "true", "Configuration File"},
36          {"idle", "false", "Whether to run in idle (unconfigured) mode"},
37          {"main", "true", "Main Class"},
38          {"mode", "true", "Run Mode"},
39          {"props", "true", "Startup Properties"},
40          {"production", "false", "Production Mode"},
41          {"debug", "false", "Configure Mule for JPDA remote debugging."},
42          {"app", "true", "Application to start"}
43      };
44  
45      /**
46       * logger used by this class
47       */
48      private static Log logger;
49  
50      /**
51       * A properties file to be read at startup. This can be useful for setting
52       * properties which depend on the run-time environment (dev, test, production).
53       */
54      private static String startupPropertiesFile = null;
55  
56      /**
57       * The Runtime shutdown thread used to undeploy this server
58       */
59      private static MuleShutdownHook muleShutdownHook;
60  
61      protected DeploymentService deploymentService;
62  
63      static
64      {
65          if (System.getProperty("mule.simpleLog") == null)
66          {
67              // TODO save this guard ref for later
68              LogManager.setRepositorySelector(new ApplicationAwareRepositorySelector(), new Object());
69          }
70          logger = LogFactory.getLog(MuleContainer.class);
71      }
72  
73      /**
74       * Application entry point.
75       *
76       * @param args command-line args
77       */
78      public static void main(String[] args) throws Exception
79      {
80          MuleContainer container = new MuleContainer(args);
81          container.start(true);
82      }
83  
84      public MuleContainer()
85      {
86          init(new String[0]);
87      }
88  
89      /**
90       * Configure the server with command-line arguments.
91       */
92      public MuleContainer(String[] args) throws IllegalArgumentException
93      {                                                                                                                                                           
94          init(args);
95      }
96  
97      protected void init(String[] args) throws IllegalArgumentException
98      {
99          Map<String, Object> commandlineOptions;
100 
101         try
102         {
103             commandlineOptions = SystemUtils.getCommandLineOptions(args, CLI_OPTIONS);
104         }
105         catch (DefaultMuleException me)
106         {
107             throw new IllegalArgumentException(me.toString());
108         }
109 
110         // set our own UrlStreamHandlerFactory to become more independent of system
111         // properties
112         MuleUrlStreamHandlerFactory.installUrlStreamHandlerFactory();
113 
114         // Startup properties
115         String propertiesFile = (String) commandlineOptions.get("props");
116         if (propertiesFile != null)
117         {
118             setStartupPropertiesFile(propertiesFile);
119         }
120         StartupContext.get().setStartupOptions(commandlineOptions);
121     }
122 
123     public void start(boolean registerShutdownHook)
124     {
125         if (registerShutdownHook)
126         {
127             registerShutdownHook();
128         }
129 
130         final MuleContainerStartupSplashScreen splashScreen = new MuleContainerStartupSplashScreen();
131         splashScreen.doBody();
132         logger.info(splashScreen.toString());
133 
134         try
135         {
136             // TODO pluggable deployer
137             deploymentService = new DeploymentService();
138             deploymentService.start();
139         }
140         catch (Throwable e)
141         {
142             shutdown(e);
143         }
144     }
145 
146     /**
147      * Will shut down the server displaying the cause and time of the shutdown
148      *
149      * @param e the exception that caused the shutdown
150      */
151     public void shutdown(Throwable e)
152     {
153         Message msg = CoreMessages.fatalErrorWhileRunning();
154         MuleException muleException = ExceptionHelper.getRootMuleException(e);
155         if (muleException != null)
156         {
157             logger.fatal(muleException.getDetailedMessage());
158         }
159         else
160         {
161             logger.fatal(msg.toString() + " " + e.getMessage(), e);
162         }
163         List<String> msgs = new ArrayList<String>();
164         msgs.add(msg.getMessage());
165         Throwable root = ExceptionHelper.getRootException(e);
166         msgs.add(root.getMessage() + " (" + root.getClass().getName() + ")");
167         msgs.add(" ");
168         msgs.add(CoreMessages.fatalErrorInShutdown().getMessage());
169         String shutdownMessage = StringMessageUtils.getBoilerPlate(msgs, '*', 80);
170         logger.fatal(shutdownMessage);
171 
172         unregisterShutdownHook();
173         doShutdown();
174     }
175 
176     /**
177      * shutdown the server. This just displays the time the server shut down
178      */
179     public void shutdown()
180     {
181         logger.info("Mule container shutting down due to normal shutdown request");
182 
183         unregisterShutdownHook();
184         doShutdown();
185     }
186 
187     protected void doShutdown()
188     {
189         if (deploymentService != null)
190         {
191             deploymentService.stop();
192         }
193 
194         System.exit(0);
195     }
196 
197     public Log getLogger()
198     {
199         return logger;
200     }
201 
202     public void registerShutdownHook()
203     {
204         if (muleShutdownHook == null)
205         {
206             muleShutdownHook = new MuleShutdownHook();
207         }
208         else
209         {
210             Runtime.getRuntime().removeShutdownHook(muleShutdownHook);
211         }
212         Runtime.getRuntime().addShutdownHook(muleShutdownHook);
213     }
214 
215     public void unregisterShutdownHook()
216     {
217         if (muleShutdownHook != null)
218         {
219             Runtime.getRuntime().removeShutdownHook(muleShutdownHook);
220         }
221     }
222 
223     // /////////////////////////////////////////////////////////////////
224     // Getters and setters
225     // /////////////////////////////////////////////////////////////////
226 
227 
228     public static String getStartupPropertiesFile()
229     {
230         return startupPropertiesFile;
231     }
232 
233     public static void setStartupPropertiesFile(String startupPropertiesFile)
234     {
235         MuleContainer.startupPropertiesFile = startupPropertiesFile;
236     }
237 
238     /**
239      * This class is installed only for MuleContainer running as commandline app. A
240      * clean Mule shutdown can be achieved by disposing the
241      * {@link org.mule.DefaultMuleContext}.
242      */
243     private class MuleShutdownHook extends Thread
244     {
245         public MuleShutdownHook()
246         {
247             super("Mule.shutdown.hook");
248         }
249 
250         @Override
251         public void run()
252         {
253             doShutdown();
254         }
255     }
256 }
257