You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ra...@apache.org on 2008/07/28 23:43:43 UTC
svn commit: r680516 - in /commons/proper/scxml/branches/J6/src:
main/java/org/apache/commons/scxml/SCXMLHelper.java
main/java/org/apache/commons/scxml/io/SCXMLSerializer.java
test/java/org/apache/commons/scxml/io/SCXMLSerializerTest.java
Author: rahul
Date: Mon Jul 28 14:43:36 2008
New Revision: 680516
URL: http://svn.apache.org/viewvc?rev=680516&view=rev
Log:
Port r680515 from trunk.
Serialization of expressions may produce invalid XML
Variant of a patch by Ingmar Kliche <ingmar dot kliche at googlemail dot com>. Thanks Ingmar!
SCXML-76
Modified:
commons/proper/scxml/branches/J6/src/main/java/org/apache/commons/scxml/SCXMLHelper.java
commons/proper/scxml/branches/J6/src/main/java/org/apache/commons/scxml/io/SCXMLSerializer.java
commons/proper/scxml/branches/J6/src/test/java/org/apache/commons/scxml/io/SCXMLSerializerTest.java
Modified: commons/proper/scxml/branches/J6/src/main/java/org/apache/commons/scxml/SCXMLHelper.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/branches/J6/src/main/java/org/apache/commons/scxml/SCXMLHelper.java?rev=680516&r1=680515&r2=680516&view=diff
==============================================================================
--- commons/proper/scxml/branches/J6/src/main/java/org/apache/commons/scxml/SCXMLHelper.java (original)
+++ commons/proper/scxml/branches/J6/src/main/java/org/apache/commons/scxml/SCXMLHelper.java Mon Jul 28 14:43:36 2008
@@ -16,6 +16,7 @@
*/
package org.apache.commons.scxml;
+import java.io.StringWriter;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;
@@ -459,6 +460,60 @@
}
/**
+ * Escape XML strings for serialization.
+ * The basic algorithm is taken from Commons Lang (see oacl.Entities.java)
+ *
+ * @param str A string to be escaped
+ * @return The escaped string
+ */
+ public static String escapeXML(final String str) {
+ if (str == null) {
+ return null;
+ }
+
+ // Make the writer an arbitrary bit larger than the source string
+ int len = str.length();
+ StringWriter stringWriter = new StringWriter(len + 8);
+
+ for (int i = 0; i < len; i++) {
+ char c = str.charAt(i);
+ String entityName = null; // Look for XML 1.0 predefined entities
+ switch (c) {
+ case '"':
+ entityName = "quot";
+ break;
+ case '&':
+ entityName = "amp";
+ break;
+ case '\'':
+ entityName = "apos";
+ break;
+ case '<':
+ entityName = "lt";
+ break;
+ case '>':
+ entityName = "gt";
+ break;
+ }
+ if (entityName == null) {
+ if (c > 0x7F) {
+ stringWriter.write("&#");
+ stringWriter.write(Integer.toString(c));
+ stringWriter.write(';');
+ } else {
+ stringWriter.write(c);
+ }
+ } else {
+ stringWriter.write('&');
+ stringWriter.write(entityName);
+ stringWriter.write(';');
+ }
+ }
+
+ return stringWriter.toString();
+ }
+
+ /**
* Discourage instantiation since this is a utility class.
*/
private SCXMLHelper() {
@@ -472,4 +527,3 @@
private static final String NAMESPACES_KEY = "_ALL_NAMESPACES";
}
-
Modified: commons/proper/scxml/branches/J6/src/main/java/org/apache/commons/scxml/io/SCXMLSerializer.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/branches/J6/src/main/java/org/apache/commons/scxml/io/SCXMLSerializer.java?rev=680516&r1=680515&r2=680516&view=diff
==============================================================================
--- commons/proper/scxml/branches/J6/src/main/java/org/apache/commons/scxml/io/SCXMLSerializer.java (original)
+++ commons/proper/scxml/branches/J6/src/main/java/org/apache/commons/scxml/io/SCXMLSerializer.java Mon Jul 28 14:43:36 2008
@@ -214,7 +214,7 @@
for (Param p : params) {
b.append(indent).append(INDENT).append("<param name=\"").
append(p.getName()).append("\" expr=\"").
- append(p.getExpr()).append("\"/>\n");
+ append(SCXMLHelper.escapeXML(p.getExpr())).append("\"/>\n");
}
Finalize f = i.getFinalize();
if (f != null) {
@@ -280,7 +280,8 @@
b.append(" event=\"").append(t.getEvent()).append("\"");
}
if (!SCXMLHelper.isStringEmpty(t.getCond())) {
- b.append(" cond=\"").append(t.getCond()).append("\"");
+ b.append(" cond=\"").append(SCXMLHelper.escapeXML(t.getCond())).
+ append("\"");
}
boolean next = !SCXMLHelper.isStringEmpty(t.getNext());
if (next) {
@@ -352,7 +353,8 @@
} else {
b.append(indent).append(INDENT).append("<data id=\"").
append(datum.getId()).append("\" expr=\"").
- append(datum.getExpr()).append("\" />\n");
+ append(SCXMLHelper.escapeXML(datum.getExpr())).
+ append("\" />\n");
}
}
b.append(indent).append("</datamodel>\n");
@@ -411,8 +413,9 @@
if (a instanceof Var) {
Var v = (Var) a;
b.append(indent).append("<var name=\"").append(v.getName())
- .append("\" expr=\"").append(v.getExpr()).append(
- "\"/>\n");
+ .append("\" expr=\"")
+ .append(SCXMLHelper.escapeXML(v.getExpr()))
+ .append("\"/>\n");
} else if (a instanceof Assign) {
Assign asn = (Assign) a;
b.append(indent).append("<assign");
@@ -421,11 +424,13 @@
if (!SCXMLHelper.isStringEmpty(asn.getSrc())) {
b.append("\" src=\"").append(asn.getSrc());
} else {
- b.append("\" expr=\"").append(asn.getExpr());
+ b.append("\" expr=\"").
+ append(SCXMLHelper.escapeXML(asn.getExpr()));
}
} else {
b.append(" name=\"").append(asn.getName()).
- append("\" expr=\"").append(asn.getExpr());
+ append("\" expr=\"").
+ append(SCXMLHelper.escapeXML(asn.getExpr()));
}
b.append("\"/>\n");
} else if (a instanceof Send) {
@@ -436,12 +441,13 @@
.append(c.getSendid()).append("\"/>\n");
} else if (a instanceof Log) {
Log lg = (Log) a;
- b.append(indent).append("<log expr=\"").append(lg.getExpr())
- .append("\"/>\n");
+ b.append(indent).append("<log expr=\"").
+ append(SCXMLHelper.escapeXML(lg.getExpr())).
+ append("\"/>\n");
} else if (a instanceof Exit) {
Exit e = (Exit) a;
b.append(indent).append("<exit");
- String expr = e.getExpr();
+ String expr = SCXMLHelper.escapeXML(e.getExpr());
String nl = e.getNamelist();
if (expr != null) {
b.append(" expr=\"" + expr + "\"");
@@ -459,7 +465,8 @@
} else if (a instanceof ElseIf) {
ElseIf eif = (ElseIf) a;
b.append(indent).append("<elseif cond=\"")
- .append(eif.getCond()).append("\" />\n");
+ .append(SCXMLHelper.escapeXML(eif.getCond()))
+ .append("\" />\n");
}
}
return exit;
@@ -526,8 +533,8 @@
*/
public static void serializeIf(final StringBuffer b,
final If iff, final String indent) {
- b.append(indent).append("<if cond=\"").append(iff.getCond()).append(
- "\">\n");
+ b.append(indent).append("<if cond=\"").append(SCXMLHelper.
+ escapeXML(iff.getCond())).append("\">\n");
serializeActions(b, iff.getActions(), indent + INDENT);
b.append(indent).append("</if>\n");
}
Modified: commons/proper/scxml/branches/J6/src/test/java/org/apache/commons/scxml/io/SCXMLSerializerTest.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/branches/J6/src/test/java/org/apache/commons/scxml/io/SCXMLSerializerTest.java?rev=680516&r1=680515&r2=680516&view=diff
==============================================================================
--- commons/proper/scxml/branches/J6/src/test/java/org/apache/commons/scxml/io/SCXMLSerializerTest.java (original)
+++ commons/proper/scxml/branches/J6/src/test/java/org/apache/commons/scxml/io/SCXMLSerializerTest.java Mon Jul 28 14:43:36 2008
@@ -36,6 +36,7 @@
import org.apache.commons.scxml.model.SCXML;
import org.apache.commons.scxml.model.Send;
import org.apache.commons.scxml.model.State;
+import org.apache.commons.scxml.model.Transition;
import org.apache.commons.scxml.model.TransitionTarget;
import org.apache.commons.scxml.model.Var;
@@ -288,4 +289,18 @@
assertEquals(actualValue, returnValue.toString());
}
+ public void testSerializeTransitionEscapeXML() {
+ Transition t = new Transition();
+
+ // note: the '<' char has to be escaped to "<" to create valid XML
+ t.setCond("i < 3");
+
+ String actualValue = "<transition cond=\"i < 3\">\n</transition>\n";
+
+ StringBuffer returnValue = new StringBuffer();
+ SCXMLSerializer.serializeTransition(returnValue, t, "");
+
+ assertEquals(actualValue, returnValue.toString());
+ }
+
}