1 package org.apache.geronimo.system.main;
2
3 import java.io.PrintStream;
4
5 import org.apache.geronimo.kernel.Kernel;
6 import org.apache.geronimo.kernel.repository.Artifact;
7 import org.apache.geronimo.system.serverinfo.ServerConstants;
8
9 /**
10 * A startup monitor that shows the progress of loading and starting
11 * modules using a text based progress bar and the use of line
12 * feeds to update the progress display, therefore minimizing the
13 * number of lines output to the terminal.
14 * <p/>
15 * A summary will also be produced containing a list of ports
16 * Geronimo is listening on, the configIds of application modules
17 * that were started and the URLs of Web applications that were started.
18 *
19 * @version $Revision: 1.0$
20 */
21 public class ProgressBarStartupMonitor implements StartupMonitor {
22 private final static char STATUS_NOT_READY = ' ';
23 private final static char STATUS_LOADING = '-';
24 private final static char STATUS_LOADED = '>';
25 private final static char STATUS_STARTED = '*';
26 private final static char STATUS_FAILED = 'x';
27 private final static int MAX_WIDTH = 70;
28 private PrintStream out;
29 private String currentOperation;
30 private Artifact[] modules;
31 private char[] moduleStatus = new char[0];
32 private long started;
33 private int percent = 0;
34 private Kernel kernel;
35 private int operationLimit = 50;
36 private boolean finished = false;
37 private UpdateThread thread;
38
39 public synchronized void systemStarting(long startTime) {
40 out = System.out;
41 started = startTime;
42 }
43
44 public synchronized void systemStarted(Kernel kernel) {
45 out.println("Starting Geronimo Application Server v" + ServerConstants.getVersion());
46 this.kernel = kernel;
47 currentOperation = "Loading";
48 }
49
50 public synchronized void foundModules(Artifact[] modules) {
51 this.modules = modules;
52 moduleStatus = new char[modules.length];
53 for (int i = 0; i < moduleStatus.length; i++) {
54 moduleStatus[i] = STATUS_NOT_READY;
55 }
56 operationLimit = MAX_WIDTH
57 - 5
58 - modules.length
59 - 4
60 - 5;
61 repaint();
62 thread = new UpdateThread();
63 thread.start();
64 }
65
66 public synchronized void calculatePercent() {
67 if (finished) {
68 this.percent = 100;
69 return;
70 }
71 int percent = 0;
72 if (kernel != null) percent += 5;
73 int total = moduleStatus.length * 2;
74 int progress = 0;
75 for (int i = 0; i < moduleStatus.length; i++) {
76 char c = moduleStatus[i];
77 switch (c) {
78 case STATUS_LOADED:
79 progress += 1;
80 break;
81 case STATUS_STARTED:
82 case STATUS_FAILED:
83 progress += 2;
84 break;
85 }
86 }
87 percent += Math.round(90f * (float) progress / (float) total);
88 this.percent = percent;
89 }
90
91 public synchronized void moduleLoading(Artifact module) {
92 currentOperation = " Loading " + module;
93 for (int i = 0; i < modules.length; i++) {
94 if (modules[i].equals(module)) {
95 moduleStatus[i] = STATUS_LOADING;
96 }
97 }
98 repaint();
99 }
100
101 public synchronized void moduleLoaded(Artifact module) {
102 for (int i = 0; i < modules.length; i++) {
103 if (modules[i].equals(module)) {
104 moduleStatus[i] = STATUS_LOADED;
105 }
106 }
107 calculatePercent();
108 repaint();
109 }
110
111 public synchronized void moduleStarting(Artifact module) {
112 currentOperation = "Starting " + module;
113 }
114
115 public synchronized void moduleStarted(Artifact module) {
116 for (int i = 0; i < modules.length; i++) {
117 if (modules[i].equals(module)) {
118 moduleStatus[i] = STATUS_STARTED;
119 }
120 }
121 calculatePercent();
122 repaint();
123 }
124
125 public synchronized void startupFinished() {
126 finished = true;
127 currentOperation = "Startup complete";
128 calculatePercent();
129 thread.done = true;
130 thread.interrupt();
131 }
132
133 public synchronized void serverStartFailed(Exception problem) {
134 currentOperation = "Startup failed";
135 repaint();
136 out.println();
137 problem.printStackTrace(out);
138 }
139
140 private synchronized void repaint() {
141 StringBuffer buf = new StringBuffer();
142 buf.append("\r[");
143 buf.append(kernel == null ? STATUS_NOT_READY : STATUS_STARTED);
144 for (int i = 0; i < moduleStatus.length; i++) {
145 buf.append(moduleStatus[i]);
146 }
147 buf.append(finished ? STATUS_STARTED : STATUS_NOT_READY);
148 buf.append("] ");
149 if (percent < 10) {
150 buf.append(' ');
151 }
152 buf.append(percent).append("% ");
153 int time = Math.round((float) (System.currentTimeMillis() - started) / 1000f);
154 if (time < 10) {
155 buf.append(' ');
156 }
157 if (time < 100) {
158 buf.append(' ');
159 }
160 buf.append(time).append("s ");
161 if (currentOperation.length() > operationLimit) {
162 int space = currentOperation.indexOf(' ', 5);
163 buf.append(currentOperation.substring(0, space + 1));
164
165
166
167 buf.append(currentOperation.substring(space + 1, operationLimit - 3)).append("...");
168 } else {
169 buf.append(currentOperation);
170 for (int i = currentOperation.length(); i < operationLimit; i++) {
171 buf.append(' ');
172 }
173 }
174 out.print(buf.toString());
175 out.flush();
176 }
177
178 private class UpdateThread extends Thread {
179 private volatile boolean done = false;
180
181 public UpdateThread() {
182 super("Progress Display Update Thread");
183 setDaemon(true);
184 }
185
186 public void run() {
187 while (!done) {
188 try {
189 Thread.sleep(500);
190 } catch (InterruptedException e) {
191 continue;
192 }
193 repaint();
194 }
195
196 repaint();
197 out.println();
198 StartupMonitorUtil.wrapUp(ProgressBarStartupMonitor.this.out, ProgressBarStartupMonitor.this.kernel);
199 }
200 }
201 }