8316996: Catalog API Enhancement: add a factory method
Reviewed-by: naoto, lancea
This commit is contained in:
parent
d2260146c9
commit
96bec3584c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2023, 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
|
||||
@ -41,6 +41,7 @@ import static javax.xml.catalog.BaseEntry.CatalogEntryType;
|
||||
import static javax.xml.catalog.CatalogFeatures.DEFER_TRUE;
|
||||
import javax.xml.catalog.CatalogFeatures.Feature;
|
||||
import static javax.xml.catalog.CatalogMessages.formatMessage;
|
||||
import javax.xml.catalog.CatalogResolver.NotFoundAction;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
@ -59,8 +60,8 @@ class CatalogImpl extends GroupEntry implements Catalog {
|
||||
//Value of the defer attribute to determine if alternative catalogs are read
|
||||
boolean isDeferred = true;
|
||||
|
||||
//Value of the resolve attribute
|
||||
ResolveType resolveType = ResolveType.STRICT;
|
||||
//Value of the resolve attribute mapped to the resolver's action type
|
||||
NotFoundAction resolveType = NotFoundAction.STRICT;
|
||||
|
||||
//indicate whether the Catalog is empty
|
||||
boolean isEmpty;
|
||||
@ -259,7 +260,7 @@ class CatalogImpl extends GroupEntry implements Catalog {
|
||||
* @param value The value of the resolve attribute
|
||||
*/
|
||||
public final void setResolve(String value) {
|
||||
resolveType = ResolveType.getType(value);
|
||||
resolveType = NotFoundAction.getType(value);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -267,7 +268,7 @@ class CatalogImpl extends GroupEntry implements Catalog {
|
||||
*
|
||||
* @return The value of the resolve attribute
|
||||
*/
|
||||
public final ResolveType getResolve() {
|
||||
public final NotFoundAction getResolve() {
|
||||
return resolveType;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2023, 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
|
||||
@ -77,6 +77,12 @@ public final class CatalogManager {
|
||||
/**
|
||||
* Creates an instance of a {@code CatalogResolver} using the specified catalog.
|
||||
*
|
||||
* @apiNote The {@code CatalogResolver} created by this method delegates to
|
||||
* the underlying {@code catalog}'s RESOLVE property. The {@code CatalogResolver}
|
||||
* created by {@link #catalogResolver(Catalog, CatalogResolver.NotFoundAction)
|
||||
* catalogResover(Catalog, CatalogResolver.NotFoundAction)} is based on the
|
||||
* specified action type when it is unable to resolve a reference.
|
||||
*
|
||||
* @param catalog the catalog instance
|
||||
* @return an instance of a {@code CatalogResolver}
|
||||
*/
|
||||
@ -85,6 +91,28 @@ public final class CatalogManager {
|
||||
return new CatalogResolverImpl(catalog);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code CatalogResolver} that resolves external references with the given
|
||||
* {@code catalog} and {@link CatalogResolver.NotFoundAction action} type
|
||||
* that determines the behavior when unable to resolve a reference.
|
||||
* <p>
|
||||
* The {@link CatalogResolver.NotFoundAction action} types are mapped to the values
|
||||
* of the {@link CatalogFeatures.Feature#RESOLVE RESOLVE} property.
|
||||
*
|
||||
* @param catalog the catalog instance
|
||||
* @param action the action to be taken when unable to resolve a reference
|
||||
*
|
||||
* @return a {@code CatalogResolver} with the {@code catalog} and {@code action} type
|
||||
*
|
||||
* @since 22
|
||||
*/
|
||||
public static CatalogResolver catalogResolver(Catalog catalog, CatalogResolver.NotFoundAction action) {
|
||||
if (catalog == null) CatalogMessages.reportNPEOnNull("catalog", null);
|
||||
if (action == null) CatalogMessages.reportNPEOnNull("action", null);
|
||||
|
||||
return new CatalogResolverImpl(catalog, action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of a {@code CatalogResolver} using the specified feature
|
||||
* settings and uri(s) to one or more catalog files.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2023, 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
|
||||
@ -159,7 +159,7 @@ class CatalogReader extends DefaultHandler implements EntityResolver, URIResolve
|
||||
CatalogFeatures.DEFER_TRUE : CatalogFeatures.DEFER_FALSE;
|
||||
}
|
||||
if (resolve == null) {
|
||||
resolve = catalog.getResolve().literal;
|
||||
resolve = catalog.getResolve().toString();
|
||||
}
|
||||
//override property settings with those from the catalog file
|
||||
catalog.setResolve(resolve);
|
||||
@ -172,7 +172,7 @@ class CatalogReader extends DefaultHandler implements EntityResolver, URIResolve
|
||||
return;
|
||||
} else {
|
||||
inGroup = true;
|
||||
group = new GroupEntry(catalog, base, prefer);
|
||||
group = new GroupEntry(catalog, Util.getAbsoluteURI(catalog.systemId, base), prefer);
|
||||
catalog.addEntry(group);
|
||||
return;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2023, 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
|
||||
@ -235,4 +235,55 @@ public interface CatalogResolver extends EntityResolver, XMLResolver,
|
||||
public LSInput resolveResource(String type, String namespaceUri,
|
||||
String publicId, String systemId, String baseUri);
|
||||
|
||||
/**
|
||||
* Defines the actions that a CatalogResolver may take when it is unable to
|
||||
* resolve an external reference. The actions are mapped to the string values
|
||||
* of the {@link CatalogFeatures.Feature#RESOLVE RESOLVE} property.
|
||||
*
|
||||
* @since 22
|
||||
*/
|
||||
public static enum NotFoundAction {
|
||||
/**
|
||||
* Indicates that the processing should continue as defined by the
|
||||
* {@link CatalogFeatures.Feature#RESOLVE RESOLVE} property.
|
||||
*/
|
||||
CONTINUE {
|
||||
@Override
|
||||
public String toString() { return "continue"; }
|
||||
},
|
||||
/**
|
||||
* Indicates that the reference is skipped as defined by the
|
||||
* {@link CatalogFeatures.Feature#RESOLVE RESOLVE} property.
|
||||
*/
|
||||
IGNORE {
|
||||
@Override
|
||||
public String toString() { return "ignore"; }
|
||||
},
|
||||
/**
|
||||
* Indicates that the resolver should throw a CatalogException as defined
|
||||
* by the {@link CatalogFeatures.Feature#RESOLVE RESOLVE} property.
|
||||
*/
|
||||
STRICT {
|
||||
@Override
|
||||
public String toString() { return "strict"; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the action type mapped to the specified
|
||||
* {@link CatalogFeatures.Feature#RESOLVE resolve} property.
|
||||
*
|
||||
* @param resolve the value of the RESOLVE property
|
||||
* @return the action type
|
||||
*/
|
||||
static public NotFoundAction getType(String resolve) {
|
||||
for (NotFoundAction type : NotFoundAction.values()) {
|
||||
if (type.toString().equals(resolve)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
CatalogMessages.reportIAE(CatalogMessages.ERR_INVALID_ARGUMENT,
|
||||
new Object[]{resolve, "RESOLVE"}, null);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2023, 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
|
||||
@ -51,6 +51,8 @@ import org.xml.sax.XMLReader;
|
||||
*/
|
||||
final class CatalogResolverImpl implements CatalogResolver {
|
||||
Catalog catalog;
|
||||
// resolution action type
|
||||
NotFoundAction resolveType;
|
||||
|
||||
/**
|
||||
* Construct an instance of the CatalogResolver from a Catalog.
|
||||
@ -58,9 +60,25 @@ final class CatalogResolverImpl implements CatalogResolver {
|
||||
* @param catalog A Catalog.
|
||||
*/
|
||||
public CatalogResolverImpl(Catalog catalog) {
|
||||
this.catalog = catalog;
|
||||
this(catalog, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an instance of the CatalogResolver from a Catalog and the
|
||||
* {@link CatalogResolver.NotFoundAction action} type.
|
||||
*
|
||||
* @param catalog a Catalog object
|
||||
* @param action the action type
|
||||
*/
|
||||
public CatalogResolverImpl(Catalog catalog, NotFoundAction action) {
|
||||
this.catalog = catalog;
|
||||
// Note: can only happen in this impl
|
||||
if (action == null) {
|
||||
resolveType = ((CatalogImpl) catalog).getResolve();
|
||||
} else {
|
||||
resolveType = action;
|
||||
}
|
||||
}
|
||||
/*
|
||||
Implements the EntityResolver interface
|
||||
*/
|
||||
@ -91,7 +109,6 @@ final class CatalogResolverImpl implements CatalogResolver {
|
||||
return new InputSource(resolvedSystemId);
|
||||
}
|
||||
|
||||
GroupEntry.ResolveType resolveType = ((CatalogImpl) catalog).getResolve();
|
||||
switch (resolveType) {
|
||||
case IGNORE:
|
||||
return new InputSource(new StringReader(""));
|
||||
@ -145,7 +162,6 @@ final class CatalogResolverImpl implements CatalogResolver {
|
||||
|
||||
//Report error or return the URI as is when no match is found
|
||||
if (result == null) {
|
||||
GroupEntry.ResolveType resolveType = c.getResolve();
|
||||
switch (resolveType) {
|
||||
case IGNORE:
|
||||
return new SAXSource(new InputSource(new StringReader("")));
|
||||
@ -229,7 +245,6 @@ final class CatalogResolverImpl implements CatalogResolver {
|
||||
|
||||
}
|
||||
|
||||
GroupEntry.ResolveType resolveType = ((CatalogImpl) catalog).getResolve();
|
||||
switch (resolveType) {
|
||||
case IGNORE:
|
||||
return null;
|
||||
@ -250,7 +265,6 @@ final class CatalogResolverImpl implements CatalogResolver {
|
||||
return new LSInputImpl(is.getSystemId());
|
||||
}
|
||||
|
||||
GroupEntry.ResolveType resolveType = ((CatalogImpl) catalog).getResolve();
|
||||
switch (resolveType) {
|
||||
case IGNORE:
|
||||
return null;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2023, 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
|
||||
@ -107,34 +107,6 @@ class GroupEntry extends BaseEntry {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PreferType represents possible values of the resolve property
|
||||
*/
|
||||
public static enum ResolveType {
|
||||
STRICT(CatalogFeatures.RESOLVE_STRICT),
|
||||
CONTINUE(CatalogFeatures.RESOLVE_CONTINUE),
|
||||
IGNORE(CatalogFeatures.RESOLVE_IGNORE);
|
||||
|
||||
final String literal;
|
||||
|
||||
ResolveType(String literal) {
|
||||
this.literal = literal;
|
||||
}
|
||||
|
||||
static public ResolveType getType(String resolveType) {
|
||||
for (ResolveType type : ResolveType.values()) {
|
||||
if (type.isType(resolveType)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isType(String type) {
|
||||
return literal.equals(type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a GroupEntry
|
||||
*
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2023, 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,6 +28,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.Iterator;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
@ -267,4 +268,32 @@ class Util {
|
||||
Util.validateUrisSyntax(value.split(";"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute form of the specified uri after resolving it against
|
||||
* the base. Returns the uri as is if it's already absolute.
|
||||
*
|
||||
* @param base the base, that is the system id of the catalog within the
|
||||
* Catalog implementation
|
||||
* @param uri the specified uri
|
||||
* @return the absolute form of the specified uri
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
static String getAbsoluteURI(String base, String uri) {
|
||||
String temp = "";
|
||||
try {
|
||||
URL baseURL = new URL(base);
|
||||
URI specURI = URI.create(uri);
|
||||
|
||||
if (specURI.isAbsolute()) {
|
||||
temp = specURI.toURL().toString();
|
||||
} else {
|
||||
temp = (new URL(baseURL, uri)).toString();
|
||||
}
|
||||
} catch (MalformedURLException ex) {
|
||||
// shouldn't happen since inputs are validated, report error in case
|
||||
CatalogMessages.reportError(CatalogMessages.ERR_INVALID_CATALOG);
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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 java.nio.file.Paths;
|
||||
import javax.xml.catalog.Catalog;
|
||||
import javax.xml.catalog.CatalogException;
|
||||
import javax.xml.catalog.CatalogFeatures;
|
||||
import javax.xml.catalog.CatalogManager;
|
||||
import javax.xml.catalog.CatalogResolver;
|
||||
import javax.xml.catalog.CatalogResolver.NotFoundAction;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Listeners;
|
||||
import org.testng.annotations.Test;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8316996
|
||||
* @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
|
||||
* @run testng/othervm catalog.CatalogResolverTest
|
||||
* @summary Tests CatalogResolver functions. See CatalogTest for existing basic
|
||||
* functional tests.
|
||||
*/
|
||||
@Listeners({jaxp.library.FilePolicy.class})
|
||||
public class CatalogResolverTest extends CatalogSupportBase {
|
||||
static final String KEY_FILES = "javax.xml.catalog.files";
|
||||
static final String SYSTEM_ID = "http://openjdk_java_net/xml/catalog/dtd/system.dtd";
|
||||
|
||||
/*
|
||||
* Initializing fields
|
||||
*/
|
||||
@BeforeClass
|
||||
public void setUpClass() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
/*
|
||||
DataProvider: data used to verify the RESOLVE property, including the valid
|
||||
values and the effect of overriding that on the Catalog.
|
||||
Data columns:
|
||||
resolve property for the Catalog, resolve property for the CatalogResolver,
|
||||
system ID to be resolved, expected result, expected exception
|
||||
*/
|
||||
@DataProvider(name = "factoryMethodInput")
|
||||
public Object[][] getInputs() throws Exception {
|
||||
|
||||
return new Object[][]{
|
||||
// Valid values and overriding verification
|
||||
// RESOLVE=strict but expected match
|
||||
{"continue", NotFoundAction.STRICT, SYSTEM_ID, "system.dtd", null},
|
||||
// RESOLVE=strict plus no match: expect exception
|
||||
{"continue", NotFoundAction.STRICT, "bogusID", "", CatalogException.class},
|
||||
// RESOLVE=ignore, continue: expect no match but without an exception
|
||||
// Note that these tests do not differentiate empty InputSource from
|
||||
// null, in both cases, the returned ID is null
|
||||
{"strict", NotFoundAction.IGNORE, "bogusID", null, null},
|
||||
{"strict", NotFoundAction.CONTINUE, "bogusID", null, null},
|
||||
};
|
||||
}
|
||||
|
||||
@DataProvider(name = "NPETest")
|
||||
public Object[][] getNPETest() throws Exception {
|
||||
return new Object[][]{
|
||||
{null, null},
|
||||
{getCatalog("ignore"), null},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the factory method for creating CatalogResolver with an
|
||||
* {@link javax.xml.catalog.CatalogResolver.NotFoundAction action} type.
|
||||
* The 2-arg {@link javax.xml.catalog.CatalogManager#catalogResolver(
|
||||
* javax.xml.catalog.Catalog, javax.xml.catalog.CatalogResolver.NotFoundAction)
|
||||
* catalogResolver} method adds the action type to be used for determining
|
||||
* the behavior instead of relying on the underlying catalog.
|
||||
*
|
||||
* @param cResolve the resolve property set on the Catalog object
|
||||
* @param action the resolve property set on the CatalogResolver to override
|
||||
* that of the Catalog
|
||||
* @param systemId the system ID to be resolved
|
||||
* @param expectedResult the expected result
|
||||
* @param expectedThrow the expected exception
|
||||
* @throws Exception if the test fails
|
||||
*/
|
||||
@Test(dataProvider = "factoryMethodInput")
|
||||
public void testResolveProperty(String cResolve, NotFoundAction action,
|
||||
String systemId, String expectedResult, Class<Throwable> expectedThrow)
|
||||
throws Exception {
|
||||
Catalog c = getCatalog(cResolve);
|
||||
|
||||
if (expectedThrow != null) {
|
||||
Assert.assertThrows(expectedThrow,
|
||||
() -> resolveRef(c, action, systemId));
|
||||
} else {
|
||||
|
||||
String sysId = resolveRef(c, action, systemId);
|
||||
System.out.println(sysId);
|
||||
Assert.assertEquals(sysId,
|
||||
(expectedResult == null) ? null : Paths.get(filepath + expectedResult).toUri().toString().replace("///", "/"),
|
||||
"System ID match not right");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the catalogResolver method throws NullPointerException if
|
||||
* any of the parameters is null.
|
||||
*/
|
||||
@Test(dataProvider = "NPETest", expectedExceptions = NullPointerException.class)
|
||||
public void testCatalogProperty(Catalog c, NotFoundAction action) {
|
||||
CatalogManager.catalogResolver(c, action);
|
||||
}
|
||||
|
||||
private String resolveRef(Catalog c, NotFoundAction action, String systemId) throws Exception {
|
||||
CatalogResolver cr = CatalogManager.catalogResolver(c, action);
|
||||
InputSource is = cr.resolveEntity("", systemId);
|
||||
return is == null ? null : is.getSystemId();
|
||||
}
|
||||
|
||||
private Catalog getCatalog(String cResolve) throws Exception {
|
||||
URI catalogFile = getClass().getResource("catalog.xml").toURI();
|
||||
Catalog c = CatalogManager.catalog(
|
||||
CatalogFeatures.builder().with(CatalogFeatures.Feature.RESOLVE, cResolve).build(),
|
||||
catalogFile);
|
||||
return c;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2023, 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
|
||||
@ -506,7 +506,7 @@ public class CatalogTest extends CatalogSupportBase {
|
||||
*/
|
||||
@Test(expectedExceptions = NullPointerException.class)
|
||||
public void testFeatureNull() {
|
||||
CatalogResolver resolver = CatalogManager.catalogResolver(null, null);
|
||||
CatalogResolver resolver = CatalogManager.catalogResolver((CatalogFeatures)null, (URI)null);
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user