diff --git a/src/etc/testcases/taskdefs/optional/echoproperties.properties b/src/etc/testcases/taskdefs/optional/echoproperties.properties
new file mode 100644
index 000000000..662666004
--- /dev/null
+++ b/src/etc/testcases/taskdefs/optional/echoproperties.properties
@@ -0,0 +1 @@
+test.infile=true
\ No newline at end of file
diff --git a/src/etc/testcases/taskdefs/optional/echoproperties.xml b/src/etc/testcases/taskdefs/optional/echoproperties.xml
index 0000bc86e..b3e39dc1c 100644
--- a/src/etc/testcases/taskdefs/optional/echoproperties.xml
+++ b/src/etc/testcases/taskdefs/optional/echoproperties.xml
@@ -12,6 +12,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -28,6 +48,10 @@
+
+
+
+
@@ -43,6 +67,7 @@
+
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/EchoProperties.java b/src/main/org/apache/tools/ant/taskdefs/optional/EchoProperties.java
index 4a30626c9..60030d6ff 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/EchoProperties.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/EchoProperties.java
@@ -56,16 +56,29 @@ package org.apache.tools.ant.taskdefs.optional;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.util.DOMElementWriter;
+import org.apache.tools.ant.util.CollectionUtils;
+import org.apache.tools.ant.types.EnumeratedAttribute;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
-import java.util.Properties;
-import java.util.Hashtable;
import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Properties;
import java.io.ByteArrayOutputStream;
-import java.io.OutputStream;
import java.io.File;
-import java.io.IOException;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
/**
* Displays all the current properties in the build. The output can be sent to
@@ -100,10 +113,37 @@ import java.io.FileOutputStream;
*
*@author Matt Albrecht
* groboclown@users.sourceforge.net
+ *@author Ingmar Stein
+ stein@xtramind.com
*@since Ant 1.5
*/
public class EchoProperties extends Task {
+ /**
+ * the properties element.
+ */
+ private static final String PROPERTIES = "properties";
+
+ /**
+ * the property element.
+ */
+ private static final String PROPERTY = "property";
+
+ /**
+ * name attribute for property, testcase and testsuite elements.
+ */
+ private static final String ATTR_NAME = "name";
+
+ /**
+ * value attribute for property elements.
+ */
+ private static final String ATTR_VALUE = "value";
+
+ /**
+ * the input file.
+ */
+ private File inFile = null;
+
/**
* File object pointing to the output file. If this is null, then we output
* to the project log, not to a file.
@@ -123,6 +163,17 @@ public class EchoProperties extends Task {
private String prefix = null;
+ private String format = "text";
+
+ /**
+ * Sets the input file.
+ *
+ * @param file the input file
+ */
+ public void setSrcfile( File file ) {
+ inFile = file;
+ }
+
/**
* Set a file to store the property output. If this is never specified,
* then the output will be sent to the Ant log.
@@ -163,6 +214,18 @@ public class EchoProperties extends Task {
}
+ public void setFormat(FormatAttribute ea) {
+ format = ea.getValue();
+ }
+
+ public static class FormatAttribute extends EnumeratedAttribute {
+ private String [] formats = new String[]{"xml", "text"};
+
+ public String[] getValues() {
+ return formats;
+ }
+ }
+
/**
* Run the task.
*
@@ -170,25 +233,109 @@ public class EchoProperties extends Task {
*/
public void execute() throws BuildException {
//copy the properties file
- Hashtable allProps = project.getProperties();
+ Hashtable allProps = new Hashtable();
+
+ /* load properties from file if specified, otherwise
+ use Ant's properties */
+ if(inFile == null) {
+ // add ant properties
+ CollectionUtils.putAll(allProps, project.getProperties());
+ } else {
+ if (inFile.exists() && inFile.isDirectory()) {
+ String message = "srcfile is a directory!";
+ if (failonerror) {
+ throw new BuildException(message, location);
+ } else {
+ log(message, Project.MSG_ERR);
+ }
+ return;
+ }
+ if (inFile.exists() && !inFile.canRead()) {
+ String message = "Can not read from the specified srcfile!";
+ if (failonerror) {
+ throw new BuildException( message, location );
+ } else {
+ log( message, Project.MSG_ERR );
+ }
+ return;
+ }
+
+ FileInputStream in = null;
+ try {
+ in = new FileInputStream( inFile );
+ Properties props = new Properties();
+ props.load(in);
+ CollectionUtils.putAll(allProps, props);
+ } catch(FileNotFoundException fnfe) {
+ String message =
+ "Could not find file " + inFile.getAbsolutePath();
+ if (failonerror) {
+ throw new BuildException(message, fnfe, location);
+ } else {
+ log( message, Project.MSG_WARN );
+ }
+ return;
+ } catch( IOException ioe ) {
+ String message =
+ "Could not read file " + inFile.getAbsolutePath();
+ if (failonerror) {
+ throw new BuildException(message, ioe, location);
+ } else {
+ log( message, Project.MSG_WARN );
+ }
+ return;
+ } finally {
+ try {
+ if( null != in ) {
+ in.close();
+ }
+ } catch(IOException ioe) {}
+ }
+ }
+
+ OutputStream os = null;
try {
if (destfile == null) {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- saveProperties(allProps, baos);
- log(baos.toString(), Project.MSG_INFO);
+ os = new ByteArrayOutputStream();
+ saveProperties(allProps, os);
+ log(os.toString(), Project.MSG_INFO);
} else {
- OutputStream os = new FileOutputStream(this.destfile);
+ if (destfile.exists() && destfile.isDirectory()) {
+ String message = "destfile is a directory!";
+ if (failonerror) {
+ throw new BuildException(message, location);
+ } else {
+ log(message, Project.MSG_ERR);
+ }
+ return;
+ }
+
+ if (destfile.exists() && !destfile.canWrite()) {
+ String message =
+ "Can not write to the specified destfile!";
+ if (failonerror) {
+ throw new BuildException(message, location);
+ } else {
+ log(message, Project.MSG_ERR);
+ }
+ return;
+ }
+ os = new FileOutputStream(this.destfile);
saveProperties(allProps, os);
}
} catch (IOException ioe) {
- String message =
- "Destfile " + destfile + " could not be written to.";
if (failonerror) {
- throw new BuildException(message, ioe,
- location);
+ throw new BuildException(ioe, location);
} else {
- log(message, Project.MSG_INFO);
+ log(ioe.getMessage(), Project.MSG_INFO);
+ }
+ } finally {
+ if (os != null) {
+ try {
+ os.close();
+ } catch (IOException e) {
+ }
}
}
}
@@ -209,20 +356,52 @@ public class EchoProperties extends Task {
Properties props = new Properties();
Enumeration enum = allProps.keys();
while (enum.hasMoreElements()) {
- String name = (String) enum.nextElement();
- String value = (String) allProps.get(name);
+ String name = enum.nextElement().toString();
+ String value = allProps.get(name).toString();
if (prefix == null || name.indexOf(prefix) == 0) {
props.put(name, value);
}
}
- try {
+
+ if ("text".equals(format)) {
jdkSaveProperties(props, os, "Ant properties");
+ } else if ("xml".equals(format)) {
+ xmlSaveProperties(props, os );
+ }
+ }
+
+ protected void xmlSaveProperties(Properties props,
+ OutputStream os) throws IOException {
+ // create XML document
+ Document doc = getDocumentBuilder().newDocument();
+ Element rootElement = doc.createElement( PROPERTIES );
+
+ // output properties
+ String name;
+ Enumeration e = props.propertyNames();
+ while( e.hasMoreElements() ) {
+ name = (String)e.nextElement();
+ Element propElement = doc.createElement( PROPERTY );
+ propElement.setAttribute( ATTR_NAME, name );
+ propElement.setAttribute( ATTR_VALUE, props.getProperty( name ) );
+ rootElement.appendChild( propElement );
+ }
+
+ Writer wri = null;
+ try {
+ wri = new OutputStreamWriter( os, "UTF8" );
+ wri.write( "" );
+ ( new DOMElementWriter() ).write( rootElement, wri, 0, "\t" );
+ wri.flush();
+ } catch( IOException ioe ) {
+ throw new BuildException( "Unable to write XML file", ioe );
} finally {
- os.close();
+ if( wri != null ) {
+ wri.close();
+ }
}
}
-
-
+
/**
* JDK 1.2 allows for the safer method
* Properties.store( OutputStream, String ), which throws an
@@ -251,7 +430,7 @@ public class EchoProperties extends Task {
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
-
+
// not an expected exception. Resort to JDK 1.0 to execute
// this method
jdk10SaveProperties(props, os, header);
@@ -264,8 +443,8 @@ public class EchoProperties extends Task {
jdk10SaveProperties(props, os, header);
}
}
-
-
+
+
/**
* Save the properties to the output stream using the JDK 1.0 compatible
* method. This won't throw an IOException on an output error.
@@ -275,8 +454,21 @@ public class EchoProperties extends Task {
*@param header prepend this header to the property output
*/
protected void jdk10SaveProperties(Properties props, OutputStream os,
- String header) {
+ String header) {
props.save(os, header);
}
+
+ /**
+ * Uses the DocumentBuilderFactory to get a DocumentBuilder instance.
+ *
+ * @return The DocumentBuilder instance
+ */
+ private static DocumentBuilder getDocumentBuilder() {
+ try {
+ return DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ } catch( Exception e ) {
+ throw new ExceptionInInitializerError( e );
+ }
+ }
}
diff --git a/src/main/org/apache/tools/ant/util/CollectionUtils.java b/src/main/org/apache/tools/ant/util/CollectionUtils.java
index 63cca4ff0..b609a562d 100644
--- a/src/main/org/apache/tools/ant/util/CollectionUtils.java
+++ b/src/main/org/apache/tools/ant/util/CollectionUtils.java
@@ -53,6 +53,7 @@
*/
package org.apache.tools.ant.util;
+import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Vector;
@@ -60,6 +61,7 @@ import java.util.Vector;
* A set of helper methods related to collection manipulation.
*
* @author Stefan Bodewig
+ * @author Ingmar Stein
*
* @since Ant 1.5
*/
@@ -93,4 +95,16 @@ public class CollectionUtils {
return true;
}
+
+ /**
+ * JDK 1.1 does not know the putAll method for hash tables.
+ *
+ * @since Ant 1.6
+ */
+ public static void putAll(Dictionary m1, Dictionary m2) {
+ for(Enumeration it = m2.keys(); it.hasMoreElements();) {
+ Object key = it.nextElement();
+ m1.put(key, m2.get(key));
+ }
+ }
}
diff --git a/src/testcases/org/apache/tools/ant/taskdefs/optional/EchoPropertiesTest.java b/src/testcases/org/apache/tools/ant/taskdefs/optional/EchoPropertiesTest.java
index 31081595e..8b31f1999 100644
--- a/src/testcases/org/apache/tools/ant/taskdefs/optional/EchoPropertiesTest.java
+++ b/src/testcases/org/apache/tools/ant/taskdefs/optional/EchoPropertiesTest.java
@@ -56,13 +56,20 @@ package org.apache.tools.ant.taskdefs.optional;
import org.apache.tools.ant.BuildFileTest;
-import java.io.*;
+import java.io.IOException;
+import java.io.File;
+import java.io.InputStream;
+import java.io.BufferedInputStream;
+import java.io.FileInputStream;
+import java.io.FileReader;
+import java.io.BufferedReader;
import java.util.Properties;
/**
* Tests the EchoProperties task.
*
* @author Matt Albrecht groboclown@users.sourceforge.net
+ * @author Ingmar Stein stein@xtramind.com
* @created 17-Jan-2002
* @since Ant 1.5
*/
@@ -70,64 +77,119 @@ public class EchoPropertiesTest extends BuildFileTest {
private final static String TASKDEFS_DIR = "src/etc/testcases/taskdefs/optional/";
private static final String GOOD_OUTFILE = "test.properties";
+ private static final String GOOD_OUTFILE_XML = "test.xml";
private static final String PREFIX_OUTFILE = "test-prefix.properties";
- private static final String BAD_OUTFILE = ".";
+ private static final String TEST_VALUE = "isSet";
public EchoPropertiesTest(String name) {
super(name);
}
+
public void setUp() {
configureProject(TASKDEFS_DIR + "echoproperties.xml");
- project.setProperty( "test.property", "is set" );
+ project.setProperty( "test.property", TEST_VALUE );
}
+
public void tearDown() {
executeTarget("cleanup");
}
-
-
+
+
public void testEchoToLog() {
- executeTarget( "testEchoToLog" );
+ expectLogContaining("testEchoToLog", "test.property="+TEST_VALUE);
+ }
+
+
+ public void testEchoToLogXml() {
+ executeTarget( "testEchoToLogXml" );
+ String out = getLog();
+ assertTrue(
+ "Did not output testEchoToLogXml.",
+ out.indexOf( "" ) >= 0 );
+ }
+
+
+ public void testReadAndEchoToLog() {
+ executeTarget( "testReadAndEchoToLog" );
String out = getLog();
assertTrue(
"Did not output testEchoToLog.",
- out.indexOf( "test.property=is set" ) >= 0 );
+ out.indexOf( "test.infile=true" ) >= 0 );
}
-
-
+
+
+ public void testReadBadFile() {
+ expectBuildExceptionContaining( "testReadBadFile",
+ "srcfile is a directory", "srcfile is a directory!" );
+ }
+
+
+ public void testReadBadFileFail() {
+ expectBuildExceptionContaining( "testReadBadFile",
+ "srcfile is a directory", "srcfile is a directory!" );
+ }
+
+
+ public void testReadBadFileNoFail() {
+ expectLog( "testReadBadFileNoFail", "srcfile is a directory!" );
+ }
+
+
public void testEchoToBadFile() {
expectBuildExceptionContaining( "testEchoToBadFile",
- "outfile is not writeable",
- "Destfile "+toAbsolute(BAD_OUTFILE)+" could not be written to." );
+ "destfile is a directory", "destfile is a directory!" );
}
-
-
+
+
public void testEchoToBadFileFail() {
expectBuildExceptionContaining( "testEchoToBadFileFail",
- "outfile is not writeable",
- "Destfile "+toAbsolute(BAD_OUTFILE)+" could not be written to." );
+ "destfile is a directory", "destfile is a directory!" );
}
-
-
+
+
public void testEchoToBadFileNoFail() {
- expectLog( "testEchoToBadFileNoFail",
- "Destfile "+toAbsolute(BAD_OUTFILE)+" could not be written to." );
+ expectLog( "testEchoToBadFileNoFail", "destfile is a directory!");
}
-
-
+
+
public void testEchoToGoodFile() throws Exception {
executeTarget( "testEchoToGoodFile" );
assertGoodFile();
}
-
-
+
+
+ public void testEchoToGoodFileXml() throws Exception {
+ executeTarget( "testEchoToGoodFileXml" );
+
+ // read in the file
+ File f = createRelativeFile( GOOD_OUTFILE_XML );
+ FileReader fr = new FileReader( f );
+ try {
+ BufferedReader br = new BufferedReader( fr );
+ String read = null;
+ while ( (read = br.readLine()) != null) {
+ if (read.indexOf("") >= 0) {
+ // found the property we set - it's good.
+ return;
+ }
+ }
+ fail( "did not encounter set property in generated file." );
+ } finally {
+ try {
+ fr.close();
+ } catch(IOException e) {}
+ }
+ }
+
+
public void testEchoToGoodFileFail() throws Exception {
executeTarget( "testEchoToGoodFileFail" );
assertGoodFile();
}
-
-
+
+
public void testEchoToGoodFileNoFail() throws Exception {
executeTarget( "testEchoToGoodFileNoFail" );
assertGoodFile();
@@ -167,26 +229,7 @@ public class EchoPropertiesTest extends BuildFileTest {
Properties props=loadPropFile(GOOD_OUTFILE);
props.list(System.out);
assertEquals("test property not found ",
- "is set",props.getProperty("test.property"));
-/*
- // read in the file
- FileReader fr = new FileReader( f );
- try {
- BufferedReader br = new BufferedReader( fr );
- String read = null;
- while ( (read = br.readLine()) != null)
- {
- if (read.indexOf("test.property=is set") >= 0)
- {
- // found the property we set - it's good.
- return;
- }
- }
- fail( "did not encounter set property in generated file." );
- } finally {
- try { fr.close(); } catch(IOException e) {}
- }
-*/
+ TEST_VALUE, props.getProperty("test.property"));
}