Merge
This commit is contained in:
commit
74cfe61a56
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2017, 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
|
||||
@ -64,7 +64,7 @@ public class EventFilterSupport extends EventReaderDelegate {
|
||||
}
|
||||
|
||||
public XMLEvent nextEvent()throws XMLStreamException{
|
||||
if(super.hasNext()){
|
||||
while (super.hasNext()) {
|
||||
//get the next event by calling XMLEventReader
|
||||
XMLEvent event = super.nextEvent();
|
||||
|
||||
@ -72,27 +72,19 @@ public class EventFilterSupport extends EventReaderDelegate {
|
||||
if(fEventFilter.accept(event)){
|
||||
return event;
|
||||
}
|
||||
else{
|
||||
return nextEvent();
|
||||
}
|
||||
}else{
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
throw new NoSuchElementException();
|
||||
}//nextEvent()
|
||||
|
||||
public XMLEvent nextTag() throws XMLStreamException{
|
||||
if(super.hasNext()){
|
||||
while (super.hasNext()) {
|
||||
XMLEvent event = super.nextTag();
|
||||
//if the filter accepts this event return this event.
|
||||
if(fEventFilter.accept(event)){
|
||||
return event;
|
||||
}
|
||||
else{
|
||||
return nextTag();
|
||||
}
|
||||
}else{
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
public XMLEvent peek() throws XMLStreamException{
|
||||
|
@ -1,6 +1,6 @@
|
||||
###########################################################################
|
||||
#
|
||||
# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2015, 2017, 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
|
||||
@ -22,5 +22,3 @@
|
||||
# questions.
|
||||
#
|
||||
###########################################################################
|
||||
|
||||
javax/xml/jaxp/isolatedjdk/catalog/PropertiesTest.sh 8169827 generic-all
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2015, 2017, 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
|
||||
@ -21,11 +21,6 @@
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
echo "The suffix of ISOLATED_JDK is mandatory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
checkVariable() {
|
||||
variable='$'$1
|
||||
|
||||
@ -42,20 +37,33 @@ checkVariables() {
|
||||
done
|
||||
}
|
||||
|
||||
# Check essential variables
|
||||
checkVariables TESTJAVA TESTSRC TESTCLASSES TESTCLASSPATH
|
||||
# Script needs parameters
|
||||
if [ $# = 0 ]; then
|
||||
echo "Syntax: IsolatedJDK.sh <Suffix> [remove]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "TESTJAVA=${TESTJAVA}"
|
||||
echo "TESTSRC=${TESTSRC}"
|
||||
echo "TESTCLASSES=${TESTCLASSES}"
|
||||
echo "TESTCLASSPATH=${TESTCLASSPATH}"
|
||||
# Is it the call to remove ?
|
||||
if [ $# = 2 ]; then
|
||||
if [ "$2" = "remove" ]; then
|
||||
removeIsolatedJdk=1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check essential variables
|
||||
checkVariables TESTJAVA
|
||||
ISOLATED_JDK="./ISOLATED_JDK_$1"
|
||||
|
||||
# Remove isolated copy
|
||||
if [ "$removeIsolatedJdk" = "1" ]; then
|
||||
echo "Removing ${ISOLATED_JDK}..."
|
||||
rm -rf ${ISOLATED_JDK}
|
||||
echo "Removed."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Make an isolated copy of the testing JDK
|
||||
ISOLATED_JDK="./ISOLATED_JDK_$1"
|
||||
echo "ISOLATED_JDK=${ISOLATED_JDK}"
|
||||
|
||||
echo "Copy testing JDK started"
|
||||
echo "Copying test JDK: ${TESTJAVA} -> ${ISOLATED_JDK}..."
|
||||
cp -H -R ${TESTJAVA} ${ISOLATED_JDK} || exit 1
|
||||
chmod -R +w ${ISOLATED_JDK} || exit 1
|
||||
echo "Copy testing JDK ended"
|
||||
|
||||
echo "Copy done."
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2017, 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
|
||||
@ -37,20 +37,95 @@ import static catalog.CatalogTestUtils.deleteJAXPProps;
|
||||
import static catalog.CatalogTestUtils.generateJAXPProps;
|
||||
import static catalog.CatalogTestUtils.getCatalogPath;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.catalog.CatalogResolver;
|
||||
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/*
|
||||
* This case tests if the properties FILES, DEFER, PREFER, RESOLVE in
|
||||
* jaxp.properties and system properties could be cared.
|
||||
* @test
|
||||
* @library /javax/xml/jaxp/libs /javax/xml/jaxp/isolatedjdk
|
||||
* @run shell/timeout=600 ../IsolatedJDK.sh JAXP_PROPS
|
||||
* @run testng catalog.PropertiesTest
|
||||
* @run shell/timeout=600 ../IsolatedJDK.sh JAXP_PROPS remove
|
||||
* @summary This test case tests if the properties FILES, DEFER, PREFER,
|
||||
* RESOLVE in jaxp.properties and system properties are used.
|
||||
* It needs to run in a copied JDK as it modifies the JDK's
|
||||
* jaxp.properties file.
|
||||
* @bug 8077931
|
||||
*/
|
||||
public class PropertiesTest {
|
||||
|
||||
private static final String CATALOG_PROPERTIES = "properties.xml";
|
||||
|
||||
@Test
|
||||
/*
|
||||
* Run main in a child process as it will modify the JDK.
|
||||
*/
|
||||
public void test() throws Exception {
|
||||
// get required properties and do some assertions
|
||||
String javaclasspath = System.getProperty("java.class.path");
|
||||
Assert.assertNotNull(javaclasspath, "Test class path is null");
|
||||
String testclasspath = System.getProperty("test.class.path");
|
||||
Assert.assertNotNull(testclasspath, "Test class path is null");
|
||||
String testsourcepath = System.getProperty("test.src");
|
||||
Assert.assertNotNull(testsourcepath, "Test source path is null");
|
||||
|
||||
// start the child process
|
||||
List<String> testCall = new ArrayList<>(6);
|
||||
testCall.add(Paths.get("ISOLATED_JDK_JAXP_PROPS", "/bin", "java").toString());
|
||||
testCall.add("-cp");
|
||||
testCall.add(javaclasspath);
|
||||
testCall.add("-Dtest.class.path=" + testclasspath);
|
||||
testCall.add("-Dtest.src=" + testsourcepath);
|
||||
testCall.add("catalog.PropertiesTest");
|
||||
System.out.println("Starting child process: " + Arrays.toString(testCall.toArray()));
|
||||
Process test = new ProcessBuilder(testCall).start();
|
||||
|
||||
// wait for it to finish
|
||||
boolean interrupted = false;
|
||||
do {
|
||||
try {
|
||||
test.waitFor();
|
||||
interrupted = false;
|
||||
} catch (InterruptedException ie) {
|
||||
interrupted = true;
|
||||
}
|
||||
} while (interrupted);
|
||||
|
||||
// trace system.out of child process
|
||||
System.out.println("Proccess Out:");
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(test.getInputStream()));
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
System.out.println(line);
|
||||
}
|
||||
br.close();
|
||||
|
||||
// trace system.err of child process
|
||||
System.out.println("Proccess Err:");
|
||||
br = new BufferedReader(new InputStreamReader(test.getErrorStream()));
|
||||
while ((line = br.readLine()) != null) {
|
||||
System.out.println(line);
|
||||
}
|
||||
br.close();
|
||||
|
||||
// trace exit value and assert 0
|
||||
int exitValue = test.exitValue();
|
||||
System.out.println("Process Exit code: " + exitValue);
|
||||
Assert.assertEquals(exitValue, 0, "PropertiesTest returned nonzero exit code.");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.out.println("testJAXPProperties started");
|
||||
testJAXPProperties();
|
||||
@ -64,7 +139,8 @@ public class PropertiesTest {
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests how does jaxp.properties affects the resolution.
|
||||
* Tests how jaxp.properties affects the resolution.
|
||||
* Be careful: This test modifies jaxp.properties in the used JDK.
|
||||
*/
|
||||
private static void testJAXPProperties() throws IOException {
|
||||
generateJAXPProps(createJAXPPropsContent());
|
||||
@ -73,7 +149,7 @@ public class PropertiesTest {
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests how does system properties affects the resolution.
|
||||
* Tests how system properties affects the resolution.
|
||||
*/
|
||||
private static void testSystemProperties() {
|
||||
setSystemProperties();
|
||||
@ -104,7 +180,7 @@ public class PropertiesTest {
|
||||
// The properties in jaxp.properties don't use default values
|
||||
private static String createJAXPPropsContent() {
|
||||
Map<String, String> props = new HashMap<>();
|
||||
props.put(FEATURE_FILES, getCatalogPath(CATALOG_PROPERTIES));
|
||||
props.put(FEATURE_FILES, getCatalogPath(CATALOG_PROPERTIES).toString());
|
||||
props.put(FEATURE_DEFER, DEFER_FALSE);
|
||||
props.put(FEATURE_PREFER, PREFER_SYSTEM);
|
||||
props.put(FEATURE_RESOLVE, RESOLVE_CONTINUE);
|
||||
@ -113,7 +189,7 @@ public class PropertiesTest {
|
||||
|
||||
// The system properties don't use default values
|
||||
private static void setSystemProperties() {
|
||||
System.setProperty(FEATURE_FILES, getCatalogPath(CATALOG_PROPERTIES));
|
||||
System.setProperty(FEATURE_FILES, getCatalogPath(CATALOG_PROPERTIES).toString());
|
||||
System.setProperty(FEATURE_DEFER, DEFER_FALSE);
|
||||
System.setProperty(FEATURE_PREFER, PREFER_SYSTEM);
|
||||
System.setProperty(FEATURE_RESOLVE, RESOLVE_CONTINUE);
|
||||
|
@ -1,58 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# 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.
|
||||
|
||||
# @test
|
||||
# @bug 8077931
|
||||
# @summary This case tests if the properties FILES, DEFER, PREFER, RESOLVE in
|
||||
# jaxp.properties and system properties could be used.
|
||||
# @key intermittent
|
||||
# @library ../../libs/
|
||||
# @build catalog.CatalogTestUtils
|
||||
# @build PropertiesTest
|
||||
# @run shell/timeout=600 ../IsolatedJDK.sh JAXP_PROPS
|
||||
# @run shell/timeout=600 PropertiesTest.sh
|
||||
|
||||
echo "Copies properties.xml to class path"
|
||||
TEST_CATALOG_PATH=${TESTCLASSES}/catalog/catalogFiles
|
||||
echo "TEST_CATALOG_PATH=${TEST_CATALOG_PATH}"
|
||||
mkdir -p ${TEST_CATALOG_PATH}
|
||||
cp ${TESTSRC}/catalogFiles/properties.xml ${TEST_CATALOG_PATH}/properties.xml
|
||||
|
||||
# Execute test
|
||||
ISOLATED_JDK=./ISOLATED_JDK_JAXP_PROPS
|
||||
echo "Executes PropertiesTest"
|
||||
${ISOLATED_JDK}/bin/java -Dtest.src="${TESTSRC}/.." ${TESTVMOPTS} -cp "${TESTCLASSPATH}" catalog.PropertiesTest
|
||||
exitCode=$?
|
||||
|
||||
# Cleanup ISOLATED_JDK
|
||||
rm -rf ${ISOLATED_JDK}
|
||||
|
||||
# Results
|
||||
echo ''
|
||||
if [ $exitCode -gt 0 ]; then
|
||||
echo "PropertiesTest failed";
|
||||
else
|
||||
echo "PropertiesTest passed";
|
||||
fi
|
||||
exit $exitCode
|
||||
|
@ -69,12 +69,6 @@ final class CatalogTestUtils {
|
||||
private static final String JAXP_PROPS = "jaxp.properties";
|
||||
private static final String JAXP_PROPS_BAK = JAXP_PROPS + ".bak";
|
||||
|
||||
/*
|
||||
* Force using slash as File separator as we always use cygwin to test in
|
||||
* Windows platform.
|
||||
*/
|
||||
private static final String FILE_SEP = "/";
|
||||
|
||||
private CatalogTestUtils() { }
|
||||
|
||||
/* ********** create resolver ********** */
|
||||
@ -133,11 +127,14 @@ final class CatalogTestUtils {
|
||||
/* ********** jaxp.properties ********** */
|
||||
|
||||
/*
|
||||
* Generates the jaxp.properties with the specified content.
|
||||
* Generates jaxp.properties with the specified content,
|
||||
* takes a backup if possible.
|
||||
*/
|
||||
static void generateJAXPProps(String content) throws IOException {
|
||||
Path filePath = getJAXPPropsPath();
|
||||
Path bakPath = filePath.resolveSibling(JAXP_PROPS_BAK);
|
||||
System.out.println("Creating new file " + filePath +
|
||||
", saving old version to " + bakPath + ".");
|
||||
if (Files.exists(filePath) && !Files.exists(bakPath)) {
|
||||
Files.move(filePath, bakPath);
|
||||
}
|
||||
@ -146,14 +143,16 @@ final class CatalogTestUtils {
|
||||
}
|
||||
|
||||
/*
|
||||
* Deletes the jaxp.properties.
|
||||
* Deletes jaxp.properties, restoring backup if possible.
|
||||
*/
|
||||
static void deleteJAXPProps() throws IOException {
|
||||
Path filePath = getJAXPPropsPath();
|
||||
Path bakPath = filePath.resolveSibling(JAXP_PROPS_BAK);
|
||||
System.out.println("Removing file " + filePath +
|
||||
", restoring old version from " + bakPath + ".");
|
||||
Files.delete(filePath);
|
||||
Path bakFilePath = filePath.resolveSibling(JAXP_PROPS_BAK);
|
||||
if (Files.exists(bakFilePath)) {
|
||||
Files.move(bakFilePath, filePath);
|
||||
if (Files.exists(bakPath)) {
|
||||
Files.move(bakPath, filePath);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2017, 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
|
||||
@ -85,13 +85,13 @@ public class JAXPTestUtilities {
|
||||
* A map storing every test's current test file pointer. File number should
|
||||
* be incremental and it's a thread-safe reading on this file number.
|
||||
*/
|
||||
private static final ConcurrentHashMap<Class, Integer> currentFileNumber
|
||||
private static final ConcurrentHashMap<Class<?>, Integer> currentFileNumber
|
||||
= new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* BOM table for storing BOM header.
|
||||
*/
|
||||
private final static Map<String, byte[]> bom = new HashMap();
|
||||
private final static Map<String, byte[]> bom = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Initialize all BOM headers.
|
||||
@ -313,7 +313,7 @@ public class JAXPTestUtilities {
|
||||
* @param clazz test class.
|
||||
* @return next test output file name.
|
||||
*/
|
||||
public static String getNextFile(Class clazz) {
|
||||
public static String getNextFile(Class<?> clazz) {
|
||||
int nextNumber = currentFileNumber.contains(clazz)
|
||||
? currentFileNumber.get(clazz) + 1 : 1;
|
||||
Integer i = currentFileNumber.putIfAbsent(clazz, nextNumber);
|
||||
@ -332,7 +332,7 @@ public class JAXPTestUtilities {
|
||||
* path.
|
||||
* @return a string represents the full path of accessing path.
|
||||
*/
|
||||
public static String getPathByClassName(Class clazz, String relativeDir) {
|
||||
public static String getPathByClassName(Class<?> clazz, String relativeDir) {
|
||||
String javaSourcePath = System.getProperty("test.src").replaceAll("\\" + File.separator, FILE_SEP);
|
||||
String normalizedPath = Paths.get(javaSourcePath, relativeDir).normalize().
|
||||
toAbsolutePath().toString();
|
||||
@ -435,7 +435,7 @@ public class JAXPTestUtilities {
|
||||
*/
|
||||
public static void runWithTmpPermission(Runnable r, Permission... ps) {
|
||||
JAXPPolicyManager policyManager = JAXPPolicyManager.getJAXPPolicyManager(false);
|
||||
List<Integer> tmpPermissionIndexes = new ArrayList();
|
||||
List<Integer> tmpPermissionIndexes = new ArrayList<>();
|
||||
if (policyManager != null) {
|
||||
for (Permission p : ps)
|
||||
tmpPermissionIndexes.add(policyManager.addTmpPermission(p));
|
||||
@ -459,7 +459,7 @@ public class JAXPTestUtilities {
|
||||
*/
|
||||
public static <T> T runWithTmpPermission(Supplier<T> s, Permission... ps) {
|
||||
JAXPPolicyManager policyManager = JAXPPolicyManager.getJAXPPolicyManager(false);
|
||||
List<Integer> tmpPermissionIndexes = new ArrayList();
|
||||
List<Integer> tmpPermissionIndexes = new ArrayList<>();
|
||||
if (policyManager != null) {
|
||||
for (Permission p : ps)
|
||||
tmpPermissionIndexes.add(policyManager.addTmpPermission(p));
|
||||
@ -483,7 +483,7 @@ public class JAXPTestUtilities {
|
||||
*/
|
||||
public static void tryRunWithTmpPermission(RunnableWithException r, Permission... ps) throws Exception {
|
||||
JAXPPolicyManager policyManager = JAXPPolicyManager.getJAXPPolicyManager(false);
|
||||
List<Integer> tmpPermissionIndexes = new ArrayList();
|
||||
List<Integer> tmpPermissionIndexes = new ArrayList<>();
|
||||
if (policyManager != null) {
|
||||
for (Permission p : ps)
|
||||
tmpPermissionIndexes.add(policyManager.addTmpPermission(p));
|
||||
|
@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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 stream.EventsTest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import javax.xml.stream.EventFilter;
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.events.XMLEvent;
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8173111
|
||||
* @summary tests that filtering out nested elements doesn't end up in
|
||||
* a StackOverflowException
|
||||
* @run testng/othervm stream.EventsTest.EventFilterSupportTest
|
||||
* @author danielfuchs
|
||||
*/
|
||||
public class EventFilterSupportTest {
|
||||
static final String ROOT = "xml";
|
||||
static final String NEXT = "foo";
|
||||
static final String SMOKE = "<?xml version=\"1.0\" encoding=\"US-ASCII\"?>"
|
||||
+ "<xml><foo><foo><foo></foo></foo></foo></xml>";
|
||||
// A number high enough to trigger StackOverflowException before the fix.
|
||||
static final int MAX = 100_000;
|
||||
|
||||
public static void main(String[] args)
|
||||
throws XMLStreamException, IOException {
|
||||
smokeTest();
|
||||
testNextEvent(MAX);
|
||||
testNextTag(MAX);
|
||||
System.out.println("Tests passed...");
|
||||
}
|
||||
|
||||
// The smoke test just verifies that our TestInputStream works as
|
||||
// expected and produces the expected stream of characters.
|
||||
// Here we test it with 4 nested elements.
|
||||
@Test
|
||||
public static void smokeTest() throws IOException {
|
||||
System.out.println("\nSmoke test...");
|
||||
StringBuilder sb = new StringBuilder();
|
||||
try (InputStream ts = new TestInputStream(4)) {
|
||||
int c;
|
||||
while ((c = ts.read()) != -1) {
|
||||
System.out.print((char)c);
|
||||
sb.append((char)c);
|
||||
}
|
||||
}
|
||||
assertEquals(sb.toString(), SMOKE, "Smoke test failed");
|
||||
System.out.println("\nSmoke test passed\n");
|
||||
}
|
||||
|
||||
// Test calling XMLEventReader.nextEvent()
|
||||
@Test
|
||||
public static void testNextEvent() throws IOException, XMLStreamException {
|
||||
testNextEvent(MAX);
|
||||
}
|
||||
|
||||
// Without the fix, will cause a StackOverflowException if 'max' is high
|
||||
// enough
|
||||
private static void testNextEvent(int max)
|
||||
throws IOException, XMLStreamException {
|
||||
System.out.println("\nTest nextEvent (" + max + ")...");
|
||||
XMLEventReader reader = createXmlReader(max);
|
||||
XMLEvent event;
|
||||
do {
|
||||
event = reader.nextEvent();
|
||||
System.out.println(event);
|
||||
} while (event.getEventType() != XMLEvent.END_DOCUMENT);
|
||||
System.out.println("nextEvent passed\n");
|
||||
}
|
||||
|
||||
// Test calling XMLEventReader.nextTag()
|
||||
@Test
|
||||
public static void testNextTag() throws IOException, XMLStreamException {
|
||||
testNextTag(MAX);
|
||||
}
|
||||
|
||||
// Without the fix, will cause a StackOverflowException if 'max' is high
|
||||
// enough
|
||||
private static void testNextTag(int max)
|
||||
throws IOException, XMLStreamException {
|
||||
System.out.println("\nTest nextTag (" + max + ")...");
|
||||
XMLEventReader reader = createXmlReader(max);
|
||||
XMLEvent event;
|
||||
do {
|
||||
event = reader.nextTag();
|
||||
System.out.println(event);
|
||||
if (event.getEventType() == XMLEvent.END_ELEMENT
|
||||
&& event.asEndElement().getName().getLocalPart().equals(ROOT)) {
|
||||
break;
|
||||
}
|
||||
} while (true);
|
||||
System.out.println("nextTag passed\n");
|
||||
}
|
||||
|
||||
private static XMLEventReader createXmlReader(int max)
|
||||
throws XMLStreamException {
|
||||
TestInputStream ts = new TestInputStream(max);
|
||||
XMLInputFactory xif = XMLInputFactory.newInstance();
|
||||
XMLEventReader reader = xif.createXMLEventReader(ts);
|
||||
return xif.createFilteredReader(reader, new TagFilter(max));
|
||||
}
|
||||
|
||||
// An input stream that pretends to contain 'max - 1' nested NEXT tags
|
||||
// within a ROOT element:
|
||||
// <?xml version="1.0" encoding="US-ASCII"?>
|
||||
// <ROOT><NEXT><NEXT>...</NEXT></NEXT></ROOT>
|
||||
// (1 ROOT element + max-1 nested NEXT elements)
|
||||
public static class TestInputStream extends InputStream {
|
||||
|
||||
int open = 0;
|
||||
int i = 0;
|
||||
int n = 0;
|
||||
final int max;
|
||||
|
||||
public TestInputStream(int max) {
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
String tag() {
|
||||
if (n == 0) {
|
||||
// opening first element - includes the XML processing instruction.
|
||||
return "?xml version=\"1.0\" encoding=\"US-ASCII\"?><" + ROOT;
|
||||
}
|
||||
if (n == 2 * max -1) {
|
||||
// closing the first element
|
||||
// we have 'max' opening tags (0..max-1) followed by
|
||||
// 'max' closing tags (max..2*max-1)
|
||||
// for n in [0..max-1] we open the tags,
|
||||
// for n in [max..2*max-1] we close them (in reverse order)
|
||||
return ROOT;
|
||||
}
|
||||
// everything between [1..max-2] is a NEXT element tag (opening
|
||||
// or closing)
|
||||
return NEXT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
if (n >= 2 * max) return -1;
|
||||
if (open == 0) {
|
||||
open = 1;
|
||||
return '<';
|
||||
}
|
||||
if (open == 1 && n >= max) {
|
||||
// we have opened the ROOT element + n-1 nested NEXT elements,
|
||||
// so now we need to start closing them all in reverse order.
|
||||
open = 2;
|
||||
return '/';
|
||||
}
|
||||
String tag = tag();
|
||||
if (open > 0 && i < tag.length()) {
|
||||
return tag.charAt(i++);
|
||||
}
|
||||
if (open > 0 && i == tag.length()) {
|
||||
open = 0; i = 0; n++;
|
||||
return '>';
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class TagFilter implements EventFilter {
|
||||
int count;
|
||||
final int max;
|
||||
|
||||
public TagFilter(int max) {
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
// Filters everything except the ROOT element.
|
||||
@Override
|
||||
public boolean accept(XMLEvent event) {
|
||||
int type = event.getEventType();
|
||||
if (type == XMLEvent.START_ELEMENT) {
|
||||
String loc = event.asStartElement().getName().getLocalPart();
|
||||
if (count == 0 || count == 1) System.out.println("<" + loc + ">");
|
||||
count++;
|
||||
return ROOT.equals(loc);
|
||||
}
|
||||
if (type == XMLEvent.END_ELEMENT) {
|
||||
if (count == max) System.out.println("Got " + count + " elements");
|
||||
String loc = event.asEndElement().getName().getLocalPart();
|
||||
count--;
|
||||
if (count == 0 || count == 1) System.out.println("</" + loc + ">");
|
||||
return ROOT.equals(loc);
|
||||
}
|
||||
if (type == XMLEvent.PROCESSING_INSTRUCTION) return true;
|
||||
if (type == XMLEvent.START_DOCUMENT) return true;
|
||||
if (type == XMLEvent.END_DOCUMENT) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user