KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > types > PropertySet


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.types;
20
21 import java.util.Enumeration JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.Map JavaDoc;
24 import java.util.HashSet JavaDoc;
25 import java.util.Set JavaDoc;
26 import java.util.TreeMap JavaDoc;
27 import java.util.Hashtable JavaDoc;
28 import java.util.Properties 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.types.resources.PropertyResource;
34 import org.apache.tools.ant.util.FileNameMapper;
35 import org.apache.tools.ant.util.regexp.RegexpMatcher;
36 import org.apache.tools.ant.util.regexp.RegexpMatcherFactory;
37
38 /**
39  * A set of properties.
40  *
41  * @since Ant 1.6
42  */

43 public class PropertySet extends DataType implements ResourceCollection {
44
45     private boolean dynamic = true;
46     private boolean negate = false;
47     private Set JavaDoc cachedNames;
48     private Vector JavaDoc ptyRefs = new Vector JavaDoc();
49     private Vector JavaDoc setRefs = new Vector JavaDoc();
50     private Mapper mapper;
51
52     /**
53      * This is a nested class containing a reference to some properties
54      * and optionally a source of properties.
55      */

56     public static class PropertyRef {
57
58         private int count;
59         private String JavaDoc name;
60         private String JavaDoc regex;
61         private String JavaDoc prefix;
62         private String JavaDoc builtin;
63
64         /**
65          * Set the name.
66          * @param name a <code>String</code> value.
67          */

68         public void setName(String JavaDoc name) {
69             assertValid("name", name);
70             this.name = name;
71         }
72
73         /**
74          * Set the regular expression to use to filter the properties.
75          * @param regex a regular expression.
76          */

77         public void setRegex(String JavaDoc regex) {
78             assertValid("regex", regex);
79             this.regex = regex;
80         }
81
82         /**
83          * Set the prefix to use.
84          * @param prefix a <code>String</code> value.
85          */

86         public void setPrefix(String JavaDoc prefix) {
87             assertValid("prefix", prefix);
88             this.prefix = prefix;
89         }
90
91         /**
92          * Builtin property names - all, system or commandline.
93          * @param b an enumerated <code>BuildinPropertySetName</code> value.
94          */

95         public void setBuiltin(BuiltinPropertySetName b) {
96             String JavaDoc pBuiltIn = b.getValue();
97             assertValid("builtin", pBuiltIn);
98             this.builtin = pBuiltIn;
99         }
100
101         private void assertValid(String JavaDoc attr, String JavaDoc value) {
102             if (value == null || value.length() < 1) {
103                 throw new BuildException("Invalid attribute: " + attr);
104             }
105
106             if (++count != 1) {
107                 throw new BuildException("Attributes name, regex, and "
108                     + "prefix are mutually exclusive");
109             }
110         }
111
112         /**
113          * A debug toString().
114          * @return a string version of this object.
115          */

116         public String JavaDoc toString() {
117             return "name=" + name + ", regex=" + regex + ", prefix=" + prefix
118                 + ", builtin=" + builtin;
119         }
120
121     } //end nested class
122

123     /**
124      * Allow properties of a particular name in the set.
125      * @param name the property name to allow.
126      */

127     public void appendName(String JavaDoc name) {
128         PropertyRef r = new PropertyRef();
129         r.setName(name);
130         addPropertyref(r);
131     }
132
133     /**
134      * Allow properties whose names match a regex in the set.
135      * @param regex the regular expression to use.
136      */

137     public void appendRegex(String JavaDoc regex) {
138         PropertyRef r = new PropertyRef();
139         r.setRegex(regex);
140         addPropertyref(r);
141     }
142
143     /**
144      * Allow properties whose names start with a prefix in the set.
145      * @param prefix the prefix to use.
146      */

147     public void appendPrefix(String JavaDoc prefix) {
148         PropertyRef r = new PropertyRef();
149         r.setPrefix(prefix);
150         addPropertyref(r);
151     }
152
153     /**
154      * Allow builtin (all, system or commandline) properties in the set.
155      * @param b the type of builtin properties.
156      */

157     public void appendBuiltin(BuiltinPropertySetName b) {
158         PropertyRef r = new PropertyRef();
159         r.setBuiltin(b);
160         addPropertyref(r);
161     }
162
163     /**
164      * Set a mapper to change property names.
165      * @param type mapper type.
166      * @param from source pattern.
167      * @param to output pattern.
168      */

169     public void setMapper(String JavaDoc type, String JavaDoc from, String JavaDoc to) {
170         Mapper m = createMapper();
171         Mapper.MapperType mapperType = new Mapper.MapperType();
172         mapperType.setValue(type);
173         m.setType(mapperType);
174         m.setFrom(from);
175         m.setTo(to);
176     }
177
178     /**
179      * Add a property reference (nested element) to the references to be used.
180      * @param ref a property reference.
181      */

182     public void addPropertyref(PropertyRef ref) {
183         assertNotReference();
184         ptyRefs.addElement(ref);
185     }
186
187     /**
188      * Add another property set to this set.
189      * @param ref another property set.
190      */

191     public void addPropertyset(PropertySet ref) {
192         assertNotReference();
193         setRefs.addElement(ref);
194     }
195
196     /**
197      * Create a mapper to map the property names.
198      * @return a mapper to be configured.
199      */

200     public Mapper createMapper() {
201         assertNotReference();
202         if (mapper != null) {
203             throw new BuildException("Too many <mapper>s!");
204         }
205         mapper = new Mapper(getProject());
206         return mapper;
207     }
208
209     /**
210      * Add a nested FileNameMapper.
211      * @param fileNameMapper the mapper to add.
212      * @since Ant 1.6.3
213      */

214     public void add(FileNameMapper fileNameMapper) {
215         createMapper().add(fileNameMapper);
216     }
217
218     /**
219      * Set whether to reevaluate the set everytime the set is used.
220      * Default is true.
221      *
222      * @param dynamic if true, reevaluate the property set each time
223      * the set is used. if false cache the property set
224      * the first time and use the cached set on subsequent
225      * occasions.
226      */

227     public void setDynamic(boolean dynamic) {
228         assertNotReference();
229         this.dynamic = dynamic;
230     }
231
232     /**
233      * Set whether to negate results.
234      * If "true", all properties not selected by nested elements will be returned.
235      * Default is "false".
236      * @param negate if true, negate the selection criteria.
237      */

238     public void setNegate(boolean negate) {
239         assertNotReference();
240         this.negate = negate;
241     }
242
243     /**
244      * Get the dynamic attribute.
245      * @return true if the property set is to be evalulated each time it is used.
246      */

247     public boolean getDynamic() {
248         return isReference() ? getRef().dynamic : dynamic;
249     }
250
251     /**
252      * Get the mapper attribute.
253      * @return the mapper attribute.
254      */

255     public Mapper getMapper() {
256         return isReference() ? getRef().mapper : mapper;
257     }
258
259     /**
260      * Convert the system properties to a hashtable.
261      * Use propertynames to get the list of properties (including
262      * default ones).
263      */

264     private Hashtable JavaDoc getAllSystemProperties() {
265         Hashtable JavaDoc ret = new Hashtable JavaDoc();
266         for (Enumeration JavaDoc e = System.getProperties().propertyNames();
267              e.hasMoreElements();) {
268             String JavaDoc name = (String JavaDoc) e.nextElement();
269             ret.put(name, System.getProperties().getProperty(name));
270         }
271         return ret;
272     }
273
274     /**
275      * This is the operation to get the existing or recalculated properties.
276      * @return the properties for this propertyset.
277      */

278     public Properties JavaDoc getProperties() {
279         if (isReference()) {
280             return getRef().getProperties();
281         }
282         Set JavaDoc names = null;
283         Project prj = getProject();
284         Hashtable JavaDoc props =
285             prj == null ? getAllSystemProperties() : prj.getProperties();
286
287         //quick & dirty, to make nested mapped p-sets work:
288
for (Enumeration JavaDoc e = setRefs.elements(); e.hasMoreElements();) {
289             PropertySet set = (PropertySet) e.nextElement();
290             props.putAll(set.getProperties());
291         }
292
293         if (getDynamic() || cachedNames == null) {
294             names = new HashSet JavaDoc();
295             addPropertyNames(names, props);
296             // Add this PropertySet's nested PropertySets' property names.
297
for (Enumeration JavaDoc e = setRefs.elements(); e.hasMoreElements();) {
298                 PropertySet set = (PropertySet) e.nextElement();
299                 names.addAll(set.getProperties().keySet());
300             }
301             if (negate) {
302                 //make a copy...
303
HashSet JavaDoc complement = new HashSet JavaDoc(props.keySet());
304                 complement.removeAll(names);
305                 names = complement;
306             }
307             if (!getDynamic()) {
308                 cachedNames = names;
309             }
310         } else {
311             names = cachedNames;
312         }
313         FileNameMapper m = null;
314         Mapper myMapper = getMapper();
315         if (myMapper != null) {
316             m = myMapper.getImplementation();
317         }
318         Properties JavaDoc properties = new Properties JavaDoc();
319         //iterate through the names, get the matching values
320
for (Iterator JavaDoc iter = names.iterator(); iter.hasNext();) {
321             String JavaDoc name = (String JavaDoc) iter.next();
322             String JavaDoc value = (String JavaDoc) props.get(name);
323             if (value != null) {
324                 // may be null if a system property has been added
325
// after the project instance has been initialized
326
if (m != null) {
327                     //map the names
328
String JavaDoc[] newname = m.mapFileName(name);
329                     if (newname != null) {
330                         name = newname[0];
331                     }
332                 }
333                 properties.setProperty(name, value);
334             }
335         }
336         return properties;
337     }
338
339     /**
340      * @param names the output Set to fill with the property names
341      * matching this PropertySet selection criteria.
342      * @param properties the current Project properties, passed in to
343      * avoid needless duplication of the Hashtable during recursion.
344      */

345     private void addPropertyNames(Set JavaDoc names, Hashtable JavaDoc properties) {
346         // Add this PropertySet's property names.
347
for (Enumeration JavaDoc e = ptyRefs.elements(); e.hasMoreElements();) {
348             PropertyRef r = (PropertyRef) e.nextElement();
349             if (r.name != null) {
350                 if (properties.get(r.name) != null) {
351                     names.add(r.name);
352                 }
353             } else if (r.prefix != null) {
354                 for (Enumeration JavaDoc p = properties.keys(); p.hasMoreElements();) {
355                     String JavaDoc name = (String JavaDoc) p.nextElement();
356                     if (name.startsWith(r.prefix)) {
357                         names.add(name);
358                     }
359                 }
360             } else if (r.regex != null) {
361                 RegexpMatcherFactory matchMaker = new RegexpMatcherFactory();
362                 RegexpMatcher matcher = matchMaker.newRegexpMatcher();
363                 matcher.setPattern(r.regex);
364                 for (Enumeration JavaDoc p = properties.keys(); p.hasMoreElements();) {
365                     String JavaDoc name = (String JavaDoc) p.nextElement();
366                     if (matcher.matches(name)) {
367                         names.add(name);
368                     }
369                 }
370             } else if (r.builtin != null) {
371
372                 if (r.builtin.equals(BuiltinPropertySetName.ALL)) {
373                     names.addAll(properties.keySet());
374                 } else if (r.builtin.equals(BuiltinPropertySetName.SYSTEM)) {
375                     names.addAll(System.getProperties().keySet());
376                 } else if (r.builtin.equals(BuiltinPropertySetName
377                                               .COMMANDLINE)) {
378                     names.addAll(getProject().getUserProperties().keySet());
379                 } else {
380                     throw new BuildException("Impossible: Invalid builtin "
381                                              + "attribute!");
382                 }
383             } else {
384                 throw new BuildException("Impossible: Invalid PropertyRef!");
385             }
386         }
387     }
388
389     /**
390      * Performs the check for circular references and returns the
391      * referenced PropertySet.
392      * @return the referenced PropertySet.
393      */

394     protected PropertySet getRef() {
395         return (PropertySet) getCheckedRef(PropertySet.class, "propertyset");
396     }
397
398     /**
399      * Sets the value of the refid attribute.
400      *
401      * @param r the reference this datatype should point to.
402      * @throws BuildException if another attribute was set, since
403      * refid and all other attributes are mutually exclusive.
404      */

405     public final void setRefid(Reference r) {
406         if (!noAttributeSet) {
407             throw tooManyAttributes();
408         }
409         super.setRefid(r);
410     }
411
412     /**
413      * Ensures this data type is not a reference.
414      *
415      * <p>Calling this method as the first line of every bean method of
416      * this data type (setXyz, addXyz, createXyz) ensure proper handling
417      * of the refid attribute.</p>
418      *
419      * @throws BuildException if the refid attribute was already set, since
420      * refid and all other attributes are mutually exclusive.
421      */

422     protected final void assertNotReference() {
423         if (isReference()) {
424             throw tooManyAttributes();
425         }
426         noAttributeSet = false;
427     }
428
429     /**
430      * Flag which tracks whether any attribute has been set; used by
431      * {@link #assertNotReference()} and {@link #setRefid(Reference)}.
432      */

433     private boolean noAttributeSet = true;
434
435     /**
436      * Used for propertyref's builtin attribute.
437      */

438     public static class BuiltinPropertySetName extends EnumeratedAttribute {
439         static final String JavaDoc ALL = "all";
440         static final String JavaDoc SYSTEM = "system";
441         static final String JavaDoc COMMANDLINE = "commandline";
442         /** {@inheritDoc}. */
443         public String JavaDoc[] getValues() {
444             return new String JavaDoc[] {ALL, SYSTEM, COMMANDLINE};
445         }
446     }
447
448     /**
449      * A debug toString.
450      * This gets a comma separated list of key=value pairs for
451      * the properties in the set.
452      * The output order is sorted according to the keys' <i>natural order</i>.
453      * @return a string rep of this object.
454      */

455     public String JavaDoc toString() {
456         StringBuffer JavaDoc b = new StringBuffer JavaDoc();
457         TreeMap JavaDoc sorted = new TreeMap JavaDoc(getProperties());
458         for (Iterator JavaDoc i = sorted.entrySet().iterator(); i.hasNext();) {
459             Map.Entry JavaDoc e = (Map.Entry JavaDoc) i.next();
460             if (b.length() != 0) {
461                 b.append(", ");
462             }
463             b.append(e.getKey().toString());
464             b.append("=");
465             b.append(e.getValue().toString());
466         }
467         return b.toString();
468     }
469
470     /**
471      * Fulfill the ResourceCollection interface.
472      * @return an Iterator of Resources.
473      * @since Ant 1.7
474      */

475     public Iterator JavaDoc iterator() {
476         final Enumeration JavaDoc e = getProperties().propertyNames();
477         return new Iterator JavaDoc() {
478             public boolean hasNext() {
479                 return e.hasMoreElements();
480             }
481             public Object JavaDoc next() {
482                 return new PropertyResource(getProject(), (String JavaDoc) e.nextElement());
483             }
484             public void remove() {
485                 throw new UnsupportedOperationException JavaDoc();
486             }
487         };
488     }
489
490     /**
491      * Fulfill the ResourceCollection contract.
492      * @return the size of this ResourceCollection.
493      */

494     public int size() {
495         return isReference() ? getRef().size() : getProperties().size();
496     }
497
498     /**
499      * Fulfill the ResourceCollection contract.
500      * @return whether this is a filesystem-only resource collection.
501      */

502     public boolean isFilesystemOnly() {
503         return isReference() && getRef().isFilesystemOnly();
504     }
505
506 }
507
Popular Tags