You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by wo...@apache.org on 2013/12/05 03:59:34 UTC
svn commit: r1548001 - in /commons/proper/scxml/trunk/src:
main/java/org/apache/commons/scxml2/io/SCXMLReader.java
test/java/org/apache/commons/scxml2/io/SCXMLReaderTest.java
test/java/org/apache/commons/scxml2/io/scxml-with-invalid-elems.xml
Author: woonsan
Date: Thu Dec 5 02:59:34 2013
New Revision: 1548001
URL: http://svn.apache.org/r1548001
Log:
SCXML-177: adding strict option and silent option in SCXMLReader
Added:
commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/io/scxml-with-invalid-elems.xml
Modified:
commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java
commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/io/SCXMLReaderTest.java
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java?rev=1548001&r1=1548000&r2=1548001&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java Thu Dec 5 02:59:34 2013
@@ -818,10 +818,12 @@ public final class SCXMLReader {
* @param parent The parent {@link TransitionTarget} for this final (null for top level state).
*
* @throws XMLStreamException An exception processing the underlying {@link XMLStreamReader}.
+ * @throws ModelException The Commons SCXML object model is incomplete or inconsistent (includes
+ * errors in the SCXML document that may not be identified by the schema).
*/
private static void readFinal(final XMLStreamReader reader, final Configuration configuration, final SCXML scxml,
final TransitionTarget parent)
- throws XMLStreamException {
+ throws XMLStreamException, ModelException {
Final end = new Final();
end.setId(readAV(reader, ATTR_ID));
@@ -1002,10 +1004,12 @@ public final class SCXMLReader {
* @param parent The parent {@link TransitionTarget} for this datamodel (null for top level).
*
* @throws XMLStreamException An exception processing the underlying {@link XMLStreamReader}.
+ * @throws ModelException The Commons SCXML object model is incomplete or inconsistent (includes
+ * errors in the SCXML document that may not be identified by the schema).
*/
private static void readDatamodel(final XMLStreamReader reader, final Configuration configuration, final SCXML scxml,
final TransitionTarget parent)
- throws XMLStreamException {
+ throws XMLStreamException, ModelException {
Datamodel dm = new Datamodel();
@@ -1075,10 +1079,12 @@ public final class SCXMLReader {
* @param parent The parent {@link State} for this invoke.
*
* @throws XMLStreamException An exception processing the underlying {@link XMLStreamReader}.
+ * @throws ModelException The Commons SCXML object model is incomplete or inconsistent (includes
+ * errors in the SCXML document that may not be identified by the schema).
*/
private static void readInvoke(final XMLStreamReader reader, final Configuration configuration,
final State parent)
- throws XMLStreamException {
+ throws XMLStreamException, ModelException {
Invoke invoke = new Invoke();
invoke.setSrc(readAV(reader, ATTR_SRC));
@@ -1153,10 +1159,12 @@ public final class SCXMLReader {
* @param invoke The parent {@link Invoke} for this finalize.
*
* @throws XMLStreamException An exception processing the underlying {@link XMLStreamReader}.
+ * @throws ModelException The Commons SCXML object model is incomplete or inconsistent (includes
+ * errors in the SCXML document that may not be identified by the schema).
*/
private static void readFinalize(final XMLStreamReader reader, final Configuration configuration,
final State state, final Invoke invoke)
- throws XMLStreamException {
+ throws XMLStreamException, ModelException {
Finalize finalize = new Finalize();
readExecutableContext(reader, configuration, state, finalize, null);
@@ -1191,10 +1199,12 @@ public final class SCXMLReader {
* @param state The parent composite {@link State} for this initial.
*
* @throws XMLStreamException An exception processing the underlying {@link XMLStreamReader}.
+ * @throws ModelException The Commons SCXML object model is incomplete or inconsistent (includes
+ * errors in the SCXML document that may not be identified by the schema).
*/
private static void readInitial(final XMLStreamReader reader, final Configuration configuration,
final State state)
- throws XMLStreamException {
+ throws XMLStreamException, ModelException {
Initial initial = new Initial();
@@ -1241,10 +1251,12 @@ public final class SCXMLReader {
* @param tt The parent {@link TransitionTarget} for this history.
*
* @throws XMLStreamException An exception processing the underlying {@link XMLStreamReader}.
+ * @throws ModelException The Commons SCXML object model is incomplete or inconsistent (includes
+ * errors in the SCXML document that may not be identified by the schema).
*/
private static void readHistory(final XMLStreamReader reader, final Configuration configuration,
final SCXML scxml, final TransitionTarget tt)
- throws XMLStreamException {
+ throws XMLStreamException, ModelException {
History history = new History();
history.setId(readAV(reader, ATTR_ID));
@@ -1294,10 +1306,12 @@ public final class SCXMLReader {
* @param tt The parent {@link TransitionTarget} for this onentry.
*
* @throws XMLStreamException An exception processing the underlying {@link XMLStreamReader}.
+ * @throws ModelException The Commons SCXML object model is incomplete or inconsistent (includes
+ * errors in the SCXML document that may not be identified by the schema).
*/
private static void readOnEntry(final XMLStreamReader reader, final Configuration configuration, final SCXML scxml,
final TransitionTarget tt)
- throws XMLStreamException {
+ throws XMLStreamException, ModelException {
OnEntry onentry = new OnEntry();
readExecutableContext(reader, configuration, tt, onentry, null);
@@ -1314,10 +1328,12 @@ public final class SCXMLReader {
* @param tt The parent {@link TransitionTarget} for this onexit.
*
* @throws XMLStreamException An exception processing the underlying {@link XMLStreamReader}.
+ * @throws ModelException The Commons SCXML object model is incomplete or inconsistent (includes
+ * errors in the SCXML document that may not be identified by the schema).
*/
private static void readOnExit(final XMLStreamReader reader, final Configuration configuration, final SCXML scxml,
final TransitionTarget tt)
- throws XMLStreamException {
+ throws XMLStreamException, ModelException {
OnExit onexit = new OnExit();
readExecutableContext(reader, configuration, tt, onexit, null);
@@ -1333,10 +1349,12 @@ public final class SCXMLReader {
* @param tt The parent {@link TransitionTarget} for this transition.
*
* @throws XMLStreamException An exception processing the underlying {@link XMLStreamReader}.
+ * @throws ModelException The Commons SCXML object model is incomplete or inconsistent (includes
+ * errors in the SCXML document that may not be identified by the schema).
*/
private static void readTransition(final XMLStreamReader reader, final Configuration configuration,
final TransitionTarget tt)
- throws XMLStreamException {
+ throws XMLStreamException, ModelException {
Transition t = new Transition();
t.setCond(readAV(reader, ATTR_COND));
@@ -1368,10 +1386,12 @@ public final class SCXMLReader {
* @param iff The optional parent {@link If} if this is child content of an if action.
*
* @throws XMLStreamException An exception processing the underlying {@link XMLStreamReader}.
+ * @throws ModelException The Commons SCXML object model is incomplete or inconsistent (includes
+ * errors in the SCXML document that may not be identified by the schema).
*/
private static void readExecutableContext(final XMLStreamReader reader, final Configuration configuration,
final TransitionTarget tt, final Executable executable, final If iff)
- throws XMLStreamException {
+ throws XMLStreamException, ModelException {
String end = "";
if (iff != null) {
@@ -1492,10 +1512,12 @@ public final class SCXMLReader {
* @param parent The optional parent {@link If} if this <if> is a child of another.
*
* @throws XMLStreamException An exception processing the underlying {@link XMLStreamReader}.
+ * @throws ModelException The Commons SCXML object model is incomplete or inconsistent (includes
+ * errors in the SCXML document that may not be identified by the schema).
*/
private static void readIf(final XMLStreamReader reader, final Configuration configuration,
final TransitionTarget tt, final Executable executable, final If parent)
- throws XMLStreamException {
+ throws XMLStreamException, ModelException {
If iff = new If();
iff.setCond(readAV(reader, ATTR_COND));
@@ -2066,16 +2088,23 @@ public final class SCXMLReader {
* @param name The local name of the ignored element.
*
* @throws XMLStreamException An exception processing the underlying {@link XMLStreamReader}.
+ * @throws ModelException The Commons SCXML object model is incomplete or inconsistent (includes
+ * errors in the SCXML document that may not be identified by the schema).
*/
private static void reportIgnoredElement(final XMLStreamReader reader, final Configuration configuration,
final String parent, final String nsURI, final String name)
- throws XMLStreamException {
+ throws XMLStreamException, ModelException {
org.apache.commons.logging.Log log = LogFactory.getLog(SCXMLReader.class);
StringBuffer sb = new StringBuffer();
sb.append("Ignoring unknown or invalid element <").append(name).append("> in namespace \"").append(nsURI).append("\" as child ").
append(" of <").append(parent).append("> at ").append(reader.getLocation());
- log.warn(sb.toString());
+ if (!configuration.isSilent() && log.isWarnEnabled()) {
+ log.warn(sb.toString());
+ }
+ if (configuration.isStrict()) {
+ throw new ModelException(sb.toString());
+ }
XMLReporter reporter = configuration.reporter;
if (reporter != null) {
reporter.report(sb.toString(), "COMMONS_SCXML", null, reader.getLocation());
@@ -2354,6 +2383,18 @@ public final class SCXMLReader {
*/
PathResolver pathResolver;
+ /**
+ * Whether to silently ignore any unknown or invalid elements
+ * or to leave warning logs for those.
+ */
+ boolean silent;
+
+ /**
+ * Whether to strictly throw a model exception when there are any unknown or invalid elements
+ * or to leniently allow to read the model even with those.
+ */
+ boolean strict;
+
/*
* Public constructors
*/
@@ -2473,6 +2514,42 @@ public final class SCXMLReader {
final String encoding, final String systemId, final boolean validate, final PathResolver pathResolver,
final SCXML parent, final List<CustomAction> customActions, final ClassLoader customActionClassLoader,
final boolean useContextClassLoaderForCustomActions) {
+ this(factoryId, factoryClassLoader, allocator, properties, resolver, reporter, encoding, systemId,
+ validate, pathResolver, parent, customActions, customActionClassLoader,
+ useContextClassLoaderForCustomActions, false, false);
+ }
+
+ /**
+ * All-purpose package access constructor.
+ *
+ * @param factoryId The <code>factoryId</code> to use.
+ * @param factoryClassLoader The {@link ClassLoader} to use for the {@link XMLInputFactory} instance to
+ * create.
+ * @param allocator The {@link XMLEventAllocator} for the {@link XMLInputFactory}.
+ * @param properties The map of properties (keys are property name strings, values are object property values)
+ * for the {@link XMLInputFactory}.
+ * @param resolver The {@link XMLResolver} for the {@link XMLInputFactory}.
+ * @param reporter The {@link XMLReporter} for the {@link XMLInputFactory}.
+ * @param encoding The <code>encoding</code> to use for the {@link XMLStreamReader}
+ * @param systemId The <code>systemId</code> to use for the {@link XMLStreamReader}
+ * @param validate Whether to validate the input with the XML Schema for SCXML.
+ * @param pathResolver The Commons SCXML {@link PathResolver} to use for this document.
+ * @param parent The parent SCXML document if this document is src'ed in via the <state> or
+ * <parallel> element's "src" attribute.
+ * @param customActions The list of Commons SCXML custom actions that will be available for this document.
+ * @param customActionClassLoader The {@link ClassLoader} to use for the {@link CustomAction} instances to
+ * create.
+ * @param useContextClassLoaderForCustomActions Whether to use the thread context {@link ClassLoader} for the
+ * {@link CustomAction} instances to create.
+ * @param silent Whether to silently ignore any unknown or invalid elements or to leave warning logs for those.
+ * @param strict Whether to strictly throw a model exception when there are any unknown or invalid elements
+ * or to leniently allow to read the model even with those.
+ */
+ Configuration(final String factoryId, final ClassLoader factoryClassLoader, final XMLEventAllocator allocator,
+ final Map<String, Object> properties, final XMLResolver resolver, final XMLReporter reporter,
+ final String encoding, final String systemId, final boolean validate, final PathResolver pathResolver,
+ final SCXML parent, final List<CustomAction> customActions, final ClassLoader customActionClassLoader,
+ final boolean useContextClassLoaderForCustomActions, final boolean silent, final boolean strict) {
this.factoryId = factoryId;
this.factoryClassLoader = factoryClassLoader;
this.allocator = allocator;
@@ -2488,6 +2565,8 @@ public final class SCXMLReader {
this.customActionClassLoader = customActionClassLoader;
this.useContextClassLoaderForCustomActions = useContextClassLoaderForCustomActions;
this.namespaces = new HashMap<String, Stack<String>>();
+ this.silent = silent;
+ this.strict = strict;
}
/*
@@ -2507,6 +2586,42 @@ public final class SCXMLReader {
return currentNamespaces;
}
+ /**
+ * Returns true if it is set to read models silently without any model error warning logs.
+ * @return
+ * @see {@link #silent}
+ */
+ public boolean isSilent() {
+ return silent;
+ }
+
+ /**
+ * Turn on/off silent mode (whether to read models silently without any model error warning logs)
+ * @param silent
+ * @see {@link #silent}
+ */
+ public void setSilent(boolean silent) {
+ this.silent = silent;
+ }
+
+ /**
+ * Returns true if it is set to check model strictly with throwing exceptions on any model error.
+ * @return
+ * @see {@link #strict}
+ */
+ public boolean isStrict() {
+ return strict;
+ }
+
+ /**
+ * Turn on/off strict model (whether to check model strictly with throwing exception on any model error)
+ * @param strict
+ * @see {@link #strict}
+ */
+ public void setStrict(boolean strict) {
+ this.strict = strict;
+ }
+
}
}
Modified: commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/io/SCXMLReaderTest.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/io/SCXMLReaderTest.java?rev=1548001&r1=1548000&r2=1548001&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/io/SCXMLReaderTest.java (original)
+++ commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/io/SCXMLReaderTest.java Thu Dec 5 02:59:34 2013
@@ -20,17 +20,27 @@ import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.LinkedList;
import java.util.List;
+import javax.xml.stream.XMLStreamException;
+
import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogConfigurationException;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.logging.impl.LogFactoryImpl;
+import org.apache.commons.logging.impl.SimpleLog;
import org.apache.commons.scxml2.ErrorReporter;
import org.apache.commons.scxml2.EventDispatcher;
import org.apache.commons.scxml2.SCInstance;
import org.apache.commons.scxml2.SCXMLExpressionException;
import org.apache.commons.scxml2.SCXMLTestHelper;
import org.apache.commons.scxml2.TriggerEvent;
+import org.apache.commons.scxml2.io.SCXMLReader.Configuration;
import org.apache.commons.scxml2.model.Action;
import org.apache.commons.scxml2.model.CustomAction;
+import org.apache.commons.scxml2.model.Data;
+import org.apache.commons.scxml2.model.Datamodel;
import org.apache.commons.scxml2.model.ExternalContent;
import org.apache.commons.scxml2.model.Final;
import org.apache.commons.scxml2.model.ModelException;
@@ -39,28 +49,49 @@ import org.apache.commons.scxml2.model.S
import org.apache.commons.scxml2.model.State;
import org.apache.commons.scxml2.model.Transition;
import org.junit.After;
+import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
+import org.junit.BeforeClass;
import org.junit.Test;
import org.w3c.dom.Node;
-import javax.xml.stream.XMLStreamException;
/**
* Unit tests {@link org.apache.commons.scxml2.io.SCXMLReader}.
*/
public class SCXMLReaderTest {
+ private static String oldLogFactoryProperty;
+
// Test data
private URL microwave01, microwave02, transitions01, prefix01, send01,
- microwave03, microwave04, scxmlinitialattr, action01;
+ microwave03, microwave04, scxmlinitialattr, action01,
+ scxmlWithInvalidElems;
private SCXML scxml;
private String scxmlAsString;
+ private Log scxmlReaderLog;
+
+ @BeforeClass
+ public static void beforeClass() {
+ oldLogFactoryProperty = System.getProperty(LogFactory.FACTORY_PROPERTY);
+ System.setProperty(LogFactory.FACTORY_PROPERTY, RecordingLogFactory.class.getName());
+ }
+
+ @AfterClass
+ public static void afterClass() {
+ if (oldLogFactoryProperty == null) {
+ System.clearProperty(LogFactory.FACTORY_PROPERTY);
+ } else {
+ System.setProperty(LogFactory.FACTORY_PROPERTY, oldLogFactoryProperty);
+ }
+ }
+
/**
* Set up instance variables required by this test case.
*/
@Before
- public void setUp() {
+ public void before() {
microwave01 = this.getClass().getClassLoader().
getResource("org/apache/commons/scxml2/env/jsp/microwave-01.xml");
microwave02 = this.getClass().getClassLoader().
@@ -79,14 +110,20 @@ public class SCXMLReaderTest {
getResource("org/apache/commons/scxml2/io/scxml-initial-attr.xml");
action01 = this.getClass().getClassLoader().
getResource("org/apache/commons/scxml2/io/custom-action-body-test-1.xml");
+ scxmlWithInvalidElems = this.getClass().getClassLoader().
+ getResource("org/apache/commons/scxml2/io/scxml-with-invalid-elems.xml");
+
+ scxmlReaderLog = LogFactory.getLog(SCXMLReader.class);
+ clearRecordedLogMessages();
}
/**
* Tear down instance variables required by this test case.
*/
@After
- public void tearDown() {
- microwave01 = microwave02 = microwave03 = microwave04 = transitions01 = prefix01 = send01 = action01 = null;
+ public void after() {
+ microwave01 = microwave02 = microwave03 = microwave04 = transitions01 = prefix01 = send01 = action01 =
+ scxmlinitialattr = scxmlWithInvalidElems = null;
scxml = null;
scxmlAsString = null;
}
@@ -192,12 +229,113 @@ public class SCXMLReaderTest {
Assert.assertTrue(my.getExternalNodes().size() > 0);
}
+ @Test
+ public void testSCXMLReaderWithInvalidElements() throws Exception {
+ // In the default lenient/verbose mode (strict == false && silent == false),
+ // the model exception should be just logged without a model exception.
+ Configuration configuration = new Configuration();
+ scxml = SCXMLReader.read(scxmlWithInvalidElems, configuration);
+ Assert.assertNotNull(scxml);
+ scxmlAsString = serialize(scxml);
+ Assert.assertNotNull(scxmlAsString);
+ Final foo = (Final) scxml.getInitialTarget();
+ Assert.assertEquals("foo", foo.getId());
+ Datamodel dataModel = scxml.getDatamodel();
+ Assert.assertNotNull(dataModel);
+ List<Data> dataList = dataModel.getData();
+ Assert.assertEquals(1, dataList.size());
+ Assert.assertEquals("time", dataList.get(0).getId());
+ assertContainsRecordedLogMessage("Ignoring unknown or invalid element <baddata> in namespace \"http://www.w3.org/2005/07/scxml\" as child of <datamodel>");
+ assertContainsRecordedLogMessage("Ignoring unknown or invalid element <baddata> in namespace \"http://www.example.com/scxml\" as child of <datamodel>");
+ assertContainsRecordedLogMessage("Ignoring unknown or invalid element <trace> in namespace \"http://www.w3.org/2005/07/scxml\" as child of <onentry>");
+ assertContainsRecordedLogMessage("Ignoring unknown or invalid element <onbeforeexit> in namespace \"http://www.w3.org/2005/07/scxml\" as child of <final>");
+
+ // In the lenient/silent mode (strict == false && silent == true),
+ // no model exception is logged.
+ clearRecordedLogMessages();
+ scxml = null;
+ configuration = new Configuration();
+ configuration.setStrict(false);
+ configuration.setSilent(true);
+ scxml = SCXMLReader.read(scxmlWithInvalidElems, configuration);
+ Assert.assertNotNull(scxml);
+ scxmlAsString = serialize(scxml);
+ Assert.assertNotNull(scxmlAsString);
+ foo = (Final) scxml.getInitialTarget();
+ Assert.assertEquals("foo", foo.getId());
+ dataModel = scxml.getDatamodel();
+ Assert.assertNotNull(dataModel);
+ dataList = dataModel.getData();
+ Assert.assertEquals(1, dataList.size());
+ Assert.assertEquals("time", dataList.get(0).getId());
+ assertNotContainsRecordedLogMessage("Ignoring unknown or invalid element <baddata> in namespace \"http://www.w3.org/2005/07/scxml\" as child of <datamodel>");
+ assertNotContainsRecordedLogMessage("Ignoring unknown or invalid element <baddata> in namespace \"http://www.example.com/scxml\" as child of <datamodel>");
+ assertNotContainsRecordedLogMessage("Ignoring unknown or invalid element <trace> in namespace \"http://www.w3.org/2005/07/scxml\" as child of <onentry>");
+ assertNotContainsRecordedLogMessage("Ignoring unknown or invalid element <onbeforeexit> in namespace \"http://www.w3.org/2005/07/scxml\" as child of <final>");
+
+ // In strict/verbose mode (strict == true && silent == false), it should fail to read the model and catch a model exception
+ // with warning logs because of the invalid <baddata> element.
+ clearRecordedLogMessages();
+ scxml = null;
+ configuration = new Configuration();
+ configuration.setStrict(true);
+ configuration.setSilent(false);
+ try {
+ scxml = SCXMLReader.read(scxmlWithInvalidElems, configuration);
+ Assert.fail("In strict mode, it should have thrown a model exception.");
+ } catch (ModelException e) {
+ Assert.assertTrue(e.getMessage().contains("Ignoring unknown or invalid element <baddata>"));
+ }
+ assertContainsRecordedLogMessage("Ignoring unknown or invalid element <baddata> in namespace \"http://www.w3.org/2005/07/scxml\" as child of <datamodel>");
+ assertContainsRecordedLogMessage("Ignoring unknown or invalid element <baddata> in namespace \"http://www.example.com/scxml\" as child of <datamodel>");
+ assertContainsRecordedLogMessage("Ignoring unknown or invalid element <trace> in namespace \"http://www.w3.org/2005/07/scxml\" as child of <onentry>");
+ assertContainsRecordedLogMessage("Ignoring unknown or invalid element <onbeforeexit> in namespace \"http://www.w3.org/2005/07/scxml\" as child of <final>");
+
+ // In strict/silent mode (strict == true && silent == true), it should fail to read the model and catch a model exception
+ // without warning logs because of the invalid <baddata> element.
+ clearRecordedLogMessages();
+ scxml = null;
+ configuration = new Configuration();
+ configuration.setStrict(true);
+ configuration.setSilent(true);
+ try {
+ scxml = SCXMLReader.read(scxmlWithInvalidElems, configuration);
+ Assert.fail("In strict mode, it should have thrown a model exception.");
+ } catch (ModelException e) {
+ Assert.assertTrue(e.getMessage().contains("Ignoring unknown or invalid element <baddata>"));
+ }
+ assertNotContainsRecordedLogMessage("Ignoring unknown or invalid element <baddata> in namespace \"http://www.w3.org/2005/07/scxml\" as child of <datamodel>");
+ assertNotContainsRecordedLogMessage("Ignoring unknown or invalid element <baddata> in namespace \"http://www.example.com/scxml\" as child of <datamodel>");
+ assertNotContainsRecordedLogMessage("Ignoring unknown or invalid element <trace> in namespace \"http://www.w3.org/2005/07/scxml\" as child of <onentry>");
+ assertNotContainsRecordedLogMessage("Ignoring unknown or invalid element <onbeforeexit> in namespace \"http://www.w3.org/2005/07/scxml\" as child of <final>");
+ }
+
private String serialize(final SCXML scxml) throws IOException, XMLStreamException {
scxmlAsString = SCXMLWriter.write(scxml);
Assert.assertNotNull(scxmlAsString);
return scxmlAsString;
}
+ private void assertContainsRecordedLogMessage(final String message) {
+ if (scxmlReaderLog instanceof RecordingSimpleLog) {
+ Assert.assertTrue(((RecordingSimpleLog) scxmlReaderLog).containsMessage(
+ "Ignoring unknown or invalid element <baddata> in namespace \"http://www.w3.org/2005/07/scxml\" as child of <datamodel>"));
+ }
+ }
+
+ private void assertNotContainsRecordedLogMessage(final String message) {
+ if (scxmlReaderLog instanceof RecordingSimpleLog) {
+ Assert.assertFalse(((RecordingSimpleLog) scxmlReaderLog).containsMessage(
+ "Ignoring unknown or invalid element <baddata> in namespace \"http://www.w3.org/2005/07/scxml\" as child of <datamodel>"));
+ }
+ }
+
+ private void clearRecordedLogMessages() {
+ if (scxmlReaderLog instanceof RecordingSimpleLog) {
+ ((RecordingSimpleLog) scxmlReaderLog).clearMessages();
+ }
+ }
+
public static class MyAction extends Action implements ExternalContent {
private static final long serialVersionUID = 1L;
@@ -218,5 +356,60 @@ public class SCXMLReaderTest {
}
+ /**
+ * Custom LogFactory implementation to capture log messages for logging verification.
+ */
+ public static class RecordingLogFactory extends LogFactoryImpl {
+ @Override
+ protected Log newInstance(String name) throws LogConfigurationException {
+ return new RecordingSimpleLog(name);
+ }
+ }
+
+ /**
+ * Custom Simple Log implemenation capturing log messages
+ */
+ public static class RecordingSimpleLog extends SimpleLog {
+
+ private static final long serialVersionUID = 1L;
+
+ private List<String> messages = new LinkedList<String>();
+
+ public RecordingSimpleLog(String name) {
+ super(name);
+ }
+
+ /**
+ * Clear all the recorded log messages.
+ */
+ public void clearMessages() {
+ messages.clear();
+ }
+
+ /**
+ * Return true if msg is found in any recorded log messages.
+ * @param msg
+ * @return
+ */
+ public boolean containsMessage(final String msg) {
+ for (String message : messages) {
+ if (message.contains(msg)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ protected boolean isLevelEnabled(int logLevel) {
+ return (logLevel >= LOG_LEVEL_INFO);
+ }
+
+ @Override
+ protected void log(int type, Object message, Throwable t) {
+ super.log(type, message, t);
+ messages.add(message.toString());
+ }
+ }
}
Added: commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/io/scxml-with-invalid-elems.xml
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/io/scxml-with-invalid-elems.xml?rev=1548001&view=auto
==============================================================================
--- commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/io/scxml-with-invalid-elems.xml (added)
+++ commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml2/io/scxml-with-invalid-elems.xml Thu Dec 5 02:59:34 2013
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<!-- Used for SrcTest.java in io package -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml"
+ xmlns:example="http://www.example.com/scxml"
+ version="1.0"
+ initial="foo">
+
+ <datamodel>
+ <data id="time"/>
+ <baddata id="badtime"/>
+ <example:baddata id="badtime2"/>
+ </datamodel>
+
+ <final id="foo">
+ <onentry>
+ <!-- <trace/> is invalid. -->
+ <trace expr="'tracing...'" />
+ </onentry>
+ <!-- <onbeforeexit/> is invalid. -->
+ <onbeforeexit>
+ </onbeforeexit>
+ </final>
+
+</scxml>