View Javadoc

1   /**
2    *
3    *  Licensed to the Apache Software Foundation (ASF) under one or more
4    *  contributor license agreements.  See the NOTICE file distributed with
5    *  this work for additional information regarding copyright ownership.
6    *  The ASF licenses this file to You under the Apache License, Version 2.0
7    *  (the "License"); you may not use this file except in compliance with
8    *  the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing, software
13   *  distributed under the License is distributed on an "AS IS" BASIS,
14   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   *  See the License for the specific language governing permissions and
16   *  limitations under the License.
17   */
18  
19  package org.apache.geronimo.system.main;
20  
21  import org.apache.commons.logging.Log;
22  import org.apache.commons.logging.LogFactory;
23  import org.apache.geronimo.common.GeronimoEnvironment;
24  import org.apache.geronimo.gbean.AbstractName;
25  import org.apache.geronimo.gbean.AbstractNameQuery;
26  import org.apache.geronimo.kernel.Kernel;
27  import org.apache.geronimo.kernel.KernelFactory;
28  import org.apache.geronimo.kernel.config.ConfigurationManager;
29  import org.apache.geronimo.kernel.config.ConfigurationUtil;
30  import org.apache.geronimo.kernel.config.PersistentConfigurationList;
31  import org.apache.geronimo.kernel.log.GeronimoLogging;
32  import org.apache.geronimo.kernel.repository.Artifact;
33  import org.apache.geronimo.system.serverinfo.DirectoryUtils;
34  
35  import java.io.File;
36  import java.io.IOException;
37  import java.io.InputStream;
38  import java.io.PrintStream;
39  import java.util.ArrayList;
40  import java.util.Iterator;
41  import java.util.List;
42  import java.util.Set;
43  
44  /**
45   * @version $Rev:385659 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $
46   */
47  public class Daemon {
48      private final static String ARGUMENT_NO_PROGRESS = "--quiet";
49      private final static String ARGUMENT_LONG_PROGRESS = "--long";
50      private final static String ARGUMENT_VERBOSE_SHORTFORM = "-v";
51      private final static String ARGUMENT_VERBOSE = "--verbose";
52      private final static String ARGUMENT_MORE_VERBOSE_SHORTFORM = "-vv";
53      private final static String ARGUMENT_MORE_VERBOSE = "--veryverbose";
54      private final static String ARGUMENT_MODULE_OVERRIDE = "--override";
55      private static boolean started = false;
56      private static Log log;
57      private StartupMonitor monitor;
58      private List configs = new ArrayList();
59      private String verboseArg = null;
60      private String noProgressArg = null;
61      private String longProgressArg = null;
62  
63      private Daemon(String[] args) {
64          // Very first startup tasks
65          long start = System.currentTimeMillis();
66          // Command line arguments affect logging configuration, etc.
67          if(processArguments(args)) {
68              System.out.println("Booting Geronimo Kernel (in Java " + System.getProperty("java.version") + ")...");
69              System.out.flush();
70  
71              // Initialization tasks that must run before anything else
72              initializeSystem();
73  
74              monitor.systemStarting(start);
75              doStartup();
76          } else {
77              System.exit(1);
78              throw new AssertionError();
79          }
80      }
81  
82      private void printHelp(PrintStream out) {
83          out.println();
84          out.println("Syntax: java -jar bin/server.jar [options]");
85          out.println();
86          out.println("Available options are: ");
87          out.println("  "+ARGUMENT_NO_PROGRESS);
88          out.println("             Suppress the normal startup progress bar.  This is typically\n" +
89                      "             used when redirecting console output to a file, or starting\n" +
90                      "             the server from an IDE or other tool.");
91          out.println("  "+ARGUMENT_LONG_PROGRESS);
92          out.println("             Write startup progress to the console in a format that is\n" +
93                      "             suitable for redirecting console output to a file, or starting\n" +
94                      "             the server from an IDE or other tool (doesn't use linefeeds to\n" +
95                      "             update the progress information that is used by default if you\n" +
96                      "             don't specify " +ARGUMENT_NO_PROGRESS +" or "+ARGUMENT_LONG_PROGRESS+").\n");
97          out.println("  "+ARGUMENT_VERBOSE_SHORTFORM +" " +ARGUMENT_VERBOSE);
98          out.println("             Reduces the console log level to DEBUG, resulting in more\n" +
99                      "             console output than is normally present.");
100         out.println("  "+ARGUMENT_MORE_VERBOSE_SHORTFORM +" " +ARGUMENT_MORE_VERBOSE);
101         out.println("             Reduces the console log level to TRACE, resulting in still\n" +
102                     "             more console output.");
103         out.println();
104         out.println("  "+ARGUMENT_MODULE_OVERRIDE+" [moduleId] [moduleId] ...");
105         out.println("             USE WITH CAUTION!  Overrides the modules in\n" +
106                     "             var/config/config.xml such that only the modules listed on\n" +
107                     "             the command line will be started.  Note that many J2EE\n" +
108                     "             features depend on certain modules being started, so you\n" +
109                     "             should be very careful what you omit.  Any arguments after\n" +
110                     "             this are assumed to be module names.");
111         out.println();
112         out.println("In addition you may specify a replacement for var/config/config.xml using by setting the property\n" +
113                     "-Dorg.apache.geronimo.config.file=var/config/<my-config.xml>\n" +
114                     "This is resolved relative to the geronimo base directory.");
115         out.println();
116     }
117 
118     /**
119      * @return true if the server startup should proceed (all arguments
120      *              make sense and the user didn't ask for help)
121      */
122     private boolean processArguments(String[] args) {
123         boolean override = false;
124         boolean help = false;
125         for (int i = 0; i < args.length; i++) {
126             if(override) {
127                 configs.add(Artifact.create(args[i]));
128             } else if (args[i].equals(ARGUMENT_NO_PROGRESS)) {
129                 noProgressArg = ARGUMENT_NO_PROGRESS;
130             } else if (args[i].equals(ARGUMENT_LONG_PROGRESS)) {
131                 longProgressArg = ARGUMENT_LONG_PROGRESS;
132             } else if (args[i].equals(ARGUMENT_VERBOSE_SHORTFORM) ||
133                     args[i].equals(ARGUMENT_VERBOSE)) {
134                 if (verboseArg == null) {
135                     verboseArg = ARGUMENT_VERBOSE;
136                 }
137             } else if (args[i].equals(ARGUMENT_MORE_VERBOSE_SHORTFORM) ||
138                     args[i].equals(ARGUMENT_MORE_VERBOSE)) {
139                 if (verboseArg == null) {
140                     verboseArg = ARGUMENT_MORE_VERBOSE;
141                 }
142             } else if (args[i].equals(ARGUMENT_MODULE_OVERRIDE)) {
143                 override = true;
144             } else if(args[i].equalsIgnoreCase("-help") || args[i].equalsIgnoreCase("--help") ||
145                     args[i].equalsIgnoreCase("-h") || args[i].equalsIgnoreCase("/?")) {
146                 help = true;
147             } else {
148                 System.out.println("Unrecognized argument: "+args[i]);
149                 help = true;
150             }
151         }
152         if(help) {
153             printHelp(System.out);
154         }
155         return !help;
156     }
157 
158     private void initializeSystem() {
159         if (!started) {
160             started = true;
161 
162             // Perform initialization tasks common with the various Geronimo environments
163             GeronimoEnvironment.init();
164 
165             // This MUST be done before the first log is acquired (WHICH THE STARTUP MONITOR 5 LINES LATER DOES!)
166             // Generally we want to suppress anything but WARN until the log GBean starts up
167             GeronimoLogging.initialize(verboseArg == null || verboseArg.equals(ARGUMENT_VERBOSE) ? GeronimoLogging.WARN : GeronimoLogging.DEBUG);
168             // The following will be used once the log GBean starts up
169             GeronimoLogging.setConsoleLogLevel(verboseArg == null ? GeronimoLogging.INFO : verboseArg.equals(ARGUMENT_VERBOSE) ? GeronimoLogging.DEBUG : GeronimoLogging.TRACE);
170             log = LogFactory.getLog(Daemon.class.getName());
171         }
172 
173         if (verboseArg != null || noProgressArg != null) {
174             monitor = new SilentStartupMonitor();
175         } else {
176             if (longProgressArg != null)
177                 monitor = new LongStartupMonitor();
178             else
179                 monitor = new ProgressBarStartupMonitor();
180         }
181 
182         // JVMCheck();   // Removed for 1.1
183     }
184 
185     private void JVMCheck() {
186         String jvmVersion = System.getProperty("java.specification.version");
187         if (! jvmVersion.equals("1.4"))
188             log.warn("\n====================================== Warning =======================================\n" +
189                      " Geronimo is currently only certified on version 1.4 of the Java Virtual Machine.\n" +
190                      " Use of version " + jvmVersion + " is not currently supported.  Use at your own risk.\n" +
191                      " Check http://geronimo.apache.org for current information on JDK certification level.\n" +
192                      "====================================== Warning =======================================");
193     }
194 
195     private void doStartup() {
196         try {
197             // Check that the tmpdir exists - if not give friendly msg and exit
198             // since we allow it to be configured in geronimo.bat and geronimo.sh
199             // (since 1.0 release) the same way Tomcat allows it to be configured.
200             String tmpDir = System.getProperty("java.io.tmpdir");
201             if (tmpDir == null || (!(new File(tmpDir)).exists()) ||
202                     (!(new File(tmpDir)).isDirectory())) {
203                     System.err.println("The java.io.tmpdir system property specifies the "+
204                             "non-existent directory " +tmpDir);
205                     System.exit(1);
206                     throw new AssertionError();
207                 }
208 
209             // Determine the geronimo installation directory
210             File geronimoInstallDirectory = DirectoryUtils.getGeronimoInstallDirectory();
211             if (geronimoInstallDirectory == null) {
212                 System.err.println("Could not determine geronimo installation directory");
213                 System.exit(1);
214                 throw new AssertionError();
215             }
216 
217             ClassLoader classLoader = Daemon.class.getClassLoader();
218 
219             // create the kernel
220             final Kernel kernel = KernelFactory.newInstance().createKernel("geronimo");
221 
222             // boot the kernel
223             try {
224                 kernel.boot();
225             } catch (Exception e) {
226                 e.printStackTrace();
227                 System.exit(1);
228                 throw new AssertionError();
229             }
230 
231             // add our shutdown hook
232             Runtime.getRuntime().addShutdownHook(new Thread("Geronimo shutdown thread") {
233                 public void run() {
234                     System.out.println("\rServer shutdown begun              ");
235                     kernel.shutdown();
236                     System.out.println("Server shutdown completed");
237                 }
238             });
239 
240             // load this configuration
241             InputStream in = classLoader.getResourceAsStream("META-INF/config.ser");
242             try {
243                 ConfigurationUtil.loadBootstrapConfiguration(kernel, in, classLoader);
244             } finally {
245                 if (in != null) {
246                     try {
247                         in.close();
248                     } catch (IOException ignored) {
249                         // ignored
250                     }
251                 }
252             }
253 
254             monitor.systemStarted(kernel);
255 
256             AbstractNameQuery query = new AbstractNameQuery(PersistentConfigurationList.class.getName());
257 
258             if (configs.isEmpty()) {
259                 // --override wasn't used (nothing explicit), see what was running before
260                 Set configLists = kernel.listGBeans(query);
261                 for (Iterator i = configLists.iterator(); i.hasNext();) {
262                     AbstractName configListName = (AbstractName) i.next();
263                     try {
264                         configs.addAll((List) kernel.invoke(configListName, "restore"));
265                     } catch (IOException e) {
266                         System.err.println("Unable to restore last known configurations");
267                         e.printStackTrace();
268                         kernel.shutdown();
269                         System.exit(1);
270                         throw new AssertionError();
271                     }
272                 }
273             }
274 
275             monitor.foundModules((Artifact[]) configs.toArray(new Artifact[configs.size()]));
276 
277             // load the rest of the configurations
278             try {
279                 ConfigurationManager configurationManager = ConfigurationUtil.getConfigurationManager(kernel);
280                 try {
281                     for (Iterator i = configs.iterator(); i.hasNext();) {
282                         Artifact configID = (Artifact) i.next();
283                         monitor.moduleLoading(configID);
284                         configurationManager.loadConfiguration(configID);
285                         monitor.moduleLoaded(configID);
286                         monitor.moduleStarting(configID);
287                         configurationManager.startConfiguration(configID);
288                         monitor.moduleStarted(configID);
289                     }
290                 } finally {
291                     ConfigurationUtil.releaseConfigurationManager(kernel, configurationManager);
292                 }
293             } catch (Exception e) {
294                 //Exception caught when starting configurations, starting kernel shutdown
295                 monitor.serverStartFailed(e);
296                 try {
297                     kernel.shutdown();
298                 } catch (Exception e1) {
299                     System.err.println("Exception caught during kernel shutdown");
300                     e1.printStackTrace();
301                 }
302                 System.exit(1);
303                 throw new AssertionError();
304             }
305 
306             // Tell every persistent configuration list that the kernel is now fully started
307             Set configLists = kernel.listGBeans(query);
308             for (Iterator i = configLists.iterator(); i.hasNext();) {
309                 AbstractName configListName = (AbstractName) i.next();
310                 kernel.setAttribute(configListName, "kernelFullyStarted", Boolean.TRUE);
311             }
312 
313             // Startup sequence is finished
314             monitor.startupFinished();
315             monitor = null;
316 
317             // capture this thread until the kernel is ready to exit
318             while (kernel.isRunning()) {
319                 try {
320                     synchronized (kernel) {
321                         kernel.wait();
322                     }
323                 } catch (InterruptedException e) {
324                     // continue
325                 }
326             }
327         } catch (Exception e) {
328             if (monitor != null) {
329                 monitor.serverStartFailed(e);
330             }
331             e.printStackTrace();
332             System.exit(1);
333             throw new AssertionError();
334         }
335     }
336 
337     private void AddToSystemProperty(String propertyName, List dirsFromManifest, File geronimoInstallDirectory) {
338         String dirs = System.getProperty(propertyName, "");
339         for (Iterator iterator = dirsFromManifest.iterator(); iterator.hasNext();) {
340             String directoryName = (String) iterator.next();
341             File directory = new File(directoryName);
342             if (!directory.isAbsolute()) {
343                 directory = new File(geronimoInstallDirectory, directoryName);
344             }
345 
346             if (dirs.length() > 0) {
347                 dirs += File.pathSeparatorChar;
348             }
349             dirs += directory.getAbsolutePath();
350         }
351         if (dirs.length() > 0) {
352             System.setProperty(propertyName, dirs);
353         }
354         log.debug(propertyName + "=" + System.getProperty(propertyName));
355     }
356 
357     /**
358      * Static entry point allowing a Kernel to be run from the command line.
359      *
360      * Once the Kernel is booted and the configuration is loaded, the process
361      * will remain running until the shutdown() method on the kernel is
362      * invoked or until the JVM exits.
363      *
364      * @param args the command line arguments
365      */
366     public static void main(String[] args) {
367         new Daemon(args);
368     }
369 
370 }