source: release-kits/lirk3/resources/gs3-release-maker/apache-ant-1.6.5/src/main/org/apache/tools/ant/taskdefs/Available.java@ 14982

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

initial import of LiRK3

File size: 17.2 KB
Line 
1/*
2 * Copyright 2000-2005 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.taskdefs;
19
20import java.io.File;
21import org.apache.tools.ant.AntClassLoader;
22import org.apache.tools.ant.BuildException;
23import org.apache.tools.ant.Project;
24import org.apache.tools.ant.Task;
25import org.apache.tools.ant.taskdefs.condition.Condition;
26import org.apache.tools.ant.types.EnumeratedAttribute;
27import org.apache.tools.ant.types.Path;
28import org.apache.tools.ant.types.Reference;
29import org.apache.tools.ant.util.FileUtils;
30import org.apache.tools.ant.util.StringUtils;
31
32/**
33 * Will set the given property if the requested resource is available at
34 * runtime. This task may also be used as a condition by the condition task.
35 *
36 * @since Ant 1.1
37 *
38 * @ant.task category="control"
39 */
40public class Available extends Task implements Condition {
41 private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
42
43 private String property;
44 private String classname;
45 private String filename;
46 private File file;
47 private Path filepath;
48 private String resource;
49 private FileDir type;
50 private Path classpath;
51 private AntClassLoader loader;
52 private String value = "true";
53 private boolean isTask = false;
54 private boolean ignoreSystemclasses = false;
55
56 /**
57 * Set the classpath to be used when searching for classes and resources.
58 *
59 * @param classpath an Ant Path object containing the search path.
60 */
61 public void setClasspath(Path classpath) {
62 createClasspath().append(classpath);
63 }
64
65 /**
66 * Classpath to be used when searching for classes and resources.
67 *
68 * @return an empty Path instance to be configured by Ant.
69 */
70 public Path createClasspath() {
71 if (this.classpath == null) {
72 this.classpath = new Path(getProject());
73 }
74 return this.classpath.createPath();
75 }
76
77 /**
78 * Set the classpath by reference.
79 *
80 * @param r a Reference to a Path instance to be used as the classpath
81 * value.
82 */
83 public void setClasspathRef(Reference r) {
84 createClasspath().setRefid(r);
85 }
86
87 /**
88 * Set the path to use when looking for a file.
89 *
90 * @param filepath a Path instance containing the search path for files.
91 */
92 public void setFilepath(Path filepath) {
93 createFilepath().append(filepath);
94 }
95
96 /**
97 * Path to search for file resources.
98 *
99 * @return a new Path instance which Ant will configure with a file search
100 * path.
101 */
102 public Path createFilepath() {
103 if (this.filepath == null) {
104 this.filepath = new Path(getProject());
105 }
106 return this.filepath.createPath();
107 }
108
109 /**
110 * Set the name of the property which will be set if the particular resource
111 * is available.
112 *
113 * @param property the name of the property to set.
114 */
115 public void setProperty(String property) {
116 this.property = property;
117 }
118
119 /**
120 * Set the value to be given to the property if the desired resource is
121 * available.
122 *
123 * @param value the value to be given.
124 */
125 public void setValue(String value) {
126 this.value = value;
127 }
128
129 /**
130 * Set a classname of a class which must be available to set the given
131 * property.
132 *
133 * @param classname the name of the class required.
134 */
135 public void setClassname(String classname) {
136 if (!"".equals(classname)) {
137 this.classname = classname;
138 }
139 }
140
141 /**
142 * Set the file which must be present in the file system to set the given
143 * property.
144 *
145 * @param file the name of the file which is required.
146 */
147 public void setFile(File file) {
148 this.file = file;
149 this.filename = FILE_UTILS.removeLeadingPath(getProject().getBaseDir(), file);
150 }
151
152 /**
153 * Set the name of a Java resource which is required to set the property.
154 *
155 * @param resource the name of a resource which is required to be available.
156 */
157 public void setResource(String resource) {
158 this.resource = resource;
159 }
160
161 /**
162 * @deprecated setType(String) is deprecated and is replaced with
163 * setType(Available.FileDir) to make Ant's Introspection
164 * mechanism do the work and also to encapsulate operations on
165 * the type in its own class.
166 * @param type the type of resource
167 */
168 public void setType(String type) {
169 log("DEPRECATED - The setType(String) method has been deprecated."
170 + " Use setType(Available.FileDir) instead.",
171 Project.MSG_WARN);
172 this.type = new FileDir();
173 this.type.setValue(type);
174 }
175
176 /**
177 * Set what type of file is required - either directory or file.
178 *
179 * @param type an instance of the FileDir enumeratedAttribute indicating
180 * whether the file required is to be a directory or a plain
181 * file.
182 */
183 public void setType(FileDir type) {
184 this.type = type;
185 }
186
187 /**
188 * Set whether the search for classes should ignore the runtime classes and
189 * just use the given classpath.
190 *
191 * @param ignore true if system classes are to be ignored.
192 */
193 public void setIgnoresystemclasses(boolean ignore) {
194 this.ignoreSystemclasses = ignore;
195 }
196
197 /**
198 * Entry point when operating as a task.
199 *
200 * @exception BuildException if the task is not configured correctly.
201 */
202 public void execute() throws BuildException {
203 if (property == null) {
204 throw new BuildException("property attribute is required",
205 getLocation());
206 }
207
208 isTask = true;
209 try {
210 if (eval()) {
211 String oldvalue = getProject().getProperty(property);
212 if (null != oldvalue && !oldvalue.equals(value)) {
213 log("DEPRECATED - <available> used to override an existing"
214 + " property."
215 + StringUtils.LINE_SEP
216 + " Build file should not reuse the same property"
217 + " name for different values.",
218 Project.MSG_WARN);
219 }
220 // NB: this makes use of Project#setProperty rather than Project#setNewProperty
221 // due to backwards compatiblity reasons
222 getProject().setProperty(property, value);
223 }
224 } finally {
225 isTask = false;
226 }
227 }
228
229 /**
230 * Evaluate the availability of a resource.
231 *
232 * @return boolean is the resource is available.
233 * @exception BuildException if the condition is not configured correctly
234 */
235 public boolean eval() throws BuildException {
236 if (classname == null && file == null && resource == null) {
237 throw new BuildException("At least one of (classname|file|"
238 + "resource) is required", getLocation());
239 }
240 if (type != null) {
241 if (file == null) {
242 throw new BuildException("The type attribute is only valid "
243 + "when specifying the file "
244 + "attribute.", getLocation());
245 }
246 }
247 if (classpath != null) {
248 classpath.setProject(getProject());
249 this.loader = getProject().createClassLoader(classpath);
250 }
251 String appendix = "";
252 if (isTask) {
253 appendix = " to set property " + property;
254 } else {
255 setTaskName("available");
256 }
257 if ((classname != null) && !checkClass(classname)) {
258 log("Unable to load class " + classname + appendix,
259 Project.MSG_VERBOSE);
260 return false;
261 }
262 if ((file != null) && !checkFile()) {
263 StringBuffer buf = new StringBuffer("Unable to find ");
264 if (type != null) {
265 buf.append(type).append(' ');
266 }
267 buf.append(filename).append(appendix);
268 log(buf.toString(), Project.MSG_VERBOSE);
269 return false;
270 }
271 if ((resource != null) && !checkResource(resource)) {
272 log("Unable to load resource " + resource + appendix,
273 Project.MSG_VERBOSE);
274 return false;
275 }
276 if (loader != null) {
277 loader.cleanup();
278 loader = null;
279 }
280 if (!isTask) {
281 setTaskName(null);
282 }
283 return true;
284 }
285
286 /**
287 * Search for file/directory either relative to project's
288 * basedir or in the path given as filepath.
289 *
290 * <p>filepath can be a list of directory and/or file names (gen'd
291 * via <fileset>)</p>
292 *
293 * <p>look for:</p><ul>
294 * <li>full-pathname specified == path in list</li>
295 * <li>full-pathname specified == parent dir of path in list</li>
296 * <li>simple name specified == path in list</li>
297 * <li>simple name specified == path in list + name</li>
298 * <li>simple name specified == parent dir + name</li>
299 * <li>simple name specified == parent of parent dir + name</li>
300 * </ul>
301 */
302 private boolean checkFile() {
303 if (filepath == null) {
304 return checkFile(file, filename);
305 } else {
306 String[] paths = filepath.list();
307 for (int i = 0; i < paths.length; ++i) {
308 log("Searching " + paths[i], Project.MSG_DEBUG);
309 File path = new File(paths[i]);
310
311 // ** full-pathname specified == path in list
312 // ** simple name specified == path in list
313 if (path.exists() && filename.equals(paths[i])) {
314 if (type == null) {
315 log("Found: " + path, Project.MSG_VERBOSE);
316 return true;
317 } else if (type.isDir()
318 && path.isDirectory()) {
319 log("Found directory: " + path, Project.MSG_VERBOSE);
320 return true;
321 } else if (type.isFile()
322 && path.isFile()) {
323 log("Found file: " + path, Project.MSG_VERBOSE);
324 return true;
325 }
326 // not the requested type
327 return false;
328 }
329 File parent = path.getParentFile();
330 // ** full-pathname specified == parent dir of path in list
331 if (parent != null && parent.exists()
332 && filename.equals(parent.getAbsolutePath())) {
333 if (type == null) {
334 log("Found: " + parent, Project.MSG_VERBOSE);
335 return true;
336 } else if (type.isDir()) {
337 log("Found directory: " + parent, Project.MSG_VERBOSE);
338 return true;
339 }
340 // not the requested type
341 return false;
342 }
343 // ** simple name specified == path in list + name
344 if (path.exists() && path.isDirectory()) {
345 if (checkFile(new File(path, filename),
346 filename + " in " + path)) {
347 return true;
348 }
349 }
350 // ** simple name specified == parent dir + name
351 if (parent != null && parent.exists()) {
352 if (checkFile(new File(parent, filename),
353 filename + " in " + parent)) {
354 return true;
355 }
356 }
357 // ** simple name specified == parent of parent dir + name
358 if (parent != null) {
359 File grandParent = parent.getParentFile();
360 if (grandParent != null && grandParent.exists()) {
361 if (checkFile(new File(grandParent, filename),
362 filename + " in " + grandParent)) {
363 return true;
364 }
365 }
366 }
367 }
368 }
369 return false;
370 }
371
372 /**
373 * Check if a given file exists and matches the required type.
374 */
375 private boolean checkFile(File f, String text) {
376 if (type != null) {
377 if (type.isDir()) {
378 if (f.isDirectory()) {
379 log("Found directory: " + text, Project.MSG_VERBOSE);
380 }
381 return f.isDirectory();
382 } else if (type.isFile()) {
383 if (f.isFile()) {
384 log("Found file: " + text, Project.MSG_VERBOSE);
385 }
386 return f.isFile();
387 }
388 }
389 if (f.exists()) {
390 log("Found: " + text, Project.MSG_VERBOSE);
391 }
392 return f.exists();
393 }
394
395 /**
396 * Check if a given resource can be loaded.
397 */
398 private boolean checkResource(String resource) {
399 if (loader != null) {
400 return (loader.getResourceAsStream(resource) != null);
401 } else {
402 ClassLoader cL = this.getClass().getClassLoader();
403 if (cL != null) {
404 return (cL.getResourceAsStream(resource) != null);
405 } else {
406 return
407 (ClassLoader.getSystemResourceAsStream(resource) != null);
408 }
409 }
410 }
411
412 /**
413 * Check if a given class can be loaded.
414 */
415 private boolean checkClass(String classname) {
416 try {
417 Class requiredClass = null;
418 if (ignoreSystemclasses) {
419 loader = getProject().createClassLoader(classpath);
420 loader.setParentFirst(false);
421 loader.addJavaLibraries();
422 if (loader != null) {
423 try {
424 requiredClass = loader.findClass(classname);
425 } catch (SecurityException se) {
426 // class found but restricted name; this is
427 // actually the case we're looking for in JDK 1.3+,
428 // so catch the exception and return
429 return true;
430 }
431 } else {
432 return false;
433 }
434 } else if (loader != null) {
435 requiredClass = loader.loadClass(classname);
436 } else {
437 ClassLoader l = this.getClass().getClassLoader();
438 // Can return null to represent the bootstrap class loader.
439 // see API docs of Class.getClassLoader.
440 if (l != null) {
441 requiredClass = Class.forName(classname, true, l);
442 } else {
443 requiredClass = Class.forName(classname);
444 }
445 }
446 return true;
447 } catch (ClassNotFoundException e) {
448 log("class \"" + classname + "\" was not found",
449 Project.MSG_DEBUG);
450 return false;
451 } catch (NoClassDefFoundError e) {
452 log("Could not load dependent class \"" + e.getMessage()
453 + "\" for class \"" + classname + "\"",
454 Project.MSG_DEBUG);
455 return false;
456 }
457 }
458
459 /**
460 * EnumeratedAttribute covering the file types to be checked for, either
461 * file or dir.
462 */
463 public static class FileDir extends EnumeratedAttribute {
464
465 private static final String[] VALUES = {"file", "dir"};
466
467 /**
468 * @see EnumeratedAttribute#getValues
469 */
470 public String[] getValues() {
471 return VALUES;
472 }
473
474 /**
475 * Indicate if the value specifies a directory.
476 *
477 * @return true if the value specifies a directory.
478 */
479 public boolean isDir() {
480 return "dir".equalsIgnoreCase(getValue());
481 }
482
483 /**
484 * Indicate if the value specifies a file.
485 *
486 * @return true if the value specifies a file.
487 */
488 public boolean isFile() {
489 return "file".equalsIgnoreCase(getValue());
490 }
491
492 }
493}
Note: See TracBrowser for help on using the repository browser.