View Javadoc

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 // two brackets, start and stop tokens, space afterward
58                  - modules.length // module tokens
59                  - 4 // 2 digits of percent plus % plus space afterward
60                  - 5;// 3 digits of time plus s plus space afterward
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             // "Foo BarBarBar" limit 9 = "Foo ...ar" = 13 - 9 + 3 + 1 + 3
165             // buf.append("...").append(currentOperation.substring(currentOperation.length()-operationLimit+space+4));
166             // "FooBar BarBarBar" limit 12 = "FooBar Ba..." = (7, 12-3)
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 }