KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > taskdefs > optional > EchoProperties


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 package org.apache.tools.ant.taskdefs.optional;
19
20 import java.io.ByteArrayOutputStream JavaDoc;
21 import java.io.File JavaDoc;
22 import java.io.FileInputStream JavaDoc;
23 import java.io.FileNotFoundException JavaDoc;
24 import java.io.FileOutputStream JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.io.OutputStream JavaDoc;
27 import java.io.OutputStreamWriter JavaDoc;
28 import java.io.Writer JavaDoc;
29 import java.util.Enumeration JavaDoc;
30 import java.util.Hashtable JavaDoc;
31 import java.util.Properties JavaDoc;
32 import java.util.Vector JavaDoc;
33 import java.util.List JavaDoc;
34 import java.util.ArrayList JavaDoc;
35 import java.util.Comparator JavaDoc;
36 import java.util.Map JavaDoc;
37 import java.util.Set JavaDoc;
38 import java.util.TreeSet JavaDoc;
39 import java.util.Collections JavaDoc;
40 import java.util.Iterator JavaDoc;
41 import javax.xml.parsers.DocumentBuilder JavaDoc;
42 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
43 import org.apache.tools.ant.BuildException;
44 import org.apache.tools.ant.Project;
45 import org.apache.tools.ant.Task;
46 import org.apache.tools.ant.types.EnumeratedAttribute;
47 import org.apache.tools.ant.types.PropertySet;
48 import org.apache.tools.ant.util.CollectionUtils;
49 import org.apache.tools.ant.util.DOMElementWriter;
50 import org.apache.tools.ant.util.FileUtils;
51 import org.apache.tools.ant.util.JavaEnvUtils;
52 import org.w3c.dom.Document JavaDoc;
53 import org.w3c.dom.Element JavaDoc;
54
55 /**
56  * Displays all the current properties in the build. The output can be sent to
57  * a file if desired. <P>
58  *
59  * Attribute "destfile" defines a file to send the properties to. This can be
60  * processed as a standard property file later. <P>
61  *
62  * Attribute "prefix" defines a prefix which is used to filter the properties
63  * only those properties starting with this prefix will be echoed. <P>
64  *
65  * By default, the "failonerror" attribute is enabled. If an error occurs while
66  * writing the properties to a file, and this attribute is enabled, then a
67  * BuildException will be thrown. If disabled, then IO errors will be reported
68  * as a log statement, but no error will be thrown. <P>
69  *
70  * Examples: <pre>
71  * &lt;echoproperties /&gt;
72  * </pre> Report the current properties to the log. <P>
73  *
74  * <pre>
75  * &lt;echoproperties destfile="my.properties" /&gt;
76  * </pre> Report the current properties to the file "my.properties", and will
77  * fail the build if the file could not be created or written to. <P>
78  *
79  * <pre>
80  * &lt;echoproperties destfile="my.properties" failonerror="false"
81  * prefix="ant" /&gt;
82  * </pre> Report all properties beginning with 'ant' to the file
83  * "my.properties", and will log a message if the file could not be created or
84  * written to, but will still allow the build to continue.
85  *
86  *@since Ant 1.5
87  */

