/*
* Copyright 2010 Philipp Erlacher
*
* Licensed 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.
*/
package org.exolab.castor.xml;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import junit.framework.TestCase;
import org.easymock.EasyMock;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
/**
* This tests the methods which SaxEventFromStaxProducer invokes on a ContentHandler.
*
* The methods which SaxEventFromStaxProducer invokes on an ErrorHandler are tested separately.
*
* @author philipperlacher
*
*/
public class Sax2EventFromStaxProducerTest extends TestCase {
/**
* all of the readers are global so that they can be closed after testing
*/
private XMLEventReader eventReader = null;
private XMLStreamReader streamReader = null;
private Reader reader;
/**
* Sets the contentMock to replay mode. Starts the producer.
* Verifies the result.
* @param contentMock an EasyMock contentHandler object
* @param producer a {@link SAX2EventAndErrorProducer}
*/
private void compareMethodInvocations(ContentHandler contentMock, SAX2EventAndErrorProducer producer) throws SAXException {
EasyMock.replay(contentMock);
producer.start();
EasyMock.verify(contentMock);
}
/**
* This method uses a XMLReader, sets recorder as ContentHandler and parses testString.
*
* @param testString
* @param contentMock a EasyMock object as contentHandler. It's in the recordMode and records event.
* @return attributes every start element contains attribute. Those get returned as a Queue
*/
private void parseWithSax(String testString, ContentHandler recorder)
throws XMLStreamException, FactoryConfigurationError, SAXException,
IOException {
InputStream in = new ByteArrayInputStream(testString.getBytes("UTF-8"));
XMLReader parser = XMLReaderFactory.createXMLReader();
parser.setContentHandler(recorder);
parser.parse(new InputSource(in));
}
/**
* this method instantiate a {@link SAX2EventAndErrorProducer} with a {@link XMLEventReader}
* and the given {@link ContentHandler}
*
* @param testString this string is going to be parsed by the {@link XMLEventReader}.
* @return {@link SAX2EventAndErrorProducer} A usable producer with a {@link ContentHandler} set as content handler
* @throws XMLStreamException
*/
private SAX2EventAndErrorProducer getSax2EventFromStaxEventProducer(String testString)
throws XMLStreamException {
XMLInputFactory factory = XMLInputFactory.newInstance();
reader = new StringReader(testString);
eventReader = factory.createXMLEventReader(reader);
return BaseSax2EventFromStaxProducer.createSax2EventFromStax(eventReader);
}
/**
* This method instantiate a {@link SAX2EventAndErrorProducer} with a {@link XMLEventReader}
* and the given {@link ContentHandler}
*
* @param testString this string is going to be parsed by the {@link XMLEventReader}
* @return {@link SAX2EventAndErrorProducer} a usable producer
* @throws XMLStreamException
*/
private SAX2EventAndErrorProducer getSax2EventFromStaxStreamProducer(String testString)
throws XMLStreamException {
XMLInputFactory factory = XMLInputFactory.newInstance();
reader = new StringReader(testString);
streamReader = factory.createXMLStreamReader(reader);
return BaseSax2EventFromStaxProducer.createSax2EventFromStax(streamReader);
}
/**
* Tests if {@link SAX2EventAndErrorProducer} invokes the same methods on a {@link ContentHandler} as a
* SAX parser would. this tests StaxStream2SaxBridge as well as
* StaxEvent2SaxBridge
*
* @param sample
* A sample XML
* @throws XMLStreamException
* @throws FactoryConfigurationError
* @throws SAXException
* @throws IOException
*/
public void executeTest(String sample) throws XMLStreamException,
FactoryConfigurationError, SAXException, IOException {
ContentHandler contentMock = EasyMock.createStrictMock(ContentHandler.class);
Sax2MethodRecorder recorder = new Sax2MethodRecorder(contentMock);
parseWithSax(sample,recorder);
SAX2EventAndErrorProducer producer = getSax2EventFromStaxEventProducer(sample);
producer.setContentHandler(contentMock);
compareMethodInvocations(contentMock, producer);
EasyMock.reset(contentMock);
recorder = new Sax2MethodRecorder(contentMock);
parseWithSax(sample,recorder);
producer = getSax2EventFromStaxStreamProducer(sample);
producer.setContentHandler(contentMock);
compareMethodInvocations(contentMock,producer);
}
/**
* runs executeTest with a sample XML in which there are two attributes
* within a single element
*
* @throws XMLStreamException
* @throws FactoryConfigurationError
* @throws SAXException
* @throws IOException
*/
public void testLNameInStartElement() throws XMLStreamException,
FactoryConfigurationError, SAXException, IOException {
String sample = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<Person first-name=\"Zaphod\" last-name=\"Beeblebrox\" />";
executeTest(sample);
}
/**
* runs executeTest with a sample XML in which there is a default namespace
* declaration
*
* @throws XMLStreamException
* @throws FactoryConfigurationError
* @throws SAXException
* @throws IOException
*/
public void testNamespaceUriInStartElement() throws SAXException,
IOException, XMLStreamException, FactoryConfigurationError {
String sample = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<Person xmlns=\"http://early.pearly\" first-name=\"Zaphod\" last-name=\"Beeblebrox\" />";
executeTest(sample);
}
/**
* runs executeTest with a sample XML in which there is a namespace
* declaration with a prefix
*
* @throws XMLStreamException
* @throws FactoryConfigurationError
* @throws SAXException
* @throws IOException
*/
public void testPrefixInStartElement() throws SAXException, IOException,
XMLStreamException, FactoryConfigurationError {
String sample = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<p:Person xmlns:p=\"http://early.pearly\" first-name=\"Zaphod\" last-name=\"Beeblebrox\" />";
executeTest(sample);
}
/**
* runs executeTest with a sample XML in which there is a namespace
* declaration with a prefix and the attributes belong to that namespace
*
* @throws XMLStreamException
* @throws FactoryConfigurationError
* @throws SAXException
* @throws IOException
*/
public void testStartElementPrefixAttributes() throws SAXException,
IOException, XMLStreamException, FactoryConfigurationError {
String sample = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<p:Person xmlns:p=\"http://early.pearly\" p:first-name=\"Zaphod\" p:last-name=\"Beeblebrox\" />";
executeTest(sample);
}
/**
* runs executeTest with a sample XML in which there is a root element with
* a namespace declaration and a subelement
*
* @throws XMLStreamException
* @throws FactoryConfigurationError
* @throws SAXException
* @throws IOException
*/
public void testStartElementChildren() throws SAXException, IOException,
XMLStreamException, FactoryConfigurationError {
String sample = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<p:Person xmlns:p=\"http://early.pearly\">"
+ "<p:first-name p:last-name=\"Beeblebrox\">Zaphod</p:first-name>"
+ "</p:Person>";
executeTest(sample);
}
/**
* runs executeTest with a sample XML in which there is a root element with
* a namespace declaration, and many sub elements
*
* @throws XMLStreamException
* @throws FactoryConfigurationError
* @throws SAXException
* @throws IOException
*/
public void testMoreElements() throws SAXException, IOException,
XMLStreamException, FactoryConfigurationError {
String sample = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<p:Author xmlns:p=\"http://ursa.minor\">"
+ "<first-name>Ford</first-name><last-name>Prefect</last-name>"
+ "<book><title>About Earth</title><description>mostly harmless</description></book>"
+ "</p:Author>";
executeTest(sample);
}
/**
* runs executeTest with a sample XML in which there are namespace
* declarations in the root element and namespace declarations in sub
* elements, default namespace is also being declared
*
* @throws XMLStreamException
* @throws FactoryConfigurationError
* @throws SAXException
* @throws IOException
*/
public void testStartPrefix() throws SAXException, IOException,
XMLStreamException, FactoryConfigurationError {
String sample = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<Authors xmlns=\"http://betel.geuse\" xmlns:p=\"http://ursa.minor\" xmlns:pM=\"http://ursa.maior\">"
+ "<q:Author xmlns:q=\"http://heart.gold\">"
+ "<first-name>Ford</first-name><last-name>Prefect</last-name>"
+ "<book><title>About Earth</title><description>mostly harmless</description></book>"
+ "</q:Author>"
+ "<pM:Author>"
+ "<first-name>Ford</first-name><last-name>Prefect</last-name>"
+ "<book><title>About Earth</title><description>mostly harmless</description></book>"
+ "</pM:Author>" + "</Authors>";
executeTest(sample);
}
/**
* runs executeTest with a sample XML in which there are namespace
* declarations in the root element and namespace declarations in sub
* elements, default namespace is also being declared
*
* @throws XMLStreamException
* @throws FactoryConfigurationError
* @throws SAXException
* @throws IOException
*/
public void testEndPrefixMapping() throws SAXException, IOException,
XMLStreamException, FactoryConfigurationError {
String sample = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<Authors xmlns=\"http://betel.geuse\" xmlns:p=\"http://ursa.minor\" xmlns:pM=\"http://ursa.maior\">"
+ "<q:Author xmlns:q=\"http://heart.gold\"></q:Author>"
+ "<pM:Author><book></book></pM:Author>" + "</Authors>";
executeTest(sample);
}
/**
* runs executeTest with a sample XML in which a DTD is used to define the
* structure of the XML and in the XML are ignorableWhitspaces
*
* @throws XMLStreamException
* @throws FactoryConfigurationError
* @throws SAXException
* @throws IOException
*/
public void testIgnorableWhitspace() throws XMLStreamException,
FactoryConfigurationError, SAXException, IOException {
String sample = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<!DOCTYPE Author [" + " <!ELEMENT Author (name)>"
+ " <!ELEMENT name (#PCDATA)>" + "]>" + "<Author>"
+ " <name>" + " Ford" + " </name>" + "</Author>";
executeTest(sample);
}
/**
* runs executeTest with a sample XML in which a DTD is used to define the
* structure of the XML and in the XML are ignorableWhitspaces
*
* @throws XMLStreamException
* @throws FactoryConfigurationError
* @throws SAXException
* @throws IOException
*/
public void testIgnorableWhitspaceWithoutDTD() throws XMLStreamException,
FactoryConfigurationError, SAXException, IOException {
String sample = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<!DOCTYPE Author [" + " <!ELEMENT Author (name)>"
+ " <!ELEMENT name (#PCDATA)>" + "]>" + "<Author>"
+ " <name>" + " Ford\n" + " </name>\n" + "</Author>";
// executeTest(sample);
}
/**
* Test if long characters that will send more characters event are recorded
* and sent properly
*
* @throws XMLStreamException
* @throws FactoryConfigurationError
* @throws SAXException
* @throws IOException
*/
public void testCharactersBuffer() throws XMLStreamException,
FactoryConfigurationError, SAXException, IOException {
StringBuffer buffer = new StringBuffer();
buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<Person>"
+ "<first-name> ");
for (int i = 0; i < 1028; i++)
buffer.append("realyLongName" + i);
buffer.append("</first-name></Person>");
executeTest(buffer.toString());
}
/**
* tests if locator is produced properly (= is the same than the SAX output)
* @throws SAXException
* @throws IOException
* @throws XMLStreamException
*/
public void testDocumentLocator() throws SAXException, IOException, XMLStreamException {
String sample = "<?xml version=\"1.0\" ?>"
+ "<Person xmlns=\"http://early.pearly\" first-name=\"Zaphod\" last-name=\"Beeblebrox\" />";
DocumentLocatorRecorder recorder = new DocumentLocatorRecorder();
parseWithSax(sample, recorder);
System.out.println();
recorder.setReplayMode();
SAX2EventAndErrorProducer producer = getSax2EventFromStaxStreamProducer(sample);
producer.setContentHandler(recorder);
producer.start();
}
/**
* tests if locator is produced properly (= the same as it is produced from SAX)
* @throws SAXException
* @throws IOException
* @throws XMLStreamException
*/
public void testAttributes() throws SAXException, IOException, XMLStreamException {
String sample = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<Authors xmlns=\"http://betel.geuse\" xmlns:p=\"http://ursa.minor\" xmlns:pM=\"http://ursa.maior\">"
+ "<q:Author xmlns:q=\"http://heart.gold\"></q:Author>"
+ "<pM:Author><book></book></pM:Author>" + "</Authors>";
AttributeRecorder recorder = new AttributeRecorder();
parseWithSax(sample, recorder);
System.out.println();
recorder.setReplayMode();
SAX2EventAndErrorProducer producer = getSax2EventFromStaxStreamProducer(sample);
producer.setContentHandler(recorder);
producer.start();
}
/**
* Closing the reader.
*
* @see junit.framework.TestCase#tearDown()
*/
public void tearDown() throws Exception {
if (reader != null)
reader.close();
reader = null;
if (eventReader != null)
eventReader.close();
eventReader = null;
if (streamReader != null)
streamReader.close();
streamReader = null;
}
}