Author: tomdz
Date: Tue May 29 21:53:41 2007
New Revision: 542749
URL: http://svn.apache.org/viewvc?view=rev&rev=542749
Log:
Fix for DDLUTILS-174
Modified:
db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DataWriter.java
db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestDataReaderAndWriter.java
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DataWriter.java
URL:
http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DataWriter.java?view=diff&rev=542749&r1=542748&r2=542749
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DataWriter.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DataWriter.java Tue May
29 21:53:41 2007
@@ -22,9 +22,11 @@
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import javax.xml.stream.XMLOutputFactory;
@@ -281,7 +283,7 @@
{
// we create an attribute only if the text is not too long
// and if it does not contain special characters
- if ((valueAsText.length() > MAX_ATTRIBUTE_LENGTH) ||
containsSpecialCharacters(valueAsText))
+ if ((valueAsText.length() > MAX_ATTRIBUTE_LENGTH) ||
analyzeText(valueAsText, null))
{
// we defer writing the sub elements
subElements.put(column.getName(), valueAsText);
@@ -294,6 +296,8 @@
}
if (!subElements.isEmpty())
{
+ List cutPoints = new ArrayList();
+
for (Iterator it = subElements.entrySet().iterator();
it.hasNext();)
{
Map.Entry entry = (Map.Entry)it.next();
@@ -304,15 +308,39 @@
_writer.writeStartElement(entry.getKey().toString());
// if the content contains special characters, we have to
apply base64 encoding to it
- // if the content is too short, then it has to contain
special characters, otherwise we check
- if ((content.length() <= MAX_ATTRIBUTE_LENGTH) ||
containsSpecialCharacters(content))
+ // if the content is too short, then it has to contain
special characters (otherwise
+ // it would have been written as an attribute already),
otherwise we check
+ cutPoints.clear();
+
+ boolean writeBase64Encoded = analyzeText(content,
cutPoints);
+
+ if (writeBase64Encoded)
{
_writer.writeAttribute(DatabaseIO.BASE64_ATTR_NAME,
"true");
_writer.writeCData(new
String(Base64.encodeBase64(content.getBytes())));
}
else
{
- _writer.writeCData(content);
+ if (cutPoints.isEmpty())
+ {
+ _writer.writeCData(content);
+ }
+ else
+ {
+ int lastPos = 0;
+
+ for (Iterator cutPointIt = cutPoints.iterator();
cutPointIt.hasNext();)
+ {
+ int curPos =
((Integer)cutPointIt.next()).intValue();
+
+ _writer.writeCData(content.substring(lastPos,
curPos));
+ lastPos = curPos;
+ }
+ if (lastPos < content.length())
+ {
+ _writer.writeCData(content.substring(lastPos));
+ }
+ }
}
_writer.writeEndElement();
@@ -335,14 +363,19 @@
/**
* Determines whether the given string contains special characters that
cannot
- * be used in XML.
+ * be used in XML, and if not, finds the cut points where to split the text
+ * when writing it in a CDATA section.
*
- * @param text The text
+ * @param text The text
+ * @param cutPoints Will be filled with cut points to split the text when
writing it
+ * in a CDATA section (only if the method returns
<code>false</code>)
* @return <code>true</code> if the text contains special characters
*/
- private boolean containsSpecialCharacters(String text)
+ private boolean analyzeText(String text, List cutPoints)
{
- int numChars = text.length();
+ List tmpCutPoints = cutPoints == null ? null : new
ArrayList();
+ int numChars = text.length();
+ int numFoundCDataEndChars = 0;
for (int charPos = 0; charPos < numChars; charPos++)
{
@@ -352,6 +385,27 @@
{
return true;
}
+ else if (cutPoints != null)
+ {
+ if ((c == ']') && ((numFoundCDataEndChars == 0) ||
(numFoundCDataEndChars == 1)))
+ {
+ numFoundCDataEndChars++;
+ }
+ else if ((c == '>') && (numFoundCDataEndChars == 2))
+ {
+ // we have to split the CDATA right here before the '>'
(see DDLUTILS-174)
+ tmpCutPoints.add(new Integer(charPos));
+ numFoundCDataEndChars = 0;
+ }
+ else
+ {
+ numFoundCDataEndChars = 0;
+ }
+ }
+ }
+ if (cutPoints != null)
+ {
+ cutPoints.addAll(tmpCutPoints);
}
return false;
}
Modified:
db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestDataReaderAndWriter.java
URL:
http://svn.apache.org/viewvc/db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestDataReaderAndWriter.java?view=diff&rev=542749&r1=542748&r2=542749
==============================================================================
---
db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestDataReaderAndWriter.java
(original)
+++
db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestDataReaderAndWriter.java
Tue May 29 21:53:41 2007
@@ -246,11 +246,15 @@
" <column name=\"value1\" type=\"VARCHAR\" size=\"50\"
required=\"true\"/>\n"+
" <column name=\"value2\" type=\"VARCHAR\" size=\"4000\"
required=\"true\"/>\n"+
" <column name=\"value3\" type=\"LONGVARCHAR\" size=\"4000\"
required=\"true\"/>\n"+
+ " <column name=\"value4\" type=\"LONGVARCHAR\" size=\"4000\"
required=\"true\"/>\n"+
+ " <column name=\"value5\" type=\"LONGVARCHAR\" size=\"4000\"
required=\"true\"/>\n"+
" </table>\n"+
"</database>";
final String testedValue1 = "<?xml version=\"1.0\"
encoding=\"ISO-8859-1\"?><test><![CDATA[some text]]></test>";
final String testedValue2 = StringUtils.repeat("a ", 1000) +
testedValue1;
final String testedValue3 = "<div>\n<h1><![CDATA[WfMOpen]]></h1>\n" +
StringUtils.repeat("Make it longer\n", 99) + "</div>";
+ final String testedValue4 = "<![CDATA[" + StringUtils.repeat("b \n",
1000) + "]]>";
+ final String testedValue5 = "<<![CDATA[" + StringUtils.repeat("b \n",
500) + "]]>><![CDATA[" + StringUtils.repeat("c \n", 500) + "]]>";
DatabaseIO modelIO = new DatabaseIO();
@@ -266,6 +270,8 @@
bean.set("value1", testedValue1);
bean.set("value2", testedValue2);
bean.set("value3", testedValue3);
+ bean.set("value4", testedValue4);
+ bean.set("value5", testedValue5);
dataWriter.writeDocumentStart();
dataWriter.write(bean);
dataWriter.writeDocumentEnd();
@@ -305,5 +311,9 @@
obj.get("value2").toString());
assertEquals(testedValue3,
obj.get("value3").toString());
+ assertEquals(testedValue4,
+ obj.get("value4").toString());
+ assertEquals(testedValue5,
+ obj.get("value5").toString());
}
}