KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > idaremedia > antx > feedback > EmitTask


1 /**
2  * $Id: EmitTask.java 180 2007-03-15 12:56:38Z ssmc $
3  * Copyright 2002-2004 iDare Media, Inc. All rights reserved.
4  *
5  * Originally written by iDare Media, Inc. for release into the public domain. This
6  * library, source form and binary form, is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public License as published by the
8  * Free Software Foundation; either version 2 of the License, or (at your option) any later
9  * version.<p>
10  *
11  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  * See the GNU LGPL (GNU Lesser General Public License) for more details.<p>
14  *
15  * You should have received a copy of the GNU Lesser General Public License along with this
16  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite
17  * 330, Boston, MA 02111-1307 USA. The LGPL can be found online at
18  * http://www.fsf.org/copyleft/lesser.html<p>
19  *
20  * This product has been influenced by several projects within the open-source community.
21  * The JWare developers wish to acknowledge the open-source community's support. For more
22  * information regarding the open-source products used within JWare, please visit the
23  * JWare website.
24  *----------------------------------------------------------------------------------------*
25  * WEBSITE- http://www.jware.info EMAIL- inquiries@jware.info
26  *----------------------------------------------------------------------------------------*
27  **/

28
29 package com.idaremedia.antx.feedback;
30
31 import java.util.Iterator JavaDoc;
32 import java.util.List JavaDoc;
33
34 import org.apache.tools.ant.BuildException;
35 import org.apache.tools.ant.Project;
36 import com.idaremedia.apis.DiagnosticsEmitter;
37
38 import com.idaremedia.antx.AntX;
39 import com.idaremedia.antx.AntXFixture;
40 import com.idaremedia.antx.ErrorSnapshot;
41 import com.idaremedia.antx.NoiseLevel;
42 import com.idaremedia.antx.helpers.Setting;
43 import com.idaremedia.antx.helpers.Strings;
44 import com.idaremedia.antx.helpers.Tk;
45 import com.idaremedia.antx.starters.MsgTask;
46
47 /**
48  * Ant-isque link to a standard log4j Logger/Category's api. Some examples:<pre>
49  * &lt;emit msgid="precompile-checks-done" echo="yes"/&gt;
50  * &lt;emit level="debug" properties="all" message="Hi" echo="no"/&gt;
51  * &lt;emit from="${feedback.compile}" message="Past precompile checks" echo="yes"/&gt;
52  * &lt;emit level="fatal" thrown="${err.last}" msgid="build.failed" properties="all"/&gt;
53  * &lt;emit message="javac.options" properties="javac.debug,javac.depend" level="verbose"/&gt;
54  * &lt;emit timestamp="on" echo="off" properties="none"/&gt;
55  * &lt;emit from="${feedback.distrib}.web" msgid="checkpoint.upload.finished"/&gt;
56  * &lt;emit from="${grp.compiling}.apis" task="javac[templates]" msgid="banner.compiling"/&gt;
57  * &lt;emit thrown="build.error" level="fatal"/&gt;
58  * </pre>
59  *
60  * @since JWare/AntX 0.1
61  * @author ssmc, &copy;2002-2004 <a HREF="http://www.jware.info">iDare&nbsp;Media,&nbsp;Inc.</a>
62  * @version 0.5
63  * @.safety single
64  * @.group api,infra
65  * @see EmitConfiguration
66  * @see EmitConfigureTask
67  * @see EmitContext
68  **/