88 public class EchoProperties extends Task {
89
90     /**
91      * the properties element.
92      */

93     private static final String JavaDoc PROPERTIES = "properties";
94
95     /**
96      * the property element.
97      */

98     private static final String JavaDoc PROPERTY = "property";
99
100     /**
101      * name attribute for property, testcase and testsuite elements.
102      */

103     private static final String JavaDoc ATTR_NAME = "name";
104
105     /**
106      * value attribute for property elements.
107      */

108     private static final String JavaDoc ATTR_VALUE = "value";
109
110     /**
111      * the input file.
112      */

113     private File JavaDoc inFile = null;
114
115     /**
116      * File object pointing to the output file. If this is null, then
117      * we output to the project log, not to a file.
118      */

119     private File JavaDoc destfile = null;
120
121     /**
122      * If this is true, then errors generated during file output will become
123      * build errors, and if false, then such errors will be logged, but not
124      * thrown.
125      */

126     private boolean failonerror = true;
127
128     private Vector JavaDoc propertySets = new Vector JavaDoc();
129
130     private String JavaDoc format = "text";
131
132     private String JavaDoc prefix;
133
134     /**
135      * @since Ant 1.7
136      */

137     private String JavaDoc regex;
138
139     /**
140      * Sets the input file.
141      *
142      * @param file the input file
143      */

144     public void setSrcfile(File JavaDoc file) {
145         inFile = file;
146     }
147
148     /**
149      * Set a file to store the property output. If this is never specified,
150      * then the output will be sent to the Ant log.
151      *
152      *@param destfile file to store the property output
153      */

154     public void setDestfile(File JavaDoc destfile) {
155         this.destfile = destfile;
156     }
157
158
159     /**
160      * If true, the task will fail if an error occurs writing the properties
161      * file, otherwise errors are just logged.
162      *
163      *@param failonerror <tt>true</tt> if IO exceptions are reported as build
164      * exceptions, or <tt>false</tt> if IO exceptions are ignored.
165      */

166     public void setFailOnError(boolean failonerror) {
167         this.failonerror = failonerror;
168     }
169
170
171     /**
172      * If the prefix is set, then only properties which start with this
173      * prefix string will be recorded. If regex is not set and if this
174      * is never set, or it is set to an empty string or <tt>null</tt>,
175      * then all properties will be recorded. <P>
176      *
177      * For example, if the attribute is set as:
178      * <PRE>&lt;echoproperties prefix="ant." /&gt;</PRE>
179      * then the property "ant.home" will be recorded, but "ant-example"
180      * will not.
181      *
182      * @param prefix The new prefix value
183      */

184     public void setPrefix(String JavaDoc prefix) {
185         if (prefix != null && prefix.length() != 0) {
186             this.prefix = prefix;
187             PropertySet ps = new PropertySet();
188             ps.setProject(getProject());
189             ps.appendPrefix(prefix);
190             addPropertyset(ps);
191         }
192     }
193
194     /**
195      * If the regex is set, then only properties whose names match it
196      * will be recorded. If prefix is not set and if this is never set,
197      * or it is set to an empty string or <tt>null</tt>, then all
198      * properties will be recorded.<P>
199      *
200      * For example, if the attribute is set as:
201      * <PRE>&lt;echoproperties prefix=".*ant.*" /&gt;</PRE>
202      * then the properties "ant.home" and "user.variant" will be recorded,
203      * but "ant-example" will not.
204      *
205      * @param regex The new regex value
206      *
207      * @since Ant 1.7
208      */

209     public void setRegex(String JavaDoc regex) {
210         if (regex != null && regex.length() != 0) {
211             this.regex = regex;
212             PropertySet ps = new PropertySet();
213             ps.setProject(getProject());
214             ps.appendRegex(regex);
215             addPropertyset(ps);
216         }
217     }
218
219     /**
220      * A set of properties to write.
221      * @param ps the property set to write
222      * @since Ant 1.6
223      */

224     public void addPropertyset(PropertySet ps) {
225         propertySets.addElement(ps);
226     }
227
228     /**
229      * Set the output format - xml or text.
230      * @param ea an enumerated <code>FormatAttribute</code> value
231      */

232     public void setFormat(FormatAttribute ea) {
233         format = ea.getValue();
234     }
235
236     /**
237      * A enumerated type for the format attribute.
238      * The values are "xml" and "text".
239      */

240     public static class FormatAttribute extends EnumeratedAttribute {
241         private String JavaDoc [] formats = new String JavaDoc[]{"xml", "text"};
242
243         /**
244          * @see EnumeratedAttribute#getValues()
245          * @return accepted values
246          */

247         public String JavaDoc[] getValues() {
248             return formats;
249         }
250     }
251
252     /**
253      * Run the task.
254      *
255      *@exception BuildException trouble, probably file IO
256      */

257     public void execute() throws BuildException {
258         if (prefix != null && regex != null) {
259             throw new BuildException("Please specify either prefix"
260                     + " or regex, but not both", getLocation());
261         }
262         //copy the properties file
263
Hashtable JavaDoc allProps = new Hashtable JavaDoc();
264
265         /* load properties from file if specified, otherwise
266         use Ant's properties */

267         if (inFile == null && propertySets.size() == 0) {
268             // add ant properties
269
allProps.putAll(getProject().getProperties());
270         } else if (inFile != null) {
271             if (inFile.exists() && inFile.isDirectory()) {
272                 String JavaDoc message = "srcfile is a directory!";
273                 if (failonerror) {
274                     throw new BuildException(message, getLocation());
275                 } else {
276                     log(message, Project.MSG_ERR);
277                 }
278                 return;
279             }
280
281             if (inFile.exists() && !inFile.canRead()) {
282                 String JavaDoc message = "Can not read from the specified srcfile!";
283                 if (failonerror) {
284                     throw new BuildException(message, getLocation());
285                 } else {
286                     log(message, Project.MSG_ERR);
287                 }
288                 return;
289             }
290
291             FileInputStream JavaDoc in = null;
292             try {
293                 in = new FileInputStream JavaDoc(inFile);
294                 Properties JavaDoc props = new Properties JavaDoc();
295                 props.load(in);
296                 allProps.putAll(props);
297             } catch (FileNotFoundException JavaDoc fnfe) {
298                 String JavaDoc message =
299                     "Could not find file " + inFile.getAbsolutePath();
300                 if (failonerror) {
301                     throw new BuildException(message, fnfe, getLocation());
302                 } else {
303                     log(message, Project.MSG_WARN);
304                 }
305                 return;
306             } catch (IOException JavaDoc ioe) {
307                 String JavaDoc message =
308                     "Could not read file " + inFile.getAbsolutePath();
309                 if (failonerror) {
310                     throw new BuildException(message, ioe, getLocation());
311                 } else {
312                     log(message, Project.MSG_WARN);
313                 }
314                 return;
315             } finally {
316                 FileUtils.close(in);
317             }
318         }
319
320         Enumeration JavaDoc e = propertySets.elements();
321         while (e.hasMoreElements()) {
322             PropertySet ps = (PropertySet) e.nextElement();
323             allProps.putAll(ps.getProperties());
324         }
325
326         OutputStream JavaDoc os = null;
327         try {
328             if (destfile == null) {
329                 os = new ByteArrayOutputStream JavaDoc();
330                 saveProperties(allProps, os);
331                 log(os.toString(), Project.MSG_INFO);
332             } else {
333                 if (destfile.exists() && destfile.isDirectory()) {
334                     String JavaDoc message = "destfile is a directory!";
335                     if (failonerror) {
336                         throw new BuildException(message, getLocation());
337                     } else {
338                         log(message, Project.MSG_ERR);
339                     }
340                     return;
341                 }
342
343                 if (destfile.exists() && !destfile.canWrite()) {
344                     String JavaDoc message =
345                         "Can not write to the specified destfile!";
346                     if (failonerror) {
347                         throw new BuildException(message, getLocation());
348                     } else {
349                         log(message, Project.MSG_ERR);
350                     }
351                     return;
352                 }
353                 os = new FileOutputStream JavaDoc(this.destfile);
354                 saveProperties(allProps, os);
355             }
356         } catch (IOException JavaDoc ioe) {
357             if (failonerror) {
358                 throw new BuildException(ioe, getLocation());
359             } else {
360                 log(ioe.getMessage(), Project.MSG_INFO);
361             }
362         } finally {
363             if (os != null) {
364                 try {
365                     os.close();
366                 } catch (IOException JavaDoc ex) {
367                     //ignore
368
}
369             }
370         }
371     }
372
373
374     /**
375      * Send the key/value pairs in the hashtable to the given output stream.
376      * Only those properties matching the <tt>prefix</tt> constraint will be
377      * sent to the output stream.
378      * The output stream will be closed when this method returns.
379      *
380      * @param allProps propfile to save
381      * @param os output stream
382      * @throws IOException on output errors
383      * @throws BuildException on other errors
384      */

385     protected void saveProperties(Hashtable JavaDoc allProps, OutputStream JavaDoc os)
386         throws IOException JavaDoc, BuildException {
387         final List JavaDoc keyList = new ArrayList JavaDoc(allProps.keySet());
388         Collections.sort(keyList);
389         Properties JavaDoc props = new Properties JavaDoc() {
390             public Enumeration JavaDoc keys() {
391                 return CollectionUtils.asEnumeration(keyList.iterator());
392             }
393             public Set JavaDoc entrySet() {
394                 Set JavaDoc result = super.entrySet();
395                 if (JavaEnvUtils.isKaffe()) {
396                     TreeSet JavaDoc t = new TreeSet JavaDoc(new Comparator JavaDoc() {
397                         public int compare(Object JavaDoc o1, Object JavaDoc o2) {
398                             String JavaDoc key1 = (String JavaDoc) ((Map.Entry JavaDoc) o1).getKey();
399                             String JavaDoc key2 = (String JavaDoc) ((Map.Entry JavaDoc) o2).getKey();
400                             return key1.compareTo(key2);
401                         }
402                     });
403                     t.addAll(result);
404                     result = t;
405                 }
406                 return result;
407             }
408         };
409         for (int i = 0; i < keyList.size(); i++) {
410             String JavaDoc name = keyList.get(i).toString();
411             String JavaDoc value = allProps.get(name).toString();
412             props.setProperty(name, value);
413         }
414         if ("text".equals(format)) {
415             jdkSaveProperties(props, os, "Ant properties");
416         } else if ("xml".equals(format)) {
417             xmlSaveProperties(props, os);
418         }
419     }
420
421     /**
422      * a tuple for the sort list.
423      */

424     private static class Tuple implements Comparable JavaDoc {
425         private String JavaDoc key;
426         private String JavaDoc value;
427
428         private Tuple(String JavaDoc key, String JavaDoc value) {
429             this.key = key;
430             this.value = value;
431         }
432
433         /**
434          * Compares this object with the specified object for order.
435          * @param o the Object to be compared.
436          * @return a negative integer, zero, or a positive integer as this object is
437          * less than, equal to, or greater than the specified object.
438          * @throws ClassCastException if the specified object's type prevents it
439          * from being compared to this Object.
440          */

441         public int compareTo(Object JavaDoc o) {
442             Tuple that = (Tuple) o;
443             return key.compareTo(that.key);
444         }
445     }
446
447     private List JavaDoc sortProperties(Properties JavaDoc props) {
448         //sort the list. Makes SCM and manual diffs easier.
449
List JavaDoc sorted = new ArrayList JavaDoc(props.size());
450         Enumeration JavaDoc e = props.propertyNames();
451         while (e.hasMoreElements()) {
452             String JavaDoc name = (String JavaDoc) e.nextElement();
453             sorted.add(new Tuple(name, props.getProperty(name)));
454         }
455         Collections.sort(sorted);
456         return sorted;
457     }
458
459     /**
460      * Output the properties as xml output.
461      * @param props the properties to save
462      * @param os the output stream to write to (Note this gets closed)
463      * @throws IOException on error in writing to the stream
464      */

465     protected void xmlSaveProperties(Properties JavaDoc props,
466                                      OutputStream JavaDoc os) throws IOException JavaDoc {
467         // create XML document
468
Document JavaDoc doc = getDocumentBuilder().newDocument();
469         Element JavaDoc rootElement = doc.createElement(PROPERTIES);
470
471         List JavaDoc sorted = sortProperties(props);
472
473
474         // output properties
475
Iterator JavaDoc iten = sorted.iterator();
476         while (iten.hasNext()) {
477             Tuple tuple = (Tuple) iten.next();
478             Element JavaDoc propElement = doc.createElement(PROPERTY);
479             propElement.setAttribute(ATTR_NAME, tuple.key);
480             propElement.setAttribute(ATTR_VALUE, tuple.value);
481             rootElement.appendChild(propElement);
482         }
483
484         Writer JavaDoc wri = null;
485         try {
486             wri = new OutputStreamWriter JavaDoc(os, "UTF8");
487             wri.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
488             (new DOMElementWriter()).write(rootElement, wri, 0, "\t");
489             wri.flush();
490         } catch (IOException JavaDoc ioe) {
491             throw new BuildException("Unable to write XML file", ioe);
492         } finally {
493             FileUtils.close(wri);
494         }
495     }
496
497     /**
498      * JDK 1.2 allows for the safer method
499      * <tt>Properties.store(OutputStream, String)</tt>, which throws an
500      * <tt>IOException</tt> on an output error.
501      *
502      *@param props the properties to record
503      *@param os record the properties to this output stream
504      *@param header prepend this header to the property output
505      *@exception IOException on an I/O error during a write.
506      */

507     protected void jdkSaveProperties(Properties JavaDoc props, OutputStream JavaDoc os,
508                                      String JavaDoc header) throws IOException JavaDoc {
509        try {
510            props.store(os, header);
511
512        } catch (IOException JavaDoc ioe) {
513            throw new BuildException(ioe, getLocation());
514        } finally {
515            if (os != null) {
516                try {
517                    os.close();
518                } catch (IOException JavaDoc ioex) {
519                    log("Failed to close output stream");
520                }
521            }
522        }
523     }
524
525
526     /**
527      * Uses the DocumentBuilderFactory to get a DocumentBuilder instance.
528      *
529      * @return The DocumentBuilder instance
530      */

531     private static DocumentBuilder JavaDoc getDocumentBuilder() {
532         try {
533             return DocumentBuilderFactory.newInstance().newDocumentBuilder();
534         } catch (Exception JavaDoc e) {
535             throw new ExceptionInInitializerError JavaDoc(e);
536         }
537     }
538 }
539
540
Popular Tags