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