--- /dev/null 2015-04-26 17:31:22.381138994 -0700 +++ new/test/javax/xml/jaxp/unittest/parsers/SaxParserStop.java 2015-09-30 14:27:44.624633858 -0700 @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package parsers; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import org.testng.Assert; +import org.testng.annotations.Test; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +/* + * @bug 8136778 + * @summary This test verifies the stop and resume methods of the SAX parser + * @author Joe Wang + */ +public class SaxParserStop { + //yep, we're only displaying two records per page + static final int RECORD_PER_PAGE = 2; + SAXParser parser = null; + DataCollector dataCollector = null; + + @Test + public void test() { + InputStream xmlFile = getClass().getResourceAsStream("SaxParserStop.xml"); + + int page; + //Get content for page 1; The parser will be started and stopped after + //collecting the required data. + page = 1; + List content = getPage(xmlFile, page); + Assert.assertEquals(2, content.size()); + Assert.assertEquals("The Martian", content.get(0)); + Assert.assertEquals("The Doll", content.get(1)); + + //The parser will be resumed and stopped again after collecting page 2. + page = 2; + content = getPage(xmlFile, page); + Assert.assertEquals(2, content.size()); + Assert.assertEquals("Transformer X", content.get(0)); + Assert.assertEquals("The Spaceship", content.get(1)); + } + + /** + * Parses the xml and returns a list of toys. + * + * @param is the input stream + * @return a list of toys + */ + private List getPage(InputStream is, int page) { + if (parser == null) { + parser = getParser(); + } + + try { + if (page == 1) { + dataCollector = new DataCollector(parser, RECORD_PER_PAGE); + parser.parse(is, dataCollector); + } else { + dataCollector.reset(); + parser.resume(); + } + return dataCollector.getContent(); + } catch (SAXException | IOException ex) { + Assert.fail("Failed to parse the inputstream", ex); + } + + return null; + } + + /** + * Returns an instance of SAXParser. + * @return a SAXParser + */ + private SAXParser getParser() { + SAXParser p = null; + try { + SAXParserFactory spf = SAXParserFactory.newInstance(); + spf.setNamespaceAware(true); + spf.setValidating(false); + spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + p = spf.newSAXParser(); + } catch (ParserConfigurationException | SAXException e) { + Assert.fail("Failed to create a parser", e); + } + return p; + } + + /** + * This class is responsible for collecting names from a toys catalog. + */ + class DataCollector extends DefaultHandler { + List toys = new ArrayList<>(); + int numOfRecord; + int recordCount; + String toyId; + SAXParser parser; + boolean inToy = false; + boolean collectName = false; + + /** + * Constructs a DataCollector instance with a parser. + * + * @param parser the SAX parser + * @param num the number of records to be collected + */ + public DataCollector(SAXParser parser, int num) { + this.parser = parser; + numOfRecord = num; + } + + public List getContent() { + return new ArrayList<>(toys); + } + + /** + * Resets the collector to get data for the next page + */ + public void reset() { + toys.clear(); + recordCount = 0; + toyId = null; + inToy = false; + collectName = false; + } + + @Override + public void startElement(String namespaceURI, + String localName, + String qName, + Attributes atts) + throws SAXException { + if (inToy) { + if (localName.equals("name")) { + collectName = true; + } + } else if (localName.equals("toy")) { + inToy = true; + String id = atts.getValue("id"); + toyId = "toy" + id; + } + } + + @Override + public void characters(char ch[], int start, int length) + throws SAXException { + if (collectName) { + toys.add(new String(ch, start, length)); + recordCount++; + collectName = false; + } + } + + /** + * Handles endElement event + */ + @Override + public void endElement(String namespaceURI, String localName, String qName) + throws SAXException { + if (inToy) { + if (localName.equals("toy")) { + inToy = false; + if (recordCount == numOfRecord) { + parser.stop(); + } + } + } + } + } +}