From 1a8bb2e5a5ef38951095904eeeba7bf8e4f4cbc6 Mon Sep 17 00:00:00 2001 From: Stefan Bodewig Date: Wed, 29 May 2002 15:24:38 +0000 Subject: [PATCH] Add ability to generate XML to . Add sourcefile attribute that can read arbitrary files to the same task. Submitted by: Ingmar Stein git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@272806 13f79535-47bb-0310-9956-ffa450edef68 --- .../optional/echoproperties.properties | 1 + .../taskdefs/optional/echoproperties.xml | 25 ++ .../ant/taskdefs/optional/EchoProperties.java | 240 ++++++++++++++++-- .../tools/ant/util/CollectionUtils.java | 14 + .../taskdefs/optional/EchoPropertiesTest.java | 133 ++++++---- 5 files changed, 344 insertions(+), 69 deletions(-) create mode 100644 src/etc/testcases/taskdefs/optional/echoproperties.properties 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")); }