1 /* |
1 /* |
2 * Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). |
2 * Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). |
3 * All rights reserved. |
3 * All rights reserved. |
4 * This component and the accompanying materials are made available |
4 * This component and the accompanying materials are made available |
5 * under the terms of the License "Eclipse Public License v1.0" |
5 * under the terms of the License "Eclipse Public License v1.0" |
6 * which accompanies this distribution, and is available |
6 * which accompanies this distribution, and is available |
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
8 * |
8 * |
9 * Initial Contributors: |
9 * Initial Contributors: |
10 * Nokia Corporation - initial contribution. |
10 * Nokia Corporation - initial contribution. |
11 * |
11 * |
12 * Contributors: |
12 * Contributors: |
13 * |
13 * |
14 * Description: |
14 * Description: |
15 * |
15 * |
16 */ |
16 */ |
17 package com.nokia.helium.logger.ant.listener; |
17 package com.nokia.helium.logger.ant.listener; |
18 |
18 |
|
19 import java.io.File; |
|
20 import java.io.FileOutputStream; |
|
21 import java.io.IOException; |
19 import java.io.PrintStream; |
22 import java.io.PrintStream; |
|
23 import java.util.Vector; |
|
24 import java.util.regex.Matcher; |
|
25 import java.util.regex.Pattern; |
20 |
26 |
21 import org.apache.log4j.Logger; |
27 import org.apache.log4j.Logger; |
22 import org.apache.tools.ant.BuildEvent; |
28 import org.apache.tools.ant.BuildEvent; |
|
29 import org.apache.tools.ant.BuildException; |
23 import org.apache.tools.ant.DefaultLogger; |
30 import org.apache.tools.ant.DefaultLogger; |
24 import org.apache.tools.ant.Project; |
31 import org.apache.tools.ant.Project; |
25 import org.apache.tools.ant.util.StringUtils; |
32 import org.apache.tools.ant.util.StringUtils; |
26 import org.apache.tools.ant.BuildException; |
|
27 |
|
28 import java.io.File; |
|
29 import java.io.FileOutputStream; |
|
30 import java.io.IOException; |
|
31 import java.util.Vector; |
|
32 import java.util.regex.Matcher; |
|
33 import java.util.regex.Pattern; |
|
34 |
33 |
35 /** |
34 /** |
36 * This is a class that represents a recorder. This is the listener to the |
35 * This is a class that represents a recorder. This is the listener to the build process. |
37 * build process. |
36 * |
38 * |
|
39 * @since Ant 1.4 |
37 * @since Ant 1.4 |
40 */ |
38 */ |
41 public class RecorderEntry implements BuildEventHandler, TargetEventHandler, TaskEventHandler, MessageEventHandler { |
39 public class RecorderEntry implements BuildEventHandler, TargetEventHandler, TaskEventHandler, |
42 |
40 MessageEventHandler { |
43 ////////////////////////////////////////////////////////////////////// |
41 |
44 // ATTRIBUTES |
42 /** The name of the file associated with this recorder entry. */ |
45 |
|
46 /** The name of the file associated with this recorder entry. */ |
|
47 private File filename; |
43 private File filename; |
48 /** The state of the recorder (recorder on or off). */ |
44 /** The state of the recorder (recorder on or off). */ |
49 private boolean record = true; |
45 private boolean record = true; |
50 /** The current verbosity level to record at. */ |
46 /** The current verbosity level to record at. */ |
51 private int loglevel = Project.MSG_INFO; |
47 private int loglevel = Project.MSG_INFO; |
52 /** The output PrintStream to record to. */ |
48 /** The output PrintStream to record to. */ |
53 private PrintStream out; |
49 private PrintStream out; |
54 /** The start time of the last know target. */ |
50 /** The start time of the last know target. */ |
55 private long targetStartTime; |
51 private long targetStartTime; |
56 /** Strip task banners if true. */ |
52 /** Strip task banners if true. */ |
57 private boolean emacsMode; |
53 private boolean emacsMode; |
58 |
54 |
59 private Pattern pattern; |
55 private Pattern pattern; |
60 |
56 |
61 private Vector<String> logRegExps = new Vector<String>(); |
57 private Vector<String> logRegExps = new Vector<String>(); |
62 private Logger log = Logger.getLogger(getClass()); |
58 private Logger log = Logger.getLogger(getClass()); |
63 |
|
64 |
|
65 ////////////////////////////////////////////////////////////////////// |
|
66 // CONSTRUCTORS / INITIALIZERS |
|
67 |
59 |
68 /** |
60 /** |
69 * @param name The name of this recorder (used as the filename). |
61 * @param name The name of this recorder (used as the filename). |
70 */ |
62 */ |
71 public RecorderEntry(File name) { |
63 public RecorderEntry(File name) { |
72 targetStartTime = System.currentTimeMillis(); |
64 targetStartTime = System.currentTimeMillis(); |
73 filename = name; |
65 filename = name; |
74 } |
66 } |
75 |
67 |
76 ////////////////////////////////////////////////////////////////////// |
|
77 // ACCESSOR METHODS |
|
78 |
|
79 /** |
68 /** |
80 * @return the name of the file the output is sent to. |
69 * @return the name of the file the output is sent to. |
81 */ |
70 */ |
82 public File getFilename() { |
71 public File getFilename() { |
83 return filename; |
72 return filename; |
84 } |
73 } |
85 |
74 |
86 /** |
75 /** |
87 * Turns off or on this recorder. |
76 * Turns off or on this recorder. |
88 * |
77 * |
89 * @param state true for on, false for off, null for no change. |
78 * @param state true for on, false for off, null for no change. |
90 */ |
79 */ |
91 public void setRecordState(boolean state) { |
80 public void setRecordState(boolean state) { |
92 flush(); |
81 flush(); |
93 record = state; |
82 record = state; |
94 } |
83 } |
95 |
84 |
96 /** |
85 /** |
97 * Get the current state of the recorder |
86 * Get the current state of the recorder |
|
87 * |
98 * @param state |
88 * @param state |
99 */ |
89 */ |
100 public boolean getRecordState() { |
90 public boolean getRecordState() { |
101 return record; |
91 return record; |
102 } |
92 } |
103 |
93 |
104 /** |
94 /** |
105 * To set the regexp to filter the logging. |
95 * To set the regexp to filter the logging. |
|
96 * |
106 * @param regexp |
97 * @param regexp |
107 */ |
98 */ |
108 public void addRegexp(String regexp) { |
99 public void addRegexp(String regexp) { |
109 logRegExps.add(regexp); |
100 logRegExps.add(regexp); |
110 } |
101 } |
111 |
102 |
112 /** |
103 /** |
113 * To clear all regexp set. |
104 * To clear all regexp set. |
114 */ |
105 */ |
115 public void resetRegExp() { |
106 public void resetRegExp() { |
116 logRegExps.clear(); |
107 logRegExps.clear(); |
117 } |
108 } |
118 |
109 |
119 /** |
110 /** |
120 * @see org.apache.tools.ant.BuildListener#buildStarted(BuildEvent) |
111 * @see org.apache.tools.ant.BuildListener#buildStarted(BuildEvent) |
134 if (record && out != null) { |
125 if (record && out != null) { |
135 Throwable error = event.getException(); |
126 Throwable error = event.getException(); |
136 |
127 |
137 if (error == null) { |
128 if (error == null) { |
138 out.println(StringUtils.LINE_SEP + "BUILD SUCCESSFUL"); |
129 out.println(StringUtils.LINE_SEP + "BUILD SUCCESSFUL"); |
139 } else { |
130 } |
140 out.println(StringUtils.LINE_SEP + "BUILD FAILED" |
131 else { |
141 + StringUtils.LINE_SEP); |
132 out.println(StringUtils.LINE_SEP + "BUILD FAILED" + StringUtils.LINE_SEP); |
142 error.printStackTrace(out); |
133 error.printStackTrace(out); |
143 } |
134 } |
144 } |
135 } |
145 cleanup(); |
136 cleanup(); |
146 } |
137 } |
147 |
138 |
148 /** |
139 /** |
149 * Cleans up any resources held by this recorder entry at the end |
140 * Cleans up any resources held by this recorder entry at the end of a subbuild if it has been |
150 * of a subbuild if it has been created for the subbuild's project |
141 * created for the subbuild's project instance. |
151 * instance. |
142 * |
152 * |
|
153 * @param event the buildFinished event |
143 * @param event the buildFinished event |
154 * |
144 * |
155 * @since Ant 1.6.2 |
145 * @since Ant 1.6.2 |
156 */ |
146 */ |
157 public void handleSubBuildFinished(BuildEvent event) { |
147 public void handleSubBuildFinished(BuildEvent event) { |
158 log("< SUBBUILD FINISHED", Project.MSG_DEBUG); |
148 log("< SUBBUILD FINISHED", Project.MSG_DEBUG); |
159 // let's keep the logging ongoing, even if sub-build finishes. |
149 // let's keep the logging ongoing, even if sub-build finishes. |
160 } |
150 } |
161 |
151 |
162 /** |
152 /** |
163 * Empty implementation to satisfy the BuildListener interface. |
153 * Empty implementation to satisfy the BuildListener interface. |
164 * |
154 * |
165 * @param event the buildStarted event |
155 * @param event the buildStarted event |
166 * |
156 * |
167 * @since Ant 1.6.2 |
157 * @since Ant 1.6.2 |
168 */ |
158 */ |
169 public void handleSubBuildStarted(BuildEvent event) { |
159 public void handleSubBuildStarted(BuildEvent event) { |
170 log("< SUBBUILD STARTED", Project.MSG_DEBUG); |
160 log("< SUBBUILD STARTED", Project.MSG_DEBUG); |
171 } |
161 } |
289 public void setOutputPrintStream(PrintStream output) { |
277 public void setOutputPrintStream(PrintStream output) { |
290 closeFile(); |
278 closeFile(); |
291 out = output; |
279 out = output; |
292 } |
280 } |
293 |
281 |
294 |
|
295 /** |
282 /** |
296 * @see BuildLogger#setEmacsMode(boolean) |
283 * @see BuildLogger#setEmacsMode(boolean) |
297 */ |
284 */ |
298 /** {@inheritDoc}. */ |
285 /** {@inheritDoc}. */ |
299 public void setEmacsMode(boolean emacsMode) { |
286 public void setEmacsMode(boolean emacsMode) { |
300 this.emacsMode = emacsMode; |
287 this.emacsMode = emacsMode; |
301 } |
288 } |
302 |
289 |
303 |
|
304 /** |
290 /** |
305 * @see BuildLogger#setErrorPrintStream(PrintStream) |
291 * @see BuildLogger#setErrorPrintStream(PrintStream) |
306 */ |
292 */ |
307 /** {@inheritDoc}. */ |
293 /** {@inheritDoc}. */ |
308 public void setErrorPrintStream(PrintStream err) { |
294 public void setErrorPrintStream(PrintStream err) { |
309 setOutputPrintStream(err); |
295 setOutputPrintStream(err); |
310 } |
296 } |
311 |
|
312 |
297 |
313 private static String formatTime(long millis) { |
298 private static String formatTime(long millis) { |
314 // CheckStyle:MagicNumber OFF |
299 // CheckStyle:MagicNumber OFF |
315 long seconds = millis / 1000; |
300 long seconds = millis / 1000; |
316 long minutes = seconds / 60; |
301 long minutes = seconds / 60; |
317 |
302 |
318 |
|
319 if (minutes > 0) { |
303 if (minutes > 0) { |
320 return Long.toString(minutes) + " minute" |
304 return Long.toString(minutes) + " minute" + (minutes == 1 ? " " : "s ") |
321 + (minutes == 1 ? " " : "s ") |
305 + Long.toString(seconds % 60) + " second" + (seconds % 60 == 1 ? "" : "s"); |
322 + Long.toString(seconds % 60) + " second" |
306 } |
323 + (seconds % 60 == 1 ? "" : "s"); |
307 else { |
324 } else { |
308 return Long.toString(seconds) + " second" + (seconds % 60 == 1 ? "" : "s"); |
325 return Long.toString(seconds) + " second" |
|
326 + (seconds % 60 == 1 ? "" : "s"); |
|
327 } |
309 } |
328 // CheckStyle:MagicNumber ON |
310 // CheckStyle:MagicNumber ON |
329 } |
311 } |
330 |
312 |
331 |
|
332 /** |
313 /** |
333 * Registering ourselves to the StatusAndLogListener. |
314 * Registering ourselves to the StatusAndLogListener. |
334 */ |
315 */ |
335 public void register() { |
316 public void register() { |
336 StatusAndLogListener listener = StatusAndLogListener.getStatusAndLogListener(); |
317 StatusAndLogListener listener = StatusAndLogListener.getStatusAndLogListener(); |
337 if (listener != null) { |
318 if (listener != null) { |
338 this.log.debug("register"); |
319 this.log.debug("register"); |
339 synchronized (listener) { |
320 synchronized (listener) { |
340 listener.register((BuildEventHandler)this); |
321 listener.register((BuildEventHandler) this); |
341 listener.register((TargetEventHandler)this); |
322 listener.register((TargetEventHandler) this); |
342 listener.register((TaskEventHandler)this); |
323 listener.register((TaskEventHandler) this); |
343 listener.register((MessageEventHandler)this); |
324 listener.register((MessageEventHandler) this); |
344 } |
325 } |
345 } |
326 } |
346 } |
327 } |
347 |
328 |
348 /** |
329 /** |
351 public void unregister() { |
332 public void unregister() { |
352 StatusAndLogListener listener = StatusAndLogListener.getStatusAndLogListener(); |
333 StatusAndLogListener listener = StatusAndLogListener.getStatusAndLogListener(); |
353 if (listener != null) { |
334 if (listener != null) { |
354 this.log.debug("unregister"); |
335 this.log.debug("unregister"); |
355 synchronized (listener) { |
336 synchronized (listener) { |
356 listener.remove((MessageEventHandler)this); |
337 listener.remove((MessageEventHandler) this); |
357 listener.remove((TaskEventHandler)this); |
338 listener.remove((TaskEventHandler) this); |
358 listener.remove((TargetEventHandler)this); |
339 listener.remove((TargetEventHandler) this); |
359 listener.remove((BuildEventHandler)this); |
340 listener.remove((BuildEventHandler) this); |
360 } |
341 } |
361 } |
342 } |
362 } |
343 } |
363 |
|
364 |
344 |
365 /** |
345 /** |
366 * @since 1.6.2 |
346 * @since 1.6.2 |
367 */ |
347 */ |
368 public void cleanup() { |
348 public void cleanup() { |
369 closeFile(); |
349 closeFile(); |
370 } |
350 } |
371 |
351 |
372 /** |
352 /** |
373 * Closes the file associated with this recorder. |
353 * Closes the file associated with this recorder. Used by Recorder. |
374 * Used by Recorder. |
354 * |
375 * @since 1.6.3 |
355 * @since 1.6.3 |
376 */ |
356 */ |
377 public void closeFile() { |
357 public void closeFile() { |
378 this.log.debug("closeFile."); |
358 this.log.debug("closeFile."); |
379 if (out != null) { |
359 if (out != null) { |
380 out.close(); |
360 out.close(); |
381 out = null; |
361 out = null; |
382 unregister(); |
362 unregister(); |
383 } |
363 } |
384 } |
364 } |
385 |
365 |
386 /** |
366 /** |
387 * Initially opens the file associated with this recorder. |
367 * Initially opens the file associated with this recorder. Used by Recorder. |
388 * Used by Recorder. |
368 * |
389 * @param append Indicates if output must be appended to the logfile or that |
369 * @param append Indicates if output must be appended to the logfile or that the logfile should |
390 * the logfile should be overwritten. |
370 * be overwritten. |
391 * @throws BuildException |
371 * @throws BuildException |
392 * @since 1.6.3 |
372 * @since 1.6.3 |
393 */ |
373 */ |
394 public void openFile(boolean append) { |
374 public void openFile(boolean append) { |
395 openFileImpl(append); |
375 openFileImpl(append); |
396 } |
376 } |
397 |
377 |
398 /** |
378 /** |
399 * Re-opens the file associated with this recorder. |
379 * Re-opens the file associated with this recorder. Used by Recorder. |
400 * Used by Recorder. |
380 * |
401 * @throws BuildException |
381 * @throws BuildException |
402 * @since 1.6.3 |
382 * @since 1.6.3 |
403 */ |
383 */ |
404 public void reopenFile() { |
384 public void reopenFile() { |
405 openFileImpl(true); |
385 openFileImpl(true); |
406 } |
386 } |
407 |
387 |
408 private void openFileImpl(boolean append) { |
388 private void openFileImpl(boolean append) { |
409 if (out == null) { |
389 if (out == null) { |
410 this.log.debug("openFileImpl: " + filename); |
390 this.log.debug("openFileImpl: " + filename); |
411 try { |
391 try { |
412 out = new PrintStream(new FileOutputStream(filename, append)); |
392 out = new PrintStream(new FileOutputStream(filename, append)); |
413 register(); |
393 register(); |
414 } catch (IOException ioe) { |
394 } |
415 throw new BuildException("Problems opening file using a " |
395 catch (IOException ioe) { |
416 + "recorder entry: " + ioe.getMessage(), ioe); |
396 throw new BuildException("Problems opening file using a " + "recorder entry: " |
417 } |
397 + ioe.getMessage(), ioe); |
418 } |
398 } |
419 } |
399 } |
420 |
400 } |
|
401 |
421 /** |
402 /** |
422 * To add user message into log file. |
403 * To add user message into log file. |
|
404 * |
423 * @param message |
405 * @param message |
424 */ |
406 */ |
425 public void addLogMessage(String message) { |
407 public void addLogMessage(String message) { |
426 out.println(StringUtils.LINE_SEP + message); |
408 out.println(StringUtils.LINE_SEP + message); |
427 |
409 |
428 } |
410 } |
429 |
411 |
430 |
|
431 |
|
432 } |
412 } |