source: release-kits/lirk3/bin/apache-ant-1.6.5/src/main/org/apache/tools/ant/Task.java@ 14982

Last change on this file since 14982 was 14982, checked in by oranfry, 16 years ago

initial import of LiRK3

File size: 15.0 KB
Line 
1/*
2 * Copyright 2000-2004 The Apache Software Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18package org.apache.tools.ant;
19
20import java.util.Enumeration;
21import java.io.IOException;
22
23/**
24 * Base class for all tasks.
25 *
26 * Use Project.createTask to create a new task instance rather than
27 * using this class directly for construction.
28 *
29 * @see Project#createTask
30 */
31public abstract class Task extends ProjectComponent {
32 /**
33 * Target this task belongs to, if any.
34 * @deprecated You should not be accessing this variable directly.
35 * Please use the {@link #getOwningTarget()} method.
36 */
37 protected Target target;
38
39 /**
40 * Description of this task, if any.
41 * @deprecated You should not be accessing this variable directly.
42 */
43 protected String description;
44
45 /**
46 * Location within the build file of this task definition.
47 * @deprecated You should not be accessing this variable directly.
48 * Please use the {@link #getLocation()} method.
49 */
50 protected Location location = Location.UNKNOWN_LOCATION;
51
52 /**
53 * Name of this task to be used for logging purposes.
54 * This defaults to the same as the type, but may be
55 * overridden by the user. For instance, the name "java"
56 * isn't terribly descriptive for a task used within
57 * another task - the outer task code can probably
58 * provide a better one.
59 * @deprecated You should not be accessing this variable directly.
60 * Please use the {@link #getTaskName()} method.
61 */
62 protected String taskName;
63
64 /**
65 * Type of this task.
66 *
67 * @deprecated You should not be accessing this variable directly.
68 * Please use the {@link #getTaskType()} method.
69 */
70 protected String taskType;
71
72 /**
73 * Wrapper for this object, used to configure it at runtime.
74 *
75 * @deprecated You should not be accessing this variable directly.
76 * Please use the {@link #getWrapper()} method.
77 */
78 protected RuntimeConfigurable wrapper;
79
80 /**
81 * Whether or not this task is invalid. A task becomes invalid
82 * if a conflicting class is specified as the implementation for
83 * its type.
84 */
85 private boolean invalid;
86
87 /** Sole constructor. */
88 public Task() {
89 }
90
91 /**
92 * Sets the target container of this task.
93 *
94 * @param target Target in whose scope this task belongs.
95 * May be <code>null</code>, indicating a top-level task.
96 */
97 public void setOwningTarget(Target target) {
98 this.target = target;
99 }
100
101 /**
102 * Returns the container target of this task.
103 *
104 * @return The target containing this task, or <code>null</code> if
105 * this task is a top-level task.
106 */
107 public Target getOwningTarget() {
108 return target;
109 }
110
111 /**
112 * Sets the name to use in logging messages.
113 *
114 * @param name The name to use in logging messages.
115 * Should not be <code>null</code>.
116 */
117 public void setTaskName(String name) {
118 this.taskName = name;
119 }
120
121 /**
122 * Returns the name to use in logging messages.
123 *
124 * @return the name to use in logging messages.
125 */
126 public String getTaskName() {
127 return taskName;
128 }
129
130 /**
131 * Sets the name with which the task has been invoked.
132 *
133 * @param type The name the task has been invoked as.
134 * Should not be <code>null</code>.
135 */
136 public void setTaskType(String type) {
137 this.taskType = type;
138 }
139
140 /**
141 * Sets a description of the current action. This may be used for logging
142 * purposes.
143 *
144 * @param desc Description of the current action.
145 * May be <code>null</code>, indicating that no description is
146 * available.
147 *
148 */
149 public void setDescription(String desc) {
150 description = desc;
151 }
152
153 /**
154 * Returns the description of the current action.
155 *
156 * @return the description of the current action, or <code>null</code> if
157 * no description is available.
158 */
159 public String getDescription() {
160 return description;
161 }
162
163 /**
164 * Called by the project to let the task initialize properly.
165 * The default implementation is a no-op.
166 *
167 * @exception BuildException if something goes wrong with the build
168 */
169 public void init() throws BuildException {
170 }
171
172 /**
173 * Called by the project to let the task do its work. This method may be
174 * called more than once, if the task is invoked more than once.
175 * For example,
176 * if target1 and target2 both depend on target3, then running
177 * "ant target1 target2" will run all tasks in target3 twice.
178 *
179 * @exception BuildException if something goes wrong with the build
180 */
181 public void execute() throws BuildException {
182 }
183
184 /**
185 * Returns the file/location where this task was defined.
186 *
187 * @return the file/location where this task was defined.
188 * Should not return <code>null</code>. Location.UNKNOWN_LOCATION
189 * is used for unknown locations.
190 *
191 * @see Location#UNKNOWN_LOCATION
192 */
193 public Location getLocation() {
194 return location;
195 }
196
197 /**
198 * Sets the file/location where this task was defined.
199 *
200 * @param location The file/location where this task was defined.
201 * Should not be <code>null</code> - use
202 * Location.UNKNOWN_LOCATION if the location isn't known.
203 *
204 * @see Location#UNKNOWN_LOCATION
205 */
206 public void setLocation(Location location) {
207 this.location = location;
208 }
209
210 /**
211 * Returns the wrapper used for runtime configuration.
212 *
213 * @return the wrapper used for runtime configuration. This
214 * method will generate a new wrapper (and cache it)
215 * if one isn't set already.
216 */
217 public RuntimeConfigurable getRuntimeConfigurableWrapper() {
218 if (wrapper == null) {
219 wrapper = new RuntimeConfigurable(this, getTaskName());
220 }
221 return wrapper;
222 }
223
224 /**
225 * Sets the wrapper to be used for runtime configuration.
226 *
227 * This method should be used only by the ProjectHelper and ant internals.
228 * It is public to allow helper plugins to operate on tasks, normal tasks
229 * should never use it.
230 *
231 * @param wrapper The wrapper to be used for runtime configuration.
232 * May be <code>null</code>, in which case the next call
233 * to getRuntimeConfigurableWrapper will generate a new
234 * wrapper.
235 */
236 public void setRuntimeConfigurableWrapper(RuntimeConfigurable wrapper) {
237 this.wrapper = wrapper;
238 }
239
240 // XXX: (Jon Skeet) The comment "if it hasn't been done already" may
241 // not be strictly true. wrapper.maybeConfigure() won't configure the same
242 // attributes/text more than once, but it may well add the children again,
243 // unless I've missed something.
244 /**
245 * Configures this task - if it hasn't been done already.
246 * If the task has been invalidated, it is replaced with an
247 * UnknownElement task which uses the new definition in the project.
248 *
249 * @exception BuildException if the task cannot be configured.
250 */
251 public void maybeConfigure() throws BuildException {
252 if (!invalid) {
253 if (wrapper != null) {
254 wrapper.maybeConfigure(getProject());
255 }
256 } else {
257 getReplacement();
258 }
259 }
260
261 /**
262 * Force the task to be reconfigured from it's RuntimeConfigurable
263 *
264 */
265 public void reconfigure() {
266 if (wrapper != null) {
267 wrapper.reconfigure(getProject());
268 }
269 }
270
271 /**
272 * Handles output by logging it with the INFO priority.
273 *
274 * @param output The output to log. Should not be <code>null</code>.
275 */
276 protected void handleOutput(String output) {
277 log(output, Project.MSG_INFO);
278 }
279
280 /**
281 * Handles output by logging it with the INFO priority.
282 *
283 * @param output The output to log. Should not be <code>null</code>.
284 *
285 * @since Ant 1.5.2
286 */
287 protected void handleFlush(String output) {
288 handleOutput(output);
289 }
290
291 /**
292 * Handle an input request by this task
293 *
294 * @param buffer the buffer into which data is to be read.
295 * @param offset the offset into the buffer at which data is stored.
296 * @param length the amount of data to read
297 *
298 * @return the number of bytes read
299 *
300 * @exception IOException if the data cannot be read
301 * @since Ant 1.6
302 */
303 protected int handleInput(byte[] buffer, int offset, int length)
304 throws IOException {
305 return getProject().defaultInput(buffer, offset, length);
306 }
307
308 /**
309 * Handles an error output by logging it with the WARN priority.
310 *
311 * @param output The error output to log. Should not be <code>null</code>.
312 */
313 protected void handleErrorOutput(String output) {
314 log(output, Project.MSG_WARN);
315 }
316
317 /**
318 * Handles an error line by logging it with the WARN priority.
319 *
320 * @param output The error output to log. Should not be <code>null</code>.
321 *
322 * @since Ant 1.5.2
323 */
324 protected void handleErrorFlush(String output) {
325 handleErrorOutput(output);
326 }
327
328 /**
329 * Logs a message with the default (INFO) priority.
330 *
331 * @param msg The message to be logged. Should not be <code>null</code>.
332 */
333 public void log(String msg) {
334 log(msg, Project.MSG_INFO);
335 }
336
337 /**
338 * Logs a message with the given priority. This delegates
339 * the actual logging to the project.
340 *
341 * @param msg The message to be logged. Should not be <code>null</code>.
342 * @param msgLevel The message priority at which this message is to
343 * be logged.
344 */
345 public void log(String msg, int msgLevel) {
346 getProject().log(this, msg, msgLevel);
347 }
348
349 /**
350 * Performs this task if it's still valid, or gets a replacement
351 * version and performs that otherwise.
352 *
353 * Performing a task consists of firing a task started event,
354 * configuring the task, executing it, and then firing task finished
355 * event. If a runtime exception is thrown, the task finished event
356 * is still fired, but with the exception as the cause.
357 */
358 public final void perform() {
359 if (!invalid) {
360 getProject().fireTaskStarted(this);
361 Throwable reason = null;
362 try {
363 maybeConfigure();
364 execute();
365 } catch (BuildException ex) {
366 if (ex.getLocation() == Location.UNKNOWN_LOCATION) {
367 ex.setLocation(getLocation());
368 }
369 reason = ex;
370 throw ex;
371 } catch (Exception ex) {
372 reason = ex;
373 BuildException be = new BuildException(ex);
374 be.setLocation(getLocation());
375 throw be;
376 } catch (Error ex) {
377 reason = ex;
378 throw ex;
379 } finally {
380 getProject().fireTaskFinished(this, reason);
381 }
382 } else {
383 UnknownElement ue = getReplacement();
384 Task task = ue.getTask();
385 task.perform();
386 }
387 }
388
389 /**
390 * Marks this task as invalid. Any further use of this task
391 * will go through a replacement with the updated definition.
392 */
393 final void markInvalid() {
394 invalid = true;
395 }
396
397 /**
398 * Has this task been marked invalid?
399 *
400 * @return true if this task is no longer valid. A new task should be
401 * configured in this case.
402 *
403 * @since Ant 1.5
404 */
405 protected final boolean isInvalid() {
406 return invalid;
407 }
408
409 /**
410 * Replacement element used if this task is invalidated.
411 */
412 private UnknownElement replacement;
413
414 /**
415 * Creates an UnknownElement that can be used to replace this task.
416 * Once this has been created once, it is cached and returned by
417 * future calls.
418 *
419 * @return the UnknownElement instance for the new definition of this task.
420 */
421 private UnknownElement getReplacement() {
422 if (replacement == null) {
423 replacement = new UnknownElement(taskType);
424 replacement.setProject(getProject());
425 replacement.setTaskType(taskType);
426 replacement.setTaskName(taskName);
427 replacement.setLocation(location);
428 replacement.setOwningTarget(target);
429 replacement.setRuntimeConfigurableWrapper(wrapper);
430 wrapper.setProxy(replacement);
431 replaceChildren(wrapper, replacement);
432 target.replaceChild(this, replacement);
433 replacement.maybeConfigure();
434 }
435 return replacement;
436 }
437
438 /**
439 * Recursively adds an UnknownElement instance for each child
440 * element of replacement.
441 *
442 * @since Ant 1.5.1
443 */
444 private void replaceChildren(RuntimeConfigurable wrapper,
445 UnknownElement parentElement) {
446 Enumeration e = wrapper.getChildren();
447 while (e.hasMoreElements()) {
448 RuntimeConfigurable childWrapper =
449 (RuntimeConfigurable) e.nextElement();
450 UnknownElement childElement =
451 new UnknownElement(childWrapper.getElementTag());
452 parentElement.addChild(childElement);
453 childElement.setProject(getProject());
454 childElement.setRuntimeConfigurableWrapper(childWrapper);
455 childWrapper.setProxy(childElement);
456 replaceChildren(childWrapper, childElement);
457 }
458 }
459
460 /**
461 * Return the type of task
462 *
463 * @return the type of task
464 */
465 public String getTaskType() {
466 return taskType;
467 }
468
469 /**
470 * Return the runtime configurable structure for this task
471 *
472 * @return the runtime structure for this task
473 */
474 protected RuntimeConfigurable getWrapper() {
475 return wrapper;
476 }
477}
Note: See TracBrowser for help on using the repository browser.