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 org.apache.geronimo.system.serverinfo.ServerConstants; 024 025 /** 026 * A startup monitor that shows the progress of loading and starting 027 * modules using a text based progress bar and the use of line 028 * feeds to update the progress display, therefore minimizing the 029 * number of lines output to the terminal. 030 * <p/> 031 * This implementation displays a fixed-size bar. 032 * <p/> 033 * A summary will also be produced containing a list of ports 034 * Geronimo is listening on, the configIds of application modules 035 * that were started and the context roots of Web applications that were started. 036 * 037 * @version $Revision: 1.0$ 038 */ 039 public class SimpleProgressBarStartupMonitor implements StartupMonitor { 040 private final static char STATUS_NOT_READY = ' '; 041 private final static char STATUS_LOADING = '-'; 042 private final static char STATUS_LOADED = '>'; 043 private final static char STATUS_STARTED = '*'; 044 private final static char STATUS_FAILED = 'x'; 045 private final static int MAX_WIDTH = 79; 046 private PrintStream out; 047 private String currentOperation; 048 private Artifact[] modules; 049 private char[] moduleStatus = new char[0]; 050 private long started; 051 private int percent = 0; 052 private Kernel kernel; 053 private int operationLimit = 50; 054 private boolean finished = false; 055 private UpdateThread thread; 056 057 private int barSize = 40; 058 private int barProgress; 059 060 public synchronized void systemStarting(long startTime) { 061 out = System.out; 062 started = startTime; 063 } 064 065 public synchronized void systemStarted(Kernel kernel) { 066 out.println("Starting Geronimo Application Server v" + ServerConstants.getVersion()); 067 this.kernel = kernel; 068 currentOperation = "Loading"; 069 } 070 071 public synchronized void foundModules(Artifact[] modules) { 072 this.modules = modules; 073 moduleStatus = new char[modules.length]; 074 for (int i = 0; i < moduleStatus.length; i++) { 075 moduleStatus[i] = STATUS_NOT_READY; 076 } 077 operationLimit = MAX_WIDTH 078 - 3 // two brackets, space afterward 079 - barSize // module tokens 080 - 5 // 3 digits of percent plus % plus space afterward 081 - 5;// 3 digits of time plus s plus space afterward 082 repaint(); 083 thread = new UpdateThread(); 084 thread.start(); 085 } 086 087 public synchronized void calculatePercent() { 088 if (finished) { 089 this.percent = 100; 090 this.barProgress = this.barSize; 091 return; 092 } 093 int percent = 0; 094 if (kernel != null) percent += 5; 095 int total = moduleStatus.length * 2; 096 int progress = 0; 097 for (int i = 0; i < moduleStatus.length; i++) { 098 char c = moduleStatus[i]; 099 switch (c) { 100 case STATUS_LOADED: 101 progress += 1; 102 break; 103 case STATUS_STARTED: 104 case STATUS_FAILED: 105 progress += 2; 106 break; 107 } 108 } 109 percent += Math.round(95f * (float) progress / (float) total); 110 this.percent = percent; 111 this.barProgress = (this.barSize * this.percent) / 100; 112 } 113 114 public synchronized void moduleLoading(Artifact module) { 115 currentOperation = " Loading " + module; 116 for (int i = 0; i < modules.length; i++) { 117 if (modules[i].equals(module)) { 118 moduleStatus[i] = STATUS_LOADING; 119 break; 120 } 121 } 122 repaint(); 123 } 124 125 public synchronized void moduleLoaded(Artifact module) { 126 for (int i = 0; i < modules.length; i++) { 127 if (modules[i].equals(module)) { 128 moduleStatus[i] = STATUS_LOADED; 129 break; 130 } 131 } 132 calculatePercent(); 133 repaint(); 134 } 135 136 public synchronized void moduleStarting(Artifact module) { 137 currentOperation = "Starting " + module; 138 } 139 140 public synchronized void moduleStarted(Artifact module) { 141 for (int i = 0; i < modules.length; i++) { 142 if (modules[i].equals(module)) { 143 moduleStatus[i] = STATUS_STARTED; 144 break; 145 } 146 } 147 calculatePercent(); 148 repaint(); 149 } 150 151 public synchronized void startupFinished() { 152 finished = true; 153 currentOperation = "Startup complete"; 154 calculatePercent(); 155 thread.done = true; 156 thread.interrupt(); 157 } 158 159 public synchronized void serverStartFailed(Exception problem) { 160 currentOperation = "Startup failed"; 161 repaint(); 162 out.println(); 163 problem.printStackTrace(out); 164 } 165 166 private synchronized void repaint() { 167 StringBuffer buf = new StringBuffer(); 168 buf.append("\r["); 169 for (int i = 0; i < barSize; i++) { 170 if (i < barProgress) { 171 buf.append("*"); 172 } else { 173 buf.append(" "); 174 } 175 } 176 buf.append("] "); 177 if (percent < 10) { 178 buf.append(" "); 179 } else if (percent >= 10 && percent < 100) { 180 buf.append(" "); 181 } 182 buf.append(percent).append("% "); 183 int time = Math.round((float) (System.currentTimeMillis() - started) / 1000f); 184 if (time < 10) { 185 buf.append(' '); 186 } 187 if (time < 100) { 188 buf.append(' '); 189 } 190 buf.append(time).append("s "); 191 if (currentOperation.length() > operationLimit) { 192 if (operationLimit > 3) { 193 buf.append(currentOperation.substring(0, operationLimit - 3)).append("..."); 194 } else { 195 for (int i = 0; i < operationLimit; i++) { 196 buf.append('.'); 197 } 198 } 199 } else { 200 buf.append(currentOperation); 201 for (int i = currentOperation.length(); i < operationLimit; i++) { 202 buf.append(' '); 203 } 204 } 205 out.print(buf.toString()); 206 out.flush(); 207 } 208 209 private class UpdateThread extends Thread { 210 private volatile boolean done = false; 211 212 public UpdateThread() { 213 super("Progress Display Update Thread"); 214 setDaemon(true); 215 } 216 217 public void run() { 218 while (!done) { 219 try { 220 Thread.sleep(500); 221 } catch (InterruptedException e) { 222 continue; 223 } 224 repaint(); 225 } 226 227 repaint(); 228 out.println(); 229 StartupMonitorUtil.wrapUp(SimpleProgressBarStartupMonitor.this.out, SimpleProgressBarStartupMonitor.this.kernel); 230 } 231 } 232 }