69
70 public class EmitTask extends MsgTask implements EmitConfigurable
71 {
72     /**
73      * Initializes a new EmitTask instance.
74      **/

75     public EmitTask()
76     {
77         super(AntX.feedback);
78     }
79
80
81     /**
82      * Initializes a new CV-labeled EmitTask instance.
83      **/

84     public EmitTask(String JavaDoc iam)
85     {
86         super(iam);
87     }
88
89
90     /**
91      * Adds an inclusion declaration to this task. This inclusion's
92      * value (property, reference, variable, etc.) will be added to
93      * any environment or error snapshot broadcast by this task.
94      * @param include the inclusion (non-null)
95      * @see #setProperties
96      **/

97     public void addConfiguredInclude(EmitInclude include)
98     {
99         require_(include!=null,"addIncl- nonzro incl");
100         getNestedInclusions().add(include);
101     }
102
103
104     /**
105      * Returns this task's list of variable inclusions. Never
106      * returns <i>null</i> but can be empty.
107      **/

108     protected final List JavaDoc getNestedInclusions()
109     {
110         return m_nestedIncludes;
111     }
112
113
114     /**
115      * Sets whether this task should echo its message to the standard
116      * Ant logging system <em>in addition</em> to the direct-to-log4j
117      * broadcast.
118      * @param wantIt preference setting (yes,no,inherit) (non-null)
119      **/

120     public void setEcho(String JavaDoc wantIt)
121     {
122         require_(wantIt!=null,"setEcho- nonzro arg");
123         m_echoPref= Setting.from(wantIt, Setting.INHERITED);//NB:allow aliases
124
}
125
126
127     /**
128      * Returns the echo-to-Ant-log preference for this task. Will
129      * return <i>Setting.INHERITED</i> if never set.
130      **/

131     public final Setting getPreferEcho()
132     {
133         return m_echoPref;
134     }
135
136
137     /**
138      * Returns <i>true</i> if this task should echo its emitted message
139      * to the standard Ant logging system (via Project).
140      **/

141     protected final boolean shouldEcho(EmitConfiguration defaults)
142     {
143         switch (getPreferEcho().getIndex()) {
144             case Setting.ON_INDEX: {
145                 return true;
146             }
147             case Setting.OFF_INDEX: {
148                 return false;
149             }
150             default: {
151                 return defaults.shouldEcho();
152             }
153         }
154     }
155
156
157     /**
158      * Returns the AntX noiselevel this task will associate with
159      * its broadcast message.
160      **/

161     protected final NoiseLevel getNoiseLevel(EmitConfiguration defaults)
162     {
163         NoiseLevel nl = getPreferredMsgLevel();
164         if (nl==null) {
165             nl= defaults.getNoiseLevel();
166         }
167         if (nl==null) {
168             nl= getDefaultMsgLevel();
169             ensure_(nl!=null,"getEffPri- nonzro lvl");
170         }
171         return nl;
172     }
173
174
175     /**
176      * Sets the list of property names automatically attached
177      * to any emitted message's snapshot. Really just an inlined
178      * 'include' set shortcut.
179      * @param nameList comma-delimited list of property names
180      * @see #addConfiguredInclude
181      **/

182     public void setProperties(String JavaDoc nameList)
183     {
184         require_(nameList!=null, "setProps- nonzro lst");
185         m_propertyNames= nameList;
186     }
187
188
189     /**
190      * Returns the list of properties names automatically included
191      * in any messages emitted from this task. Returns <i>null</i> if
192      * never set.
193      **/

194     public final String JavaDoc getPropertyNamesList()
195     {
196         return m_propertyNames;
197     }
198
199
200     /**
201      * Captures a list of named properties to the given error snapshot.
202      * Returns <i>true</i> if all properties captured as result of
203      * this call.
204      * @param es the environment snapshot to update (non-null)
205      * @param nameList the comma-delimited list of property names
206      **/

207     private boolean captureNamedProperties(ErrorSnapshot es, String JavaDoc nameList)
208     {
209         boolean all=false;
210
211         if (nameList!=null) {
212             String JavaDoc normalized = Tk.lowercaseFrom(nameList.trim());
213             if (Strings.USER.equals(normalized)) {
214                 es.captureUserProperties();
215             } else if (Strings.ALL.equals(normalized)) {
216                 es.captureAllProperties();
217                 all=true;
218             } else {
219                 es.captureProperties(nameList);
220             }
221         }
222         return all;
223     }
224
225
226     /**
227      * Captures the appropriate properties to the given snapshot.
228      * Captured properties include properties inherited from this task's
229      * enclosing configuration, inlined property names, and nested
230      * include declarations.
231      * @param es the environment snapshot to update (non-null)
232      **/

233     private void captureProperties(EmitConfiguration defaults,
234                                    StringBuffer JavaDoc defaultProperties,
235                                    ErrorSnapshot es)
236     {
237         boolean ignore = false;
238
239         if (defaultProperties.length()>0) {
240             ignore = captureNamedProperties(es,defaultProperties.substring(0));
241         }
242
243         if (!ignore) {
244             String JavaDoc nameList = getPropertyNamesList();
245             if (nameList!=null) {
246                 ignore= captureNamedProperties(es,nameList);
247             }
248         }
249
250         if (!getNestedInclusions().isEmpty()) {
251             Iterator JavaDoc itr= getNestedInclusions().iterator();
252             while (itr.hasNext()) {
253                 ((EmitInclude)itr.next()).apply(es);
254             }
255         }
256     }
257
258
259     /**
260      * Sets this task's thrown-build-exception's refid. The refid
261      * should point to a BuildException that should be included in
262      * the snapshot passed to the log4j object render. If the reference
263      * points to an ErrorSnapshot, its thrown BuildException is used.
264      * The reference isn't extracted until this task is executed.
265      **/

266     public void setThrownRefId(String JavaDoc refId)
267     {
268         require_(refId!=null,"setThrownRefId- nonzro refid");
269         m_thrownRefId= refId;
270     }
271
272
273     /**
274      * The script-facing synonymn for {@linkplain #setThrownRefId
275      * setThrownRefId}.
276      **/

277     public final void setThrown(String JavaDoc refId)
278     {
279         setThrownRefId(refId);
280     }
281
282
283     /**
284      * Returns this task's thrown-build-exception's refid. Returns
285      * <i>null</i> if never set.
286      **/

287     public final String JavaDoc getThrownRefId()
288     {
289         return m_thrownRefId;
290     }
291
292
293     /**
294      * Returns the thrown build exception this task should attach to
295      * its error snapshot. Returns <i>null</i> if no exception defined,
296      * or this method is unable to retrieve a build exception from the
297      * {@linkplain #setThrownRefId reference}.
298      **/

299     private Exception JavaDoc getThrown()
300     {
301         String JavaDoc refid = getThrownRefId();
302         if (refid!=null) {
303             Object JavaDoc ox= getProject().getReference(refid);
304             if (ox instanceof BuildException) {
305                 return (BuildException)ox;
306             } else if (ox instanceof ErrorSnapshot) {
307                 return ((ErrorSnapshot)ox).getThrown();
308             }
309             String JavaDoc ermsg = uistrs().get("task.echo.bad.refid", refid);
310             log(ermsg, Project.MSG_WARN);
311         }
312         return null;
313     }
314
315
316     /**
317      * Sets whether this emit task should include a local timestamp
318      * with emitted message.
319      * @param setin setting option (on,off,inherited), non-null
320      **/

321     public void setTimestamp(String JavaDoc setin)
322     {
323         require_(setin!=null,"setTm- nonzro setin");
324         m_timestampPref = Setting.from(setin, Setting.INHERITED);//NB: allow aliases
325
}
326
327
328     /**
329      * Returns <i>Setting.ON</i> if this task will include a local
330      * timestamp with emitted messages. Defaults to <i>Setting.INHERITED</i>.
331      **/

332     public final Setting getPreferTimestamp()
333     {
334         return m_timestampPref;
335     }
336
337
338     /**
339      * Returns the stringized timestamp this emission's time-of-execution.
340      * Returns the empty string if a timestamp is not specified in this
341      * task's (or its configuration's) definition.
342      **/

343     protected final String JavaDoc getTimestampLiteral(EmitConfiguration defaults, final long NOW)
344     {
345         String JavaDoc tsl = "";
346         switch (getPreferTimestamp().getIndex()) {
347             case Setting.OFF_INDEX: {
348                 break;
349             }
350             case Setting.ON_INDEX: {
351                 tsl = defaults.stampify(NOW);
352                 break;
353             }
354             default: {
355                 if (defaults.wantTimestamp()) {
356                     tsl = defaults.stampify(NOW);
357                 }
358             }
359         }
360         return tsl;
361     }
362
363
364     /**
365      * Determine what if any local message should be broadcast or
366      * attached to the emitted snapshot. Current EmitTasks support two forms
367      * of local message: msgid (inherited) and a literal 'message'
368      * attribute. Can have one or the other; not both.
369      **/

370     private String JavaDoc getLocalComment(EmitConfiguration defaults, final long NOW)
371     {
372         String JavaDoc tsl= getTimestampLiteral(defaults,NOW);
373         String JavaDoc msg= null;
374
375         if (getMsgId()!=null) {
376
377             /**
378              * Handle the optional msg arguments feature we inherited from
379              * our superclass 'MsgTask'. The timestamp is *always* argument
380              * number 3 after the fixed taskname(0) and location(1) args.
381              **/

382             String JavaDoc arg3 = getMsgArg1();
383             String JavaDoc arg4 = getMsgArg2();
384
385             if (arg3!=null || arg4!=null) {
386                 if (arg3!=null) {
387                     if (arg4!=null) {
388                         msg = getMsg(newMsgGetter(tsl,arg3,arg4));
389                     } else {
390                         msg = getMsg(newMsgGetter(tsl,arg3));
391                     }
392                 } else {
393                     msg = getMsg(newMsgGetter(tsl,"",arg4));
394                 }
395             }
396             else {
397                 msg = getMsg(newMsgGetter(tsl));
398             }
399         }
400
401         /**
402          * Fallback to a default message (if defined) from MsgTask. This
403          * might also have been an inlined 'message' attribute.
404          **/

405         if (Tk.isWhitespace(msg) && getDefaultMsg()!=null) {
406             msg = getDefaultMsg();
407         }
408
409         /**
410          * Sheesh...ok just use the timestamp string as the message.
411          **/

412         if (Tk.isWhitespace(msg)) {
413             msg = tsl;
414         }
415
416         return msg;
417     }
418
419
420     /**
421      * Customize the broadcasting log4j logger to something other
422      * than the one defined by this task's enclosing context.
423      * @param categoryId category of logger to use (non-null)
424      **/

425     public void setFrom(String JavaDoc categoryId)
426     {
427         require_(categoryId!=null,"setFrom- nonzro category");
428         m_categoryId= categoryId;
429     }
430
431
432     /**
433      * Returns the custom log4j grouping with which all messages sent
434      * from this task are associated. Returns <i>null</i> if never
435      * set.
436      **/

437     public final String JavaDoc getFrom()
438     {
439         return m_categoryId;
440     }
441
442
443     /**
444      * Associates a custom task name with any emitted snapshots.
445      **/

446     public void setTask(String JavaDoc pseudoTaskName)
447     {
448         require_(pseudoTaskName!=null,"setTsk- nonzro pseudoNam");
449         m_customTaskName= pseudoTaskName;
450     }
451
452
453     /**
454      * Returns the task name associated with emitted snapshot. Will
455      * return this task's names if a custom task name never set.
456      **/

457     public final String JavaDoc getEmittedTaskName()
458     {
459         String JavaDoc name = getTaskName();
460         if (m_customTaskName!=null) {
461             name = m_customTaskName;
462         }
463         return name;
464     }
465
466
467     /**
468      * Returns this task's diagnostics emitter. Never returns <i>null</i>.
469      **/

470     protected final synchronized DiagnosticsEmitter getEmitter(EmitConfiguration defaults)
471     {
472         if (m_emitr!=null) {
473             return m_emitr;
474         }
475         String JavaDoc grpId = getFrom();
476         if (grpId!=null) {
477             m_emitr = defaults.getCustomEmitter(grpId);
478         } else {
479             m_emitr = defaults.getEmitter();
480         }
481         return m_emitr;
482     }
483
484
485     /**
486      * Factory method for this task's environment snapshot. This snapshot
487      * is passed to the emitter service provider. For log4j-based emitters,
488      * a custom object renderer is required to make sense of the snapshot.
489      **/

490     private ErrorSnapshot getSnapshot(EmitConfiguration defaults,
491                                       StringBuffer JavaDoc properties,
492                                       final long NOW)
493     {
494         ErrorSnapshot es =null;
495
496         //capture thrown exception or not
497
Exception JavaDoc thrown= getThrown();
498         if (thrown!=null) {
499             es = new ErrorSnapshot(this, thrown);
500         } else {
501             es = new ErrorSnapshot(this);
502         }
503         if (getThrownRefId()!=null) {
504             es.setName(getThrownRefId());
505         }
506
507         //make it look like it's coming from caller
508
es.setEffectiveTaskName(getEmittedTaskName());
509
510         //capture properties, etc.
511
captureProperties(defaults,properties,es);
512
513         //attach a special commentary message if defined
514
es.setComment(getLocalComment(defaults,NOW));
515
516         return es;
517     }
518
519
520     /**
521      * Returns <i>true</i> if enuf kruft has been attached to this
522      * emit task that an environment snapshot is the best object to broadcast
523      * to the emitter service (instead of a simple String). Basically if
524      * any properties must be captured, it needs a snapshot.
525      **/

526     private boolean needsSnapshot(EmitConfiguration defaults,
527                                   StringBuffer JavaDoc defaultProperties)
528     {
529         return (defaults.getPropertiesNameList(defaultProperties) ||
530                 defaultProperties.length()>0 ||
531                 getPropertyNamesList()!=null ||
532                 !getNestedInclusions().isEmpty()
533                 );
534     }
535
536
537     /**
538      * Returns this tasks closest configuration controller. Usually
539      * an enclosing 'emitconfigure' outer task.
540      **/

541     public EmitConfiguration getDefaults()
542     {
543         EmitConfiguration ec = EmitContext.getConfiguration();
544         if (ec==null) {
545             ec= DefaultEmitConfiguration.INSTANCE;
546         }
547         return ec;
548     }
549
550
551     /**
552      * Sends message to the appropriate DiagnosticsEmitter. Optionally
553      * echoes message to standard Ant logging infrastructure.
554      * @throws BuildException if unable to execute
555      **/

556     public void execute() throws BuildException
557     {
558         final long NOW = System.currentTimeMillis();
559
560         verifyCanExecute_("execute");
561
562         EmitConfiguration defaults = getDefaults();//NB:cache on my stack
563

564         DiagnosticsEmitter emitter = getEmitter(defaults);
565         NoiseLevel nl = getNoiseLevel(defaults);
566
567         boolean isEchoed = shouldEcho(defaults);
568         boolean isEmitted = emitter.emits(nl.getIndex());
569
570         if (isEmitted || isEchoed) {
571             StringBuffer JavaDoc defaultProperties = new StringBuffer JavaDoc(71);
572
573             if (needsSnapshot(defaults, defaultProperties)) {
574                 ErrorSnapshot es = getSnapshot(defaults,defaultProperties,NOW);
575
576                 if (isEmitted) {
577                     Emit.broadcast(emitter, es, es.getThrown(), nl);
578                 }
579                 if (isEchoed) {
580                     log(es.toString(), nl.getNativeIndex());
581                 }
582             }
583             else {
584                 String JavaDoc msg = getLocalComment(defaults,NOW);
585                 Exception JavaDoc thrown = getThrown();
586                 if (thrown!=null) {
587                     msg += uistrs().get("emit.cause.msg.addon",thrown.getMessage());
588                 }
589
590                 if (isEmitted) {
591                     Emit.broadcast(emitter, msg, thrown, nl);
592                 }
593                 if (isEchoed) {
594                     log(msg, nl.getNativeIndex());
595                 }
596             }
597         }
598     }
599
600     private List JavaDoc m_nestedIncludes = AntXFixture.newList(4);//NB:embeded <include>
601
private String JavaDoc m_customTaskName;//NB:=> this.getTaskName();
602
private String JavaDoc m_propertyNames;//NB:use inherited
603
private String JavaDoc m_thrownRefId;//NB:nothing
604
private Setting m_timestampPref=Setting.INHERITED;//NB:does what enclosing configure wants
605
private Setting m_echoPref= Setting.INHERITED;//NB:ditto
606
private String JavaDoc m_categoryId=null;//NB:use inherited
607
private DiagnosticsEmitter m_emitr;//NB:cached on first use
608
}
609
610 /* end-of-EmitTask.java */
611
Popular Tags