KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > Task


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */

18
19 package org.apache.tools.ant;
20
21 import org.apache.tools.ant.dispatch.DispatchUtils;
22
23 import java.util.Enumeration JavaDoc;
24 import java.io.IOException JavaDoc;
25
26 /**
27  * Base class for all tasks.
28  *
29  * Use Project.createTask to create a new task instance rather than
30  * using this class directly for construction.
31  *
32  * @see Project#createTask
33  */

34 public abstract class Task extends ProjectComponent {
35     // CheckStyle:VisibilityModifier OFF - bc
36
/**
37      * Target this task belongs to, if any.
38      * @deprecated since 1.6.x.
39      * You should not be accessing this variable directly.
40      * Please use the {@link #getOwningTarget()} method.
41      */

42     protected Target target;
43
44     /**
45      * Name of this task to be used for logging purposes.
46      * This defaults to the same as the type, but may be
47      * overridden by the user. For instance, the name "java"
48      * isn't terribly descriptive for a task used within
49      * another task - the outer task code can probably
50      * provide a better one.
51      * @deprecated since 1.6.x.
52      * You should not be accessing this variable directly.
53      * Please use the {@link #getTaskName()} method.
54      */

55     protected String JavaDoc taskName;
56
57     /**
58      * Type of this task.
59      *
60      * @deprecated since 1.6.x.
61      * You should not be accessing this variable directly.
62      * Please use the {@link #getTaskType()} method.
63      */

64     protected String JavaDoc taskType;
65
66     /**
67      * Wrapper for this object, used to configure it at runtime.
68      *
69      * @deprecated since 1.6.x.
70      * You should not be accessing this variable directly.
71      * Please use the {@link #getWrapper()} method.
72      */

73     protected RuntimeConfigurable wrapper;
74
75     // CheckStyle:VisibilityModifier ON
76

77     /**
78      * Whether or not this task is invalid. A task becomes invalid
79      * if a conflicting class is specified as the implementation for
80      * its type.
81      */

82     private boolean invalid;
83
84     /** Sole constructor. */
85     public Task() {
86     }
87
88     /**
89      * Sets the target container of this task.
90      *
91      * @param target Target in whose scope this task belongs.
92      * May be <code>null</code>, indicating a top-level task.
93      */

94     public void setOwningTarget(Target target) {
95         this.target = target;
96     }
97
98     /**
99      * Returns the container target of this task.
100      *
101      * @return The target containing this task, or <code>null</code> if
102      * this task is a top-level task.
103      */

104     public Target getOwningTarget() {
105         return target;
106     }
107
108     /**
109      * Sets the name to use in logging messages.
110      *
111      * @param name The name to use in logging messages.
112      * Should not be <code>null</code>.
113      */

114     public void setTaskName(String JavaDoc name) {
115         this.taskName = name;
116     }
117
118     /**
119      * Returns the name to use in logging messages.
120      *
121      * @return the name to use in logging messages.
122      */

123     public String JavaDoc getTaskName() {
124         return taskName;
125     }
126
127     /**
128      * Sets the name with which the task has been invoked.
129      *
130      * @param type The name the task has been invoked as.
131      * Should not be <code>null</code>.
132      */

133     public void setTaskType(String JavaDoc type) {
134         this.taskType = type;
135     }
136
137     /**
138      * Called by the project to let the task initialize properly.
139      * The default implementation is a no-op.
140      *
141      * @exception BuildException if something goes wrong with the build
142      */

143     public void init() throws BuildException {
144     }
145
146     /**
147      * Called by the project to let the task do its work. This method may be
148      * called more than once, if the task is invoked more than once.
149      * For example,
150      * if target1 and target2 both depend on target3, then running
151      * "ant target1 target2" will run all tasks in target3 twice.
152      *
153      * @exception BuildException if something goes wrong with the build.
154      */

155     public void execute() throws BuildException {
156     }
157
158     /**
159      * Returns the wrapper used for runtime configuration.
160      *
161      * @return the wrapper used for runtime configuration. This
162      * method will generate a new wrapper (and cache it)
163      * if one isn't set already.
164      */

165     public RuntimeConfigurable getRuntimeConfigurableWrapper() {
166         if (wrapper == null) {
167             wrapper = new RuntimeConfigurable(this, getTaskName());
168         }
169         return wrapper;
170     }
171
172     /**
173      * Sets the wrapper to be used for runtime configuration.
174      *
175      * This method should be used only by the ProjectHelper and Ant internals.
176      * It is public to allow helper plugins to operate on tasks, normal tasks
177      * should never use it.
178      *
179      * @param wrapper The wrapper to be used for runtime configuration.
180      * May be <code>null</code>, in which case the next call
181      * to getRuntimeConfigurableWrapper will generate a new
182      * wrapper.
183      */

184     public void setRuntimeConfigurableWrapper(RuntimeConfigurable wrapper) {
185         this.wrapper = wrapper;
186     }
187
188     // XXX: (Jon Skeet) The comment "if it hasn't been done already" may
189
// not be strictly true. wrapper.maybeConfigure() won't configure the same
190
// attributes/text more than once, but it may well add the children again,
191
// unless I've missed something.
192
/**
193      * Configures this task - if it hasn't been done already.
194      * If the task has been invalidated, it is replaced with an
195      * UnknownElement task which uses the new definition in the project.
196      *
197      * @exception BuildException if the task cannot be configured.
198      */

199     public void maybeConfigure() throws BuildException {
200         if (!invalid) {
201             if (wrapper != null) {
202                 wrapper.maybeConfigure(getProject());
203             }
204         } else {
205             getReplacement();
206         }
207     }
208
209     /**
210      * Force the task to be reconfigured from its RuntimeConfigurable.
211      */

212     public void reconfigure() {
213         if (wrapper != null) {
214             wrapper.reconfigure(getProject());
215         }
216     }
217
218     /**
219      * Handles output by logging it with the INFO priority.
220      *
221      * @param output The output to log. Should not be <code>null</code>.
222      */

223     protected void handleOutput(String JavaDoc output) {
224         log(output, Project.MSG_INFO);
225     }
226
227     /**
228      * Handles output by logging it with the INFO priority.
229      *
230      * @param output The output to log. Should not be <code>null</code>.
231      *
232      * @since Ant 1.5.2
233      */

234     protected void handleFlush(String JavaDoc output) {
235         handleOutput(output);
236     }
237
238     /**
239      * Handle an input request by this task.
240      *
241      * @param buffer the buffer into which data is to be read.
242      * @param offset the offset into the buffer at which data is stored.
243      * @param length the amount of data to read.
244      *
245      * @return the number of bytes read.
246      *
247      * @exception IOException if the data cannot be read.
248      * @since Ant 1.6
249      */

250     protected int handleInput(byte[] buffer, int offset, int length)
251         throws IOException JavaDoc {
252         return getProject().defaultInput(buffer, offset, length);
253     }
254
255     /**
256      * Handles an error output by logging it with the WARN priority.
257      *
258      * @param output The error output to log. Should not be <code>null</code>.
259      */

260     protected void handleErrorOutput(String JavaDoc output) {
261         log(output, Project.MSG_WARN);
262     }
263
264     /**
265      * Handles an error line by logging it with the WARN priority.
266      *
267      * @param output The error output to log. Should not be <code>null</code>.
268      *
269      * @since Ant 1.5.2
270      */

271     protected void handleErrorFlush(String JavaDoc output) {
272         handleErrorOutput(output);
273     }
274
275     /**
276      * Logs a message with the default (INFO) priority.
277      *
278      * @param msg The message to be logged. Should not be <code>null</code>.
279      */

280     public void log(String JavaDoc msg) {
281         log(msg, Project.MSG_INFO);
282     }
283
284     /**
285      * Logs a message with the given priority. This delegates
286      * the actual logging to the project.
287      *
288      * @param msg The message to be logged. Should not be <code>null</code>.
289      * @param msgLevel The message priority at which this message is to
290      * be logged.
291      */

292     public void log(String JavaDoc msg, int msgLevel) {
293         if (getProject() != null) {
294             getProject().log(this, msg, msgLevel);
295         } else {
296             super.log(msg, msgLevel);
297         }
298     }
299
300     /**
301      * Logs a message with the given priority. This delegates
302      * the actual logging to the project.
303      *
304      * @param t The exception to be logged. Should not be <code>null</code>.
305      * @param msgLevel The message priority at which this message is to
306      * be logged.
307      * @since 1.7
308      */

309     public void log(Throwable JavaDoc t, int msgLevel) {
310         if (t != null) {
311             log(t.getMessage(), t, msgLevel);
312         }
313     }
314
315     /**
316      * Logs a message with the given priority. This delegates
317      * the actual logging to the project.
318      *
319      * @param msg The message to be logged. Should not be <code>null</code>.
320      * @param t The exception to be logged. May be <code>null</code>.
321      * @param msgLevel The message priority at which this message is to
322      * be logged.
323      * @since 1.7
324      */

325     public void log(String JavaDoc msg, Throwable JavaDoc t, int msgLevel) {
326         if (getProject() != null) {
327             getProject().log(this, msg, t, msgLevel);
328         } else {
329             super.log(msg, msgLevel);
330         }
331     }
332
333     /**
334      * Performs this task if it's still valid, or gets a replacement
335      * version and performs that otherwise.
336      *
337      * Performing a task consists of firing a task started event,
338      * configuring the task, executing it, and then firing task finished
339      * event. If a runtime exception is thrown, the task finished event
340      * is still fired, but with the exception as the cause.
341      */

342     public final void perform() {
343         if (!invalid) {
344             getProject().fireTaskStarted(this);
345             Throwable JavaDoc reason = null;
346             try {
347                 maybeConfigure();
348                 DispatchUtils.execute(this);
349             } catch (BuildException ex) {
350                 if (ex.getLocation() == Location.UNKNOWN_LOCATION) {
351                     ex.setLocation(getLocation());
352                 }
353                 reason = ex;
354                 throw ex;
355             } catch (Exception JavaDoc ex) {
356                 reason = ex;
357                 BuildException be = new BuildException(ex);
358                 be.setLocation(getLocation());
359                 throw be;
360             } catch (Error JavaDoc ex) {
361                 reason = ex;
362                 throw ex;
363             } finally {
364                 getProject().fireTaskFinished(this, reason);
365             }
366         } else {
367             UnknownElement ue = getReplacement();
368             Task task = ue.getTask();
369             task.perform();
370         }
371     }
372
373     /**
374      * Marks this task as invalid. Any further use of this task
375      * will go through a replacement with the updated definition.
376      */

377     final void markInvalid() {
378         invalid = true;
379     }
380
381     /**
382      * Has this task been marked invalid?
383      *
384      * @return true if this task is no longer valid. A new task should be
385      * configured in this case.
386      *
387      * @since Ant 1.5
388      */

389     protected final boolean isInvalid() {
390         return invalid;
391     }
392
393     /**
394      * Replacement element used if this task is invalidated.
395      */

396     private UnknownElement replacement;
397
398     /**
399      * Creates an UnknownElement that can be used to replace this task.
400      * Once this has been created once, it is cached and returned by
401      * future calls.
402      *
403      * @return the UnknownElement instance for the new definition of this task.
404      */

405     private UnknownElement getReplacement() {
406         if (replacement == null) {
407             replacement = new UnknownElement(taskType);
408             replacement.setProject(getProject());
409             replacement.setTaskType(taskType);
410             replacement.setTaskName(taskName);
411             replacement.setLocation(location);
412             replacement.setOwningTarget(target);
413             replacement.setRuntimeConfigurableWrapper(wrapper);
414             wrapper.setProxy(replacement);
415             replaceChildren(wrapper, replacement);
416             target.replaceChild(this, replacement);
417             replacement.maybeConfigure();
418         }
419         return replacement;
420     }
421
422     /**
423      * Recursively adds an UnknownElement instance for each child
424      * element of replacement.
425      *
426      * @since Ant 1.5.1
427      */

428     private void replaceChildren(RuntimeConfigurable wrapper,
429                                  UnknownElement parentElement) {
430         Enumeration JavaDoc e = wrapper.getChildren();
431         while (e.hasMoreElements()) {
432             RuntimeConfigurable childWrapper =
433                 (RuntimeConfigurable) e.nextElement();
434             UnknownElement childElement =
435                 new UnknownElement(childWrapper.getElementTag());
436             parentElement.addChild(childElement);
437             childElement.setProject(getProject());
438             childElement.setRuntimeConfigurableWrapper(childWrapper);
439             childWrapper.setProxy(childElement);
440             replaceChildren(childWrapper, childElement);
441         }
442     }
443
444     /**
445      * Return the type of task.
446      *
447      * @return the type of task.
448      */

449     public String JavaDoc getTaskType() {
450         return taskType;
451     }
452
453     /**
454      * Return the runtime configurable structure for this task.
455      *
456      * @return the runtime structure for this task.
457      */

458     protected RuntimeConfigurable getWrapper() {
459         return wrapper;
460     }
461
462     /**
463      * Bind a task to another; use this when configuring a newly created
464      * task to do work on behalf of another.
465      * Project, OwningTarget, TaskName, Location and Description are all copied
466      *
467      * Important: this method does not call {@link Task#init()}.
468      * If you are creating a task to delegate work to, call {@link Task#init()}
469      * to initialize it.
470      *
471      * @param owner owning target
472      * @since Ant1.7
473      */

474     public final void bindToOwner(Task owner) {
475         setProject(owner.getProject());
476         setOwningTarget(owner.getOwningTarget());
477         setTaskName(owner.getTaskName());
478         setDescription(owner.getDescription());
479         setLocation(owner.getLocation());
480         setTaskType(owner.getTaskType());
481     }
482 }
483
Popular Tags