* Remove dependency of <loadproperties> on StringInputStream * Modify StringInputStream to support encoding * Note that StringInputStream is not being used by any other Ant classes - the sole consumer was LoadProperties which no longer uses it. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@273132 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -24,6 +24,8 @@ Fixed bugs: | |||||
| Other changes: | Other changes: | ||||
| -------------- | -------------- | ||||
| * <loadproperties> has a new encoding attribute. | |||||
| * <echoproperties> can now create XML output. | * <echoproperties> can now create XML output. | ||||
| * <echoproperties> has a new srcfile attribute that can make it read | * <echoproperties> has a new srcfile attribute that can make it read | ||||
| @@ -28,6 +28,11 @@ specified outside a target. | |||||
| <td valign="top">source file</td> | <td valign="top">source file</td> | ||||
| <td valign="top" align="center">Yes</td> | <td valign="top" align="center">Yes</td> | ||||
| </tr> | </tr> | ||||
| <tr> | |||||
| <td valign="top">encoding</td> | |||||
| <td valign="top">encoding to use when loading the file</td> | |||||
| <td align="center" valign="top">No</td> | |||||
| </tr> | |||||
| </table> | </table> | ||||
| <p> | <p> | ||||
| The LoadProperties task supports nested <a href="../CoreTypes/filterchain.html"> | The LoadProperties task supports nested <a href="../CoreTypes/filterchain.html"> | ||||
| @@ -58,8 +58,7 @@ import java.io.InputStream; | |||||
| import java.io.StringReader; | 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 <a href="mailto:umagesh@apache.org">Magesh Umasankar</a> | * @author <a href="mailto:umagesh@apache.org">Magesh Umasankar</a> | ||||
| */ | */ | ||||
| @@ -68,9 +67,15 @@ public class StringInputStream | |||||
| /** Source string, stored as a StringReader */ | /** Source string, stored as a StringReader */ | ||||
| private StringReader in; | private StringReader in; | ||||
| private String encoding; | |||||
| private byte[] slack; | |||||
| private int begin; | |||||
| /** | /** | ||||
| * Composes a stream from a String | * Composes a stream from a String | ||||
| * | |||||
| * | |||||
| * @param source The string to read from. Must not be <code>null</code>. | * @param source The string to read from. Must not be <code>null</code>. | ||||
| */ | */ | ||||
| public StringInputStream(String source) { | 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 <code>null</code>. | |||||
| * @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. | * 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 | * mark position becomes invalid | ||||
| */ | */ | ||||
| public synchronized void mark(final int limit) { | 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. | * Resets the StringReader. | ||||
| * | |||||
| * | |||||
| * @exception IOException if the StringReader fails to be reset | * @exception IOException if the StringReader fails to be reset | ||||
| */ | */ | ||||
| public synchronized void reset() throws IOException { | public synchronized void reset() throws IOException { | ||||
| if (in == null) { | |||||
| throw new IOException("Stream Closed"); | |||||
| } | |||||
| slack = null; | |||||
| in.reset(); | 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; | |||||
| } | } | ||||
| } | } | ||||
| @@ -56,12 +56,12 @@ package org.apache.tools.ant.taskdefs; | |||||
| import org.apache.tools.ant.Task; | import org.apache.tools.ant.Task; | ||||
| import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
| import org.apache.tools.ant.types.FilterChain; | import org.apache.tools.ant.types.FilterChain; | ||||
| import org.apache.tools.ant.filters.StringInputStream; | |||||
| import org.apache.tools.ant.filters.util.ChainReaderHelper; | import org.apache.tools.ant.filters.util.ChainReaderHelper; | ||||
| import java.io.File; | import java.io.File; | ||||
| import java.io.FileInputStream; | import java.io.FileInputStream; | ||||
| import java.io.BufferedInputStream; | import java.io.BufferedInputStream; | ||||
| import java.io.ByteArrayInputStream; | |||||
| import java.io.InputStreamReader; | import java.io.InputStreamReader; | ||||
| import java.io.Reader; | import java.io.Reader; | ||||
| import java.io.IOException; | import java.io.IOException; | ||||
| @@ -88,6 +88,12 @@ public final class LoadProperties extends Task { | |||||
| */ | */ | ||||
| private final Vector filterChains = new Vector(); | 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. | * Sets the file to load. | ||||
| * | * | ||||
| @@ -97,6 +103,21 @@ public final class LoadProperties extends Task { | |||||
| this.srcFile = srcFile; | this.srcFile = srcFile; | ||||
| } | } | ||||
| /** | |||||
| * Encoding to use for input, defaults to the platform's default | |||||
| * encoding. <p> | |||||
| * | |||||
| * For a list of possible values see <a href="http://java.sun.com/products/jdk/1.2/docs/guide/internat/encoding.doc.html"> | |||||
| * http://java.sun.com/products/jdk/1.2/docs/guide/internat/encoding.doc.html | |||||
| * </a>.</p> | |||||
| * | |||||
| * @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 | * 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 | //open up the file | ||||
| fis = new FileInputStream(srcFile); | fis = new FileInputStream(srcFile); | ||||
| bis = new BufferedInputStream(fis); | 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(); | ChainReaderHelper crh = new ChainReaderHelper(); | ||||
| crh.setBufferSize(size); | crh.setBufferSize(size); | ||||
| @@ -143,9 +168,14 @@ public final class LoadProperties extends Task { | |||||
| text = text + "\n"; | 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(); | final Properties props = new Properties(); | ||||
| props.load(sis); | |||||
| props.load(tis); | |||||
| final Enumeration e = props.keys(); | final Enumeration e = props.keys(); | ||||
| while (e.hasMoreElements()) { | while (e.hasMoreElements()) { | ||||
| final String key = (String) e.nextElement(); | final String key = (String) e.nextElement(); | ||||
| @@ -155,7 +185,7 @@ public final class LoadProperties extends Task { | |||||
| project.setNewProperty(key, value); | project.setNewProperty(key, value); | ||||
| } | } | ||||
| } | } | ||||
| sis.close(); | |||||
| tis.close(); | |||||
| } | } | ||||
| } catch (final IOException ioe) { | } catch (final IOException ioe) { | ||||