Browse Source

Add ability to generate XML to <echoproperties>.

Add sourcefile attribute that can read arbitrary files to the same task.

Submitted by:	Ingmar Stein <stein@xtramind.com>


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@272806 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 23 years ago
parent
commit
1a8bb2e5a5
5 changed files with 344 additions and 69 deletions
  1. +1
    -0
      src/etc/testcases/taskdefs/optional/echoproperties.properties
  2. +25
    -0
      src/etc/testcases/taskdefs/optional/echoproperties.xml
  3. +216
    -24
      src/main/org/apache/tools/ant/taskdefs/optional/EchoProperties.java
  4. +14
    -0
      src/main/org/apache/tools/ant/util/CollectionUtils.java
  5. +88
    -45
      src/testcases/org/apache/tools/ant/taskdefs/optional/EchoPropertiesTest.java

+ 1
- 0
src/etc/testcases/taskdefs/optional/echoproperties.properties View File

@@ -0,0 +1 @@
test.infile=true

+ 25
- 0
src/etc/testcases/taskdefs/optional/echoproperties.xml View File

@@ -12,6 +12,26 @@
<echoproperties />
</target>

<target name="testEchoToLogXml" depends="setup">
<echoproperties format="xml" />
</target>

<target name="testReadAndEchoToLog" depends="setup">
<echoproperties srcfile="echoproperties.properties" />
</target>

<target name="testReadBadFile" depends="setup">
<echoproperties srcfile="." />
</target>

<target name="testReadBadFileFail" depends="setup">
<echoproperties srcfile="." failonerror="yes" />
</target>

<target name="testReadBadFileNoFail" depends="setup">
<echoproperties srcfile="." failonerror="no" />
</target>

<target name="testEchoToBadFile" depends="setup">
<echoproperties destfile="." />
</target>
@@ -28,6 +48,10 @@
<echoproperties destfile="test.properties" />
</target>

<target name="testEchoToGoodFileXml" depends="setup">
<echoproperties destfile="test.xml" format="xml" />
</target>

<target name="testEchoToGoodFileFail" depends="setup">
<echoproperties destfile="test.properties" failonerror="yes" />
</target>
@@ -43,6 +67,7 @@
<target name="cleanup">
<delete file="test.properties" failonerror="no" />
<delete file="test-prefix.properties" failonerror="no" />
<delete file="test.xml" failonerror="no" />
</target>

</project>


+ 216
- 24
src/main/org/apache/tools/ant/taskdefs/optional/EchoProperties.java View File

@@ -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 <a href="mailto:groboclown@users.sourceforge.net">
* groboclown@users.sourceforge.net</a>
*@author Ingmar Stein <a href="mailto:stein@xtramind.com">
stein@xtramind.com</a>
*@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( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" );
( 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
* <tt>Properties.store( OutputStream, String )</tt>, 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 <tt>IOException</tt> 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 );
}
}
}


+ 14
- 0
src/main/org/apache/tools/ant/util/CollectionUtils.java View File

@@ -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 <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
* @author <a href="mailto:stein@xtramind.com">Ingmar Stein</a>
*
* @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));
}
}
}

+ 88
- 45
src/testcases/org/apache/tools/ant/taskdefs/optional/EchoPropertiesTest.java View File

@@ -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 <a href="mailto:groboclown@users.sourceforge.net">groboclown@users.sourceforge.net</a>
* @author Ingmar Stein <a href="mailto:stein@xtramind.com">stein@xtramind.com</a>
* @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( "<property name=\"test.property\" value=\""+TEST_VALUE+"\"></property>" ) >= 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("<property name=\"test.property\" value=\""+TEST_VALUE+"\"></property>") >= 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"));
}




Loading…
Cancel
Save