KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > taskdefs > Available


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.taskdefs;
20
21 import java.io.File JavaDoc;
22 import org.apache.tools.ant.AntClassLoader;
23 import org.apache.tools.ant.BuildException;
24 import org.apache.tools.ant.Project;
25 import org.apache.tools.ant.Task;
26 import org.apache.tools.ant.taskdefs.condition.Condition;
27 import org.apache.tools.ant.types.EnumeratedAttribute;
28 import org.apache.tools.ant.types.Path;
29 import org.apache.tools.ant.types.Reference;
30 import org.apache.tools.ant.util.FileUtils;
31 import org.apache.tools.ant.util.StringUtils;
32
33 /**
34  * Will set the given property if the requested resource is available at
35  * runtime. This task may also be used as a condition by the condition task.
36  *
37  * @since Ant 1.1
38  *
39  * @ant.task category="control"
40  */

41 public class Available extends Task implements Condition {
42     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
43
44     private String JavaDoc property;
45     private String JavaDoc classname;
46     private String JavaDoc filename;
47     private File JavaDoc file;
48     private Path filepath;
49     private String JavaDoc resource;
50     private FileDir type;
51     private Path classpath;
52     private AntClassLoader loader;
53     private String JavaDoc value = "true";
54     private boolean isTask = false;
55     private boolean ignoreSystemclasses = false;
56     private boolean searchParents = false;
57
58     /**
59      * Set the searchParents attribute.
60      * This controls the behaviour of the the "file" type.
61      * If true, the path, parent path and grandparent path are
62      * searched for the file. If false, only the path is seached.
63      * The default value is false.
64      * @param searchParents the value to set.
65      */

66     public void setSearchParents(boolean searchParents) {
67         this.searchParents = searchParents;
68     }
69
70     /**
71      * Set the classpath to be used when searching for classes and resources.
72      *
73      * @param classpath an Ant Path object containing the search path.
74      */

75     public void setClasspath(Path classpath) {
76         createClasspath().append(classpath);
77     }
78
79     /**
80      * Classpath to be used when searching for classes and resources.
81      *
82      * @return an empty Path instance to be configured by Ant.
83      */

84     public Path createClasspath() {
85         if (this.classpath == null) {
86             this.classpath = new Path(getProject());
87         }
88         return this.classpath.createPath();
89     }
90
91     /**
92      * Set the classpath by reference.
93      *
94      * @param r a Reference to a Path instance to be used as the classpath
95      * value.
96      */

97     public void setClasspathRef(Reference r) {
98         createClasspath().setRefid(r);
99     }
100
101     /**
102      * Set the path to use when looking for a file.
103      *
104      * @param filepath a Path instance containing the search path for files.
105      */

106     public void setFilepath(Path filepath) {
107         createFilepath().append(filepath);
108     }
109
110     /**
111      * Path to search for file resources.
112      *
113      * @return a new Path instance which Ant will configure with a file search
114      * path.
115      */

116     public Path createFilepath() {
117         if (this.filepath == null) {
118             this.filepath = new Path(getProject());
119         }
120         return this.filepath.createPath();
121     }
122
123     /**
124      * Set the name of the property which will be set if the particular resource
125      * is available.
126      *
127      * @param property the name of the property to set.
128      */

129     public void setProperty(String JavaDoc property) {
130         this.property = property;
131     }
132
133     /**
134      * Set the value to be given to the property if the desired resource is
135      * available.
136      *
137      * @param value the value to be given.
138      */

139     public void setValue(String JavaDoc value) {
140         this.value = value;
141     }
142
143     /**
144      * Set a classname of a class which must be available to set the given
145      * property.
146      *
147      * @param classname the name of the class required.
148      */

149     public void setClassname(String JavaDoc classname) {
150         if (!"".equals(classname)) {
151             this.classname = classname;
152         }
153     }
154
155     /**
156      * Set the file which must be present in the file system to set the given
157      * property.
158      *
159      * @param file the name of the file which is required.
160      */

161     public void setFile(File JavaDoc file) {
162         this.file = file;
163         this.filename = FILE_UTILS.removeLeadingPath(getProject().getBaseDir(), file);
164     }
165
166     /**
167      * Set the name of a Java resource which is required to set the property.
168      *
169      * @param resource the name of a resource which is required to be available.
170      */

171     public void setResource(String JavaDoc resource) {
172         this.resource = resource;
173     }
174
175     /**
176      * @deprecated since 1.5.x.
177      * setType(String) is deprecated and is replaced with
178      * setType(Available.FileDir) to make Ant's Introspection
179      * mechanism do the work and also to encapsulate operations on
180      * the type in its own class.
181      * @param type the type of resource
182      */

183     public void setType(String JavaDoc type) {
184         log("DEPRECATED - The setType(String) method has been deprecated."
185             + " Use setType(Available.FileDir) instead.",
186             Project.MSG_WARN);
187         this.type = new FileDir();
188         this.type.setValue(type);
189     }
190
191     /**
192      * Set what type of file is required - either directory or file.
193      *
194      * @param type an instance of the FileDir enumeratedAttribute indicating
195      * whether the file required is to be a directory or a plain
196      * file.
197      */

198     public void setType(FileDir type) {
199         this.type = type;
200     }
201
202     /**
203      * Set whether the search for classes should ignore the runtime classes and
204      * just use the given classpath.
205      *
206      * @param ignore true if system classes are to be ignored.
207      */

208     public void setIgnoresystemclasses(boolean ignore) {
209         this.ignoreSystemclasses = ignore;
210     }
211
212     /**
213      * Entry point when operating as a task.
214      *
215      * @exception BuildException if the task is not configured correctly.
216      */

217     public void execute() throws BuildException {
218         if (property == null) {
219             throw new BuildException("property attribute is required",
220                                      getLocation());
221         }
222
223         isTask = true;
224         try {
225             if (eval()) {
226                 String JavaDoc oldvalue = getProject().getProperty(property);
227                 if (null != oldvalue && !oldvalue.equals(value)) {
228                     log("DEPRECATED - <available> used to override an existing"
229                         + " property."
230                         + StringUtils.LINE_SEP
231                         + " Build file should not reuse the same property"
232                         + " name for different values.",
233                         Project.MSG_WARN);
234                 }
235                 // NB: this makes use of Project#setProperty rather than Project#setNewProperty
236
// due to backwards compatiblity reasons
237
getProject().setProperty(property, value);
238             }
239         } finally {
240             isTask = false;
241         }
242     }
243
244     /**
245      * Evaluate the availability of a resource.
246      *
247      * @return boolean is the resource is available.
248      * @exception BuildException if the condition is not configured correctly
249      */

250     public boolean eval() throws BuildException {
251         try {
252             if (classname == null && file == null && resource == null) {
253                 throw new BuildException("At least one of (classname|file|"
254                                          + "resource) is required", getLocation());
255             }
256             if (type != null) {
257                 if (file == null) {
258                     throw new BuildException("The type attribute is only valid "
259                                              + "when specifying the file "
260                                              + "attribute.", getLocation());
261                 }
262             }
263             if (classpath != null) {
264                 classpath.setProject(getProject());
265                 this.loader = getProject().createClassLoader(classpath);
266             }
267             String JavaDoc appendix = "";
268             if (isTask) {
269                 appendix = " to set property " + property;
270             } else {
271                 setTaskName("available");
272             }
273             if ((classname != null) && !checkClass(classname)) {
274                 log("Unable to load class " + classname + appendix,
275                     Project.MSG_VERBOSE);
276                 return false;
277             }
278             if ((file != null) && !checkFile()) {
279                 StringBuffer JavaDoc buf = new StringBuffer JavaDoc("Unable to find ");
280                 if (type != null) {
281                     buf.append(type).append(' ');
282                 }
283                 buf.append(filename).append(appendix);
284                 log(buf.toString(), Project.MSG_VERBOSE);
285                 return false;
286             }
287             if ((resource != null) && !checkResource(resource)) {
288                 log("Unable to load resource " + resource + appendix,
289                     Project.MSG_VERBOSE);
290                 return false;
291             }
292         } finally {
293             if (loader != null) {
294                 loader.cleanup();
295                 loader = null;
296             }
297             if (!isTask) {
298                 setTaskName(null);
299             }
300         }
301         return true;
302     }
303
304     /**
305      * Search for file/directory either relative to project's
306      * basedir or in the path given as filepath.
307      *
308      * <p>filepath can be a list of directory and/or file names (gen'd
309      * via <fileset>)</p>
310      *
311      * <p>look for:</p><ul>
312      * <li>full-pathname specified == path in list</li>
313      * <li>full-pathname specified == parent dir of path in list</li>
314      * <li>simple name specified == path in list</li>
315      * <li>simple name specified == path in list + name</li>
316      * <li>simple name specified == parent dir + name</li>
317      * <li>simple name specified == parent of parent dir + name</li>
318      * </ul>
319      */

320     private boolean checkFile() {
321         if (filepath == null) {
322             return checkFile(file, filename);
323         } else {
324             String JavaDoc[] paths = filepath.list();
325             for (int i = 0; i < paths.length; ++i) {
326                 log("Searching " + paths[i], Project.MSG_DEBUG);
327                 File JavaDoc path = new File JavaDoc(paths[i]);
328
329                 // ** full-pathname specified == path in list
330
// ** simple name specified == path in list
331
if (path.exists() && filename.equals(paths[i])) {
332                     if (type == null) {
333                         log("Found: " + path, Project.MSG_VERBOSE);
334                         return true;
335                     } else if (type.isDir()
336                                && path.isDirectory()) {
337                         log("Found directory: " + path, Project.MSG_VERBOSE);
338                         return true;
339                     } else if (type.isFile()
340                                && path.isFile()) {
341                         log("Found file: " + path, Project.MSG_VERBOSE);
342                         return true;
343                     }
344                     // not the requested type
345
return false;
346                 }
347                 File JavaDoc parent = path.getParentFile();
348                 // ** full-pathname specified == parent dir of path in list
349
if (parent != null && parent.exists()
350                     && filename.equals(parent.getAbsolutePath())) {
351                     if (type == null) {
352                         log("Found: " + parent, Project.MSG_VERBOSE);
353                         return true;
354                     } else if (type.isDir()) {
355                         log("Found directory: " + parent, Project.MSG_VERBOSE);
356                         return true;
357                     }
358                     // not the requested type
359
return false;
360                 }
361                 // ** simple name specified == path in list + name
362
if (path.exists() && path.isDirectory()) {
363                     if (checkFile(new File JavaDoc(path, filename),
364                                   filename + " in " + path)) {
365                         return true;
366                     }
367                 }
368                 // ** simple name specified == parent dir + name
369
while (searchParents && parent != null && parent.exists()) {
370                     if (checkFile(new File JavaDoc(parent, filename),
371                                   filename + " in " + parent)) {
372                         return true;
373                     }
374                     parent = parent.getParentFile();
375                 }
376             }
377         }
378         return false;
379     }
380
381     /**
382      * Check if a given file exists and matches the required type.
383      */

384     private boolean checkFile(File JavaDoc f, String JavaDoc text) {
385         if (type != null) {
386             if (type.isDir()) {
387                 if (f.isDirectory()) {
388                     log("Found directory: " + text, Project.MSG_VERBOSE);
389                 }
390                 return f.isDirectory();
391             } else if (type.isFile()) {
392                 if (f.isFile()) {
393                     log("Found file: " + text, Project.MSG_VERBOSE);
394                 }
395                 return f.isFile();
396             }
397         }
398         if (f.exists()) {
399             log("Found: " + text, Project.MSG_VERBOSE);
400         }
401         return f.exists();
402     }
403
404     /**
405      * Check if a given resource can be loaded.
406      */

407     private boolean checkResource(String JavaDoc resource) {
408         if (loader != null) {
409             return (loader.getResourceAsStream(resource) != null);
410         } else {
411             ClassLoader JavaDoc cL = this.getClass().getClassLoader();
412             if (cL != null) {
413                 return (cL.getResourceAsStream(resource) != null);
414             } else {
415                 return
416                     (ClassLoader.getSystemResourceAsStream(resource) != null);
417             }
418         }
419     }
420
421     /**
422      * Check if a given class can be loaded.
423      */

424     private boolean checkClass(String JavaDoc classname) {
425         try {
426             if (ignoreSystemclasses) {
427                 loader = getProject().createClassLoader(classpath);
428                 loader.setParentFirst(false);
429                 loader.addJavaLibraries();
430                 if (loader != null) {
431                     try {
432                         loader.findClass(classname);
433                     } catch (SecurityException JavaDoc se) {
434                         // class found but restricted name; this is
435
// actually the case we're looking for in JDK 1.3+,
436
// so catch the exception and return
437
return true;
438                     }
439                 } else {
440                     return false;
441                 }
442             } else if (loader != null) {
443                 loader.loadClass(classname);
444             } else {
445                 ClassLoader JavaDoc l = this.getClass().getClassLoader();
446                 // Can return null to represent the bootstrap class loader.
447
// see API docs of Class.getClassLoader.
448
if (l != null) {
449                     Class.forName(classname, true, l);
450                 } else {
451                     Class.forName(classname);
452                 }
453             }
454             return true;
455         } catch (ClassNotFoundException JavaDoc e) {
456             log("class \"" + classname + "\" was not found",
457                 Project.MSG_DEBUG);
458             return false;
459         } catch (NoClassDefFoundError JavaDoc e) {
460             log("Could not load dependent class \"" + e.getMessage()
461                 + "\" for class \"" + classname + "\"",
462                 Project.MSG_DEBUG);
463             return false;
464         }
465     }
466
467     /**
468      * EnumeratedAttribute covering the file types to be checked for, either
469      * file or dir.
470      */

471     public static class FileDir extends EnumeratedAttribute {
472
473         private static final String JavaDoc[] VALUES = {"file", "dir"};
474
475         /**
476          * @see EnumeratedAttribute#getValues
477          */

478         /** {@inheritDoc}. */
479         public String JavaDoc[] getValues() {
480             return VALUES;
481         }
482
483         /**
484          * Indicate if the value specifies a directory.
485          *
486          * @return true if the value specifies a directory.
487          */

488         public boolean isDir() {
489             return "dir".equalsIgnoreCase(getValue());
490         }
491
492         /**
493          * Indicate if the value specifies a file.
494          *
495          * @return true if the value specifies a file.
496          */

497         public boolean isFile() {
498             return "file".equalsIgnoreCase(getValue());
499         }
500
501     }
502 }
503
Popular Tags