diff --git a/WHATSNEW b/WHATSNEW index 55ec69981..6622d420a 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -24,6 +24,8 @@ Fixed bugs: Other changes: -------------- +* has a new encoding attribute. + * can now create XML output. * has a new srcfile attribute that can make it read diff --git a/docs/manual/CoreTasks/loadproperties.html b/docs/manual/CoreTasks/loadproperties.html index 91d94ad26..6e9fdcf1c 100644 --- a/docs/manual/CoreTasks/loadproperties.html +++ b/docs/manual/CoreTasks/loadproperties.html @@ -28,6 +28,11 @@ specified outside a target. source file Yes + + encoding + encoding to use when loading the file + No +

The LoadProperties task supports nested diff --git a/src/main/org/apache/tools/ant/filters/StringInputStream.java b/src/main/org/apache/tools/ant/filters/StringInputStream.java index 5eb3e4e0d..01b9024d1 100644 --- a/src/main/org/apache/tools/ant/filters/StringInputStream.java +++ b/src/main/org/apache/tools/ant/filters/StringInputStream.java @@ -58,8 +58,7 @@ import java.io.InputStream; import java.io.StringReader; /** - * Wraps a String as an InputStream. Note that data will be lost for - * characters not in ISO Latin 1, as a simple char->byte mapping is assumed. + * Wraps a String as an InputStream. * * @author Magesh Umasankar */ @@ -68,9 +67,15 @@ public class StringInputStream /** Source string, stored as a StringReader */ private StringReader in; + private String encoding; + + private byte[] slack; + + private int begin; + /** * Composes a stream from a String - * + * * @param source The string to read from. Must not be null. */ public StringInputStream(String source) { @@ -78,32 +83,88 @@ public class StringInputStream } /** - * Reads from the Stringreader, returning the same value. Note that - * data will be lost for characters not in ISO Latin 1. Clients - * assuming a return value in the range -1 to 255 may even fail on - * such input. - * - * @return the value of the next character in the StringReader - * - * @exception IOException if the original StringReader fails to be read + * Composes a stream from a String with the specified encoding + * + * @param source The string to read from. Must not be null. + * @param encoding The encoding scheme. */ - public int read() throws IOException { - return in.read(); + public StringInputStream(String source, String encoding) { + in = new StringReader(source); + this.encoding = encoding; } /** - * Closes the Stringreader. - * - * @exception IOException if the original StringReader fails to be closed + * Reads from the Stringreader, returning the same value. + * + * @return the value of the next character in the StringReader + * + * @exception IOException if the original StringReader fails to be read */ - public void close() throws IOException { - in.close(); + public synchronized int read() throws IOException { + if (in == null) { + throw new IOException("Stream Closed"); + } + + byte result; + if (slack != null && begin < slack.length) { + result = slack[begin]; + if (++begin == slack.length) { + slack = null; + } + } else { + byte[] buf = new byte[1]; + if (read(buf, 0, 1) <= 0) { + return -1; + } + result = buf[0]; + } + if (result < 0) { + return 256 + result; + } else { + return result; + } + } + + public synchronized int read(byte[] b, int off, int len) + throws IOException { + + if (in == null) { + throw new IOException("Stream Closed"); + } + + while (slack == null) { + char[] buf = new char[len]; // might read too much + int n = in.read(buf); + if (n == -1) { + return -1; + } + if (n > 0) { + String s = new String(buf, 0, n); + if (encoding == null) { + slack = s.getBytes(); + } else { + slack = s.getBytes(encoding); + } + begin = 0; + } + } + + if (len > slack.length - begin) { + len = slack.length - begin; + } + + System.arraycopy(slack, begin, b, off, len); + + if ((begin += len) >= slack.length) { + slack = null; + } + return len; } /** * Marks the read limit of the StringReader. - * - * @param limit the maximum limit of bytes that can be read before the + * + * @param limit the maximum limit of bytes that can be read before the * mark position becomes invalid */ public synchronized void mark(final int limit) { @@ -114,20 +175,46 @@ public class StringInputStream } } + + public synchronized int available() throws IOException { + if (in == null) { + throw new IOException("Stream Closed"); + } + if (slack != null) { + return slack.length - begin; + } + if (in.ready()) { + return 1; + } else { + return 0; + } + } + + public boolean markSupported () { + return false; // would be imprecise + } + /** * Resets the StringReader. - * + * * @exception IOException if the StringReader fails to be reset */ public synchronized void reset() throws IOException { + if (in == null) { + throw new IOException("Stream Closed"); + } + slack = null; in.reset(); } /** - * @see InputStream#markSupported + * Closes the Stringreader. + * + * @exception IOException if the original StringReader fails to be closed */ - public boolean markSupported() { - return in.markSupported(); + public synchronized void close() throws IOException { + in.close(); + slack = null; + in = null; } } - diff --git a/src/main/org/apache/tools/ant/taskdefs/LoadProperties.java b/src/main/org/apache/tools/ant/taskdefs/LoadProperties.java index 98c49f413..4363eb033 100644 --- a/src/main/org/apache/tools/ant/taskdefs/LoadProperties.java +++ b/src/main/org/apache/tools/ant/taskdefs/LoadProperties.java @@ -56,12 +56,12 @@ package org.apache.tools.ant.taskdefs; import org.apache.tools.ant.Task; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.types.FilterChain; -import org.apache.tools.ant.filters.StringInputStream; import org.apache.tools.ant.filters.util.ChainReaderHelper; import java.io.File; import java.io.FileInputStream; import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.IOException; @@ -88,6 +88,12 @@ public final class LoadProperties extends Task { */ private final Vector filterChains = new Vector(); + /** + * Encoding to use for filenames, defaults to the platform's default + * encoding. + */ + private String encoding = null; + /** * Sets the file to load. * @@ -97,6 +103,21 @@ public final class LoadProperties extends Task { this.srcFile = srcFile; } + /** + * Encoding to use for input, defaults to the platform's default + * encoding.

+ * + * For a list of possible values see + * http://java.sun.com/products/jdk/1.2/docs/guide/internat/encoding.doc.html + * .

+ * + * @param encoding The new Encoding value + */ + + public final void setEncoding(final String encoding) { + this.encoding = encoding; + } + /** * read in a source file's contents and load them up as Ant properties * @@ -127,7 +148,11 @@ public final class LoadProperties extends Task { //open up the file fis = new FileInputStream(srcFile); bis = new BufferedInputStream(fis); - instream = new InputStreamReader(bis); + if (encoding == null) { + instream = new InputStreamReader(bis); + } else { + instream = new InputStreamReader(bis, encoding); + } ChainReaderHelper crh = new ChainReaderHelper(); crh.setBufferSize(size); @@ -143,9 +168,14 @@ public final class LoadProperties extends Task { text = text + "\n"; } - final StringInputStream sis = new StringInputStream(text); + ByteArrayInputStream tis = null; + if ( encoding == null ) { + tis = new ByteArrayInputStream(text.getBytes()); + } else { + tis = new ByteArrayInputStream(text.getBytes(encoding)); + } final Properties props = new Properties(); - props.load(sis); + props.load(tis); final Enumeration e = props.keys(); while (e.hasMoreElements()) { final String key = (String) e.nextElement(); @@ -155,7 +185,7 @@ public final class LoadProperties extends Task { project.setNewProperty(key, value); } } - sis.close(); + tis.close(); } } catch (final IOException ioe) {