KickJava   Java API By Example, From Geeks To Geeks.

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


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 java.io.FileInputStream JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.io.InputStream JavaDoc;
25 import java.net.URL JavaDoc;
26 import java.util.Enumeration JavaDoc;
27 import java.util.Properties JavaDoc;
28 import java.util.Stack JavaDoc;
29 import java.util.Vector JavaDoc;
30
31 import org.apache.tools.ant.BuildException;
32 import org.apache.tools.ant.Project;
33 import org.apache.tools.ant.PropertyHelper;
34 import org.apache.tools.ant.Task;
35 import org.apache.tools.ant.types.Path;
36 import org.apache.tools.ant.types.Reference;
37
38 /**
39  * Sets a property by name, or set of properties (from file or
40  * resource) in the project. </p>
41  * Properties are immutable: whoever sets a property first freezes it for the
42  * rest of the build; they are most definitely not variable.
43  * <p>There are five ways to set properties:</p>
44  * <ul>
45  * <li>By supplying both the <i>name</i> and <i>value</i> attribute.</li>
46  * <li>By supplying both the <i>name</i> and <i>refid</i> attribute.</li>
47  * <li>By setting the <i>file</i> attribute with the filename of the property
48  * file to load. This property file has the format as defined by the file used
49  * in the class java.util.Properties.</li>
50  * <li>By setting the <i>resource</i> attribute with the resource name of the
51  * property file to load. This property file has the format as defined by the
52  * file used in the class java.util.Properties.</li>
53  * <li>By setting the <i>environment</i> attribute with a prefix to use.
54  * Properties will be defined for every environment variable by
55  * prefixing the supplied name and a period to the name of the variable.</li>
56  * </ul>
57  * <p>Although combinations of these ways are possible, only one should be used
58  * at a time. Problems might occur with the order in which properties are set, for
59  * instance.</p>
60  * <p>The value part of the properties being set, might contain references to other
61  * properties. These references are resolved at the time these properties are set.
62  * This also holds for properties loaded from a property file.</p>
63  * Properties are case sensitive.
64  *
65  * @since Ant 1.1
66  *
67  * @ant.attribute.group name="name" description="One of these, when using the name attribute"
68  * @ant.attribute.group name="noname" description="One of these, when not using the name attribute"
69  * @ant.task category="property"
70  */

