source: release-kits/wirk3/ant-scripts/tasks/antelope/src/ise/antelope/tasks/Variable.java@ 15023

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

did the bulk of the work on wirk3

File size: 11.0 KB
Line 
1/*
2 * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
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 */
16package ise.antelope.tasks;
17
18import java.io.File;
19import java.io.FileInputStream;
20import java.io.IOException;
21import java.lang.reflect.Field;
22import java.util.Enumeration;
23import java.util.Hashtable;
24import java.util.Properties;
25import java.util.Vector;
26
27import org.apache.tools.ant.BuildException;
28import org.apache.tools.ant.Project;
29import org.apache.tools.ant.ProjectHelper;
30import org.apache.tools.ant.Task;
31
32/**
33 * Similar to Property, but this property is mutable. In fact, much of the code
34 * in this class is copy and paste from Property. In general, the standard Ant
35 * property should be used, but occasionally it is useful to use a mutable
36 * property.
37 * <p>
38 * This used to be a nice little task that took advantage of what is probably
39 * a flaw in the Ant Project API -- setting a "user" property programatically
40 * causes the project to overwrite a previously set property. Now this task
41 * has become more violent and employs a technique known as "object rape" to
42 * directly access the Project's private property hashtable.
43 * <p>Developed for use with Antelope, migrated to ant-contrib Oct 2003.
44 *
45 * @author Dale Anson, [email protected]
46 * @since Ant 1.5
47 * @version $Revision: 1.3 $
48 */
49public class Variable extends Task {
50
51 // attribute storage
52 private String value = "";
53 private String name = null;
54 private File file = null;
55 private boolean remove = false;
56
57
58 /**
59 * Set the name of the property. Required unless 'file' is used.
60 *
61 * @param name the name of the property.
62 */
63 public void setName( String name ) {
64 this.name = name;
65 }
66
67
68 /**
69 * Set the value of the property. Optional, defaults to "".
70 *
71 * @param value the value of the property.
72 */
73 public void setValue( String value ) {
74 this.value = value;
75 }
76
77
78 /**
79 * Set the name of a file to read properties from. Optional.
80 *
81 * @param file the file to read properties from.
82 */
83 public void setFile( File file ) {
84 this.file = file;
85 }
86
87 /**
88 * Determines whether the property should be removed from the project.
89 * Default is false. Once removed, conditions that check for property
90 * existence will find this property does not exist.
91 *
92 * @param b set to true to remove the property from the project.
93 */
94 public void setUnset( boolean b ) {
95 remove = b;
96 }
97
98
99 /**
100 * Execute this task.
101 *
102 * @exception BuildException Description of the Exception
103 */
104 public void execute() throws BuildException {
105 if ( remove ) {
106 if ( name == null || name.equals( "" ) ) {
107 throw new BuildException( "The 'name' attribute is required with 'unset'." );
108 }
109 removeProperty( name );
110 return ;
111 }
112 if ( file == null ) {
113 // check for the required name attribute
114 if ( name == null || name.equals( "" ) ) {
115 throw new BuildException( "The 'name' attribute is required." );
116 }
117
118 // check for the required value attribute
119 if ( value == null ) {
120 value = "";
121 }
122
123 // adjust the property value if necessary -- is this necessary?
124 // Doesn't Ant do this automatically?
125 value = getProject().replaceProperties( value );
126
127 // set the property
128 forceProperty( name, value );
129 }
130 else {
131 if ( !file.exists() ) {
132 throw new BuildException( file.getAbsolutePath() + " does not exists." );
133 }
134 loadFile( file );
135 }
136 }
137
138 /**
139 * Remove a property from the project's property table and the userProperty table.
140 * Note that Ant 1.6 uses a helper for this.
141 */
142 private void removeProperty( String name ) {
143 Hashtable properties = null;
144 // Ant 1.5 stores properties in Project
145 try {
146 properties = ( Hashtable ) getValue( getProject(), "properties" );
147 if ( properties != null ) {
148 properties.remove( name );
149 }
150 }
151 catch ( Exception e ) {
152 // ignore, could be Ant 1.6
153 }
154 try {
155 properties = ( Hashtable ) getValue( getProject(), "userProperties" );
156 if ( properties != null ) {
157 properties.remove( name );
158 }
159 }
160 catch ( Exception e ) {
161 // ignore, could be Ant 1.6
162 }
163
164 // Ant 1.6 uses a PropertyHelper, can check for it by checking for a
165 // reference to "ant.PropertyHelper"
166 try {
167 Object property_helper = getProject().getReference( "ant.PropertyHelper" );
168 if ( property_helper != null ) {
169 try {
170 properties = ( Hashtable ) getValue( property_helper, "properties" );
171 if ( properties != null ) {
172 properties.remove( name );
173 }
174 }
175 catch ( Exception e ) {
176 // ignore
177 }
178 try {
179 properties = ( Hashtable ) getValue( property_helper, "userProperties" );
180 if ( properties != null ) {
181 properties.remove( name );
182 }
183 }
184 catch ( Exception e ) {
185 // ignore
186 }
187 }
188 }
189 catch ( Exception e ) {
190 // ignore, could be Ant 1.5
191 }
192 }
193
194 private void forceProperty( String name, String value ) {
195 try {
196 Hashtable properties = ( Hashtable ) getValue( getProject(), "properties" );
197 if ( properties == null ) {
198 getProject().setUserProperty( name, value );
199 }
200 else {
201 properties.put( name, value );
202 }
203 }
204 catch ( Exception e ) {
205 getProject().setUserProperty( name, value );
206 }
207 }
208
209
210 /**
211 * Object rape: fondle the private parts of an object without it's
212 * permission.
213 *
214 * @param thisClass The class to rape.
215 * @param fieldName The field to fondle
216 * @return The field value
217 * @exception NoSuchFieldException Darn, nothing to fondle.
218 */
219 private Field getField( Class thisClass, String fieldName ) throws NoSuchFieldException {
220 if ( thisClass == null ) {
221 throw new NoSuchFieldException( "Invalid field : " + fieldName );
222 }
223 try {
224 return thisClass.getDeclaredField( fieldName );
225 }
226 catch ( NoSuchFieldException e ) {
227 return getField( thisClass.getSuperclass(), fieldName );
228 }
229 }
230
231
232 /**
233 * Object rape: fondle the private parts of an object without it's
234 * permission.
235 *
236 * @param instance the object instance
237 * @param fieldName the name of the field
238 * @return an object representing the value of the
239 * field
240 * @exception IllegalAccessException foiled by the security manager
241 * @exception NoSuchFieldException Darn, nothing to fondle
242 */
243 private Object getValue( Object instance, String fieldName )
244 throws IllegalAccessException, NoSuchFieldException {
245 Field field = getField( instance.getClass(), fieldName );
246 field.setAccessible( true );
247 return field.get( instance );
248 }
249
250
251 /**
252 * load variables from a file
253 *
254 * @param file file to load
255 * @exception BuildException Description of the Exception
256 */
257 private void loadFile( File file ) throws BuildException {
258 Properties props = new Properties();
259 try {
260 if ( file.exists() ) {
261 FileInputStream fis = new FileInputStream( file );
262 try {
263 props.load( fis );
264 }
265 finally {
266 if ( fis != null ) {
267 fis.close();
268 }
269 }
270 addProperties( props );
271 }
272 else {
273 log( "Unable to find property file: " + file.getAbsolutePath(),
274 Project.MSG_VERBOSE );
275 }
276 }
277 catch ( IOException ex ) {
278 throw new BuildException( ex, location );
279 }
280 }
281
282
283 /**
284 * iterate through a set of properties, resolve them, then assign them
285 *
286 * @param props The feature to be added to the Properties attribute
287 */
288 protected void addProperties( Properties props ) {
289 resolveAllProperties( props );
290 Enumeration e = props.keys();
291 while ( e.hasMoreElements() ) {
292 String name = ( String ) e.nextElement();
293 String value = props.getProperty( name );
294 forceProperty( name, value );
295 }
296 }
297
298
299 /**
300 * resolve properties inside a properties hashtable
301 *
302 * @param props properties object to resolve
303 * @exception BuildException Description of the Exception
304 */
305 private void resolveAllProperties( Properties props ) throws BuildException {
306 for ( Enumeration e = props.keys(); e.hasMoreElements(); ) {
307 String name = ( String ) e.nextElement();
308 String value = props.getProperty( name );
309
310 boolean resolved = false;
311 while ( !resolved ) {
312 Vector fragments = new Vector();
313 Vector propertyRefs = new Vector();
314 ProjectHelper.parsePropertyString( value, fragments,
315 propertyRefs );
316
317 resolved = true;
318 if ( propertyRefs.size() != 0 ) {
319 StringBuffer sb = new StringBuffer();
320 Enumeration i = fragments.elements();
321 Enumeration j = propertyRefs.elements();
322 while ( i.hasMoreElements() ) {
323 String fragment = ( String ) i.nextElement();
324 if ( fragment == null ) {
325 String propertyName = ( String ) j.nextElement();
326 if ( propertyName.equals( name ) ) {
327 throw new BuildException( "Property " + name
328 + " was circularly "
329 + "defined." );
330 }
331 fragment = getProject().getProperty( propertyName );
332 if ( fragment == null ) {
333 if ( props.containsKey( propertyName ) ) {
334 fragment = props.getProperty( propertyName );
335 resolved = false;
336 }
337 else {
338 fragment = "${" + propertyName + "}";
339 }
340 }
341 }
342 sb.append( fragment );
343 }
344 value = sb.toString();
345 props.put( name, value );
346 }
347 }
348 }
349 }
350
351}
352
353
Note: See TracBrowser for help on using the repository browser.