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 }