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

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

initial import of LiRK3

File size: 18.4 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.taskdefs;
19
20import java.io.File;
21import java.io.FileInputStream;
22import java.io.IOException;
23import java.io.InputStream;
24import java.net.URL;
25import java.util.Enumeration;
26import java.util.Properties;
27import java.util.Stack;
28import java.util.Vector;
29import org.apache.tools.ant.BuildException;
30import org.apache.tools.ant.Project;
31import org.apache.tools.ant.ProjectHelper;
32import org.apache.tools.ant.Task;
33import org.apache.tools.ant.types.Path;
34import org.apache.tools.ant.types.Reference;
35
36/**
37 * Sets a property by name, or set of properties (from file or
38 * resource) in the project. </p>
39 * Properties are immutable: whoever sets a property first freezes it for the
40 * rest of the build; they are most definitely not variable.
41 * <p>There are five ways to set properties:</p>
42 * <ul>
43 * <li>By supplying both the <i>name</i> and <i>value</i> attribute.</li>
44 * <li>By supplying both the <i>name</i> and <i>refid</i> attribute.</li>
45 * <li>By setting the <i>file</i> attribute with the filename of the property
46 * file to load. This property file has the format as defined by the file used
47 * in the class java.util.Properties.</li>
48 * <li>By setting the <i>resource</i> attribute with the resource name of the
49 * property file to load. This property file has the format as defined by the
50 * file used in the class java.util.Properties.</li>
51 * <li>By setting the <i>environment</i> attribute with a prefix to use.
52 * Properties will be defined for every environment variable by
53 * prefixing the supplied name and a period to the name of the variable.</li>
54 * </ul>
55 * <p>Although combinations of these ways are possible, only one should be used
56 * at a time. Problems might occur with the order in which properties are set, for
57 * instance.</p>
58 * <p>The value part of the properties being set, might contain references to other
59 * properties. These references are resolved at the time these properties are set.
60 * This also holds for properties loaded from a property file.</p>
61 * Properties are case sensitive.
62 *
63 * @since Ant 1.1
64 *
65 * @ant.attribute.group name="name" description="One of these, when using the name attribute"
66 * @ant.attribute.group name="noname" description="One of these, when not using the name attribute"
67 */
68public class Property extends Task {
69
70 protected String name;
71 protected String value;
72 protected File file;
73 protected URL url;
74 protected String resource;
75 protected Path classpath;
76 protected String env;
77 protected Reference ref;
78 protected String prefix;
79 private Project fallback;
80
81 protected boolean userProperty; // set read-only properties
82
83 public Property() {
84 this(false);
85 }
86
87 /**
88 * @since Ant 1.5
89 */
90 protected Property(boolean userProperty) {
91 this(userProperty, null);
92 }
93
94 /**
95 * @since Ant 1.5
96 */
97 protected Property(boolean userProperty, Project fallback) {
98 this.userProperty = userProperty;
99 this.fallback = fallback;
100 }
101
102 /**
103 * The name of the property to set.
104 * @param name property name
105 */
106 public void setName(String name) {
107 this.name = name;
108 }
109
110 public String getName() {
111 return name;
112 }
113
114 /**
115 * Sets the property to the absolute filename of the
116 * given file. If the value of this attribute is an absolute path, it
117 * is left unchanged (with / and \ characters converted to the
118 * current platforms conventions). Otherwise it is taken as a path
119 * relative to the project's basedir and expanded.
120 * @param location path to set
121 *
122 * @ant.attribute group="name"
123 */
124 public void setLocation(File location) {
125 setValue(location.getAbsolutePath());
126 }
127
128 /**
129 * The value of the property.
130 * @param value value to assign
131 *
132 * @ant.attribute group="name"
133 */
134 public void setValue(String value) {
135 this.value = value;
136 }
137
138 public String getValue() {
139 return value;
140 }
141
142 /**
143 * Filename of a property file to load.
144 * @param file filename
145 *
146 * @ant.attribute group="noname"
147 */
148 public void setFile(File file) {
149 this.file = file;
150 }
151
152 public File getFile() {
153 return file;
154 }
155
156 /**
157 * The url from which to load properties.
158 * @param url url string
159 *
160 * @ant.attribute group="noname"
161 */
162 public void setUrl(URL url) {
163 this.url = url;
164 }
165
166 public URL getUrl() {
167 return url;
168 }
169
170 /**
171 * Prefix to apply to properties loaded using <code>file</code>
172 * or <code>resource</code>.
173 * A "." is appended to the prefix if not specified.
174 * @param prefix prefix string
175 * @since Ant 1.5
176 */
177 public void setPrefix(String prefix) {
178 this.prefix = prefix;
179 if (!prefix.endsWith(".")) {
180 this.prefix += ".";
181 }
182 }
183
184 /**
185 * @since Ant 1.5
186 */
187 public String getPrefix() {
188 return prefix;
189 }
190
191 /**
192 * Sets a reference to an Ant datatype
193 * declared elsewhere.
194 * Only yields reasonable results for references
195 * PATH like structures or properties.
196 * @param ref reference
197 *
198 * @ant.attribute group="name"
199 */
200 public void setRefid(Reference ref) {
201 this.ref = ref;
202 }
203
204 public Reference getRefid() {
205 return ref;
206 }
207
208 /**
209 * The resource name of a property file to load
210 * @param resource resource on classpath
211 *
212 * @ant.attribute group="noname"
213 */
214 public void setResource(String resource) {
215 this.resource = resource;
216 }
217
218 public String getResource() {
219 return resource;
220 }
221
222 /**
223 * Prefix to use when retrieving environment variables.
224 * Thus if you specify environment=&quot;myenv&quot;
225 * you will be able to access OS-specific
226 * environment variables via property names &quot;myenv.PATH&quot; or
227 * &quot;myenv.TERM&quot;.
228 * <p>
229 * Note that if you supply a property name with a final
230 * &quot;.&quot; it will not be doubled. ie environment=&quot;myenv.&quot; will still
231 * allow access of environment variables through &quot;myenv.PATH&quot; and
232 * &quot;myenv.TERM&quot;. This functionality is currently only implemented
233 * on select platforms. Feel free to send patches to increase the number of platforms
234 * this functionality is supported on ;).<br>
235 * Note also that properties are case sensitive, even if the
236 * environment variables on your operating system are not, e.g. it
237 * will be ${env.Path} not ${env.PATH} on Windows 2000.
238 * @param env prefix
239 *
240 * @ant.attribute group="noname"
241 */
242 public void setEnvironment(String env) {
243 this.env = env;
244 }
245
246 /**
247 * @since Ant 1.5
248 */
249 public String getEnvironment() {
250 return env;
251 }
252
253 /**
254 * The classpath to use when looking up a resource.
255 * @param classpath to add to any existing classpath
256 */
257 public void setClasspath(Path classpath) {
258 if (this.classpath == null) {
259 this.classpath = classpath;
260 } else {
261 this.classpath.append(classpath);
262 }
263 }
264
265 /**
266 * The classpath to use when looking up a resource.
267 */
268 public Path createClasspath() {
269 if (this.classpath == null) {
270 this.classpath = new Path(getProject());
271 }
272 return this.classpath.createPath();
273 }
274
275 /**
276 * the classpath to use when looking up a resource,
277 * given as reference to a &lt;path&gt; defined elsewhere
278 */
279 public void setClasspathRef(Reference r) {
280 createClasspath().setRefid(r);
281 }
282
283 /**
284 * @since Ant 1.5
285 */
286 public Path getClasspath() {
287 return classpath;
288 }
289
290 /**
291 * @deprecated This was never a supported feature and has been
292 * deprecated without replacement
293 * @ant.attribute ignore="true"
294 */
295 public void setUserProperty(boolean userProperty) {
296 log("DEPRECATED: Ignoring request to set user property in Property"
297 + " task.", Project.MSG_WARN);
298 }
299
300 /**
301 * get the value of this property
302 * @return the current value or the empty string
303 */
304 public String toString() {
305 return value == null ? "" : value;
306 }
307
308 /**
309 * set the property in the project to the value.
310 * if the task was give a file, resource or env attribute
311 * here is where it is loaded
312 */
313 public void execute() throws BuildException {
314 if (getProject() == null) {
315 throw new IllegalStateException("project has not been set");
316 }
317
318 if (name != null) {
319 if (value == null && ref == null) {
320 throw new BuildException("You must specify value, location or "
321 + "refid with the name attribute",
322 getLocation());
323 }
324 } else {
325 if (url == null && file == null && resource == null && env == null) {
326 throw new BuildException("You must specify url, file, resource or "
327 + "environment when not using the "
328 + "name attribute", getLocation());
329 }
330 }
331
332 if (url == null && file == null && resource == null && prefix != null) {
333 throw new BuildException("Prefix is only valid when loading from "
334 + "a url, file or resource", getLocation());
335 }
336
337 if ((name != null) && (value != null)) {
338 addProperty(name, value);
339 }
340
341 if (file != null) {
342 loadFile(file);
343 }
344
345 if (url != null) {
346 loadUrl(url);
347 }
348
349 if (resource != null) {
350 loadResource(resource);
351 }
352
353 if (env != null) {
354 loadEnvironment(env);
355 }
356
357 if ((name != null) && (ref != null)) {
358 try {
359 addProperty(name,
360 ref.getReferencedObject(getProject()).toString());
361 } catch (BuildException be) {
362 if (fallback != null) {
363 addProperty(name,
364 ref.getReferencedObject(fallback).toString());
365 } else {
366 throw be;
367 }
368 }
369 }
370 }
371
372 /**
373 * load properties from a url
374 * @param url url to load from
375 */
376 protected void loadUrl(URL url) throws BuildException {
377 Properties props = new Properties();
378 log("Loading " + url, Project.MSG_VERBOSE);
379 try {
380 InputStream is = url.openStream();
381 try {
382 props.load(is);
383 } finally {
384 if (is != null) {
385 is.close();
386 }
387 }
388 addProperties(props);
389 } catch (IOException ex) {
390 throw new BuildException(ex, getLocation());
391 }
392 }
393
394
395 /**
396 * load properties from a file
397 * @param file file to load
398 */
399 protected void loadFile(File file) throws BuildException {
400 Properties props = new Properties();
401 log("Loading " + file.getAbsolutePath(), Project.MSG_VERBOSE);
402 try {
403 if (file.exists()) {
404 FileInputStream fis = new FileInputStream(file);
405 try {
406 props.load(fis);
407 } finally {
408 if (fis != null) {
409 fis.close();
410 }
411 }
412 addProperties(props);
413 } else {
414 log("Unable to find property file: " + file.getAbsolutePath(),
415 Project.MSG_VERBOSE);
416 }
417 } catch (IOException ex) {
418 throw new BuildException(ex, getLocation());
419 }
420 }
421
422 /**
423 * load properties from a resource in the current classpath
424 * @param name name of resource to load
425 */
426 protected void loadResource(String name) {
427 Properties props = new Properties();
428 log("Resource Loading " + name, Project.MSG_VERBOSE);
429 InputStream is = null;
430 try {
431 ClassLoader cL = null;
432
433 if (classpath != null) {
434 cL = getProject().createClassLoader(classpath);
435 } else {
436 cL = this.getClass().getClassLoader();
437 }
438
439 if (cL == null) {
440 is = ClassLoader.getSystemResourceAsStream(name);
441 } else {
442 is = cL.getResourceAsStream(name);
443 }
444
445 if (is != null) {
446 props.load(is);
447 addProperties(props);
448 } else {
449 log("Unable to find resource " + name, Project.MSG_WARN);
450 }
451 } catch (IOException ex) {
452 throw new BuildException(ex, getLocation());
453 } finally {
454 if (is != null) {
455 try {
456 is.close();
457 } catch (IOException e) {
458 // ignore
459 }
460 }
461 }
462
463 }
464
465 /**
466 * load the environment values
467 * @param prefix prefix to place before them
468 */
469 protected void loadEnvironment(String prefix) {
470 Properties props = new Properties();
471 if (!prefix.endsWith(".")) {
472 prefix += ".";
473 }
474 log("Loading Environment " + prefix, Project.MSG_VERBOSE);
475 Vector osEnv = Execute.getProcEnvironment();
476 for (Enumeration e = osEnv.elements(); e.hasMoreElements();) {
477 String entry = (String) e.nextElement();
478 int pos = entry.indexOf('=');
479 if (pos == -1) {
480 log("Ignoring: " + entry, Project.MSG_WARN);
481 } else {
482 props.put(prefix + entry.substring(0, pos),
483 entry.substring(pos + 1));
484 }
485 }
486 addProperties(props);
487 }
488
489 /**
490 * iterate through a set of properties,
491 * resolve them then assign them
492 */
493 protected void addProperties(Properties props) {
494 resolveAllProperties(props);
495 Enumeration e = props.keys();
496 while (e.hasMoreElements()) {
497 String name = (String) e.nextElement();
498 String value = props.getProperty(name);
499
500 String v = getProject().replaceProperties(value);
501
502 if (prefix != null) {
503 name = prefix + name;
504 }
505
506 addProperty(name, v);
507 }
508 }
509
510 /**
511 * add a name value pair to the project property set
512 * @param n name of property
513 * @param v value to set
514 */
515 protected void addProperty(String n, String v) {
516 if (userProperty) {
517 if (getProject().getUserProperty(n) == null) {
518 getProject().setInheritedProperty(n, v);
519 } else {
520 log("Override ignored for " + n, Project.MSG_VERBOSE);
521 }
522 } else {
523 getProject().setNewProperty(n, v);
524 }
525 }
526
527 /**
528 * resolve properties inside a properties hashtable
529 * @param props properties object to resolve
530 */
531 private void resolveAllProperties(Properties props) throws BuildException {
532 for (Enumeration e = props.keys(); e.hasMoreElements();) {
533 String name = (String) e.nextElement();
534 Stack referencesSeen = new Stack();
535 resolve(props, name, referencesSeen);
536 }
537 }
538
539 /**
540 * Recursively expand the named property using the project's
541 * reference table and the given set of properties - fail if a
542 * circular definition is detected.
543 *
544 * @param props properties object to resolve
545 * @param name of the property to resolve
546 * @param referencesSeen stack of all property names that have
547 * been tried to expand before coming here.
548 */
549 private void resolve(Properties props, String name, Stack referencesSeen)
550 throws BuildException {
551 if (referencesSeen.contains(name)) {
552 throw new BuildException("Property " + name + " was circularly "
553 + "defined.");
554 }
555
556 String value = props.getProperty(name);
557 Vector fragments = new Vector();
558 Vector propertyRefs = new Vector();
559 ProjectHelper.parsePropertyString(value, fragments, propertyRefs);
560
561 if (propertyRefs.size() != 0) {
562 referencesSeen.push(name);
563 StringBuffer sb = new StringBuffer();
564 Enumeration i = fragments.elements();
565 Enumeration j = propertyRefs.elements();
566 while (i.hasMoreElements()) {
567 String fragment = (String) i.nextElement();
568 if (fragment == null) {
569 String propertyName = (String) j.nextElement();
570 fragment = getProject().getProperty(propertyName);
571 if (fragment == null) {
572 if (props.containsKey(propertyName)) {
573 resolve(props, propertyName, referencesSeen);
574 fragment = props.getProperty(propertyName);
575 } else {
576 fragment = "${" + propertyName + "}";
577 }
578 }
579 }
580 sb.append(fragment);
581 }
582 value = sb.toString();
583 props.put(name, value);
584 referencesSeen.pop();
585 }
586 }
587}
Note: See TracBrowser for help on using the repository browser.