KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > cruisecontrol > listeners > CurrentBuildStatusPageListener


1 package net.sourceforge.cruisecontrol.listeners;
2
3 import java.io.BufferedReader JavaDoc;
4 import java.io.File JavaDoc;
5 import java.io.FileReader JavaDoc;
6 import java.io.FileWriter JavaDoc;
7 import java.io.IOException JavaDoc;
8 import java.text.DateFormat JavaDoc;
9 import java.util.ArrayList JavaDoc;
10 import java.util.Date JavaDoc;
11 import java.util.Iterator JavaDoc;
12 import java.util.List JavaDoc;
13
14 import net.sourceforge.cruisecontrol.CruiseControlException;
15 import net.sourceforge.cruisecontrol.DateFormatFactory;
16 import net.sourceforge.cruisecontrol.Listener;
17 import net.sourceforge.cruisecontrol.ProjectEvent;
18 import net.sourceforge.cruisecontrol.ProjectState;
19 import net.sourceforge.cruisecontrol.util.CurrentBuildFileWriter;
20 import net.sourceforge.cruisecontrol.util.ValidationHelper;
21
22 import org.apache.log4j.Logger;
23
24 /**
25  * Updates replaceable text in a pattern file each time the Project status changes. Can show full
26  * project status history. The following items will be replaced with their values each time they
27  * occur in the source file:
28  * <ul>
29  * <li>{Project} - Project Name.</li>
30  * <li>{State.Name} - Name of current project state.</li>
31  * <li>{State.Description} - Description of current project state.</li>
32  * <li>{State.Date} - Date/time the current state happened</li>
33  * <li>{State.Duration} - How long since this state was in effect. (Only useful in {History} line.)
34  * <li>{History} - Historical states. Must be first on line. This line will be processed and output
35  * once for each state the project has previously been in. The {History} tag will be deleted from
36  * the line.</li>
37  * </ul>
38  * <p>
39  * {@link net.sourceforge.cruisecontrol.DateFormatFactory} for the dateformat
40  *
41  * @author John Lussmyer
42  */

