From eeca3a31559c2e334958c6d929cff8eb350c32a3 Mon Sep 17 00:00:00 2001 From: Joe Wang Date: Thu, 31 Mar 2022 01:50:41 +0000 Subject: [PATCH] 8253569: javax.xml.catalog.Catalog.matchURI() implementation should reset state variables Reviewed-by: lancea, naoto --- .../javax/xml/catalog/CatalogImpl.java | 4 +- .../classes/javax/xml/catalog/GroupEntry.java | 64 ++++++++- .../share/classes/javax/xml/catalog/Util.java | 20 +-- .../unittest/catalog/CatalogReuseTest.java | 126 ++++++++++++++++++ .../jaxp/unittest/catalog/catalogReuse.xml | 5 + 5 files changed, 197 insertions(+), 22 deletions(-) create mode 100644 test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogReuseTest.java create mode 100644 test/jaxp/javax/xml/jaxp/unittest/catalog/catalogReuse.xml diff --git a/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java b/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java index 92c407e103f..6bbbdc77b7d 100644 --- a/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java +++ b/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 @@ -28,10 +28,8 @@ import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl; import java.io.IOException; import java.net.MalformedURLException; import java.net.URI; -import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; -import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; diff --git a/src/java.xml/share/classes/javax/xml/catalog/GroupEntry.java b/src/java.xml/share/classes/javax/xml/catalog/GroupEntry.java index 103078b1555..1082f00450e 100644 --- a/src/java.xml/share/classes/javax/xml/catalog/GroupEntry.java +++ b/src/java.xml/share/classes/javax/xml/catalog/GroupEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 @@ -40,6 +40,9 @@ class GroupEntry extends BaseEntry { static final int ATTRIBUTE_DEFFER = 1; static final int ATTRIBUTE_RESOLUTION = 2; + //Indicates a continuous session, should not reset state + boolean shouldKeepState = false; + //Unmodifiable features when the Catalog is created CatalogFeatures features; @@ -164,6 +167,16 @@ class GroupEntry extends BaseEntry { longestSuffixMatch = 0; systemEntrySearched = false; } + + /** + * Resets the state of the Catalog instance, allowing it to be reused. + */ + private void resetOnStart() { + if (this instanceof Catalog && !shouldKeepState) { + reset(); + } + } + /** * Constructs a group entry. * @param catalog the catalog this GroupEntry belongs to @@ -228,6 +241,7 @@ class GroupEntry extends BaseEntry { * @return a URI string if a mapping is found, or null otherwise. */ public String matchSystem(String systemId) { + resetOnStart(); systemEntrySearched = true; String match = null; for (BaseEntry entry : entries) { @@ -296,6 +310,7 @@ class GroupEntry extends BaseEntry { * @return a URI string if a mapping is found, or null otherwise. */ public String matchPublic(String publicId) { + resetOnStart(); /* When both public and system identifiers are specified, and prefer is not public (that is, system), only system entry will be used. @@ -326,6 +341,51 @@ class GroupEntry extends BaseEntry { return matchDelegate(CatalogEntryType.DELEGATEPUBLIC, publicId); } + /** + * Attempt to find a matching entry in the catalog by publicId or systemId. + * + *

+ * The resolution follows the following rules determined by the prefer + * setting: + * + * prefer "system": attempts to resolve with a system entry; attempts to + * resolve with a public entry when only publicId is specified. + * + * prefer "public": attempts to resolve with a system entry; attempts to + * resolve with a public entry if no matching system entry is found. + * + * If no match is found, continue searching uri entries. + * + * @param publicId The public identifier of the external entity being + * referenced. + * + * @param systemId The system identifier of the external entity being + * referenced. + * + * @return the resolved systemId if a match is found, null otherwise + */ + String resolve(String publicId, String systemId) { + String resolvedSystemId = null; + shouldKeepState = true; + if (systemId != null) { + /* + If a system identifier is specified, it is used no matter how + prefer is set. + */ + resolvedSystemId = matchSystem(systemId); + } + + if (resolvedSystemId == null && publicId != null) { + resolvedSystemId = matchPublic(publicId); + } + + if (resolvedSystemId == null && systemId != null) { + resolvedSystemId = matchURI(systemId); + } + shouldKeepState = false; + return resolvedSystemId; + } + /** * Attempt to find a matching entry in the catalog by the uri element. * @@ -340,6 +400,7 @@ class GroupEntry extends BaseEntry { * @return a URI string if a mapping is found, or null otherwise. */ public String matchURI(String uri) { + resetOnStart(); String match = null; for (BaseEntry entry : entries) { switch (entry.type) { @@ -399,6 +460,7 @@ class GroupEntry extends BaseEntry { * @return the URI string if a mapping is found, or null otherwise. */ private String matchDelegate(CatalogEntryType type, String id) { + resetOnStart(); String match = null; int longestMatch = 0; URI catalogId = null; diff --git a/src/java.xml/share/classes/javax/xml/catalog/Util.java b/src/java.xml/share/classes/javax/xml/catalog/Util.java index af84c3f825d..50a72aed620 100644 --- a/src/java.xml/share/classes/javax/xml/catalog/Util.java +++ b/src/java.xml/share/classes/javax/xml/catalog/Util.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 @@ -74,25 +74,9 @@ class Util { * @return the resolved systemId if a match is found, null otherwise */ static String resolve(CatalogImpl catalog, String publicId, String systemId) { - String resolvedSystemId = null; - //search the current catalog catalog.reset(); - if (systemId != null) { - /* - If a system identifier is specified, it is used no matter how - prefer is set. - */ - resolvedSystemId = catalog.matchSystem(systemId); - } - - if (resolvedSystemId == null && publicId != null) { - resolvedSystemId = catalog.matchPublic(publicId); - } - - if (resolvedSystemId == null && systemId != null) { - resolvedSystemId = catalog.matchURI(systemId); - } + String resolvedSystemId = catalog.resolve(publicId, systemId); //mark the catalog as having been searched before trying alternatives catalog.markAsSearched(); diff --git a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogReuseTest.java b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogReuseTest.java new file mode 100644 index 00000000000..6bc563f3df3 --- /dev/null +++ b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogReuseTest.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2022, 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 catalog; + +import java.net.URI; +import javax.xml.catalog.Catalog; +import javax.xml.catalog.CatalogFeatures; +import javax.xml.catalog.CatalogManager; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/* + * @test + * @bug 8253569 + * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest + * @run testng catalog.CatalogReuseTest + * @summary Verifies that a catalog can be reused. + */ +public class CatalogReuseTest extends CatalogSupportBase { + static final CatalogFeatures FEATURES_STRICT = CatalogFeatures.builder(). + with(CatalogFeatures.Feature.RESOLVE, "strict").build(); + + /* + DataProvider: reuses a catalog. The length of the URIs is in descending order. + Data columns: catalog, uri, expected + */ + @DataProvider(name = "dataWithCatalogD") + public Object[][] dataWithCatalogD() { + Catalog c = getCatalog(); + return new Object[][]{ + {c, "http://entailments/example.org/A/B/derived.ttl", "derived/A/B/derived.ttl"}, + {c, "http://example.org/A/B.owl", "sources/A/B.owl"}, + }; + } + + /* + DataProvider: reuses a catalog. The length of the URIs is in ascending order. + Data columns: catalog, uri, expected + */ + @DataProvider(name = "dataWithCatalogA") + public Object[][] dataWithCatalogA() { + Catalog c = getCatalog(); + return new Object[][]{ + {c, "http://example.org/A/B.owl", "sources/A/B.owl"}, + {c, "http://entailments/example.org/A/B/derived.ttl", "derived/A/B/derived.ttl"}, + }; + } + + /* + DataProvider: provides no catalog. A new catalog will be created for each test. + Data columns: uri, expected + */ + @DataProvider(name = "dataWithoutCatalog") + public Object[][] dataWithoutCatalog() { + return new Object[][]{ + {"http://entailments/example.org/A/B/derived.ttl", "derived/A/B/derived.ttl"}, + {"http://example.org/A/B.owl", "sources/A/B.owl"}, + }; + } + + /* + * Initializing fields + */ + @BeforeClass + public void setUpClass() throws Exception { + super.setUp(); + } + + /* + * Verifies that a Catalog object can be reused, that no state data are + * in the way of a subsequent matching attempt. + */ + @Test(dataProvider = "dataWithCatalogD") + public void testD(Catalog c, String uri, String expected) throws Exception { + String m = c.matchURI(uri); + Assert.assertTrue(m.endsWith(expected), "Expected: " + expected); + } + + /* + * Verifies that a Catalog object can be reused. + */ + @Test(dataProvider = "dataWithCatalogA") + public void testA(Catalog c, String uri, String expected) throws Exception { + String m = c.matchURI(uri); + Assert.assertTrue(m.endsWith(expected), "Expected: " + expected); + } + + /* + * Verifies that a match is found in a newly created Catalog. + */ + @Test(dataProvider = "dataWithoutCatalog") + public void testNew(String uri, String expected) throws Exception { + Catalog c = getCatalog(); + String m = c.matchURI(uri); + Assert.assertTrue(m.endsWith(expected), "Expected: " + expected); + + } + + private Catalog getCatalog() { + String uri = "file://" + slash + filepath + "/catalogReuse.xml"; + Catalog c = CatalogManager.catalog(FEATURES_STRICT, uri != null? URI.create(uri) : null); + return c; + } +} diff --git a/test/jaxp/javax/xml/jaxp/unittest/catalog/catalogReuse.xml b/test/jaxp/javax/xml/jaxp/unittest/catalog/catalogReuse.xml new file mode 100644 index 00000000000..adbee60ba87 --- /dev/null +++ b/test/jaxp/javax/xml/jaxp/unittest/catalog/catalogReuse.xml @@ -0,0 +1,5 @@ + + + + +