/* * 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(); } } } } } }