KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > idaremedia > antx > flowcontrol > call > StepLauncher


1 /**
2  * $Id: StepLauncher.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.flowcontrol.call;
30
31 import java.util.ArrayList JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.List JavaDoc;
34
35 import org.apache.tools.ant.BuildException;
36 import org.apache.tools.ant.Project;
37 import org.apache.tools.ant.Target;
38 import org.apache.tools.ant.Task;
39
40 import com.idaremedia.antx.AntX;
41 import com.idaremedia.antx.AssertableTask;
42 import com.idaremedia.antx.flowcontrol.FlowConstants;
43 import com.idaremedia.antx.ownhelpers.TaskExaminer;
44
45 /**
46  * Special task that receives a calling target and step name from an source parent
47  * Ant process. The launcher task will then try to execute the tasks nested within
48  * a local instance of the the calling target and step.
49  * <p>
50  * The entire 'Ant' and 'CallTarget' mechanism is based on reloading/reparsing an
51  * existing build file, so it is incapable of handling dynamically added targets
52  * (which better match the concept of a step, but alas the default ProjectHelper
53  * requires a real file-system build file to read/parse). This launcher task must
54  * be nested inside a special target the originating StepCallers will use.
55  * <p>
56  * When executed launchers execute the nested tasks in a single step, much like
57  * the builtin '<i>sequential</i>' task.
58  *
59  * @since JWare/AntX 0.1
60  * @author ssmc, &copy;2002-2004 <a HREF="http://www.jware.info">iDare&nbsp;Media,&nbsp;Inc.</a>
61  * @version 0.5
62  * @.safety single
63  * @.group impl,infra
64  * @see InlinedTarget
65  * @see StepLauncherCaller
66  * @see StepLauncherInstallTask
67  **/