43 public class CurrentBuildStatusPageListener
44     implements Listener {
45     private static final Logger LOG = Logger.getLogger(CurrentBuildStatusPageListener.class);
46     /** Name of file to write/create */
47     private String JavaDoc dstFileName;
48     /** File to read pattern text from */
49     private File JavaDoc sourceFile = null;
50     /** Pattern text to use, contains String objects */
51     private List JavaDoc sourceText = new ArrayList JavaDoc();
52     /** Default text to use if no source file provided. */
53     private static final String JavaDoc DEFAULT_TEXT = "{Project}: {State.Date} - {State.Name}: {State.Description}";
54     /** Historical Status changes, contains HistoryItem objects */
55     private List JavaDoc history = new ArrayList JavaDoc();
56
57     private static final String JavaDoc KEY_PROJECT = "{project}";
58     private static final String JavaDoc KEY_NAME = "{state.name}";
59     private static final String JavaDoc KEY_DESC = "{state.description}";
60     private static final String JavaDoc KEY_DATE = "{state.date}";
61     private static final String JavaDoc KEY_DURATION = "{state.duration}";
62     private static final String JavaDoc KEY_HISTORY = "{history}";
63
64     /**
65      * Holds info about a project state that has happened.
66      *
67      * @author jlussmyer Created on: Jan 12, 2006
68      */

69     private class HistoryItem {
70         public HistoryItem(ProjectState projstate) {
71             state = projstate.getName();
72             desc = projstate.getDescription();
73             when = System.currentTimeMillis();
74         }
75
76         public String JavaDoc state;
77         public String JavaDoc desc;
78         public long when;
79     }
80
81
82     /**
83      * Default constructor just used for initialization of local members.
84      */

85     public CurrentBuildStatusPageListener() {
86         sourceText.add(DEFAULT_TEXT);
87     }
88
89
90     public void handleEvent(ProjectEvent event)
91         throws CruiseControlException {
92         if (!(event instanceof ProjectStateChangedEvent)) {
93             // ignore other ProjectEvents
94
LOG.debug("ignoring event " + event.getClass().getName() + " for project " + event.getProjectName());
95             return;
96         }
97
98         final ProjectStateChangedEvent stateChanged = (ProjectStateChangedEvent) event;
99         final ProjectState newState = stateChanged.getNewState();
100         LOG.debug("updating status to " + newState.getName() + " for project " + stateChanged.getProjectName());
101
102         HistoryItem hist = new HistoryItem(newState);
103         String JavaDoc result = substituteText(hist, stateChanged.getProjectName());
104         history.add(0, hist);
105         writeFile(result);
106     }
107
108
109     /**
110      * Perform all the needed text substitutions.
111      *
112      * @return String resulting form substituting entries from sourceText.
113      */

114     private String JavaDoc substituteText(HistoryItem current, String JavaDoc projectName) {
115         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
116         Iterator JavaDoc lineIter = sourceText.iterator();
117
118         while (lineIter.hasNext()) {
119             String JavaDoc src = (String JavaDoc) lineIter.next();
120
121             // See if we need to output this line once for each historical state
122
if (src.toLowerCase().startsWith(KEY_HISTORY)) {
123                 src = src.substring(KEY_HISTORY.length());
124                 Iterator JavaDoc histIter = history.iterator();
125                 long prevtime = current.when;
126
127                 while (histIter.hasNext()) {
128                     HistoryItem hist = (HistoryItem) histIter.next();
129                     result.append(substituteItems(src, projectName, hist, prevtime));
130                     result.append('\n');
131                     prevtime = hist.when;
132                 }
133             } else {
134                 // Just do this line once
135
result.append(substituteItems(src, projectName, current, 0));
136                 result.append('\n');
137             }
138
139         }
140
141         return result.toString();
142     }
143
144
145     /**
146      * Substitute values for any and all key items in a line of text.
147      *
148      * @param src Source line to have substitutions made
149      * @param projectName Name of project being processed
150      * @param current current project state information
151      */

152     private String JavaDoc substituteItems(String JavaDoc src, String JavaDoc projectName, HistoryItem current, long prevtime) {
153         int idx;
154         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
155         DateFormat JavaDoc dateFmt = DateFormatFactory.getDateFormat();
156
157         // Find and substitute entries in this line
158
while ((idx = src.indexOf('{')) != -1) {
159             if (idx > 0) {
160                 result.append(src.substring(0, idx));
161             }
162
163             src = src.substring(idx); // Trim off preceding text
164

165             int skiplen;
166
167             if (src.toLowerCase().startsWith(KEY_PROJECT)) {
168                 result.append(projectName);
169                 skiplen = KEY_PROJECT.length();
170             } else if (src.toLowerCase().startsWith(KEY_NAME)) {
171                 result.append(current.state);
172                 skiplen = KEY_NAME.length();
173             } else if (src.toLowerCase().startsWith(KEY_DESC)) {
174                 result.append(current.desc);
175                 skiplen = KEY_DESC.length();
176             } else if (src.toLowerCase().startsWith(KEY_DATE)) {
177                 result.append(dateFmt.format(new Date JavaDoc(current.when)));
178                 skiplen = KEY_DATE.length();
179             } else if (src.toLowerCase().startsWith(KEY_DURATION)) {
180                 result.append(formatDuration(prevtime - current.when));
181                 skiplen = KEY_DURATION.length();
182             } else {
183                 result.append('{');
184                 skiplen = 1;
185             }
186
187             if (skiplen > 0) {
188                 src = src.substring(skiplen); // remove KEY text
189
}
190         }
191
192         result.append(src); // Pick up any leftover text
193

194         return (result.toString());
195     }
196
197
198     /**
199      * formats the given number of milliseconds as HH:MM:SS.sss
200      *
201      * @param msecs number of milliseconds
202      * @return String of the form HH:MM:SS.sss representing the given milliseconds
203      */

204     private String JavaDoc formatDuration(long msecs) {
205         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
206         long hours = msecs / (60 * 60 * 1000);
207         msecs %= (60 * 60 * 1000);
208         long mins = msecs / (60 * 1000);
209         msecs %= (60 * 1000);
210         long secs = msecs / 1000;
211         msecs %= 1000;
212
213         if (hours > 0) {
214             buf.append(hours);
215             buf.append(':');
216         }
217
218         if ((mins > 0) || (hours > 0)) {
219             if (mins < 10) {
220                 buf.append('0');
221             }
222             buf.append(mins);
223             buf.append(':');
224         }
225
226         if ((secs < 10) && ((mins > 0) || (hours > 0))) {
227             buf.append('0');
228         }
229
230         buf.append(secs);
231         buf.append('.');
232
233         if (msecs < 100) {
234             buf.append('0');
235         }
236
237         if (msecs < 10) {
238             buf.append('0');
239         }
240
241         buf.append(msecs);
242
243         return buf.toString();
244     }
245
246
247     public void validate()
248         throws CruiseControlException {
249
250         ValidationHelper.assertIsSet(dstFileName, "file", this.getClass());
251         CurrentBuildFileWriter.validate(dstFileName);
252
253         if (sourceFile != null) {
254             ValidationHelper.assertTrue(sourceFile.exists(), dstFileName + " does not exist: "
255                                                              + sourceFile.getAbsolutePath());
256             ValidationHelper.assertTrue(sourceFile.isFile(), dstFileName + " is not a file: "
257                                                              + sourceFile.getAbsolutePath());
258
259             sourceText = readSource();
260         }
261     }
262
263
264     /**
265      * Write the resulting substituted text to the output file.
266      *
267      * @param content New content for the output file.
268      * @throws CruiseControlException
269      */

270     private void writeFile(String JavaDoc content)
271         throws CruiseControlException {
272
273         FileWriter JavaDoc fw = null;
274         try {
275             fw = new FileWriter JavaDoc(dstFileName);
276             fw.write(content);
277         } catch (IOException JavaDoc ioe) {
278             throw new CruiseControlException("Error writing file: " + dstFileName, ioe);
279         } finally {
280             if (fw != null) {
281                 try {
282                     fw.close();
283                 } catch (IOException JavaDoc ignore) {
284
285                 }
286             }
287         }
288     }
289
290
291     /**
292      * Read the source text file
293      *
294      * @return List of lines of text (String objects)
295      * @throws CruiseControlException
296      */

297     private List JavaDoc readSource()
298         throws CruiseControlException {
299
300         List JavaDoc result = new ArrayList JavaDoc();
301         BufferedReader JavaDoc reader = null;
302
303         try {
304             reader = new BufferedReader JavaDoc(new FileReader JavaDoc(sourceFile));
305             String JavaDoc line;
306
307             while ((line = reader.readLine()) != null) {
308                 result.add(line);
309             }
310         } catch (IOException JavaDoc ioe) {
311             throw new CruiseControlException("Error reading file: " + sourceFile, ioe);
312         } finally {
313             if (reader != null) {
314                 try {
315                     reader.close();
316                 } catch (IOException JavaDoc ignore) {
317
318                 }
319             }
320         }
321
322         return result;
323     }
324
325
326     public void setFile(String JavaDoc fileName) {
327         this.dstFileName = fileName.trim();
328         LOG.debug("set fileName = " + fileName);
329     }
330
331
332     public void setSourceFile(String JavaDoc fileName) {
333         sourceFile = new File JavaDoc(fileName);
334         LOG.debug("set sourceFile = " + fileName);
335     }
336 }
337
Popular Tags