001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.geronimo.system.main;
018
019 import java.io.PrintStream;
020
021 import org.apache.geronimo.kernel.Kernel;
022 import org.apache.geronimo.kernel.repository.Artifact;
023 import java.text.DateFormat;
024 import java.text.SimpleDateFormat;
025 import java.util.TimeZone;
026 import java.util.Date;
027
028 /**
029 * A startup monitor that shows the progress of loading and starting
030 * modules, outputing a new line for each module started
031 * showing the time taken to start the module along with the
032 * moduleId.
033 * <p/>
034 * This startup monitor produces more lines of output than the
035 * ProgressBarStartupMonitor but its output is suitable for redirection
036 * to a file or for when Geronimo is running under an IDE or other tool.
037 * <p/>
038 * A summary will also be produced containing a list of ports
039 * Geronimo is listening on, the configIds of application modules
040 * that were started and the URLs of Web applications that were started.
041 *
042 * @version $Revision: 1.0$
043 */
044 public class LongStartupMonitor implements StartupMonitor {
045
046 /**
047 * PrintStream
048 */
049 private PrintStream out;
050
051 /**
052 * Number of modules to start
053 */
054 private int numModules;
055
056 /**
057 * Number of digits in number of modules to start
058 */
059 private int numModulesDigits;
060
061 /**
062 * Number of modules currently being started
063 */
064 private int moduleNum;
065
066 /**
067 * Length of longest module name
068 */
069 private int longestModuleNameLength;
070
071 /**
072 * Time Geronimo was started
073 */
074 private long started;
075
076 /**
077 * Time the current module being processed was started
078 */
079 private long moduleStarted;
080
081 /**
082 * The Kernel of the system being started
083 */
084 private Kernel kernel;
085
086 public synchronized void systemStarting(long startTime) {
087 out = System.out;
088 started = startTime;
089 }
090
091 public synchronized void systemStarted(Kernel kernel) {
092 this.kernel = kernel;
093 }
094
095 public synchronized void foundModules(Artifact[] modules) {
096 numModules = modules.length;
097 numModulesDigits = Integer.toString(numModules).length();
098
099 for (int i = 0, len= 0; i < modules.length; i++) {
100 len = modules[i].toString().length();
101 if (len > longestModuleNameLength)
102 longestModuleNameLength = len;
103 }
104 }
105
106 public synchronized void moduleLoading(Artifact module) {
107 StringBuffer buf = new StringBuffer("Module ");
108 // pad module index
109 int configIndexDigits = Integer.toString(++moduleNum).length();
110 for (; configIndexDigits < numModulesDigits; configIndexDigits++) {
111 buf.append(' ');
112 }
113 // append module index / total configs
114 buf.append(moduleNum).append('/').append(numModules).append(' ');
115 // append module name
116 buf.append(module);
117 // pad end of module with spaces so trailing startup times will line up
118 int len = module.toString().length();
119 for (; len < longestModuleNameLength; len++) {
120 buf.append(' ');
121 }
122 out.print(buf);
123 }
124
125 public synchronized void moduleLoaded(Artifact module) {
126 }
127
128 public synchronized void moduleStarting(Artifact module) {
129 moduleStarted = System.currentTimeMillis();
130 }
131
132 public synchronized void moduleStarted(Artifact module) {
133 long time = System.currentTimeMillis() - moduleStarted;
134 StringBuffer buf = new StringBuffer();
135 buf.append(" started in ");
136
137 String formattedTime = getFormattedTime(time);
138 if (formattedTime.startsWith("0.")) {
139 // don't display zero seconds
140 formattedTime = " " +formattedTime.substring(1);
141 }
142
143 // if first number (e.g. seconds or minutes) is one digit,
144 // pad it with a leading space to get times to line up nicely
145 int index = formattedTime.indexOf(':'); // must look for colon first
146 if (index == -1)
147 index = formattedTime.indexOf('.');
148
149 if (index == 1)
150 buf.append(' ');
151
152 buf.append(formattedTime);
153
154 out.println(buf.toString());
155 }
156
157 public synchronized void startupFinished() {
158 long time = System.currentTimeMillis() - started;
159 out.println("Startup completed in " + getFormattedTime(time) + " seconds");
160 StartupMonitorUtil.wrapUp(out, kernel);
161 }
162
163 public synchronized void serverStartFailed(Exception problem) {
164 out.println("Server Startup failed");
165 out.println();
166 problem.printStackTrace(out);
167 }
168
169 // time formatting method - thanks to Maven
170 private static String getFormattedTime( long time )
171 {
172 String pattern = "s.SSS's'";
173 if ( time / 60000L > 0 )
174 {
175 pattern = "m:s" + pattern;
176 if ( time / 3600000L > 0 )
177 {
178 pattern = "H:m" + pattern;
179 }
180 }
181 DateFormat fmt = new SimpleDateFormat( pattern );
182 fmt.setTimeZone( TimeZone.getTimeZone( "UTC" ) );
183 return fmt.format( new Date( time ) );
184 }
185 }