68
69 public class StepLauncher extends AssertableTask
70 {
71     /**
72      * Creates a new step launcher task.
73      **/

74     public StepLauncher()
75     {
76         super(AntX.flow+"steplauncher");
77     }
78
79
80     /**
81      * Optionally delays this launcher's configuration if I'm being
82      * swapped with a placeholder.
83      * @see TaskExaminer#ignoreConfigure TaskExaminer.ignoreConfigure(&#8230;)
84      * @since JWare/AntX 0.4
85      **/

86     public void maybeConfigure()
87         throws BuildException
88     {
89         if (!TaskExaminer.ignoreConfigure(this)) {
90             super.maybeConfigure();
91         }
92     }
93
94
95
96     /**
97      * Helper to broadcast missing information to log/runtime.
98      **/

99     private BuildException missingInformation(String JavaDoc msgId, String JavaDoc arg1)
100     {
101         String JavaDoc ermsg = uistrs().get(msgId,arg1);
102         log(ermsg,Project.MSG_ERR);
103         return new BuildException(ermsg, getLocation());
104     }
105
106
107     /**
108      * Checks all required pre-conditions for execute method. By default
109      * ensures in valid project and all required properties are defined.
110      * @throws BuildException if any precondition not met
111      **/

112     protected void verifyCanExecute_(String JavaDoc calr)
113         throws BuildException
114     {
115         verifyInProject_(calr);
116
117         String JavaDoc targetProperty = getTargetProperty();
118         require_(targetProperty!=null,"exec- nonzro target property");
119
120         String JavaDoc nameProperty = getInlinedTargetNameProperty();
121         require_(nameProperty!=null,"exec- nonzro stepname property");
122
123         final Project P= getProject();
124
125         if (P.getProperty(targetProperty)==null) {
126             throw missingInformation("flow.steplaunch.need.target",targetProperty);
127         }
128         if (P.getProperty(nameProperty)==null) {
129             throw missingInformation("flow.steplaunch.need.stepname",nameProperty);
130         }
131     }
132
133
134
135     /**
136      * Returns the local target that matches the owning target of the
137      * step-caller that triggered this launcher. By default this launcher
138      * assumes the calling task inserted its target's name and the required
139      * step name into two specially named properties.
140      * @see #getTargetProperty
141      * @throws BuildException if unable to find local target match
142      **/

143     protected Target getLocalTarget()
144         throws BuildException
145     {
146         Target localTarget = (Target)getProject().getTargets().get(getTargetName());
147
148         if (localTarget==null) {
149             throw missingInformation("flow.steplaunch.missing.caller",
150                                      getTargetName());
151         }
152         return localTarget;
153     }
154
155
156     /**
157      * Returns a kind-of subset of tasks from a set of generic tasks. All
158      * returned items implement the filter class or interface.
159      * @param tasks the set of tasks to filter and update (non-null)
160      * @param ofKind the filter class or interface (non-null)
161      **/

162     protected final List JavaDoc getTasksOfKind(Task[] tasks, Class JavaDoc ofKind)
163         throws BuildException
164     {
165         List JavaDoc l= new ArrayList JavaDoc(tasks.length);
166         Class JavaDoc[] COI= new Class JavaDoc[]{ofKind};
167         for (int i=0;i<tasks.length;i++) {
168             Task task = TaskExaminer.trueTask(tasks[i],COI,this);
169             if (ofKind.isAssignableFrom(task.getClass())) {
170                 l.add(task);
171                 if (task!=tasks[i]) {//@since AntX0.4+Ant1.6.1
172
tasks[i]= task; //replace Unknown with Known!
173
}
174             }
175         }
176         return l;
177     }
178
179
180     /**
181      * Extracts a named inlined target from within a set of generic tasks. Iff
182      * the inline-target is not found within the given top-level task set, nested
183      * inline-target containers are searched, in order, up to '<i>depthLimit</i>'
184      * deep <em>each</em>. Returns <i>null</i> if no matching inlined-target found.
185      * @param stepName the inlined-target's name (non-whitespace)
186      * @param filterClass [optional] if non-null the matching target must be of this class
187      * @param tasks the set of possible tasks (non-null)
188      * @param depth the current search depth
189      * @param depthLimit the maximum search depth
190      **/

191     protected InlinedTarget getInlinedTarget(final String JavaDoc stepName, final Class JavaDoc filterClass,
192                                              Task[] tasks, int depth, final int depthLimit)
193     {
194         InlinedTarget it = null;
195         List JavaDoc candidates = getTasksOfKind(tasks, InlinedTarget.class);
196
197         if (!candidates.isEmpty()) {
198             Iterator JavaDoc itr= candidates.iterator();
199             while (itr.hasNext()) {
200                 it = (InlinedTarget)itr.next();
201                 //NB: handles delayed maybeConfigure (pre Ant 1.6)
202
if (it.getName()==null && (it instanceof Task)) {
203                     ((Task)it).maybeConfigure();
204                 }
205                 if (stepName.equals(it.getName())) {
206                     if (filterClass!=null && !filterClass.isInstance(it)) {
207                         continue;
208                     }
209                     return it;
210                 }
211             }
212             it = null;
213             candidates.clear();
214         }
215         candidates=null;
216
217         if (depth<depthLimit) {
218             candidates = getTasksOfKind(tasks, InlinedTargetContainer.class);
219             if (!candidates.isEmpty()) {
220                 Iterator JavaDoc itr = candidates.iterator();
221                 Task[] nestedtasks;
222                 while (itr.hasNext()) {
223                     InlinedTargetContainer itc = (InlinedTargetContainer)itr.next();
224                     nestedtasks = itc.getTasks();
225                     if (nestedtasks.length>0) {
226                         it = getInlinedTarget(stepName, filterClass, nestedtasks,
227                                               depth+1,depthLimit);
228                         if (it!=null) {
229                             break;
230                         }
231                     }
232                 }
233                 candidates.clear();
234             }
235             candidates=null;
236         }
237
238         return it;
239     }
240
241
242     /**
243      * Returns the local instance of the requested step within the local target.
244      * Returns <i>null</i> if no local step matches criteria.
245      * @param stepName caller's inlined-targets name (non-null)
246      * @param requiredClass [optional] further refinement of the acceptable target
247      * @throws BuildException if unable to load requiredClass reference or unable
248      * to locate local target.
249      **/

250     protected InlinedTarget findInlinedTarget(String JavaDoc stepName, String JavaDoc requiredClass)
251         throws BuildException
252     {
253         require_(stepName!=null,"fndInlinTargt- nonzro name");
254
255         Class JavaDoc filterClass = null;
256         if (requiredClass!=null) {
257             try {
258                 filterClass = Class.forName(requiredClass);
259             } catch(ClassNotFoundException JavaDoc cnfx) {
260                 throw new BuildException(cnfx, getLocation());
261             }
262         }
263
264         return getInlinedTarget(stepName, filterClass,
265                                 getLocalTarget().getTasks(),
266                                 1, getMaxSearchDepth());
267     }
268
269
270
271     /**
272      * Executes locally the inlined-target that matches the calling
273      * step-caller's target. Note the calling step-caller should belong
274      * to a separate project (and environment space).
275      * @see #getInlinedTargetNameProperty
276      * @see #findInlinedTarget
277      * @throws BuildException if unable to locate local inlined-target or
278      * the inlined-target throws an exception
279      **/

280     public void execute() throws BuildException
281     {
282         verifyCanExecute_("execute");
283
284         InlinedTarget it = findInlinedTarget(getInlinedTargetName(),
285                                              getKindOfInlinedTargetClass());
286         if (it==null) {
287             String JavaDoc ermsg = uistrs().get("flow.steplaunch.missing.step",
288                                         getInlinedTargetName(), getTargetName());
289             log(ermsg, Project.MSG_ERR);
290             throw new BuildException(ermsg, getLocation());
291         }
292
293         it.run();
294     }
295
296
297
298     /**
299      * Returns the property that contains the local target's name. Must
300      * be defined from the step caller's "call-target" code.
301      * @see FlowConstants#DEFAULT_STEP_LAUNCHER_TARGET_PROP
302      **/

303     protected String JavaDoc getTargetProperty()
304     {
305         return FlowConstants.DEFAULT_STEP_LAUNCHER_TARGET_PROP;
306     }
307
308
309     /**
310      * Returns the property that contains the local inlined-target's name.
311      * Must be defined from the step-caller's "call-target" code.
312      * @see FlowConstants#DEFAULT_STEP_LAUNCHER_STEPNAME_PROP
313      **/

314     protected String JavaDoc getInlinedTargetNameProperty()
315     {
316         return FlowConstants.DEFAULT_STEP_LAUNCHER_STEPNAME_PROP;
317     }
318
319
320
321     /**
322      * Returns class name of custom {@linkplain InlinedTarget InlinedTarget}
323      * subclass that is being targeted with this launcher. By default assumes only
324      * {@linkplain InlineStep InlineStep} implementations are targeted.
325      * @see FlowConstants#DEFAULT_STEP_LAUNCHER_STEPCLASS_PROP
326      **/

327     protected String JavaDoc getKindOfInlinedTargetClass()
328     {
329         String JavaDoc kindOfInlinedTargetClass =
330             getProject().getProperty
331                 (FlowConstants.DEFAULT_STEP_LAUNCHER_STEPCLASS_PROP);
332
333         if (kindOfInlinedTargetClass==null) {
334             kindOfInlinedTargetClass = InlineStep.class.getName();
335         }
336
337         return kindOfInlinedTargetClass;
338     }
339
340
341
342     /**
343      * Returns calling target's name.
344      **/

345     private String JavaDoc getTargetName()
346     {
347         return getProject().getProperty(getTargetProperty());
348     }
349
350
351     /**
352      * Returns called inlined-target's name.
353      **/

354     private String JavaDoc getInlinedTargetName()
355     {
356         return getProject().getProperty(getInlinedTargetNameProperty());
357     }
358
359
360     /**
361      * Returns maximum search depth for inlined-targets. Returned number
362      * must be equal-to or greater than one (1).
363      **/

364     protected int getMaxSearchDepth()
365     {
366         String JavaDoc s =
367             getProject().getProperty
368                 (FlowConstants.DEFAULT_STEP_LAUNCHER_SEARCHDEPTH_PROP);
369         if (s!=null) {
370             try {
371                 int i = Integer.parseInt(s);
372                 if (i>0) {
373                     return i;
374                 }
375             } catch(NumberFormatException JavaDoc nfx) {/*burp*/}
376             String JavaDoc ermsg = uistrs().get("flow.steplaunch.bad.depth",s,"1");
377             log(ermsg,Project.MSG_WARN);
378         }
379         return 1;
380     }
381
382 }
383
384 /* end-of-StepLauncher.java */
385
Popular Tags