source: other-projects/trunk/gs3-release-maker/apache-ant-1.6.5/src/main/org/apache/tools/ant/types/PropertySet.java@ 14627

Last change on this file since 14627 was 14627, checked in by oranfry, 17 years ago

initial import of the gs3-release-maker

File size: 15.3 KB
Line 
1/*
2 * Copyright 2003-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.types;
19
20import java.util.Enumeration;
21import java.util.Iterator;
22import java.util.Map;
23import java.util.HashSet;
24import java.util.Set;
25import java.util.TreeMap;
26import java.util.Hashtable;
27import java.util.Properties;
28import java.util.Stack;
29import java.util.Vector;
30
31import org.apache.tools.ant.BuildException;
32import org.apache.tools.ant.Project;
33import org.apache.tools.ant.util.FileNameMapper;
34import org.apache.tools.ant.util.regexp.RegexpMatcher;
35import org.apache.tools.ant.util.regexp.RegexpMatcherFactory;
36
37/**
38 * A set of properties.
39 *
40 * @since Ant 1.6
41 */
42public class PropertySet extends DataType {
43
44 private boolean dynamic = true;
45 private boolean negate = false;
46 private Set cachedNames;
47 private Vector ptyRefs = new Vector();
48 private Vector setRefs = new Vector();
49 private Mapper mapper;
50
51 /**
52 * This is a nested class containing a reference to some properties
53 * and optionally a source of properties.
54 */
55 public static class PropertyRef {
56
57 private int count;
58 private String name;
59 private String regex;
60 private String prefix;
61 private String builtin;
62
63 /**
64 * Set the name.
65 * @param name a <code>String</code> value.
66 */
67 public void setName(String name) {
68 assertValid("name", name);
69 this.name = name;
70 }
71
72 /**
73 * Set the regular expression to use to filter the properties.
74 * @param regex a regular expression.
75 */
76 public void setRegex(String regex) {
77 assertValid("regex", regex);
78 this.regex = regex;
79 }
80
81 /**
82 * Set the prefix to use.
83 * @param prefix a <code>String</code> value.
84 */
85 public void setPrefix(String prefix) {
86 assertValid("prefix", prefix);
87 this.prefix = prefix;
88 }
89
90 /**
91 * Builtin property names - all, system or commandline.
92 * @param b an enumerated <code>BuildinPropertySetName</code> value.
93 */
94 public void setBuiltin(BuiltinPropertySetName b) {
95 String pBuiltIn = b.getValue();
96 assertValid("builtin", pBuiltIn);
97 this.builtin = pBuiltIn;
98 }
99
100 private void assertValid(String attr, String value) {
101 if (value == null || value.length() < 1) {
102 throw new BuildException("Invalid attribute: " + attr);
103 }
104
105 if (++count != 1) {
106 throw new BuildException("Attributes name, regex, and "
107 + "prefix are mutually exclusive");
108 }
109 }
110
111 /**
112 * A debug toString().
113 * @return a string version of this object.
114 */
115 public String toString() {
116 return "name=" + name + ", regex=" + regex + ", prefix=" + prefix
117 + ", builtin=" + builtin;
118 }
119
120 } //end nested class
121
122 /**
123 * Allow properties of a particular name in the set.
124 * @param name the property name to allow.
125 */
126 public void appendName(String name) {
127 PropertyRef r = new PropertyRef();
128 r.setName(name);
129 addPropertyref(r);
130 }
131
132 /**
133 * Allow properties whose names match a regex in the set.
134 * @param regex the regular expression to use.
135 */
136 public void appendRegex(String regex) {
137 PropertyRef r = new PropertyRef();
138 r.setRegex(regex);
139 addPropertyref(r);
140 }
141
142 /**
143 * Allow properties whose names start with a prefix in the set.
144 * @param prefix the prefix to use.
145 */
146 public void appendPrefix(String prefix) {
147 PropertyRef r = new PropertyRef();
148 r.setPrefix(prefix);
149 addPropertyref(r);
150 }
151
152 /**
153 * Allow builtin (all, system or commandline) properties in the set.
154 * @param b the type of builtin properties.
155 */
156 public void appendBuiltin(BuiltinPropertySetName b) {
157 PropertyRef r = new PropertyRef();
158 r.setBuiltin(b);
159 addPropertyref(r);
160 }
161
162 /**
163 * Set a mapper to change property names.
164 * @param type mapper type.
165 * @param from source pattern.
166 * @param to output pattern.
167 */
168 public void setMapper(String type, String from, String to) {
169 Mapper m = createMapper();
170 Mapper.MapperType mapperType = new Mapper.MapperType();
171 mapperType.setValue(type);
172 m.setFrom(from);
173 m.setTo(to);
174 }
175
176 /**
177 * Add a property reference (nested element) to the references to be used.
178 * @param ref a property reference.
179 */
180 public void addPropertyref(PropertyRef ref) {
181 assertNotReference();
182 ptyRefs.addElement(ref);
183 }
184
185 /**
186 * Add another property set to this set.
187 * @param ref another property set.
188 */
189 public void addPropertyset(PropertySet ref) {
190 assertNotReference();
191 setRefs.addElement(ref);
192 }
193
194 /**
195 * Create a mapper to map the property names.
196 * @return a mapper to be configured.
197 */
198 public Mapper createMapper() {
199 assertNotReference();
200 if (mapper != null) {
201 throw new BuildException("Too many <mapper>s!");
202 }
203 mapper = new Mapper(getProject());
204 return mapper;
205 }
206
207 /**
208 * Add a nested FileNameMapper.
209 * @param fileNameMapper the mapper to add.
210 * @since Ant 1.6.3
211 */
212 public void add(FileNameMapper fileNameMapper) {
213 createMapper().add(fileNameMapper);
214 }
215
216 /**
217 * Set whether to reevaluate the set everytime the set is used.
218 * Default is true.
219 *
220 * @param dynamic if true, reevaluate the property set each time
221 * the set is used. if false cache the property set
222 * the first time and use the cached set on subsequent
223 * occasions.
224 */
225 public void setDynamic(boolean dynamic) {
226 assertNotReference();
227 this.dynamic = dynamic;
228 }
229
230 /**
231 * Set whether to negate results.
232 * If "true", all properties not selected by nested elements will be returned.
233 * Default is "false".
234 * @param negate if true, negate the selection criteria.
235 */
236 public void setNegate(boolean negate) {
237 assertNotReference();
238 this.negate = negate;
239 }
240
241 /**
242 * Get the dynamic attribute.
243 * @return true if the property set is to be evalulated each time it is used.
244 */
245 public boolean getDynamic() {
246 return isReference() ? getRef().dynamic : dynamic;
247 }
248
249 /**
250 * Get the mapper attribute.
251 * @return the mapper attribute.
252 */
253 public Mapper getMapper() {
254 return isReference() ? getRef().mapper : mapper;
255 }
256
257 /**
258 * Convert the system properties to a hashtable.
259 * Use propertynames to get the list of properties (including
260 * default ones).
261 */
262 private Hashtable getAllSystemProperties() {
263 Hashtable ret = new Hashtable();
264 for (Enumeration e = System.getProperties().propertyNames();
265 e.hasMoreElements();) {
266 String name = (String) e.nextElement();
267 ret.put(name, System.getProperties().getProperty(name));
268 }
269 return ret;
270 }
271
272 /**
273 * This is the operation to get the existing or recalculated properties.
274 * @return the properties for this propertyset.
275 */
276 public Properties getProperties() {
277 if (isReference()) {
278 return getRef().getProperties();
279 }
280 Set names = null;
281 Project prj = getProject();
282 Hashtable props =
283 prj == null ? getAllSystemProperties() : prj.getProperties();
284
285 //quick & dirty, to make nested mapped p-sets work:
286 for (Enumeration e = setRefs.elements(); e.hasMoreElements();) {
287 PropertySet set = (PropertySet) e.nextElement();
288 props.putAll(set.getProperties());
289 }
290
291 if (getDynamic() || cachedNames == null) {
292 names = new HashSet();
293 addPropertyNames(names, props);
294 // Add this PropertySet's nested PropertySets' property names.
295 for (Enumeration e = setRefs.elements(); e.hasMoreElements();) {
296 PropertySet set = (PropertySet) e.nextElement();
297 names.addAll(set.getProperties().keySet());
298 }
299 if (negate) {
300 //make a copy...
301 HashSet complement = new HashSet(props.keySet());
302 complement.removeAll(names);
303 names = complement;
304 }
305 if (!getDynamic()) {
306 cachedNames = names;
307 }
308 } else {
309 names = cachedNames;
310 }
311 FileNameMapper m = null;
312 Mapper myMapper = getMapper();
313 if (myMapper != null) {
314 m = myMapper.getImplementation();
315 }
316 Properties properties = new Properties();
317 //iterate through the names, get the matching values
318 for (Iterator iter = names.iterator(); iter.hasNext();) {
319 String name = (String) iter.next();
320 String value = (String) props.get(name);
321 if (m != null) {
322 //map the names
323 String[] newname = m.mapFileName(name);
324 if (newname != null) {
325 name = newname[0];
326 }
327 }
328 properties.setProperty(name, value);
329 }
330 return properties;
331 }
332
333 /**
334 * @param names the output Set to fill with the property names
335 * matching this PropertySet selection criteria.
336 * @param properties the current Project properties, passed in to
337 * avoid needless duplication of the Hashtable during recursion.
338 */
339 private void addPropertyNames(Set names, Hashtable properties) {
340 Project prj = getProject();
341
342 // Add this PropertySet's property names.
343 for (Enumeration e = ptyRefs.elements(); e.hasMoreElements();) {
344 PropertyRef r = (PropertyRef) e.nextElement();
345 if (r.name != null) {
346 if (prj != null && prj.getProperty(r.name) != null) {
347 names.add(r.name);
348 }
349 } else if (r.prefix != null) {
350 for (Enumeration p = properties.keys(); p.hasMoreElements();) {
351 String name = (String) p.nextElement();
352 if (name.startsWith(r.prefix)) {
353 names.add(name);
354 }
355 }
356 } else if (r.regex != null) {
357 RegexpMatcherFactory matchMaker = new RegexpMatcherFactory();
358 RegexpMatcher matcher = matchMaker.newRegexpMatcher();
359 matcher.setPattern(r.regex);
360 for (Enumeration p = properties.keys(); p.hasMoreElements();) {
361 String name = (String) p.nextElement();
362 if (matcher.matches(name)) {
363 names.add(name);
364 }
365 }
366 } else if (r.builtin != null) {
367
368 if (r.builtin.equals(BuiltinPropertySetName.ALL)) {
369 names.addAll(properties.keySet());
370 } else if (r.builtin.equals(BuiltinPropertySetName.SYSTEM)) {
371 names.addAll(System.getProperties().keySet());
372 } else if (r.builtin.equals(BuiltinPropertySetName
373 .COMMANDLINE)) {
374 names.addAll(getProject().getUserProperties().keySet());
375 } else {
376 throw new BuildException("Impossible: Invalid builtin "
377 + "attribute!");
378 }
379 } else {
380 throw new BuildException("Impossible: Invalid PropertyRef!");
381 }
382 }
383 }
384
385 /**
386 * Performs the check for circular references and returns the
387 * referenced PropertySet.
388 * @return the referenced PropertySet.
389 */
390 protected PropertySet getRef() {
391 return (PropertySet) getCheckedRef(PropertySet.class, "propertyset");
392 }
393
394 /**
395 * Sets the value of the refid attribute.
396 *
397 * @param r the reference this datatype should point to.
398 * @throws BuildException if another attribute was set, since
399 * refid and all other attributes are mutually exclusive.
400 */
401 public final void setRefid(Reference r) {
402 if (!noAttributeSet) {
403 throw tooManyAttributes();
404 }
405 super.setRefid(r);
406 }
407
408 /**
409 * Ensures this data type is not a reference.
410 *
411 * <p>Calling this method as the first line of every bean method of
412 * this data type (setXyz, addXyz, createXyz) ensure proper handling
413 * of the refid attribute.</p>
414 *
415 * @throws BuildException if the refid attribute was already set, since
416 * refid and all other attributes are mutually exclusive.
417 */
418 protected final void assertNotReference() {
419 if (isReference()) {
420 throw tooManyAttributes();
421 }
422 noAttributeSet = false;
423 }
424
425 /**
426 * Flag which tracks whether any attribute has been set; used by
427 * {@link #assertNotReference()} and {@link #setRefid(Reference)}.
428 */
429 private boolean noAttributeSet = true;
430
431 /**
432 * Used for propertyref's builtin attribute.
433 */
434 public static class BuiltinPropertySetName extends EnumeratedAttribute {
435 static final String ALL = "all";
436 static final String SYSTEM = "system";
437 static final String COMMANDLINE = "commandline";
438 /** @see EnumeratedAttribute#getValues() */
439 public String[] getValues() {
440 return new String[] {ALL, SYSTEM, COMMANDLINE};
441 }
442 }
443
444 /**
445 * A debug toString.
446 * This gets a comma separated list of key=value pairs for
447 * the properties in the set.
448 * The output order is sorted according to the keys' <i>natural order</i>.
449 * @return a string rep of this object.
450 */
451 public String toString() {
452 StringBuffer b = new StringBuffer();
453 TreeMap sorted = new TreeMap(getProperties());
454 for (Iterator i = sorted.entrySet().iterator(); i.hasNext();) {
455 Map.Entry e = (Map.Entry) i.next();
456 if (b.length() != 0) {
457 b.append(", ");
458 }
459 b.append(e.getKey().toString());
460 b.append("=");
461 b.append(e.getValue().toString());
462 }
463 return b.toString();
464 }
465
466}
Note: See TracBrowser for help on using the repository browser.