8253569: javax.xml.catalog.Catalog.matchURI() implementation should reset state variables
Reviewed-by: lancea, naoto
This commit is contained in:
parent
ec0897ab80
commit
eeca3a3155
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.io.IOException;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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_DEFFER = 1;
|
||||||
static final int ATTRIBUTE_RESOLUTION = 2;
|
static final int ATTRIBUTE_RESOLUTION = 2;
|
||||||
|
|
||||||
|
//Indicates a continuous session, should not reset state
|
||||||
|
boolean shouldKeepState = false;
|
||||||
|
|
||||||
//Unmodifiable features when the Catalog is created
|
//Unmodifiable features when the Catalog is created
|
||||||
CatalogFeatures features;
|
CatalogFeatures features;
|
||||||
|
|
||||||
@ -164,6 +167,16 @@ class GroupEntry extends BaseEntry {
|
|||||||
longestSuffixMatch = 0;
|
longestSuffixMatch = 0;
|
||||||
systemEntrySearched = false;
|
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.
|
* Constructs a group entry.
|
||||||
* @param catalog the catalog this GroupEntry belongs to
|
* @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.
|
* @return a URI string if a mapping is found, or null otherwise.
|
||||||
*/
|
*/
|
||||||
public String matchSystem(String systemId) {
|
public String matchSystem(String systemId) {
|
||||||
|
resetOnStart();
|
||||||
systemEntrySearched = true;
|
systemEntrySearched = true;
|
||||||
String match = null;
|
String match = null;
|
||||||
for (BaseEntry entry : entries) {
|
for (BaseEntry entry : entries) {
|
||||||
@ -296,6 +310,7 @@ class GroupEntry extends BaseEntry {
|
|||||||
* @return a URI string if a mapping is found, or null otherwise.
|
* @return a URI string if a mapping is found, or null otherwise.
|
||||||
*/
|
*/
|
||||||
public String matchPublic(String publicId) {
|
public String matchPublic(String publicId) {
|
||||||
|
resetOnStart();
|
||||||
/*
|
/*
|
||||||
When both public and system identifiers are specified, and prefer is
|
When both public and system identifiers are specified, and prefer is
|
||||||
not public (that is, system), only system entry will be used.
|
not public (that is, system), only system entry will be used.
|
||||||
@ -326,6 +341,51 @@ class GroupEntry extends BaseEntry {
|
|||||||
return matchDelegate(CatalogEntryType.DELEGATEPUBLIC, publicId);
|
return matchDelegate(CatalogEntryType.DELEGATEPUBLIC, publicId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to find a matching entry in the catalog by publicId or systemId.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 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.
|
* 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.
|
* @return a URI string if a mapping is found, or null otherwise.
|
||||||
*/
|
*/
|
||||||
public String matchURI(String uri) {
|
public String matchURI(String uri) {
|
||||||
|
resetOnStart();
|
||||||
String match = null;
|
String match = null;
|
||||||
for (BaseEntry entry : entries) {
|
for (BaseEntry entry : entries) {
|
||||||
switch (entry.type) {
|
switch (entry.type) {
|
||||||
@ -399,6 +460,7 @@ class GroupEntry extends BaseEntry {
|
|||||||
* @return the URI string if a mapping is found, or null otherwise.
|
* @return the URI string if a mapping is found, or null otherwise.
|
||||||
*/
|
*/
|
||||||
private String matchDelegate(CatalogEntryType type, String id) {
|
private String matchDelegate(CatalogEntryType type, String id) {
|
||||||
|
resetOnStart();
|
||||||
String match = null;
|
String match = null;
|
||||||
int longestMatch = 0;
|
int longestMatch = 0;
|
||||||
URI catalogId = null;
|
URI catalogId = null;
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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
|
* @return the resolved systemId if a match is found, null otherwise
|
||||||
*/
|
*/
|
||||||
static String resolve(CatalogImpl catalog, String publicId, String systemId) {
|
static String resolve(CatalogImpl catalog, String publicId, String systemId) {
|
||||||
String resolvedSystemId = null;
|
|
||||||
|
|
||||||
//search the current catalog
|
//search the current catalog
|
||||||
catalog.reset();
|
catalog.reset();
|
||||||
if (systemId != null) {
|
String resolvedSystemId = catalog.resolve(publicId, systemId);
|
||||||
/*
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
//mark the catalog as having been searched before trying alternatives
|
//mark the catalog as having been searched before trying alternatives
|
||||||
catalog.markAsSearched();
|
catalog.markAsSearched();
|
||||||
|
126
test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogReuseTest.java
Normal file
126
test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogReuseTest.java
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version='1.0'?>
|
||||||
|
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer="public">
|
||||||
|
<rewriteURI uriStartString="http://entailments/example.org/" rewritePrefix="derived/"/>
|
||||||
|
<rewriteURI uriStartString="http://example.org/" rewritePrefix="sources/"/>
|
||||||
|
</catalog>
|
Loading…
Reference in New Issue
Block a user