Fix for DDLUTILS-233: DataReader doesn't support UTF-8
git-svn-id: https://svn.apache.org/repos/asf/db/ddlutils/trunk@987976 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/ddlutils/io/DataReader.java b/src/main/java/org/apache/ddlutils/io/DataReader.java
index c8cd65c..8bc7b87 100644
--- a/src/main/java/org/apache/ddlutils/io/DataReader.java
+++ b/src/main/java/org/apache/ddlutils/io/DataReader.java
@@ -19,8 +19,10 @@
* under the License.
*/
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
import java.io.File;
-import java.io.FileReader;
+import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
@@ -155,14 +157,7 @@
*/
public void read(String filename) throws DdlUtilsXMLException
{
- try
- {
- read(new FileReader(filename));
- }
- catch (IOException ex)
- {
- throw new DdlUtilsXMLException(ex);
- }
+ read(new File(filename));
}
/**
@@ -172,14 +167,31 @@
*/
public void read(File file) throws DdlUtilsXMLException
{
+ FileInputStream input = null;
+
try
{
- read(new FileReader(file));
+ input = new FileInputStream(file);
+ read(input);
}
catch (IOException ex)
{
throw new DdlUtilsXMLException(ex);
}
+ finally
+ {
+ if (input != null)
+ {
+ try
+ {
+ input.close();
+ }
+ catch (IOException ex)
+ {
+ _log.warn("Error while trying to close the input stream for " + file, ex);
+ }
+ }
+ }
}
/**
@@ -189,9 +201,19 @@
*/
public void read(Reader reader) throws DdlUtilsXMLException
{
+ BufferedReader bufferedReader;
+
+ if (reader instanceof BufferedReader)
+ {
+ bufferedReader = (BufferedReader)reader;
+ }
+ else
+ {
+ bufferedReader = new BufferedReader(reader);
+ }
try
{
- read(getXMLInputFactory().createXMLStreamReader(reader));
+ read(getXMLInputFactory().createXMLStreamReader(bufferedReader));
}
catch (XMLStreamException ex)
{
@@ -206,9 +228,19 @@
*/
public void read(InputStream input) throws DdlUtilsXMLException
{
+ BufferedInputStream bufferedInput;
+
+ if (input instanceof BufferedInputStream)
+ {
+ bufferedInput = (BufferedInputStream)input;
+ }
+ else
+ {
+ bufferedInput = new BufferedInputStream(input);
+ }
try
{
- read(getXMLInputFactory().createXMLStreamReader(input));
+ read(getXMLInputFactory().createXMLStreamReader(bufferedInput));
}
catch (XMLStreamException ex)
{
diff --git a/src/main/java/org/apache/ddlutils/io/DataWriter.java b/src/main/java/org/apache/ddlutils/io/DataWriter.java
index b90b06c..1fd7a72 100644
--- a/src/main/java/org/apache/ddlutils/io/DataWriter.java
+++ b/src/main/java/org/apache/ddlutils/io/DataWriter.java
@@ -20,6 +20,7 @@
*/
import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
@@ -202,7 +203,12 @@
if (writeBase64Encoded)
{
writeAttribute(null, DatabaseIO.BASE64_ATTR_NAME, "true");
- writeCData(new String(Base64.encodeBase64(content.getBytes())));
+ try {
+ writeCData(new String(Base64.encodeBase64(content.getBytes()), getEncoding()));
+ }
+ catch (UnsupportedEncodingException ex) {
+ throw new DataWriterException(ex);
+ }
}
else
{
diff --git a/src/main/java/org/apache/ddlutils/io/PrettyPrintingXmlWriter.java b/src/main/java/org/apache/ddlutils/io/PrettyPrintingXmlWriter.java
index ed86d66..c01bb26 100644
--- a/src/main/java/org/apache/ddlutils/io/PrettyPrintingXmlWriter.java
+++ b/src/main/java/org/apache/ddlutils/io/PrettyPrintingXmlWriter.java
@@ -19,8 +19,9 @@
* under the License.
*/
+import java.io.BufferedOutputStream;
+import java.io.BufferedWriter;
import java.io.OutputStream;
-import java.io.PrintWriter;
import java.io.Writer;
import javax.xml.stream.XMLOutputFactory;
@@ -37,8 +38,6 @@
/** The indentation string. */
private static final String INDENT_STRING = " ";
- /** The output stream. */
- private PrintWriter _output;
/** The xml writer. */
private XMLStreamWriter _writer;
/** The output encoding. */
@@ -64,7 +63,16 @@
*/
public PrettyPrintingXmlWriter(OutputStream output, String encoding) throws DdlUtilsXMLException
{
- _output = new PrintWriter(output);
+ BufferedOutputStream bufferedOutput;
+
+ if (output instanceof BufferedOutputStream)
+ {
+ bufferedOutput = (BufferedOutputStream)output;
+ }
+ else
+ {
+ bufferedOutput = new BufferedOutputStream(output);
+ }
if ((encoding == null) || (encoding.length() == 0))
{
_encoding = "UTF-8";
@@ -78,7 +86,7 @@
{
XMLOutputFactory factory = XMLOutputFactory.newInstance();
- _writer = factory.createXMLStreamWriter(output, _encoding);
+ _writer = factory.createXMLStreamWriter(bufferedOutput, _encoding);
}
catch (XMLStreamException ex)
{
@@ -95,13 +103,22 @@
*/
public PrettyPrintingXmlWriter(Writer output, String encoding) throws DdlUtilsXMLException
{
- _output = new PrintWriter(output);
+ BufferedWriter bufferedWriter;
+
+ if (output instanceof BufferedWriter)
+ {
+ bufferedWriter = (BufferedWriter)output;
+ }
+ else
+ {
+ bufferedWriter = new BufferedWriter(output);
+ }
_encoding = encoding;
try
{
XMLOutputFactory factory = XMLOutputFactory.newInstance();
- _writer = factory.createXMLStreamWriter(_output);
+ _writer = factory.createXMLStreamWriter(bufferedWriter);
}
catch (XMLStreamException ex)
{
@@ -110,6 +127,16 @@
}
/**
+ * Returnd the encoding used by this xml writer.
+ *
+ * @return The encoding
+ */
+ public String getEncoding()
+ {
+ return _encoding;
+ }
+
+ /**
* Rethrows the given exception, wrapped in a {@link DdlUtilsXMLException}. This
* method allows subclasses to throw their own subclasses of this exception.
*
diff --git a/src/test/java/org/apache/ddlutils/io/TestDataReaderAndWriter.java b/src/test/java/org/apache/ddlutils/io/TestDataReaderAndWriter.java
index f53a3bf..982e9de 100644
--- a/src/test/java/org/apache/ddlutils/io/TestDataReaderAndWriter.java
+++ b/src/test/java/org/apache/ddlutils/io/TestDataReaderAndWriter.java
@@ -20,6 +20,8 @@
*/
import java.io.BufferedWriter;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
@@ -31,6 +33,7 @@
import junit.framework.TestCase;
import org.apache.commons.beanutils.DynaBean;
+import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.apache.ddlutils.dynabean.SqlDynaBean;
import org.apache.ddlutils.model.Database;
@@ -738,10 +741,10 @@
modelIO.setValidateXml(true);
- Database model = modelIO.read(new StringReader(testSchemaXml));
- StringWriter output = new StringWriter();
- DataWriter dataWriter = new DataWriter(output, "UTF-8");
- SqlDynaBean bean = (SqlDynaBean)model.createDynaBeanFor(model.getTable(0));
+ Database model = modelIO.read(new StringReader(testSchemaXml));
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ DataWriter dataWriter = new DataWriter(output, "ISO-8859-1");
+ SqlDynaBean bean = (SqlDynaBean)model.createDynaBeanFor(model.getTable(0));
bean.set("id", new Integer(1));
bean.set("value", testedValue);
@@ -749,14 +752,81 @@
dataWriter.write(bean);
dataWriter.writeDocumentEnd();
- String dataXml = output.toString();
+ final ArrayList readObjects = new ArrayList();
+ DataReader dataReader = new DataReader();
+
+ String dataXml = new String(output.toByteArray(), "ISO-8859-1");
+
+ assertEquals("<?xml version='1.0' encoding='ISO-8859-1'?>\n" +
+ "<data>\n" +
+ " <test id=\"1\">\n" +
+ " <value " + DatabaseIO.BASE64_ATTR_NAME + "=\"true\"><![CDATA[" + new String(Base64.encodeBase64(testedValue.getBytes()), "ISO-8859-1") + "]]></value>\n" +
+ " </test>\n" +
+ "</data>\n",
+ dataXml);
+
+ dataReader.setModel(model);
+ dataReader.setSink(new TestDataSink(readObjects));
+ dataReader.read(new ByteArrayInputStream(output.toByteArray()));
+
+ assertEquals(1, readObjects.size());
+
+ DynaBean obj = (DynaBean)readObjects.get(0);
+
+ assertEquals("test",
+ obj.getDynaClass().getName());
+ assertEquals("1",
+ obj.get("id").toString());
+ assertEquals(testedValue,
+ obj.get("value").toString());
+ }
+
+ /**
+ * Tests special characters in the data XML (for DDLUTILS-233).
+ */
+ public void testSpecialCharactersUTF8() throws Exception
+ {
+ final String testSchemaXml =
+ "<?xml version='1.0' encoding='UTF-8'?>\n"+
+ "<database xmlns='" + DatabaseIO.DDLUTILS_NAMESPACE + "' name='test'>\n" +
+ " <table name='test'>\n"+
+ " <column name='id' type='INTEGER' primaryKey='true' required='true'/>\n"+
+ " <column name='value' type='VARCHAR' size='50' required='true'/>\n"+
+ " </table>\n"+
+ "</database>";
+ final String testedValue = "Some Special Characters: \u0001\u0009\u0010";
+
+ DatabaseIO modelIO = new DatabaseIO();
+
+ modelIO.setValidateXml(true);
+
+ Database model = modelIO.read(new StringReader(testSchemaXml));
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ DataWriter dataWriter = new DataWriter(output, "UTF-8");
+ SqlDynaBean bean = (SqlDynaBean)model.createDynaBeanFor(model.getTable(0));
+
+ bean.set("id", new Integer(1));
+ bean.set("value", testedValue);
+ dataWriter.writeDocumentStart();
+ dataWriter.write(bean);
+ dataWriter.writeDocumentEnd();
+
+ String dataXml = new String(output.toByteArray(), "UTF-8");
+
+ assertEquals("<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "<data>\n" +
+ " <test id=\"1\">\n" +
+ " <value " + DatabaseIO.BASE64_ATTR_NAME + "=\"true\"><![CDATA[" + new String(Base64.encodeBase64(testedValue.getBytes()), "UTF-8") + "]]></value>\n" +
+ " </test>\n" +
+ "</data>\n",
+ dataXml);
final ArrayList readObjects = new ArrayList();
DataReader dataReader = new DataReader();
dataReader.setModel(model);
dataReader.setSink(new TestDataSink(readObjects));
- dataReader.read(new StringReader(dataXml));
+ dataReader.read(new ByteArrayInputStream(output.toByteArray()));
assertEquals(1, readObjects.size());