71 public class Property extends Task {
72
73     // CheckStyle:VisibilityModifier OFF - bc
74
protected String JavaDoc name;
75     protected String JavaDoc value;
76     protected File JavaDoc file;
77     protected URL JavaDoc url;
78     protected String JavaDoc resource;
79     protected Path classpath;
80     protected String JavaDoc env;
81     protected Reference ref;
82     protected String JavaDoc prefix;
83     private Project fallback;
84
85     protected boolean userProperty; // set read-only properties
86
// CheckStyle:VisibilityModifier ON
87

88     /**
89      * Constructor for Property.
90      */

91     public Property() {
92         this(false);
93     }
94
95     /**
96      * Constructor for Property.
97      * @param userProperty if true this is a user property
98      * @since Ant 1.5
99      */

100     protected Property(boolean userProperty) {
101         this(userProperty, null);
102     }
103
104     /**
105      * Constructor for Property.
106      * @param userProperty if true this is a user property
107      * @param fallback a project to use to look for references if the reference is
108      * not in the current project
109      * @since Ant 1.5
110      */

111     protected Property(boolean userProperty, Project fallback) {
112         this.userProperty = userProperty;
113         this.fallback = fallback;
114     }
115
116     /**
117      * The name of the property to set.
118      * @param name property name
119      */

120     public void setName(String JavaDoc name) {
121         this.name = name;
122     }
123
124     /**
125      * Get the property name.
126      * @return the property name
127      */

128     public String JavaDoc getName() {
129         return name;
130     }
131
132     /**
133      * Sets the property to the absolute filename of the
134      * given file. If the value of this attribute is an absolute path, it
135      * is left unchanged (with / and \ characters converted to the
136      * current platforms conventions). Otherwise it is taken as a path
137      * relative to the project's basedir and expanded.
138      * @param location path to set
139      *
140      * @ant.attribute group="name"
141      */

142     public void setLocation(File JavaDoc location) {
143         setValue(location.getAbsolutePath());
144     }
145
146     /**
147      * The value of the property.
148      * @param value value to assign
149      *
150      * @ant.attribute group="name"
151      */

152     public void setValue(String JavaDoc value) {
153         this.value = value;
154     }
155
156     /**
157      * Get the property value.
158      * @return the property value
159      */

160     public String JavaDoc getValue() {
161         return value;
162     }
163
164     /**
165      * Filename of a property file to load.
166      * @param file filename
167      *
168      * @ant.attribute group="noname"
169      */

170     public void setFile(File JavaDoc file) {
171         this.file = file;
172     }
173
174     /**
175      * Get the file attribute.
176      * @return the file attribute
177      */

178     public File JavaDoc getFile() {
179         return file;
180     }
181
182     /**
183      * The url from which to load properties.
184      * @param url url string
185      *
186      * @ant.attribute group="noname"
187      */

188     public void setUrl(URL JavaDoc url) {
189         this.url = url;
190     }
191
192     /**
193      * Get the url attribute.
194      * @return the url attribute
195      */

196     public URL JavaDoc getUrl() {
197         return url;
198     }
199
200     /**
201      * Prefix to apply to properties loaded using <code>file</code>
202      * or <code>resource</code>.
203      * A "." is appended to the prefix if not specified.
204      * @param prefix prefix string
205      * @since Ant 1.5
206      */

207     public void setPrefix(String JavaDoc prefix) {
208         this.prefix = prefix;
209         if (!prefix.endsWith(".")) {
210             this.prefix += ".";
211         }
212     }
213
214     /**
215      * Get the prefix attribute.
216      * @return the prefix attribute
217      * @since Ant 1.5
218      */

219     public String JavaDoc getPrefix() {
220         return prefix;
221     }
222
223     /**
224      * Sets a reference to an Ant datatype
225      * declared elsewhere.
226      * Only yields reasonable results for references
227      * PATH like structures or properties.
228      * @param ref reference
229      *
230      * @ant.attribute group="name"
231      */

232     public void setRefid(Reference ref) {
233         this.ref = ref;
234     }
235
236     /**
237      * Get the refid attribute.
238      * @return the refid attribute
239      */

240     public Reference getRefid() {
241         return ref;
242     }
243
244     /**
245      * The resource name of a property file to load
246      * @param resource resource on classpath
247      *
248      * @ant.attribute group="noname"
249      */

250     public void setResource(String JavaDoc resource) {
251         this.resource = resource;
252     }
253
254     /**
255      * Get the resource attribute.
256      * @return the resource attribute
257      */

258     public String JavaDoc getResource() {
259         return resource;
260     }
261
262     /**
263      * Prefix to use when retrieving environment variables.
264      * Thus if you specify environment=&quot;myenv&quot;
265      * you will be able to access OS-specific
266      * environment variables via property names &quot;myenv.PATH&quot; or
267      * &quot;myenv.TERM&quot;.
268      * <p>
269      * Note that if you supply a property name with a final
270      * &quot;.&quot; it will not be doubled. ie environment=&quot;myenv.&quot; will still
271      * allow access of environment variables through &quot;myenv.PATH&quot; and
272      * &quot;myenv.TERM&quot;. This functionality is currently only implemented
273      * on select platforms. Feel free to send patches to increase the number of platforms
274      * this functionality is supported on ;).<br>
275      * Note also that properties are case sensitive, even if the
276      * environment variables on your operating system are not, e.g. it
277      * will be ${env.Path} not ${env.PATH} on Windows 2000.
278      * @param env prefix
279      *
280      * @ant.attribute group="noname"
281      */

282     public void setEnvironment(String JavaDoc env) {
283         this.env = env;
284     }
285
286     /**
287      * Get the environment attribute.
288      * @return the environment attribute
289      * @since Ant 1.5
290      */

291     public String JavaDoc getEnvironment() {
292         return env;
293     }
294
295     /**
296      * The classpath to use when looking up a resource.
297      * @param classpath to add to any existing classpath
298      */

299     public void setClasspath(Path classpath) {
300         if (this.classpath == null) {
301             this.classpath = classpath;
302         } else {
303             this.classpath.append(classpath);
304         }
305     }
306
307     /**
308      * The classpath to use when looking up a resource.
309      * @return a path to be configured
310      */

311     public Path createClasspath() {
312         if (this.classpath == null) {
313             this.classpath = new Path(getProject());
314         }
315         return this.classpath.createPath();
316     }
317
318     /**
319      * the classpath to use when looking up a resource,
320      * given as reference to a &lt;path&gt; defined elsewhere
321      * @param r a reference to a classpath
322      */

323     public void setClasspathRef(Reference r) {
324         createClasspath().setRefid(r);
325     }
326
327     /**
328      * Get the classpath used when looking up a resource.
329      * @return the classpath
330      * @since Ant 1.5
331      */

332     public Path getClasspath() {
333         return classpath;
334     }
335
336     /**
337      * @param userProperty ignored
338      * @deprecated since 1.5.x.
339      * This was never a supported feature and has been
340      * deprecated without replacement.
341      * @ant.attribute ignore="true"
342      */

343     public void setUserProperty(boolean userProperty) {
344         log("DEPRECATED: Ignoring request to set user property in Property"
345             + " task.", Project.MSG_WARN);
346     }
347
348     /**
349      * get the value of this property
350      * @return the current value or the empty string
351      */

352     public String JavaDoc toString() {
353         return value == null ? "" : value;
354     }
355
356     /**
357      * set the property in the project to the value.
358      * if the task was give a file, resource or env attribute
359      * here is where it is loaded
360      * @throws BuildException on error
361      */

362     public void execute() throws BuildException {
363         if (getProject() == null) {
364             throw new IllegalStateException JavaDoc("project has not been set");
365         }
366
367         if (name != null) {
368             if (value == null && ref == null) {
369                 throw new BuildException("You must specify value, location or "
370                                          + "refid with the name attribute",
371                                          getLocation());
372             }
373         } else {
374             if (url == null && file == null && resource == null && env == null) {
375                 throw new BuildException("You must specify url, file, resource or "
376                                          + "environment when not using the "
377                                          + "name attribute", getLocation());
378             }
379         }
380
381         if (url == null && file == null && resource == null && prefix != null) {
382             throw new BuildException("Prefix is only valid when loading from "
383                                      + "a url, file or resource", getLocation());
384         }
385
386         if ((name != null) && (value != null)) {
387             addProperty(name, value);
388         }
389
390         if (file != null) {
391             loadFile(file);
392         }
393
394         if (url != null) {
395             loadUrl(url);
396         }
397
398         if (resource != null) {
399             loadResource(resource);
400         }
401
402         if (env != null) {
403             loadEnvironment(env);
404         }
405
406         if ((name != null) && (ref != null)) {
407             try {
408                 addProperty(name,
409                             ref.getReferencedObject(getProject()).toString());
410             } catch (BuildException be) {
411                 if (fallback != null) {
412                     addProperty(name,
413                                 ref.getReferencedObject(fallback).toString());
414                 } else {
415                     throw be;
416                 }
417             }
418         }
419     }
420
421     /**
422      * load properties from a url
423      * @param url url to load from
424      * @throws BuildException on error
425      */

426     protected void loadUrl(URL JavaDoc url) throws BuildException {
427         Properties JavaDoc props = new Properties JavaDoc();
428         log("Loading " + url, Project.MSG_VERBOSE);
429         try {
430             InputStream JavaDoc is = url.openStream();
431             try {
432                 props.load(is);
433             } finally {
434                 if (is != null) {
435                     is.close();
436                 }
437             }
438             addProperties(props);
439         } catch (IOException JavaDoc ex) {
440             throw new BuildException(ex, getLocation());
441         }
442     }
443
444
445     /**
446      * load properties from a file
447      * @param file file to load
448      * @throws BuildException on error
449      */

450     protected void loadFile(File JavaDoc file) throws BuildException {
451         Properties JavaDoc props = new Properties JavaDoc();
452         log("Loading " + file.getAbsolutePath(), Project.MSG_VERBOSE);
453         try {
454             if (file.exists()) {
455                 FileInputStream JavaDoc fis = new FileInputStream JavaDoc(file);
456                 try {
457                     props.load(fis);
458                 } finally {
459                     if (fis != null) {
460                         fis.close();
461                     }
462                 }
463                 addProperties(props);
464             } else {
465                 log("Unable to find property file: " + file.getAbsolutePath(),
466                     Project.MSG_VERBOSE);
467             }
468         } catch (IOException JavaDoc ex) {
469             throw new BuildException(ex, getLocation());
470         }
471     }
472
473     /**
474      * load properties from a resource in the current classpath
475      * @param name name of resource to load
476      */

477     protected void loadResource(String JavaDoc name) {
478         Properties JavaDoc props = new Properties JavaDoc();
479         log("Resource Loading " + name, Project.MSG_VERBOSE);
480         InputStream JavaDoc is = null;
481         try {
482             ClassLoader JavaDoc cL = null;
483
484             if (classpath != null) {
485                 cL = getProject().createClassLoader(classpath);
486             } else {
487                 cL = this.getClass().getClassLoader();
488             }
489
490             if (cL == null) {
491                 is = ClassLoader.getSystemResourceAsStream(name);
492             } else {
493                 is = cL.getResourceAsStream(name);
494             }
495
496             if (is != null) {
497                 props.load(is);
498                 addProperties(props);
499             } else {
500                 log("Unable to find resource " + name, Project.MSG_WARN);
501             }
502         } catch (IOException JavaDoc ex) {
503             throw new BuildException(ex, getLocation());
504         } finally {
505             if (is != null) {
506                 try {
507                     is.close();
508                 } catch (IOException JavaDoc e) {
509                     // ignore
510
}
511             }
512         }
513
514     }
515
516     /**
517      * load the environment values
518      * @param prefix prefix to place before them
519      */

520     protected void loadEnvironment(String JavaDoc prefix) {
521         Properties JavaDoc props = new Properties JavaDoc();
522         if (!prefix.endsWith(".")) {
523             prefix += ".";
524         }
525         log("Loading Environment " + prefix, Project.MSG_VERBOSE);
526         Vector JavaDoc osEnv = Execute.getProcEnvironment();
527         for (Enumeration JavaDoc e = osEnv.elements(); e.hasMoreElements();) {
528             String JavaDoc entry = (String JavaDoc) e.nextElement();
529             int pos = entry.indexOf('=');
530             if (pos == -1) {
531                 log("Ignoring: " + entry, Project.MSG_WARN);
532             } else {
533                 props.put(prefix + entry.substring(0, pos),
534                 entry.substring(pos + 1));
535             }
536         }
537         addProperties(props);
538     }
539
540     /**
541      * iterate through a set of properties,
542      * resolve them then assign them
543      * @param props the properties to iterate over
544      */

545     protected void addProperties(Properties JavaDoc props) {
546         resolveAllProperties(props);
547         Enumeration JavaDoc e = props.keys();
548         while (e.hasMoreElements()) {
549             String JavaDoc propertyName = (String JavaDoc) e.nextElement();
550             String JavaDoc propertyValue = props.getProperty(propertyName);
551
552             String JavaDoc v = getProject().replaceProperties(propertyValue);
553
554             if (prefix != null) {
555                 propertyName = prefix + propertyName;
556             }
557
558             addProperty(propertyName, v);
559         }
560     }
561
562     /**
563      * add a name value pair to the project property set
564      * @param n name of property
565      * @param v value to set
566      */

567     protected void addProperty(String JavaDoc n, String JavaDoc v) {
568         if (userProperty) {
569             if (getProject().getUserProperty(n) == null) {
570                 getProject().setInheritedProperty(n, v);
571             } else {
572                 log("Override ignored for " + n, Project.MSG_VERBOSE);
573             }
574         } else {
575             getProject().setNewProperty(n, v);
576         }
577     }
578
579     /**
580      * resolve properties inside a properties hashtable
581      * @param props properties object to resolve
582      */

583     private void resolveAllProperties(Properties JavaDoc props) throws BuildException {
584         for (Enumeration JavaDoc e = props.keys(); e.hasMoreElements();) {
585             String JavaDoc propertyName = (String JavaDoc) e.nextElement();
586             Stack JavaDoc referencesSeen = new Stack JavaDoc();
587             resolve(props, propertyName, referencesSeen);
588         }
589     }
590
591     /**
592      * Recursively expand the named property using the project's
593      * reference table and the given set of properties - fail if a
594      * circular definition is detected.
595      *
596      * @param props properties object to resolve
597      * @param name of the property to resolve
598      * @param referencesSeen stack of all property names that have
599      * been tried to expand before coming here.
600      */

601     private void resolve(Properties JavaDoc props, String JavaDoc name, Stack JavaDoc referencesSeen)
602         throws BuildException {
603         if (referencesSeen.contains(name)) {
604             throw new BuildException("Property " + name + " was circularly "
605                                      + "defined.");
606         }
607
608         String JavaDoc propertyValue = props.getProperty(name);
609         Vector JavaDoc fragments = new Vector JavaDoc();
610         Vector JavaDoc propertyRefs = new Vector JavaDoc();
611         PropertyHelper.getPropertyHelper(
612             this.getProject()).parsePropertyString(
613                 propertyValue, fragments, propertyRefs);
614
615         if (propertyRefs.size() != 0) {
616             referencesSeen.push(name);
617             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
618             Enumeration JavaDoc i = fragments.elements();
619             Enumeration JavaDoc j = propertyRefs.elements();
620             while (i.hasMoreElements()) {
621                 String JavaDoc fragment = (String JavaDoc) i.nextElement();
622                 if (fragment == null) {
623                     String JavaDoc propertyName = (String JavaDoc) j.nextElement();
624                     fragment = getProject().getProperty(propertyName);
625                     if (fragment == null) {
626                         if (props.containsKey(propertyName)) {
627                             resolve(props, propertyName, referencesSeen);
628                             fragment = props.getProperty(propertyName);
629                         } else {
630                             fragment = "${" + propertyName + "}";
631                         }
632                     }
633                 }
634                 sb.append(fragment);
635             }
636             propertyValue = sb.toString();
637             props.put(name, propertyValue);
638             referencesSeen.pop();
639         }
640     }
641 }
642
Popular Tags