001: /*
002: * Copyright (C) 2004 Joe Walnes.
003: * Copyright (C) 2006, 2007 XStream Committers.
004: * All rights reserved.
005: *
006: * The software in this package is published under the terms of the BSD
007: * style license a copy of which has been included with this distribution in
008: * the LICENSE.txt file.
009: *
010: * Created on 14. August 2004 by Joe Walnes
011: */
012: package com.thoughtworks.xstream.io.xml;
013:
014: import com.megginson.sax.DataWriter;
015: import com.thoughtworks.acceptance.someobjects.X;
016: import com.thoughtworks.acceptance.someobjects.Y;
017: import com.thoughtworks.xstream.XStream;
018:
019: import junit.framework.TestCase;
020:
021: import javax.xml.transform.ErrorListener;
022: import javax.xml.transform.Templates;
023: import javax.xml.transform.Transformer;
024: import javax.xml.transform.TransformerException;
025: import javax.xml.transform.TransformerFactory;
026: import javax.xml.transform.stream.StreamResult;
027: import javax.xml.transform.stream.StreamSource;
028:
029: import java.io.StringReader;
030: import java.io.StringWriter;
031: import java.io.Writer;
032: import java.util.ArrayList;
033: import java.util.Arrays;
034: import java.util.Collections;
035: import java.util.List;
036:
037: /*
038: * @author Laurent Bihanic
039: */
040: public class SaxWriterTest extends TestCase {
041:
042: private final static String IDENTITY_STYLESHEET = "<xsl:stylesheet version=\"1.0\""
043: + " xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n"
044: + "\n"
045: + " <xsl:output method=\"xml\""
046: + " omit-xml-declaration=\"yes\" indent=\"no\"/>\n"
047: + "\n"
048: + " <xsl:template"
049: + " match=\"*|@*|comment()|processing-instruction()|text()\">\n"
050: + " <xsl:copy>\n"
051: + " <xsl:apply-templates"
052: + " select=\"*|@*|comment()|processing-instruction()|text()\"/>\n"
053: + " </xsl:copy>\n"
054: + " </xsl:template>\n"
055: + "</xsl:stylesheet>";
056:
057: private XStream xstream;
058: private X testInput;
059: private Templates identityStylesheet;
060:
061: protected void setUp() throws Exception {
062: super .setUp();
063: xstream = new XStream();
064: xstream.alias("x", X.class);
065: xstream.alias("y", Y.class);
066:
067: testInput = new X();
068: testInput.anInt = 9;
069: testInput.aStr = "zzz";
070: testInput.innerObj = new Y();
071: testInput.innerObj.yField = "ooo";
072:
073: identityStylesheet = TransformerFactory.newInstance()
074: .newTemplates(
075: new StreamSource(new StringReader(
076: IDENTITY_STYLESHEET)));
077: }
078:
079: public void testMarshalsObjectToSAX() {
080: String expected = "<?xml version=\"1.0\" standalone=\"yes\"?>\n\n"
081: + "<x>\n"
082: + " <aStr>zzz</aStr>\n"
083: + " <anInt>9</anInt>\n"
084: + " <innerObj>\n"
085: + " <yField>ooo</yField>\n"
086: + " </innerObj>\n"
087: + "</x>\n\n";
088:
089: Writer buffer = new StringWriter();
090: SaxWriter writer = new SaxWriter();
091: DataWriter outputter = new DataWriter(writer, buffer);
092: outputter.setIndentStep(2);
093:
094: writer.setContentHandler(outputter);
095:
096: xstream.marshal(testInput, writer);
097:
098: assertEquals(expected, buffer.toString());
099: }
100:
101: public void testAllowsStartAndEndDocCallbacksToBeSkipped() {
102: String expected = "<int>1</int>\n" + "<int>2</int>\n"
103: + "<int>3</int>\n";
104:
105: Writer buffer = new StringWriter();
106: SaxWriter writer = new SaxWriter(false);
107: DataWriter outputter = new DataWriter(writer, buffer);
108: outputter.setIndentStep(2);
109:
110: writer.setContentHandler(outputter);
111:
112: xstream.marshal(new Integer(1), writer);
113: xstream.marshal(new Integer(2), writer);
114: xstream.marshal(new Integer(3), writer);
115:
116: assertEquals(expected, buffer.toString());
117: }
118:
119: public void testMarshalsObjectToTrAX() throws Exception {
120: String expected = "<x><aStr>zzz</aStr><anInt>9</anInt>"
121: + "<innerObj><yField>ooo</yField></innerObj>" + "</x>"
122: + "<y><yField>ooo</yField></y>";
123:
124: TraxSource traxSource = new TraxSource();
125: traxSource.setXStream(xstream);
126: traxSource.setSourceAsList(Arrays.asList(new Object[] {
127: testInput, testInput.innerObj }));
128:
129: Writer buffer = new StringWriter();
130: Transformer transformer = identityStylesheet.newTransformer();
131:
132: transformer.transform(traxSource, new StreamResult(buffer));
133:
134: assertEquals(expected, buffer.toString());
135: }
136:
137: public void testNullSourceObject() {
138: TraxSource traxSource = new TraxSource();
139:
140: try {
141: traxSource.setSource(null);
142: fail("Null source object not rejected");
143: } catch (IllegalArgumentException e) { /* good! */
144: }
145: }
146:
147: public void testNullSourceList() {
148: TraxSource traxSource = new TraxSource();
149:
150: try {
151: traxSource.setSourceAsList(null);
152: fail("Null source list not rejected");
153: } catch (IllegalArgumentException e) { /* good! */
154: }
155: }
156:
157: public void testEmptySourceList() {
158: TraxSource traxSource = new TraxSource();
159:
160: try {
161: traxSource.setSourceAsList(Collections.EMPTY_LIST);
162: fail("Empty source list not rejected");
163: } catch (IllegalArgumentException e) { /* good! */
164: }
165: }
166:
167: /**
168: * This method tests a quite insidious side-effect of
169: * XStreamSource delaying the allocation and configuration of
170: * the SAXWriter until the XSLT processor requests it.
171: * <p/>
172: * SAXWriter performs a copy of the source list contents upon
173: * property setting to avoid objects being added or removed from
174: * the list during the parse.</p>
175: * <p/>
176: * To avoid just another list copy, XStreamSource does not
177: * protect itself against list changes. Hence, it is possible
178: * for an application to configure the XStreamSource and then
179: * empty the list prior triggering the XSL transformation.</p>.
180: * <p/>
181: * This method ensures SAXWriter indeed checks the list content
182: * prior starting the parse.</p>
183: */
184: public void testEmptySourceListAtParse() throws Exception {
185: TraxSource traxSource = new TraxSource();
186: Writer buffer = new StringWriter();
187:
188: List list = new ArrayList();
189: list.add(testInput);
190:
191: traxSource.setSourceAsList(list);
192: list.clear();
193:
194: Transformer transformer = identityStylesheet.newTransformer();
195: transformer.setErrorListener(new TrAXErrorListener());
196:
197: try {
198: transformer.transform(traxSource, new StreamResult(buffer));
199:
200: fail("Empty source list not rejected");
201: } catch (Exception expectedException) {
202: if (expectedException.getMessage().endsWith(
203: "shall not be an empty list")) {
204: // Good!
205: } else {
206: throw expectedException;
207: }
208: }
209: }
210:
211: private static class TrAXErrorListener implements ErrorListener {
212: public TrAXErrorListener() {
213: super ();
214: }
215:
216: public void warning(TransformerException e) {
217: /* Ignore... */
218: }
219:
220: public void error(TransformerException e) {
221: /* Ignore... */
222: }
223:
224: public void fatalError(TransformerException e)
225: throws TransformerException {
226: throw e;
227: }
228: }
229: }
|