8357394: Add JDK specific property for external resource access

This commit is contained in:
JoeWang-Java 2026-07-30 06:14:54 +00:00
parent e1218165ef
commit 8f0207a8f2
44 changed files with 2192 additions and 225 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2026, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -33,6 +33,7 @@ import java.util.Iterator;
import javax.xml.XMLConstants;
import jdk.xml.internal.JdkConstants;
import jdk.xml.internal.SecuritySupport;
import jdk.xml.internal.XMLSecurityManager;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
@ -41,7 +42,7 @@ import org.xml.sax.XMLReader;
* @author Morten Jorgensen
* @author Erwin Bolwidt <ejb@klomp.org>
* @author Gunnlaugur Briem <gthb@dimon.is>
* @LastModified: May 2021
* @LastModified: July 2026
*/
final class Import extends TopLevelElement {
@ -84,8 +85,9 @@ final class Import extends TopLevelElement {
if (input == null) {
docToLoad = SystemIDResolver.getAbsoluteURI(docToLoad, currLoadedDoc);
String accessError = SecuritySupport.checkAccess(docToLoad,
(String)xsltc.getProperty(XMLConstants.ACCESS_EXTERNAL_STYLESHEET),
JdkConstants.ACCESS_EXTERNAL_ALL);
(XMLSecurityManager)xsltc.getProperty(JdkConstants.SECURITY_MANAGER),
XMLConstants.ACCESS_EXTERNAL_STYLESHEET,
(String)xsltc.getProperty(XMLConstants.ACCESS_EXTERNAL_STYLESHEET));
if (accessError != null) {
final ErrorMsg msg = new ErrorMsg(ErrorMsg.ACCESSING_XSLT_TARGET_ERR,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2026, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -33,6 +33,7 @@ import java.util.Iterator;
import javax.xml.XMLConstants;
import jdk.xml.internal.JdkConstants;
import jdk.xml.internal.SecuritySupport;
import jdk.xml.internal.XMLSecurityManager;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
@ -41,7 +42,7 @@ import org.xml.sax.XMLReader;
* @author Morten Jorgensen
* @author Erwin Bolwidt <ejb@klomp.org>
* @author Gunnlaugur Briem <gthb@dimon.is>
* @LastModified: May 2021
* @LastModified: July 2026
*/
final class Include extends TopLevelElement {
@ -84,8 +85,9 @@ final class Include extends TopLevelElement {
if (input == null) {
docToLoad = SystemIDResolver.getAbsoluteURI(docToLoad, currLoadedDoc);
String accessError = SecuritySupport.checkAccess(docToLoad,
(String)xsltc.getProperty(XMLConstants.ACCESS_EXTERNAL_STYLESHEET),
JdkConstants.ACCESS_EXTERNAL_ALL);
(XMLSecurityManager)xsltc.getProperty(JdkConstants.SECURITY_MANAGER),
XMLConstants.ACCESS_EXTERNAL_STYLESHEET,
(String)xsltc.getProperty(XMLConstants.ACCESS_EXTERNAL_STYLESHEET));
if (accessError != null) {
final ErrorMsg msg = new ErrorMsg(ErrorMsg.ACCESSING_XSLT_TARGET_ERR,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -60,7 +60,7 @@ import org.xml.sax.helpers.AttributesImpl;
* @author G. Todd Miller
* @author Morten Jorgensen
* @author Erwin Bolwidt <ejb@klomp.org>
* @LastModified: July 2023
* @LastModified: July 2026
*/
public class Parser implements Constants, ContentHandler {
@ -540,23 +540,20 @@ public class Parser implements Constants, ContentHandler {
return(element);
}
else {
try {
String path = _target;
if (path.indexOf(":")==-1) {
path = "file:" + path;
}
path = SystemIDResolver.getAbsoluteURI(path);
String accessError = SecuritySupport.checkAccess(path,
(String)_xsltc.getProperty(XMLConstants.ACCESS_EXTERNAL_STYLESHEET),
JdkConstants.ACCESS_EXTERNAL_ALL);
if (accessError != null) {
ErrorMsg msg = new ErrorMsg(ErrorMsg.ACCESSING_XSLT_TARGET_ERR,
SecuritySupport.sanitizePath(_target), accessError,
root);
throw new CompilerException(msg.toString());
}
} catch (IOException ex) {
throw new CompilerException(ex);
String path = _target;
if (path.indexOf(":")==-1) {
path = "file:" + path;
}
path = SystemIDResolver.getAbsoluteURI(path);
String accessError = SecuritySupport.checkAccess(path,
(XMLSecurityManager)_xsltc.getProperty(JdkConstants.SECURITY_MANAGER),
XMLConstants.ACCESS_EXTERNAL_STYLESHEET,
(String)_xsltc.getProperty(XMLConstants.ACCESS_EXTERNAL_STYLESHEET));
if (accessError != null) {
ErrorMsg msg = new ErrorMsg(ErrorMsg.ACCESSING_XSLT_TARGET_ERR,
SecuritySupport.sanitizePath(_target), accessError,
root);
throw new CompilerException(msg.toString());
}
return(loadExternalStylesheet(_target));

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -24,7 +24,7 @@ import java.util.ListResourceBundle;
/**
* @author Morten Jorgensen
* @LastModified: Dec 2024
* @LastModified: July 2026
*/
public class ErrorMessages extends ListResourceBundle {
@ -469,7 +469,7 @@ public class ErrorMessages extends ListResourceBundle {
* Note to translators: access to the stylesheet target is denied
*/
{ErrorMsg.ACCESSING_XSLT_TARGET_ERR,
"Could not read stylesheet target ''{0}'', because ''{1}'' access is not allowed due to restriction set by the accessExternalStylesheet property."},
"Could not read stylesheet target ''{0}'', because access is not allowed due to restriction set by ''{1}''."},
/*
* Note to translators: This message represents an internal error in

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -39,7 +39,7 @@ import jdk.xml.internal.SecuritySupport;
/**
* @author Morten Jorgensen
* @LastModified: Sept 2021
* @LastModified: July 2026
*/
public final class LoadDocument {
@ -197,12 +197,7 @@ public final class LoadDocument {
throw new TransletException(e);
}
} else {
String accessError = SecuritySupport.checkAccess(uri, translet.getAllowedProtocols(), JdkConstants.ACCESS_EXTERNAL_ALL);
if (accessError != null) {
ErrorMsg msg = new ErrorMsg(ErrorMsg.ACCESSING_XSLT_TARGET_ERR,
SecuritySupport.sanitizePath(uri), accessError);
throw new Exception(msg.toString());
}
translet.verifyAccess(uri);
// Parse the input document and construct DOM object
// Trust the DTMManager to pick the right parser and

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2026, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -25,6 +25,7 @@ import com.sun.org.apache.xalan.internal.xsltc.DOMCache;
import com.sun.org.apache.xalan.internal.xsltc.DOMEnhancedForDTM;
import com.sun.org.apache.xalan.internal.xsltc.Translet;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
import com.sun.org.apache.xalan.internal.xsltc.dom.DOMAdapter;
import com.sun.org.apache.xalan.internal.xsltc.dom.KeyIndex;
import com.sun.org.apache.xalan.internal.xsltc.runtime.output.TransletOutputHandlerFactory;
@ -40,11 +41,14 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Templates;
import jdk.xml.internal.JdkConstants;
import jdk.xml.internal.JdkXmlUtils;
import jdk.xml.internal.SecuritySupport;
import jdk.xml.internal.XMLSecurityManager;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
@ -54,7 +58,7 @@ import org.w3c.dom.Document;
* @author Morten Jorgensen
* @author G. Todd Miller
* @author John Howard, JohnH@schemasoft.com
* @LastModified: Sept 2021
* @LastModified: July 2026
*/
public abstract class AbstractTranslet implements Translet {
@ -115,6 +119,7 @@ public abstract class AbstractTranslet implements Translet {
* protocols allowed for external references set by the stylesheet processing instruction, Document() function, Import and Include element.
*/
private String _accessExternalStylesheet = JdkConstants.EXTERNAL_ACCESS_DEFAULT;
private XMLSecurityManager _xsm;
// The error message when access to exteranl resources is rejected
private String _accessErr = null;
@ -789,6 +794,37 @@ public abstract class AbstractTranslet implements Translet {
_accessExternalStylesheet = protocols;
}
/**
* Returns the XMLSecurityManager
*/
public XMLSecurityManager getXMLSecurityManager() {
return _xsm;
}
/**
* Sets the XMLSecurityManager
* @param xsm the XMLSecurityManager instance
*/
public void setXMLSecurityManager(XMLSecurityManager xsm) {
_xsm = xsm;
}
/**
* Verifies that access to the resource represented by the systemId is permitted.
* @param systemId the systemId
* @throws TransletException if access is not permitted
*/
public void verifyAccess(String systemId) throws TransletException {
String accessError = SecuritySupport.checkAccess(systemId, _xsm,
XMLConstants.ACCESS_EXTERNAL_STYLESHEET, _accessExternalStylesheet);
if (accessError != null) {
ErrorMsg msg = new ErrorMsg(ErrorMsg.ACCESSING_XSLT_TARGET_ERR,
SecuritySupport.sanitizePath(systemId), accessError);
throw new TransletException(msg.toString());
}
}
/**
* Returns the access error.
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2026, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -58,6 +58,7 @@ import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.URIResolver;
import jdk.xml.internal.JdkConstants;
import jdk.xml.internal.XMLSecurityManager;
/**
@ -65,7 +66,7 @@ import jdk.xml.internal.JdkConstants;
* @author G. Todd Millerj
* @author Jochen Cordes <Jochen.Cordes@t-online.de>
* @author Santiago Pericas-Geertsen
* @LastModified: Jan 2025
* @LastModified: July 2026
*/
public final class TemplatesImpl implements Templates, Serializable {
static final long serialVersionUID = 673094361519270707L;
@ -147,6 +148,7 @@ public final class TemplatesImpl implements Templates, Serializable {
* protocols allowed for external references set by the stylesheet processing instruction, Import and Include element.
*/
private transient String _accessExternalStylesheet = JdkConstants.EXTERNAL_ACCESS_DEFAULT;
private transient XMLSecurityManager _xsm;
/**
* @serialField _name String The Name of the main class
@ -240,6 +242,7 @@ public final class TemplatesImpl implements Templates, Serializable {
_tfactory = tfactory;
_overrideDefaultParser = tfactory.overrideDefaultParser();
_accessExternalStylesheet = (String) tfactory.getAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET);
_xsm = (XMLSecurityManager) tfactory.getAttribute(JdkConstants.SECURITY_MANAGER);
}
/**
* Need for de-serialization, see readObject().
@ -540,6 +543,7 @@ public final class TemplatesImpl implements Templates, Serializable {
translet.setTemplates(this);
translet.setOverrideDefaultParser(_overrideDefaultParser);
translet.setAllowedProtocols(_accessExternalStylesheet);
translet.setXMLSecurityManager(_xsm);
if (_auxClasses != null) {
translet.setAuxiliaryClasses(_auxClasses);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2026, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -88,7 +88,7 @@ import org.xml.sax.XMLReader;
* @author G. Todd Miller
* @author Morten Jorgensen
* @author Santiago Pericas-Geertsen
* @LastModified: May 2025
* @LastModified: July 2026
*/
public class TransformerFactoryImpl
extends SAXTransformerFactory implements SourceLoader
@ -515,7 +515,7 @@ public class TransformerFactoryImpl
}
if (_xmlSecurityPropertyMgr != null &&
_xmlSecurityPropertyMgr.setValue(name, FeaturePropertyBase.State.APIPROPERTY, value)) {
_xmlSecurityPropertyMgr.setValue(name, JdkProperty.State.APIPROPERTY, value)) {
_accessExternalDTD = _xmlSecurityPropertyMgr.getValue(
Property.ACCESS_EXTERNAL_DTD);
_accessExternalStylesheet = _xmlSecurityPropertyMgr.getValue(
@ -572,9 +572,9 @@ public class TransformerFactoryImpl
// set external access restriction when FSP is explicitly set
if (value) {
_xmlSecurityPropertyMgr.setValue(Property.ACCESS_EXTERNAL_DTD,
FeaturePropertyBase.State.FSP, JdkConstants.EXTERNAL_ACCESS_DEFAULT_FSP);
JdkProperty.State.FSP, JdkConstants.EXTERNAL_ACCESS_DEFAULT_FSP);
_xmlSecurityPropertyMgr.setValue(Property.ACCESS_EXTERNAL_STYLESHEET,
FeaturePropertyBase.State.FSP, JdkConstants.EXTERNAL_ACCESS_DEFAULT_FSP);
JdkProperty.State.FSP, JdkConstants.EXTERNAL_ACCESS_DEFAULT_FSP);
_accessExternalDTD = _xmlSecurityPropertyMgr.getValue(
Property.ACCESS_EXTERNAL_DTD);
_accessExternalStylesheet = _xmlSecurityPropertyMgr.getValue(

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2026, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -100,7 +100,7 @@ import org.xml.sax.ext.LexicalHandler;
* @author Morten Jorgensen
* @author G. Todd Miller
* @author Santiago Pericas-Geertsen
* @LastModified: Jan 2025
* @LastModified: July 2026
*/
public final class TransformerImpl extends Transformer
implements DOMCache
@ -1357,21 +1357,13 @@ public final class TransformerImpl extends Transformer
*/
AbstractTranslet t = (AbstractTranslet)translet;
String systemId = SystemIDResolver.getAbsoluteURI(href, baseURI);
String errMsg = null;
try {
String accessError = SecuritySupport.checkAccess(systemId,
t.getAllowedProtocols(),
JdkConstants.ACCESS_EXTERNAL_ALL);
if (accessError != null) {
ErrorMsg msg = new ErrorMsg(ErrorMsg.ACCESSING_XSLT_TARGET_ERR,
SecuritySupport.sanitizePath(href), accessError);
errMsg = msg.toString();
}
} catch (IOException ioe) {
errMsg = ioe.getMessage();
}
if (errMsg != null) {
t.setAccessError(errMsg);
String accessError = SecuritySupport.checkAccess(systemId,
t.getXMLSecurityManager(), XMLConstants.ACCESS_EXTERNAL_STYLESHEET,
t.getAllowedProtocols());
if (accessError != null) {
ErrorMsg msg = new ErrorMsg(ErrorMsg.ACCESSING_XSLT_TARGET_ERR,
SecuritySupport.sanitizePath(href), accessError);
t.setAccessError(msg.toString());
return null;
}

View File

@ -2023,7 +2023,8 @@ public class XMLDocumentFragmentScannerImpl
String checkAccess(String systemId, String allowedProtocols) throws IOException {
String baseSystemId = fEntityScanner.getBaseSystemId();
String expandedSystemId = XMLEntityManager.expandSystemId(systemId, baseSystemId, fStrictURI);
return SecuritySupport.checkAccess(expandedSystemId, allowedProtocols, JdkConstants.ACCESS_EXTERNAL_ALL);
return SecuritySupport.checkAccess(expandedSystemId, fSecurityManager,
XMLConstants.ACCESS_EXTERNAL_DTD, allowedProtocols);
}
//

View File

@ -1361,20 +1361,15 @@ public class XMLEntityManager implements XMLComponent, XMLEntityResolver {
if (external) {
staxInputSource = resolveEntityAsPerStax(externalEntity.entityLocation);
/** xxx: Waiting from the EG
* //simply return if there was entity resolver registered and application
* //returns either XMLStreamReader or XMLEventReader.
* if(staxInputSource.hasXMLStreamOrXMLEventReader()) return ;
*/
xmlInputSource = staxInputSource.getXMLInputSource() ;
if (!fISCreatedByResolver) {
String accessError = SecuritySupport.checkAccess(expandedSystemId,
fAccessExternalDTD, JdkConstants.ACCESS_EXTERNAL_ALL);
String accessError = SecuritySupport.checkAccess(expandedSystemId, fSecurityManager,
XMLConstants.ACCESS_EXTERNAL_DTD, fAccessExternalDTD);
if (accessError != null) {
fErrorReporter.reportError(this.getEntityScanner(),XMLMessageFormatter.XML_DOMAIN,
"AccessExternalEntity",
new Object[] { SecuritySupport.sanitizePath(expandedSystemId), accessError },
XMLErrorReporter.SEVERITY_FATAL_ERROR);
fErrorReporter.reportError(this.getEntityScanner(), XMLMessageFormatter.XML_DOMAIN,
"AccessExternalEntity",
new Object[]{SecuritySupport.sanitizePath(expandedSystemId), accessError},
XMLErrorReporter.SEVERITY_FATAL_ERROR);
}
}
}

View File

@ -283,8 +283,9 @@
# Entity related messages
# 3.1 Start-Tags, End-Tags, and Empty-Element Tags
ReferenceToExternalEntity = The external entity reference \"&{0};\" is not permitted in an attribute value.
AccessExternalDTD = External DTD: Failed to read external DTD ''{0}'', because ''{1}'' access is not allowed due to restriction set by the accessExternalDTD property.
AccessExternalEntity = External Entity: Failed to read external document ''{0}'', because ''{1}'' access is not allowed due to restriction set by the accessExternalDTD property.
AccessExternalDTD = External DTD: Failed to read external DTD ''{0}'', because access is not allowed due to restriction set by ''{1}''.
AccessExternalEntity = External Entity: Failed to read external document ''{0}'', because access is not allowed due to restriction set by ''{1}''.
ResourceAccess = Resource Access: Failed to read external document ''{0}'', because the ''{1}'' property is set to not allow accessing the document.
# 4.1 Character and Entity References
EntityNotDeclared = The entity \"{0}\" was referenced, but not declared.

View File

@ -108,7 +108,7 @@
#schema valid (3.X.3)
schema_reference.access = schema_reference: Failed to read schema document ''{0}'', because ''{1}'' access is not allowed due to restriction set by the accessExternalSchema property.
schema_reference.access = schema_reference: Failed to read schema document ''{0}'', because access is not allowed due to restriction set by ''{1}''.
schema_reference.4 = schema_reference.4: Failed to read schema document ''{0}'', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.
src-annotation = src-annotation: <annotation> elements can only contain <appinfo> and <documentation> elements, but ''{0}'' was found.
src-attribute.1 = src-attribute.1: The properties ''default'' and ''fixed'' cannot both be present in attribute declaration ''{0}''. Use only one of them.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -103,7 +103,7 @@ import org.xml.sax.InputSource;
* @xerces.internal
*
* @author Neil Graham, IBM
* @LastModified: May 2025
* @LastModified: July 2026
*/
public class XMLSchemaLoader implements XMLGrammarLoader, XMLComponent, XSElementDeclHelper,
@ -285,6 +285,7 @@ XSLoader, DOMConfiguration {
private CMBuilder fCMBuilder;
private XSDDescription fXSDDescription = new XSDDescription();
private String faccessExternalSchema = JdkConstants.EXTERNAL_ACCESS_DEFAULT;
private XMLSecurityManager fXMLScurityManager = null;
private WeakHashMap<Object, SchemaGrammar> fJAXPCache;
private Locale fLocale = Locale.getDefault();
@ -476,6 +477,9 @@ XSLoader, DOMConfiguration {
XMLSecurityPropertyManager spm = (XMLSecurityPropertyManager)state;
faccessExternalSchema = spm.getValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA);
}
else if (propertyId.equals(SECURITY_MANAGER)) {
fXMLScurityManager = (XMLSecurityManager)state;
}
} // setProperty(String, Object)
/**
@ -567,6 +571,7 @@ XSLoader, DOMConfiguration {
desc.fContextType = XSDDescription.CONTEXT_PREPARSE;
desc.setBaseSystemId(source.getBaseSystemId());
desc.setLiteralSystemId( source.getSystemId());
fXSDDescription = desc;
// none of the other fields make sense for preparsing
Map<String, LocationArray> locationPairs = new HashMap<>();
// Process external schema location properties.
@ -607,8 +612,9 @@ XSLoader, DOMConfiguration {
processJAXPSchemaSource(locationPairs);
}
if (desc.isExternal() && !source.isCreatedByResolver()) {
String accessError = SecuritySupport.checkAccess(desc.getExpandedSystemId(), faccessExternalSchema, JdkConstants.ACCESS_EXTERNAL_ALL);
if (fXSDDescription.isExternal() && !source.isCreatedByResolver()) {
String accessError = SecuritySupport.checkAccess(desc.getExpandedSystemId(),
fXMLScurityManager, XMLConstants.ACCESS_EXTERNAL_SCHEMA, faccessExternalSchema);
if (accessError != null) {
throw new XNIException(fErrorReporter.reportError(XSMessageFormatter.SCHEMA_DOMAIN,
"schema_reference.access",
@ -1006,9 +1012,10 @@ XSLoader, DOMConfiguration {
setProperty(XML_SECURITY_PROPERTY_MANAGER, spm);
}
XMLSecurityManager sm = (XMLSecurityManager)componentManager.getProperty(SECURITY_MANAGER);
if (sm == null)
setProperty(SECURITY_MANAGER, JdkXmlConfig.getInstance(false).getXMLSecurityManager(false));
fXMLScurityManager = (XMLSecurityManager)componentManager.getProperty(SECURITY_MANAGER);
if (fXMLScurityManager == null)
fXMLScurityManager = JdkXmlConfig.getInstance(false).getXMLSecurityManager(false);
setProperty(SECURITY_MANAGER, fXMLScurityManager);
faccessExternalSchema = spm.getValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2026, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -132,7 +132,7 @@ import org.xml.sax.XMLReader;
* @author Neil Graham, IBM
* @author Pavani Mukthipudi, Sun Microsystems
*
* @LastModified: May 2025
* @LastModified: July 2026
*/
public class XSDHandler {
@ -2216,7 +2216,8 @@ public class XSDHandler {
if ((!schemaSource.isCreatedByResolver()) &&
(referType == XSDDescription.CONTEXT_IMPORT || referType == XSDDescription.CONTEXT_INCLUDE
|| referType == XSDDescription.CONTEXT_REDEFINE)) {
String accessError = SecuritySupport.checkAccess(schemaId, fAccessExternalSchema, JdkConstants.ACCESS_EXTERNAL_ALL);
String accessError = SecuritySupport.checkAccess(schemaId,
fSecurityManager, XMLConstants.ACCESS_EXTERNAL_SCHEMA, fAccessExternalSchema);
if (accessError != null) {
reportSchemaFatalError("schema_reference.access",
new Object[] { SecuritySupport.sanitizePath(schemaId), accessError },

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2026, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -41,7 +41,7 @@ import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration;
import jdk.xml.internal.FeaturePropertyBase.State;
import jdk.xml.internal.JdkProperty.State;
import jdk.xml.internal.JdkConstants;
import jdk.xml.internal.JdkXmlUtils;
import jdk.xml.internal.XMLSecurityManager;
@ -59,7 +59,7 @@ import org.xml.sax.SAXNotSupportedException;
/**
* @author Rajiv Mordani
* @author Edwin Goei
* @LastModified: May 2025
* @LastModified: July 2026
*/
public class DocumentBuilderImpl extends DocumentBuilder
implements JAXPConstants

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2026, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -43,6 +43,7 @@ import javax.xml.XMLConstants;
import javax.xml.validation.Schema;
import jdk.xml.internal.FeaturePropertyBase;
import jdk.xml.internal.JdkConstants;
import jdk.xml.internal.JdkProperty;
import jdk.xml.internal.JdkXmlConfig;
import jdk.xml.internal.JdkXmlUtils;
import jdk.xml.internal.XMLSecurityManager;
@ -65,7 +66,7 @@ import org.xml.sax.helpers.DefaultHandler;
* @author Rajiv Mordani
* @author Edwin Goei
*
* @LastModified: May 2025
* @LastModified: July 2026
*/
@SuppressWarnings("deprecation")
public class SAXParserImpl extends javax.xml.parsers.SAXParser
@ -171,9 +172,9 @@ public class SAXParserImpl extends javax.xml.parsers.SAXParser
Boolean temp = features.get(XMLConstants.FEATURE_SECURE_PROCESSING);
if (temp != null && temp) {
fSecurityPropertyMgr.setValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD,
FeaturePropertyBase.State.FSP, JdkConstants.EXTERNAL_ACCESS_DEFAULT_FSP);
JdkProperty.State.FSP, JdkConstants.EXTERNAL_ACCESS_DEFAULT_FSP);
fSecurityPropertyMgr.setValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA,
FeaturePropertyBase.State.FSP, JdkConstants.EXTERNAL_ACCESS_DEFAULT_FSP);
JdkProperty.State.FSP, JdkConstants.EXTERNAL_ACCESS_DEFAULT_FSP);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2026, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -71,7 +71,7 @@ import org.xml.sax.SAXParseException;
*
* @author Kohsuke Kawaguchi
*
* @LastModified: May 2025
* @LastModified: July 2026
*/
public final class XMLSchemaFactory extends SchemaFactory {
@ -446,9 +446,9 @@ public final class XMLSchemaFactory extends SchemaFactory {
fSecurityManager.setSecureProcessing(value);
if (value) {
fSecurityPropertyMgr.setValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD,
FeaturePropertyBase.State.FSP, JdkConstants.EXTERNAL_ACCESS_DEFAULT_FSP);
JdkProperty.State.FSP, JdkConstants.EXTERNAL_ACCESS_DEFAULT_FSP);
fSecurityPropertyMgr.setValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA,
FeaturePropertyBase.State.FSP, JdkConstants.EXTERNAL_ACCESS_DEFAULT_FSP);
JdkProperty.State.FSP, JdkConstants.EXTERNAL_ACCESS_DEFAULT_FSP);
}
fXMLSchemaLoader.setProperty(SECURITY_MANAGER, fSecurityManager);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2026, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -48,6 +48,7 @@ import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
import javax.xml.catalog.CatalogFeatures;
import jdk.xml.internal.FeaturePropertyBase;
import jdk.xml.internal.JdkConstants;
import jdk.xml.internal.JdkProperty;
import jdk.xml.internal.JdkXmlConfig;
import jdk.xml.internal.JdkXmlUtils;
import jdk.xml.internal.XMLSecurityManager;
@ -59,7 +60,7 @@ import org.xml.sax.ErrorHandler;
* <p>An implementation of XMLComponentManager for a schema validator.</p>
*
* @author Michael Glavassevich, IBM
* @LastModified: May 2025
* @LastModified: July 2026
*/
final class XMLSchemaValidatorComponentManager extends ParserConfigurationSettings implements
XMLComponentManager {
@ -378,9 +379,9 @@ final class XMLSchemaValidatorComponentManager extends ParserConfigurationSettin
if (value) {
fSecurityPropertyMgr.setValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD,
FeaturePropertyBase.State.FSP, JdkConstants.EXTERNAL_ACCESS_DEFAULT_FSP);
JdkProperty.State.FSP, JdkConstants.EXTERNAL_ACCESS_DEFAULT_FSP);
fSecurityPropertyMgr.setValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA,
FeaturePropertyBase.State.FSP, JdkConstants.EXTERNAL_ACCESS_DEFAULT_FSP);
JdkProperty.State.FSP, JdkConstants.EXTERNAL_ACCESS_DEFAULT_FSP);
setProperty(XML_SECURITY_PROPERTY_MANAGER, fSecurityPropertyMgr);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -61,7 +61,7 @@ import org.xml.sax.helpers.LocatorImpl;
*
* @author Arnaud Le Hors, IBM
* @author Andy Clark, IBM
* @LastModified: May 2025
* @LastModified: July 2026
*/
public class DOMParser
extends AbstractDOMParser {
@ -575,7 +575,7 @@ public class DOMParser
* internally the support of this property is done through
* XMLSecurityPropertyManager
*/
securityPropertyManager.setValue(index, FeaturePropertyBase.State.APIPROPERTY, (String)value);
securityPropertyManager.setValue(index, JdkProperty.State.APIPROPERTY, (String)value);
} else {
//check if the property is managed by security manager
if (!securityManager.setLimit(propertyId, JdkProperty.State.APIPROPERTY, value)) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -42,7 +42,7 @@ import org.xml.sax.SAXNotSupportedException;
* @author Arnaud Le Hors, IBM
* @author Andy Clark, IBM
*
* @LastModified: May 2025
* @LastModified: July 2026
*/
public class SAXParser
extends AbstractSAXParser {
@ -169,7 +169,7 @@ public class SAXParser
* internally the support of this property is done through
* XMLSecurityPropertyManager
*/
securityPropertyManager.setValue(index, FeaturePropertyBase.State.APIPROPERTY, (String)value);
securityPropertyManager.setValue(index, JdkProperty.State.APIPROPERTY, (String)value);
} else {
//check if the property is managed by security manager
if (!securityManager.setLimit(name, JdkProperty.State.APIPROPERTY, value)) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2026, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -78,6 +78,7 @@ import javax.xml.catalog.CatalogResolver;
import javax.xml.transform.Source;
import jdk.xml.internal.JdkConstants;
import jdk.xml.internal.JdkXmlUtils;
import jdk.xml.internal.SecuritySupport;
import jdk.xml.internal.XMLSecurityManager;
import jdk.xml.internal.XMLSecurityPropertyManager;
import org.xml.sax.InputSource;
@ -128,7 +129,7 @@ import org.xml.sax.InputSource;
*
*
* @see XIncludeNamespaceSupport
* @LastModified: Apr 2025
* @LastModified: July 2026
*/
public class XIncludeHandler
implements XMLComponent, XMLDocumentFilter, XMLDTDFilter {
@ -1704,6 +1705,23 @@ public class XIncludeHandler
}
if (includedSource == null) {
String expandedSystemId;
try {
expandedSystemId = XMLEntityManager.expandSystemId(
href, fCurrentBaseURI.getExpandedSystemId(), false);
} catch (MalformedURIException e) {
reportResourceError("XMLResourceError",
new Object[] { href, e.getMessage()}, e);
return false;
}
String accessError = SecuritySupport.checkAccess(expandedSystemId,
fSecurityManager, null, JdkConstants.ACCESS_EXTERNAL_ALL);
if (accessError != null) {
reportFatalError("XMLResourceError",
new Object[] { href, accessError});
return false;
}
// setup an HTTPInputSource if either of the content negotation attributes were specified.
if (accept != null || acceptLanguage != null) {
includedSource = createInputSource(null, href, fCurrentBaseURI.getExpandedSystemId(), accept, acceptLanguage);

View File

@ -0,0 +1,441 @@
/*
* Copyright (c) 2026, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 jdk.xml.internal;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
/**
* Represents a parsed rule for matching external resource access permissions based on URI patterns.
* <p>
* This class encapsulates a resource access rule consisting of a scheme, optional host and port,
* and path pattern. It is used to determine if a specific {@link java.net.URI} is permitted based on
* rules specified with the {@code jdk.xml.resource.access} property.
* </p>
* <p>
* Supported rule format:
* <pre>
* [scheme]://host[:port][/path-pattern]
* [scheme]:/[path-pattern] (for local schemes such as file, jar, jrt)
* </pre>
* <ul>
* <li><b>scheme</b>: The URI scheme (e.g., http, https, ftp, file, jar, jrt).</li>
* <li><b>host</b>: Domain name, IPv4, or IPv6 address. For local schemes ("file", "jar", "jrt"), host is omitted.</li>
* <li><b>port</b>: (optional) Port number to match. If omitted, matches the default port for the scheme.</li>
* <li><b>path-pattern</b>: (optional) Resource path. Supports wildcards (e.g., {@code /*}, {@code /dtds/*}).</li>
* </ul>
* <p>
* Wildcards are allowed in host (e.g., <code>*.foo.com</code>) and path (e.g., <code>/*</code> or <code>/foo/*</code>).
* </p>
* <p>
* Example patterns:
* <ul>
* <li>{@code http://*.foo.com:8080/*} - allows HTTP resources on any subdomain of foo.com at port 8080, any path</li>
* <li>{@code file:/dtds/*} - allows all files under /dtds</li>
* <li>{@code file:/foo/bar.dtd} - allows only the local file /foo/bar.dtd</li>
* <li>{@code *} - allows unrestricted access</li>
* </ul>
* </p>
* <p>
* The {@link #allows(java.net.URI)} method determines whether a given URI is permitted according to this rule.
* </p>
*/
public class AccessRule {
public static final AccessRule RULE_NONE = new AccessRule("");
public static final AccessRule RULE_ALL = new AccessRule("*");
private final List<URIPatternRule> rules = new ArrayList<>();
private final boolean allowAll;
private final boolean denyAll;
private final String rawInput;
public AccessRule(String input) {
this.rawInput = input;
String trimmedInput = input == null ? "" : input.trim();
if (trimmedInput.equals("*")) {
allowAll = true;
denyAll = false;
return;
} else if (trimmedInput.isEmpty()) {
allowAll = false;
denyAll = true;
return;
}
allowAll = false;
denyAll = false;
String[] tokens = input.split(",");
for (String rawToken : tokens) {
String token = checkToken(input, rawToken);
rules.add(URIPatternRule.parse(token));
}
}
private String checkToken(String input, String rawToken) {
String token = rawToken.trim();
if (token.isEmpty() && !rules.isEmpty()) {
throw new IllegalArgumentException("Invalid format for the resource.access property: "
+ input + ". Empty rule cannot coexist with other rules.");
} else if (token.equals("*") && !rules.isEmpty()) {
throw new IllegalArgumentException("Invalid format for the resource.access property: "
+ input + ". All access (*) rule cannot coexist with other rules.");
}
return token;
}
public boolean allows(URI uri) {
if (denyAll) return false;
if (allowAll) return true;
for (URIPatternRule rule : rules) {
if (rule.matches(uri)) return true;
}
return false;
}
@Override
public String toString() { return rawInput; }
/**
* Represents a parsed URI-based pattern rule.
*/
public static class URIPatternRule {
private final String scheme;
private final HostPattern hostPattern;
private final Integer port; // null if not set
private final PathPattern pathPattern;
// for scheme==jar
private final URIPatternRule jarBaseRule;
private final PathPattern jarEntryPathPattern;
// Constructor for schemes other than jar
private URIPatternRule(String scheme, HostPattern hostPattern, Integer port, PathPattern pathPattern) {
this.scheme = scheme;
this.hostPattern = hostPattern;
this.port = port;
this.pathPattern = pathPattern;
this.jarBaseRule = null;
this.jarEntryPathPattern = null;
}
// Constructor for jar patterns
public URIPatternRule(URIPatternRule jarBaseRule, PathPattern jarEntryPathPattern) {
this.scheme = "jar";
this.hostPattern = null;
this.port = null;
this.pathPattern = null;
this.jarBaseRule = jarBaseRule;
this.jarEntryPathPattern = jarEntryPathPattern;
}
/**
* Parses the specified pattern string.
* Example patterns: file:*, file:/foo, http://foo.com, https://*.foo.com:8080
* @param pattern the pattern string
* @return an instance of URIPatternRule from the pattern string
*/
public static URIPatternRule parse(String pattern) {
// Syntax: [scheme]:/{0,3}[host[:port]][/path-pattern]
int schemeSep = pattern.indexOf(':');
if (schemeSep <= 0)
throw new IllegalArgumentException("Missing or invalid scheme in resource access pattern: " + pattern);
String scheme = pattern.substring(0, schemeSep).toLowerCase(Locale.ROOT);
if (!isSupportedScheme(scheme))
throw new IllegalArgumentException("Unsupported scheme in resource access pattern: " + pattern);
if ("jar".equals(scheme)) {
int exclIdx = pattern.indexOf('!', scheme.length() + 1);
String nestedPart, entryPart;
boolean isLocalScheme = false;
if (exclIdx < 0) {
nestedPart = pattern.substring(scheme.length() + 1); // after "jar:"
entryPart = null;
isLocalScheme = nestedPart.startsWith("file") || nestedPart.startsWith("jar") || nestedPart.startsWith("jrt");
} else {
nestedPart = pattern.substring(scheme.length() + 1, exclIdx);
entryPart = pattern.substring(exclIdx + 1);
}
// Check for illegal forms
if (Utils.isEmpty(nestedPart) && Utils.isNotEmpty(entryPart))
throw new IllegalArgumentException("Invalid JAR rule: entry pattern present but missing jar base: " + pattern);
if (!isLocalScheme && Utils.isEmpty(entryPart) && Utils.isNotEmptyOrWildcard(nestedPart))
throw new IllegalArgumentException("Invalid JAR rule: entry pattern is empty: " + pattern);
URIPatternRule jarBaseRule = null;
if (Utils.isNotEmptyOrWildcard(nestedPart)) {
jarBaseRule = URIPatternRule.parse(nestedPart);
}
PathPattern jarEntryPathPattern = (entryPart == null || entryPart.isEmpty() || entryPart.equals("/*") || entryPart.equals("*"))
? PathPattern.of("*")
: PathPattern.of(entryPart.startsWith("/") ? entryPart : "/" + entryPart);
return new URIPatternRule(jarBaseRule, jarEntryPathPattern);
}
String rest = pattern.substring(schemeSep + 1);
// Remove up to 3 leading slashes
String afterSlashes;
HostPattern hostPattern = null;
Integer port = null;
PathPattern pathPattern = null;
// Handle file/jar/jrt schemes as path patterns
boolean isLocalScheme = scheme.equals("file") || scheme.equals("jar") || scheme.equals("jrt");
if (isLocalScheme) {
// Remove up to 3 leading slashes
afterSlashes = rest.replaceFirst("^/{0,3}", "");
// Should be only path or wildcard, must not be empty (file: is not allowed)
if (afterSlashes.isEmpty())
throw new IllegalArgumentException(scheme + " rule must have non-empty path: " + pattern);
// afterSlashes is the path pattern, can be "*"
if (afterSlashes.equals("*")) {
pathPattern = PathPattern.of("*");
} else {
if (!afterSlashes.startsWith("/")) afterSlashes = "/" + afterSlashes;
pathPattern = PathPattern.of(afterSlashes);
}
} else {
// Remove up to 2 leading slashes
afterSlashes = rest.replaceFirst("^/{0,2}", "");
// Find "host[:port][/path]"
if (afterSlashes.isEmpty() || afterSlashes.startsWith(":") || afterSlashes.startsWith("/")) {
throw new IllegalArgumentException("Rule for scheme '" + scheme + "' must specify a non-empty host: " + pattern);
}
String hostPart;
String pathPart = null;
int slashIndex = afterSlashes.indexOf('/');
if (slashIndex >= 0) {
hostPart = afterSlashes.substring(0, slashIndex);
pathPart = afterSlashes.substring(slashIndex); // includes "/"
} else {
hostPart = afterSlashes;
}
// Validate host
if (hostPart.isEmpty())
throw new IllegalArgumentException("Host must not be blank for scheme: " + scheme);
// Port
int portSep = hostPart.lastIndexOf(':');
if (portSep > 0 && portSep < hostPart.length() - 1
&& isPortNumber(hostPart.substring(portSep + 1))) {
hostPattern = HostPattern.of(hostPart.substring(0, portSep));
try {
port = Integer.parseInt(hostPart.substring(portSep + 1));
if (port < 0 || port > 65535)
throw new IllegalArgumentException("Port must be 0-65535: " + pattern);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Port must be numeric: " + pattern);
}
} else if (!hostPart.isEmpty()) {
hostPattern = HostPattern.of(hostPart);
}
// Validate path
if (pathPart != null && pathPart.length() > 1 && pathPart.indexOf("//") >= 0)
throw new IllegalArgumentException("Path component must not contain empty segments: " + pattern);
// pathPattern is set only if specified, null otherwise
if (pathPart != null && !pathPart.isEmpty() && !pathPart.equals("/*")) {
pathPattern = PathPattern.of(pathPart);
} else if (pathPart != null && (pathPart.isEmpty() || pathPart.equals("/*"))) {
pathPattern = PathPattern.of("*");
}
}
return new URIPatternRule(scheme, hostPattern, port, pathPattern);
}
public boolean matches(URI uri) {
if (uri == null) return false;
String testScheme = uri.getScheme();
if (testScheme == null || !testScheme.equalsIgnoreCase(scheme)) return false;
if ("jar".equalsIgnoreCase(testScheme)) {
String ssp = uri.getSchemeSpecificPart();
int exclIdx = ssp.indexOf("!/");
String basePart, entryPart;
if (exclIdx < 0) {
basePart = ssp;
entryPart = "";
} else {
basePart = ssp.substring(0, exclIdx);
entryPart = ssp.substring(exclIdx + 1); // may be empty
}
URI baseUri = URI.create(basePart);
boolean baseMatches = (jarBaseRule == null) || jarBaseRule.matches(baseUri); // wildcard/null means match any
boolean entryMatches = jarEntryPathPattern == null || jarEntryPathPattern.matches(entryPart); // always at least "/*"
return baseMatches && entryMatches;
}
// Local: path-pattern match only
if (hostPattern == null) {
if (pathPattern == null) return true; // match all local of that scheme
String uriPath = uri.getPath();
return pathPattern.matches(uriPath);
}
// Network: host and port required
String testHost = uri.getHost();
if (!hostPattern.matches(testHost)) return false;
if (port != null && port != (uri.getPort() == -1 ? getDefaultPort(scheme) : uri.getPort())) return false;
// If a pathPattern is present, also match path; else, path is ignored
if (pathPattern != null) {
String uriPath = uri.getPath();
return pathPattern.matches(uriPath);
}
return true;
}
private static boolean isSupportedScheme(String scheme) {
return switch (scheme) {
case "http", "https", "ftp", "file", "jar", "jrt" -> true;
default -> false;
};
}
/**
* Check if string is an integer between 0 and 65535 (valid TCP/UDP port range).
*/
private static boolean isPortNumber(String str) {
try {
int port = Integer.parseInt(str);
return port >= 0 && port <= 65535;
} catch (NumberFormatException e) {
return false;
}
}
// standard ports for known schemes
private static int getDefaultPort(String scheme) {
return switch (scheme) {
case "http" -> 80;
case "https" -> 443;
case "ftp" -> 21;
default -> -1;
};
}
}
// Host pattern matching for exact, IPv4 and IPv6 hosts.
public static class HostPattern {
private final String pattern;
private final boolean isAny;
private final boolean isSubdomainPattern;
private final byte[] literalAddress;
private HostPattern(String pattern, boolean isAny, boolean isSubdomainPattern, byte[] literalAddress) {
this.pattern = pattern;
this.isAny = isAny;
this.isSubdomainPattern = isSubdomainPattern;
this.literalAddress = literalAddress;
}
public static HostPattern of(String hostPattern) {
String trimmed = hostPattern.trim();
if (trimmed.equals("*")) {
return new HostPattern("*", true, false, null);
}
if (trimmed.startsWith("*.")) {
// *.example.com
return new HostPattern(trimmed.substring(2).toLowerCase(Locale.ROOT), false, true, null);
}
byte[] literalAddress = parseLiteralAddress(trimmed);
if (literalAddress != null)
return new HostPattern(trimmed, false, false, literalAddress);
// Otherwise, treat as literal domain
return new HostPattern(trimmed.toLowerCase(Locale.ROOT), false, false, null);
}
public boolean matches(String testHost) {
if (isAny) return true;
if (testHost == null) return false;
if (literalAddress != null) {
byte[] testAddress = parseLiteralAddress(testHost);
return testAddress != null && Arrays.equals(literalAddress, testAddress);
}
testHost = testHost.toLowerCase(Locale.ROOT);
// Subdomain wildcard
if (isSubdomainPattern) {
return testHost.endsWith("." + pattern);
}
// Exact match (domain, IPv4, or IPv6)
return testHost.equals(pattern);
}
private static byte[] parseLiteralAddress(String host) {
try {
return Inet4Address.ofLiteral(host).getAddress();
} catch (IllegalArgumentException ignored) {
// Not an IPv4 literal; try IPv6 below.
}
try {
return Inet6Address.ofLiteral(host).getAddress();
} catch (IllegalArgumentException ignored) {
return null;
}
}
}
public static class PathPattern {
private final String pattern; // E.g. /dtds/* or /*
private final boolean isAny;
private final boolean isDirectory; // endsWith /*
private PathPattern(String pattern, boolean isAny, boolean isDirectory) {
this.pattern = pattern;
this.isAny = isAny;
this.isDirectory = isDirectory;
}
public static PathPattern of(String pattern) {
pattern = (pattern == null || pattern.isEmpty()) ? "/" : pattern;
// supports *, /foo/*, /foo/bar
if (pattern.equals("*") || pattern.equals("/*")) {
return new PathPattern(pattern, true, false);
}
if (pattern.endsWith("/*")) {
return new PathPattern(pattern.substring(0, pattern.length() - 2), false, true);
}
return new PathPattern(pattern, false, false);
}
public boolean matches(String testPath) {
if (isAny) return true;
if (testPath == null) return false;
if (isDirectory) {
// Path starts with this directory
return testPath.startsWith(pattern + "/") || testPath.equals(pattern);
}
return testPath.equals(pattern);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2026, 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
@ -24,23 +24,12 @@
*/
package jdk.xml.internal;
import jdk.xml.internal.JdkProperty.State;
/**
* This is the base class for features and properties
*/
public abstract class FeaturePropertyBase {
/**
* States of the settings of a property, in the order: default value, value
* set by FEATURE_SECURE_PROCESSING, jaxp.properties file, jaxp system
* properties, and jaxp api properties
*/
public static enum State {
//this order reflects the overriding order
DEFAULT, FSP, JAXPDOTPROPERTIES, SYSTEMPROPERTY, APIPROPERTY
}
/**
* Values of the properties as defined in enum Properties
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2026, 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
@ -311,6 +311,17 @@ public final class JdkConstants {
//public static final int IGNORE = 1; // same as that of DTD
public static final int STRICT = 2;
/**
* System Property for the Resource Access property
* @since 26
*/
public static final String RESOURCE_ACCESS = "jdk.xml.resource.access";
// Integer Values that maps to broad access settings such as *, remote
public static final int ACCESS_NONE = 0;
public static final int ACCESS_ALL = 1; // same as that of DTD
public static final int ACCESS_REMOTE = 2;
/**
* Values for a feature
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2026, 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
@ -113,7 +113,7 @@ public class JdkXmlUtils {
return xsm.setLimit(property, JdkProperty.State.APIPROPERTY, value);
} else if (xspm != null && xspm.find(property) != null) {
return xspm.setValue(property, FeaturePropertyBase.State.APIPROPERTY, value);
return xspm.setValue(property, JdkProperty.State.APIPROPERTY, value);
}
return false;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2026, 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
@ -29,15 +29,18 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.Paths;
import java.security.CodeSource;
import java.text.MessageFormat;
import java.util.HashSet;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.Set;
/**
* This class contains utility methods for reading resources in the JAXP packages
@ -267,66 +270,90 @@ public class SecuritySupport {
return input;
}
/**
* Checks whether access to resource represented by the systemId is permitted
* by Resource Access and/or External Access Properties (EAP)
* @param systemId the systemId
* @param xsm the XMLSecurityManager
* @param eap the External Access Property, e.g. ACCESS_EXTERNAL_DTD
* @param allowedProtocols protocols allowed by the EAP
* @return true if access is permitted, false otherwise
* @throws IOException if the systemId is invalid
*/
public static String checkAccess(String systemId, XMLSecurityManager xsm,
String eap, String allowedProtocols) {
String errMsg = null;
if (xsm != null && !xsm.isAccessAllowed(systemId)) {
errMsg = "Resource Access (jdk.xml.resource.access)";
}
if (!checkAccess(systemId, allowedProtocols)) {
errMsg = (errMsg != null) ? errMsg + " and " + eap : eap;
}
return errMsg;
}
/**
* Check the protocol used in the systemId against allowed protocols
*
* @param systemId the Id of the URI
* @param allowedProtocols a list of allowed protocols separated by comma
* @param accessAny keyword to indicate allowing any protocol
* @return the name of the protocol if rejected, null otherwise
* @return true if access is permitted, false otherwise
*/
public static String checkAccess(String systemId, String allowedProtocols,
String accessAny) throws IOException {
public static boolean checkAccess(String systemId, String allowedProtocols) {
if (Utils.isEmpty(allowedProtocols)) {
return false;
}
if (systemId == null || (allowedProtocols != null &&
allowedProtocols.equalsIgnoreCase(accessAny))) {
return null;
allowedProtocols.equalsIgnoreCase(JdkConstants.ACCESS_EXTERNAL_ALL))) {
return true;
}
String protocol;
if (!systemId.contains(":")) {
protocol = "file";
URI uri = Utils.createURI(systemId);
String scheme = uri.getScheme();
if (scheme == null) {
scheme = "file";
} else {
@SuppressWarnings("deprecation")
URL url = new URL(systemId);
protocol = url.getProtocol();
if (protocol.equalsIgnoreCase("jar")) {
String path = url.getPath();
protocol = path.substring(0, path.indexOf(":"));
} else if (protocol.equalsIgnoreCase("jrt")) {
// if the systemId is "jrt" then allow access if "file" allowed
protocol = "file";
scheme = scheme.toLowerCase(Locale.ROOT);
if ("jar".equals(scheme)) {
String ssp = uri.getSchemeSpecificPart(); // e.g. file:/x.jar!/a.xml
int sep = ssp.indexOf("!/");
if (sep != -1) {
URI nested = Utils.createURI(ssp.substring(0, sep));
String nestedScheme = nested.getScheme();
if (nestedScheme != null) {
scheme = nestedScheme.toLowerCase(Locale.ROOT);
}
}
} else if ("jrt".equals(scheme)) {
// allow access if it's "file"
scheme = "file";
}
}
if (isProtocolAllowed(protocol, allowedProtocols)) {
//access allowed
return null;
} else {
return protocol;
}
Set<String> allowed = parseProtocols(allowedProtocols);
return allowed.contains(scheme);
}
/**
* Check if the protocol is in the allowed list of protocols. The check
* is case-insensitive while ignoring whitespaces.
*
* @param protocol a protocol
* @param allowedProtocols a list of allowed protocols
* @return true if the protocol is in the list
* Parses allowed protocols.
* @param protocols the protocol setting
* @return a set containing allowed protocols
*/
private static boolean isProtocolAllowed(String protocol, String allowedProtocols) {
if (allowedProtocols == null) {
return false;
}
String temp[] = allowedProtocols.split(",");
for (String t : temp) {
t = t.trim();
if (t.equalsIgnoreCase(protocol)) {
return true;
}
}
return false;
}
private static Set<String> parseProtocols(String protocols) {
Set<String> set = new HashSet<>();
if (protocols == null || protocols.isEmpty()) {
return set;
}
for (String p : protocols.split(",")) {
String trimmed = p.trim().toLowerCase(Locale.ROOT);
if (!trimmed.isEmpty()) {
set.add(trimmed);
}
}
return set;
}
public static ClassLoader getContextClassLoader() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2026, 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
@ -26,6 +26,8 @@
package jdk.xml.internal;
import java.lang.reflect.Array;
import java.net.URI;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Objects;
import java.util.function.Supplier;
@ -132,6 +134,52 @@ public class Utils {
* @return {@code true} if the CharSequence is empty or null
*/
public static boolean isEmpty(final CharSequence cs) {
return cs == null || cs.length() == 0;
return cs == null || cs.isEmpty();
}
/**
* Checks if a CharSequence is not null and empty ("").
* @param cs the CharSequence to check, may be null
* @return {@code true} if the CharSequence is not null and empty ("")
*/
public static boolean isNotEmpty(final CharSequence cs) {
return cs != null && !cs.isEmpty();
}
/**
* Checks if a CharSequence is not null and empty (""), and also does not end
* with a wildcard (*).
* @param cs the CharSequence to check, may be null
* @return {@code true} if the CharSequence is not null and empty ("") and does
* not end with a wildcard
*/
public static boolean isNotEmptyOrWildcard(final CharSequence cs) {
return cs != null && !cs.isEmpty() && (cs.charAt(cs.length() - 1) != '*');
}
/**
* Creates a {@link URI} instance from a systemId.
* This method handles strings that are either absolute URIs or local file
* system paths.
*
* @param systemId the systemId
* @return a {@link URI} instance corresponding to the systemId
*/
public static URI createURI(String systemId) {
if (systemId == null) {
return null;
}
try {
URI uri = new URI(systemId);
if (uri.getScheme() == null) {
return Path.of(systemId).toUri();
}
return uri;
} catch (Exception e) {
// fallback for paths with illegal characters (e.g. spaces)
return Path.of(systemId).toUri();
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2026, 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
@ -26,6 +26,8 @@ package jdk.xml.internal;
import com.sun.org.apache.xerces.internal.util.SecurityManager;
import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@ -82,6 +84,17 @@ public final class XMLSecurityManager implements Cloneable {
CR_MAP = Collections.unmodifiableMap(map);
}
// Valid values for Resource Access, and mappings between the string and
// integer values
static final Map<String, Integer> RA_MAP;
// Source Level JDK 8
static {
Map<String, Integer> map = new HashMap<>();
map.put("*", 0);
map.put("", 2);
RA_MAP = Collections.unmodifiableMap(map);
}
// Value converter for properties of type Boolean
private static final BooleanMapper BOOLMAPPER = new BooleanMapper();
@ -94,6 +107,9 @@ public final class XMLSecurityManager implements Cloneable {
// Catalog Resolve value mapper
private static final StringMapper CRMAPPER = new StringMapper(CR_MAP);
// Resource Access value mapper
private static final StringMapper RAMAPPER = new StringMapper(RA_MAP);
/**
* Limits managed by the security manager
*/
@ -129,6 +145,8 @@ public final class XMLSecurityManager implements Cloneable {
STAX_SUPPORT_DTD("supportDTD", XMLInputFactory.SUPPORT_DTD, null, null, 1, 1, Processor.PARSER, BOOLMAPPER),
JDKCATALOG_RESOLVE("JDKCatalogResolve", JdkConstants.JDKCATALOG_RESOLVE, JdkConstants.JDKCATALOG_RESOLVE, null,
JdkConstants.CONTINUE, JdkConstants.CONTINUE, Processor.PARSER, CRMAPPER),
RESOURCE_ACCESS("ResourceAccess", JdkConstants.RESOURCE_ACCESS, JdkConstants.RESOURCE_ACCESS, null,
JdkConstants.ALLOW, JdkConstants.ALLOW, Processor.PARSER, RAMAPPER),
;
final String key;
@ -262,6 +280,8 @@ public final class XMLSecurityManager implements Cloneable {
private final int indexEntityCountInfo = 10000;
private String printEntityCountInfo = "";
private AccessRule accessRule = null;
/**
* Default constructor. Establishes default values for known security
* vulnerabilities.
@ -289,6 +309,11 @@ public final class XMLSecurityManager implements Cloneable {
states[limit.ordinal()] = State.DEFAULT;
}
}
if (secureProcessing) {
accessRule = (Limit.RESOURCE_ACCESS.secureValue == JdkConstants.ALLOW) ? AccessRule.RULE_ALL : AccessRule.RULE_NONE;
} else {
accessRule = (Limit.RESOURCE_ACCESS.defaultValue() == JdkConstants.ALLOW) ? AccessRule.RULE_ALL : AccessRule.RULE_NONE;
}
}
/**
@ -380,6 +405,15 @@ public final class XMLSecurityManager implements Cloneable {
* @return the limit's new name if found, null otherwise
*/
public String find(String propertyName) {
/*
* Access property is unique in its value type. Using the SecurityManager
* infrastructure, but handles differently than other limits
*/
if (Limit.RESOURCE_ACCESS.is(propertyName)) {
return (Limit.RESOURCE_ACCESS.systemProperty != null)
? Limit.RESOURCE_ACCESS.systemProperty
: Limit.RESOURCE_ACCESS.apiProperty;
}
for (Limit limit : Limit.values()) {
if (limit.is(propertyName)) {
// current spec: new property name == systemProperty
@ -440,6 +474,24 @@ public final class XMLSecurityManager implements Cloneable {
* @param value the value of the property
*/
public void setLimit(Limit limit, State state, Object value) {
/*
* Access property is unique in its value type. Using the SecurityManager
* infrastructure, but handles differently than other limits
*/
if (limit == Limit.RESOURCE_ACCESS) {
int index = limit.ordinal();
if (state.compareTo(states[index]) >= 0) {
String ruleValue = (String)value;
AccessRule rule = new AccessRule(ruleValue);
int intValue = limit.mapper().toInt(ruleValue);
accessRule = rule;
values[index] = intValue;
states[index] = state;
isSet[index] = true;
}
return;
}
int intValue = limit.mapper().toInt(value);
if (intValue < 0) {
intValue = 0;
@ -469,6 +521,29 @@ public final class XMLSecurityManager implements Cloneable {
}
}
public AccessRule getAccessRule() {
return accessRule;
}
public boolean isAccessAllowed(String systemId) {
URI uri = Utils.createURI(systemId);
if (uri == null) return true;
return isAccessAllowed(uri);
}
/**
* Checks the RESOURCE_ACCESS property to see if access to the specified
* uri is allowed.
*
* @param uri the specified uri
* @return true if the RESOURCE_ACCESS property is set to allow access to the
* specified uri, false otherwise
*/
public boolean isAccessAllowed(URI uri) {
return accessRule.allows(uri);
}
/**
* Return the value of the specified property
*
@ -477,6 +552,10 @@ public final class XMLSecurityManager implements Cloneable {
* by this manager, its value shall not be null.
*/
public String getLimitAsString(String propertyName) {
if (Limit.RESOURCE_ACCESS.is(propertyName)) {
return accessRule.toString();
}
int index = getIndex(propertyName);
if (index > -1) {
return getLimitValueByIndex(index);
@ -620,10 +699,10 @@ public final class XMLSecurityManager implements Cloneable {
}
/**
* Check against cumulated value
* Check limit against the cumulated value
*
* @param limit the type of the limit property
* @param size the size (count or length) of the entity
* @param limitAnalyzer the limit analyzer
* @return true if the size is over the limit, false otherwise
*/
public boolean isOverLimit(Limit limit, XMLLimitAnalyzer limitAnalyzer) {
@ -739,7 +818,7 @@ public final class XMLSecurityManager implements Cloneable {
try {
String value = System.getProperty(sysPropertyName);
if (value != null && !value.equals("")) {
if (isPropertyValuePresent(limit, value)) {
setLimit(limit, State.SYSTEMPROPERTY, value);
return true;
}
@ -760,7 +839,7 @@ public final class XMLSecurityManager implements Cloneable {
private boolean getPropertyConfig(Limit limit, String sysPropertyName) {
try {
String value = SecuritySupport.readConfig(sysPropertyName);
if (value != null && !value.equals("")) {
if (isPropertyValuePresent(limit, value)) {
setLimit(limit, State.JAXPDOTPROPERTIES, value);
return true;
}
@ -771,6 +850,10 @@ public final class XMLSecurityManager implements Cloneable {
return false;
}
private boolean isPropertyValuePresent(Limit limit, String value) {
return value != null && (!value.isEmpty() || limit == Limit.RESOURCE_ACCESS);
}
/**
* Convert a value set through setProperty to XMLSecurityManager.
* If the value is an instance of XMLSecurityManager, use it to override the default;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2026, 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
@ -26,6 +26,7 @@
package jdk.xml.internal;
import javax.xml.XMLConstants;
import jdk.xml.internal.JdkProperty.State;
/**
* This class manages security related properties
@ -161,6 +162,15 @@ public final class XMLSecurityPropertyManager extends FeaturePropertyBase implem
return values[property.ordinal()];
}
/**
* {@return the state of the specified property}
*
* @param property the specified property
*/
public State getState(Property property) {
return states[property.ordinal()];
}
/**
* Read from system properties, or those in jaxp.properties
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2026, 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
@ -23,6 +23,8 @@
* questions.
*/
import java.net.URI;
/**
* Defines the Java APIs for XML Processing (JAXP).
*
@ -197,6 +199,14 @@
* </li>
* </ul>
*
* If more than one property affects an aspect of operation, all properties must
* permit the operation in order for it to proceed. For example, both the
* <a href="#RES_ACCESS">Resource Access</a> property
* and <a href="javax/xml/XMLConstants.html#EAP">External Access Properties</a> (EAPs) must
* be set to allow in order for a direct fetch of an external resource to be
* carried out. For more details, refer to the
* <a href="#JC_PROCESS">External Resource Resolution Process</a>.
* <p>
* Using the {@link javax.xml.catalog.CatalogFeatures CatalogFeatures}' RESOLVE
* property as an example, the following illustrates how these rules are applied:
* <ul>
@ -403,10 +413,7 @@
*
* <ul>
* <li><a href="#JDKCATALOG">JDK built-in Catalog</a>
* <ul>
* <li><a href="#JC_PROCESS">External Resource Resolution Process with the built-in Catalog</a></li>
* </ul>
* </li>
* <li><a href="#JC_PROCESS">External Resource Resolution Process</a></li>
* <li><a href="#IN_ISFP">Implementation Specific Properties</a>
* <ul>
* <li><a href="#Processor">Processor Support</a></li>
@ -511,23 +518,60 @@
* <p>
* The catalog is loaded once when the first JAXP processor factory is created.
*
* <h3 id="JC_PROCESS">External Resource Resolution Process with the built-in Catalog</h3>
* The JDK creates a {@link javax.xml.catalog.CatalogResolver CatalogResolver}
* with the built-in catalog when needed. This CatalogResolver is used as the
* default external resource resolver.
* <h2 id="JC_PROCESS">External Resource Resolution Process</h2>
* <p>
* XML processors may use resolvers (such as {@link org.xml.sax.EntityResolver EntityResolver},
* {@link javax.xml.stream.XMLResolver XMLResolver}, and {@link javax.xml.catalog.CatalogResolver CatalogResolver})
* to handle external references. In the absence of the user-defined resolvers,
* the JDK XML processors fall back to the default CatalogResolver to attempt to
* find a resolution before making a connection to fetch the resources. The fall-back
* also takes place if a user-defined resolver exists but allows the process to
* continue when unable to resolve the resource.
* The XML processor resolves external resources using the following steps:
* <ul>
* <li><b>User-defined resolver</b>, such as {@link org.xml.sax.EntityResolver EntityResolver},
* {@link javax.xml.stream.XMLResolver XMLResolver}, if registered on the XML factory</li>
* <li><b>{@link javax.xml.catalog.CatalogResolver CatalogResolver}</b> if registered or
* if a catalog file is provided</li>
* <li><b>The JDK Built-in Catalog</b></li>
* <li><b>Direct fetch</b></li>
* </ul>
*
* <p>
* If the default CatalogResolver is unable to locate a resource, it may signal
* the XML processors to continue processing, or skip the resource, or
* throw a CatalogException. The behavior is configured with the
* <a href="#JDKCATALOG_RESOLVE">{@code jdk.xml.jdkcatalog.resolve}</a> property.
* If a resolver or catalog successfully resolves the resource, the process ends.
* Otherwise, the XML processor evaluates the signal returned to decide whether
* to continue, ignore, or reject the resource.
* <p>
* It continues to the next step if:
* <ul>
* <li><b>User-defined resolver</b> returns {@code null}</li>
* <li><b>{@link javax.xml.catalog.CatalogResolver CatalogResolver}</b> returns {@code null}
* and the {@link javax.xml.catalog.CatalogFeatures.Feature#RESOLVE RESOLVE} feature
* is set to {@code continue}
* </li>
* <li><b>The JDK Built-in Catalog</b> returns {@code null} and its Resolve property
* <a href="#JDKCATALOG_RESOLVE">{@code jdk.xml.jdkcatalog.resolve}</a> is set to {@code continue}</li>
* </ul>
* <div style="padding-left: 1.5em;">
* The XML processor then will attempt a direct fetch if the resource is allowed
* by the Resource Access property <a href="#RES_ACCESS">{@code jdk.xml.resource.access}</a> and
* the <a href="javax/xml/XMLConstants.html#EAP">External Access Properties</a>.
* </div>
* <p>
* It ignores the resource and returns an empty source if:
* <ul>
* <li><b>User-defined resolver</b> returns an empty source</li>
* <li><b>{@link javax.xml.catalog.CatalogResolver CatalogResolver}</b> returns an empty source
* and the {@link javax.xml.catalog.CatalogFeatures.Feature#RESOLVE RESOLVE} feature
* is set to {@code ignore}
* </li>
* </ul>
*
* It terminates and throws an exception if:
* <ul>
* <li><b>User-defined resolver</b> throws an exception</li>
* <li><b>{@link javax.xml.catalog.CatalogResolver CatalogResolver}</b> returns {@code null},
* the {@link javax.xml.catalog.CatalogFeatures.Feature#RESOLVE RESOLVE} feature
* is {@code strict}
* </li>
* <li>The resource is not allowed by Resource Access property
* <a href="#RES_ACCESS">{@code jdk.xml.resource.access}</a> or
* <a href="javax/xml/XMLConstants.html#EAP">External Access Properties</a>
* </li>
* </ul>
*
* <h2 id="IN_ISFP">Implementation Specific Properties</h2>
* In addition to the standard <a href="#Conf_Properties">JAXP Properties</a>,
@ -871,7 +915,7 @@
* <td>Determines whether extension functions in the Transform API are to be allowed.
* The extension functions in the XPath API are not affected by this property.
* </td>
* <td style="text-align:center" rowspan="5">yes</td>
* <td style="text-align:center" rowspan="6">yes</td>
* <td style="text-align:center" rowspan="3">Boolean</td>
* <td>
* true or false. True indicates that extension functions are allowed; False otherwise.
@ -994,6 +1038,109 @@
* <td style="text-align:center"><a href="#Processor">Method 1</a></td>
* <td style="text-align:center">22</td>
* </tr>
* <tr>
* <td id="RES_ACCESS">{@systemProperty jdk.xml.resource.access}</td>
* <td>Defines allowed network access to external resources by specifying a list
* of URI patterns, each following the syntax: <br><br>
* {@code scheme:[/][host][:port]/[path pattern]}<br><br>
* Except where this specification explicitly extends or overrides the syntax or
* semantics defined by the {@link java.net.URI URI} class, such as the support for wildcard
* patterns, the definitions of {@link java.net.URI URI} apply.<br><br>
* Where:
* <ul>
* <li><b>Component Syntax</b>: A resource access entry is either:
* <ul>
* <li>
* An exact-match URI, where the scheme, host, port, and path components
* must conform to the syntax requirements of the {@link java.net.URI URI}
* class and the URI is interpreted as a hierarchical URI.
* </li>
* <li>
* A wildcard URI pattern, where the URI syntax is extended to allow
* the wildcard {@code *} in the components explicitly defined by this specification.
* The wildcard matching rules for each supported component are described below.
* </li>
* </ul>
* For both forms, the scheme and host are case-insensitive, while the path is case-sensitive.
* </li>
* <li><b>scheme</b>: The URI scheme. Unless the entire pattern is the single wildcard {@code *},
* the scheme must be one of the supported schemes (http, https, ftp, file, or jrt).
* </li>
* <li><b>jar</b>: jar URIs are matched against the URI of the underlying JAR file
* using the corresponding rule pattern. For example, the rule pattern
* {@code file:/tmp/foo.jar} permits access to {@code jar:file:/tmp/foo.jar!/dtds/test.dtd}.
*
* Permission to access the JAR file automatically grants access to all entries within
* that JAR; entry-level restrictions are not supported.
* </li>
* <li><b>/ (slash)</b>: The slash following the scheme may appear one to three times.
* Two slashes (//) indicate the start of an authority (for example, http://example.com).
* One or three slashes (/ or ///) indicate the start of a local resource path
* (for example, {@code file:/foo/bar.dtd, file:///foo/bar.dtd}).
* </li>
* <li><b>host</b>: Optional. A domain name, IPv4 address, IPv6 literal, or supported
* wildcard pattern. The wildcard {@code *} denotes any host. A leading wildcard followed
* by a domain, such as {@code*.example.com}, matches all subdomains of {@code example.com}.
* For network schemes, the host component must not be empty.</li>
* <li><b>IPv6 Literals</b>: IPv6 literals must be enclosed in square brackets,
* as defined by {@link java.net.URI URI}, for example {@code https://[2001:db8::6]}</li>
* <li><b>port</b>: Optional. A decimal port number, as per the URI standard,
* to indicate only the specified port is permitted. If specified,
* it can not be empty. {@code http://example.com:}, for example, is illegal. </li>
* <li><b>path pattern</b>: Optional. Specifies a resource path. Wildcard {@code *}
* may be used in the path to match any sequence (e.g., {@code /foo/*} matches
* all resources under {@code /foo/}). For local schemes, paths are typically
* absolute (e.g., {@code file:/dtds/*}). To match all resources under a directory,
* the wildcard {@code *} must be added. Without it, the path is treated as
* a literal file or directory. </li>
* <li><b>entire pattern</b>: can be a wildcard {@code *} or empty "", which
* represents all access or no access permitted respectively. </li>
* <li><b>wildcard</b>: The wildcard {@code *} may be used only in the forms
* explicitly defined by this specification:
* <ul>
* <li>as the entire pattern ({@code *});</li>
* <li>as the entire host component ({@code http://*});</li>
* <li>as a leading wildcard in the host component ({@code http://*.example.com});</li>
* <li>as the final path segment ({@code file:/foo/*}).</li>
* </ul>
* Any other occurrence of * is treated as a literal character and does not perform wildcard matching.
* </li>
* </ul>
* Example:
* {@snippet :
* jdk.xml.resource.access = https://*.sun.com, http://www.w3.org, https://127.0.0.1, file:/dtds/, jrt:*, file:/tmp/foo.jar
* }
* This configuration permits access to:
* <ul>
* <li>https access to any subdomain of sun.com, e.g. java.sun.com</li>
* <li>Resources from specific domain as listed in the example, w3.org, 127.0.0.1</li>
* <li>All local resources under the dtds directory</li>
* <li>Resources from the Java runtime image</li>
* <li>Resources inside a jar file {@code /tmp/foo.jar}</li>
* </ul>
* The following configuration permits all access:<br>
* {@code jdk.xml.resource.access = *}<br>
* The following configuration permits no access:<br>
* {@code jdk.xml.resource.access = ""}
*
* </td>
* <td style="text-align:center">String</td>
* <td>
* A comma-separated list of URL patterns, * (wildcard), or "" (empty string).
* </td>
* <td style="text-align:center">{@code *}</td>
* <td style="text-align:center">{@code *}</td>
* <td style="text-align:center">No <a href="#Note8">[8]</a></td>
* <td style="text-align:center">
* <a href="#DOM">DOM</a><br>
* <a href="#SAX">SAX</a><br>
* <a href="#StAX">StAX</a><br>
* <a href="#Validation">Validation</a><br>
* <a href="#Transform">Transform</a>
* </td>
* <td style="text-align:center"><a href="#Processor">Method 1</a></td>
* <td style="text-align:center">27</td>
* </tr>
* </tbody>
* </table>
* <p id="Note1">
@ -1037,6 +1184,11 @@
* These three properties control whether DTDs as a whole shall be processed. When
* they are set to deny or ignore, other properties that regulate a part or an
* aspect of DTD shall have no effect.
* <p id="Note8">
* <b>[8]</b> In the current release, the state of the {@code jdk.xml.resource.access}
* property does not change when {@link javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING FEATURE_SECURE_PROCESSING}
* (FSP) is enabled. In future releases, it will transition to a restrictive setting
* when FSP is enabled.
*
* <h3 id="IN_Legacy">Legacy Property Names (deprecated)</h3>
* JDK releases prior to JDK 17 support the use of URI style prefix for properties.

View File

@ -95,6 +95,81 @@ jdk.xml.overrideDefaultParser=false
# javax.xml.accessExternalStylesheet="all"
#
#
# XML Resource Access Property:
#
# A comma-separated list of URI patterns, * (wildcard), or "" (empty string),
# each following the syntax: scheme:[/][host][:port]/[path]
#
# Component Syntax: A resource access entry is either:
# - An exact-match URI, where the scheme, host, port, and path components must conform
# to the syntax requirements of the java.net.URI class.
# - A wildcard URI pattern, where the URI syntax is extended to allow the wildcard *
# in the components explicitly defined by this specification.
#
# For both forms, the scheme and host are case-insensitive, while the path is case-sensitive.
#
# scheme: The URI scheme. Unless the entire pattern is the single wildcard *,
# the scheme must be one of the supported schemes (http, https, ftp, file, or jrt).
#
# jar: jar URIs are matched against the URI of the underlying JAR file using the
# corresponding rule pattern. For example, the rule pattern file:/tmp/foo.jar permits
# access to jar:file:/tmp/foo.jar!/dtds/test.dtd.
#
# Permission to access the JAR file automatically grants access to all entries within that JAR;
# entry-level restrictions are not supported.
# / (slash): The slash following the scheme may appear one to three times.
# Two slashes (//) indicate the start of an authority (for example, http://example.com).
# One or three slashes (/ or ///) indicate the start of a local resource path
# (for example, file:/foo/bar.dtd or file:///foo/bar.dtd).
# host: Optional. A domain name, IPv4 address, IPv6 literal, or supported wildcard pattern.
# The wildcard * denotes any host. A leading wildcard followed by a domain,
# such as *.example.com, matches all subdomains of example.com. For network schemes,
# the host component must not be empty.
#
# IPv6 Literals: IPv6 literals must be enclosed in square brackets,
# as defined by java.net.URI, for example https://[2001:db8::6].
#
# port: Optional. A decimal port number, as per the URI standard, to indicate only
# the specified port is permitted. If specified, it can not be empty.
# http://example.com:, for example, is illegal.
#
# path: Optional. Specifies a resource path. Wildcard * may be used in the path
# to match any sequence (e.g., /foo/* matches all resources under /foo/).
# For local schemes, paths are typically absolute (e.g., file:/dtds/*).
# To match all resources under a directory, the wildcard * must be added.
# Without it, the path is treated as a literal file or directory.
#
# entire pattern: can be a wildcard * or empty "", which represents all access
# or no access permitted respectively.
#
# wildcard: The wildcard * may be used only in the forms explicitly defined by this specification:
# - as the entire pattern (*);
# - as the entire host component (http://*);
# - as a leading wildcard in the host component (http://*.example.com);
# - as the final path segment (file:/foo/*).
#
# Any other occurrence of * is treated as a literal character and does not perform wildcard matching.
#
#
# Example:
# jdk.xml.resource.access = https://*.sun.com, http://www.w3.org, https://127.0.0.1, file:/dtds/, jrt:*, file:/tmp/foo.jar
#Examples:
#
# jdk.xml.resource.access = https://*.example.com, http://www.example.com, https://127.0.0.1, \
# https://127.0.0.1:80, https://[fe80::1%lo0], https://[fe80::1%lo0]:80, file:/dtds/*, jrt:/*, file:/tmp/foo.jar
#
# This configuration permits access to:
# - https access to any subdomain of example.com, e.g. foo.example.com
# - Resources from specific domain as listed in the example, example.com, 127.0.0.1 and [fe80::1%lo0]
# - All local resources under the dtds directory
# - Resources from the Java runtime image
# - Resources from local /tmp/foo.jar
#
# The default setting allows unrestricted access
jdk.xml.resource.access=*
#
# Catalog Properties:
#
# The Catalog API defines four features: FILES, PREFER, DEFER and RESOLVE.

View File

@ -0,0 +1,147 @@
/*
* Copyright (c) 2026, 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 common.access;
import jdk.xml.internal.AccessRule;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import java.net.URI;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
/*
* @test
* @bug 8357394
* @summary Verifies access rules defined by property jdk.xml.resource.access
* @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest /test/lib
* @modules java.xml/jdk.xml.internal
* @run junit/othervm common.access.AccessRuleTest
*/
public class AccessRuleTest {
/**
* Returns test data for testAccessRule.
* Data: rules, URI strings, result (true if allowed, false otherwise)
* @return test data for testAccessRule
*/
private static Stream<Arguments> testData() {
return Stream.of(
Arguments.of("*", "http://all.access", true),
Arguments.of("", "http://no.access", false),
Arguments.of("http:*; http:/*; http://*", "http://all.http.access", true),
Arguments.of("http://*.oracle.com", "http://subdomains.oracle.com/dtds/example.dtd", true),
Arguments.of("https:*;https:/*;https://*", "https://all.https.access", true),
Arguments.of("https://*.oracle.com", "https://subdomains.oracle.com/dtds/example.dtd", true),
Arguments.of("file:*;file:/*;file://*;file:///*", "file://all.file.access", true),
Arguments.of("http://www.oracle.com", "http://www.oracle.com/dtds/example.dtd", true),
Arguments.of("http://www.oracle.com, http://*.oracle.com",
"http://www.oracle.com/dtds/example.dtd; http://subdomains.oracle.com/dtds/example.dtd", true),
Arguments.of("file:/dtds/dtd1.dtd", "file:/dtds/dtd1.dtd", true),
Arguments.of("file:/dtds/dtd1.dtd, file:/xsds/*", "file:/dtds/dtd1.dtd; file:/xsds/example.xsd", true),
Arguments.of("http://www.oracle.com, file:/dtds/dtd1.dtd, file:/xsds/*",
"http://www.oracle.com/dtds/example.dtd; file:/dtds/dtd1.dtd; file:/xsds/example.xsd", true),
Arguments.of("http://[2001:db8::1]",
"http://[2001:0db8:0000:0000:0000:0000:0000:0001]/dtds/example.dtd; "
+ "http://[2001:db8:0:0:0:0:0:1]/dtds/example.dtd", true),
Arguments.of("http://[2001:0db8:0000:0000:0000:0000:0000:0001]",
"http://[2001:db8::1]/dtds/example.dtd", true),
Arguments.of("jrt:*; jrt:/java.xml/*", "jrt:/java.xml/jdk/xml/internal/jdkcatalog/JDKCatalog.xml", true),
Arguments.of("jar:file:/tmp/foo.jar; jar:file:/tmp/foo.jar!/dtds/*", "jar:file:/tmp/foo.jar!/dtds/example.dtd", true),
Arguments.of("jar:*; jar:file:*", "jar:file://all.file.access", true)
);
}
/**
* Returns test data for testInvalidRules.
* Data: rules, exception class
* @return test data for testInvalidRules
*/
private static Stream<Arguments> testInvalidInput() {
return Stream.of(
Arguments.of("http://:8080", IllegalArgumentException.class),
Arguments.of("http:///dtds", IllegalArgumentException.class),
Arguments.of("scheme", IllegalArgumentException.class),
Arguments.of("http", IllegalArgumentException.class),
Arguments.of("http:", IllegalArgumentException.class),
Arguments.of("http://:8080", IllegalArgumentException.class),
Arguments.of("http:///dtds", IllegalArgumentException.class),
Arguments.of("http://example.com, , file:*", IllegalArgumentException.class),
Arguments.of("http://example.com, *, file:*", IllegalArgumentException.class)
);
}
/**
* Verifies that the Access External Properties are supported throughout the
* JAXP APIs.
* @param rules the access rules separate by ";"
* @param systemIds system IDs represented as semicolon-separated URI strings
* @param permitted the flag indicating whether the rules permit the resource
* represented by the systemId
* @throws Exception if the test fails due to test configuration issues other
* than the expected result
*/
@ParameterizedTest
@MethodSource("testData")
public void testAccessExternalProperties(String rules, String systemIds, boolean permitted)
throws Exception {
String[] accessRules = rules.split(";");
for (String rule : accessRules) {
AccessRule accessRule = new AccessRule(rule.trim());
String[] ids = systemIds.split(";");
for (String systemId : ids) {
assertEquals(accessRule.allows(URI.create(systemId.trim())), permitted);
}
}
}
/**
* Verifies that the specified rule is invalid.
* @param rule indicates whether there is a custom resolver
* @param expectedType the expected throw type
* @throws Exception if the test fails other than the expected Exception, which
* would indicate an issue in configuring the test
*/
@ParameterizedTest
@MethodSource("testInvalidInput")
public void testAccessRule(String rule, Class<Throwable> expectedType) throws Exception {
assertThrows(expectedType, () -> parseRules(rule));
}
/**
* Attempts to parse an access rule
* @param rule the access rule
* @throws Exception if the test fails due to test configuration issues other
* than the expected result
*/
private void parseRules(String rule) {
AccessRule accessRule = new AccessRule(rule.trim());
}
}

View File

@ -0,0 +1,447 @@
/*
* Copyright (c) 2026, 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 common.access;
import common.util.TestBase;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.SAXParser;
import javax.xml.stream.XMLInputFactory;
import javax.xml.transform.TransformerFactory;
import javax.xml.validation.SchemaFactory;
/**
* Test base for Access Rule test.
*/
public class AccessTestBase extends TestBase {
/*
* Test scenarios for verifying preferences.
*
* Fields:
* file, FSP, state of setting, config file, system property, api property,
* Custom Catalog, error expected, error code or expected result
*/
public Object[][] getConfigs(Processor processor) {
// file with an external DTD that's not in JdkCatalog
String fileDTDNotInC = "properties1.xml";
// file with an external DTD that's in the Custom Catalog
String fileDTDInCC = "test.xml";
// file with an external DTD that's in JdkCatalog
String javaDTD = "properties.xml";
// error code when CATALOG=strict; The cause for DOM
String errCode = "JAXP09040001";
// error (not from catalog) is expect when CATALOG=continue
boolean isErrExpected = true;
String expected1 = UNKNOWN_HOST;
// expected when reference is resolved by Catalog
String expected2 = "";
switch (processor) {
case SAX:
errCode = "JAXP00090001";
break;
case STAX:
errCode = "JAXP00090001";
// StAX is non-validating parser
isErrExpected = false;
expected1 = ".*[\\w\\s]*(value1)[\\w\\s]*.*";
expected2 = ".*(123)[\\w\\s]*.*";
break;
default:
break;
}
return new Object[][]{
/**
* Case 1: all properties must permit
* Note: External reference not in the built-in catalog
* Expect: error as the parser continues and tries to access an invalid site
* java.net.UnknownHostException: invalid.site.com
*/
/**
* Case 1-1: by default, both RESOURCE_ACCESS and EAP allow access
*/
{fileDTDNotInC, null, null, null, null, null, null, isErrExpected, expected1},
/**
* Case 1-2: FSP is set, both RESOURCE_ACCESS and EAP are set to allow
*/
{fileDTDNotInC, Properties.FSP, PropertyState.CONFIG_FILE_SYSTEM_API, null, null, new Properties[]{Properties.ACCESS0, Properties.AED0}, null, isErrExpected, expected1},
/**
* Case 2: access is denied unless all properties permit the operation
*
* Sample Error Message: [Fatal Error] properties1.xml:7:11: External DTD: Failed to read external DTD 'properties1.dtd',
* because access is not allowed due to restriction set by 'Resource Access (jdk.xml.resource.access) and http://javax.xml.XMLConstants/property/accessExternalDTD'.
*
*/
/**
* Case 2-1: FSP is set. RESOURCE_ACCESS is unchanged, and EAP denies access
* Expect: [Fatal Error] access denied by ACCESS_EXTERNAL_DTD
*/
{fileDTDNotInC, Properties.FSP, null, null, null, null, null, true, XMLConstants.ACCESS_EXTERNAL_DTD},
/**
* Case 2-2: RESOURCE_ACCESS is set to deny access though EAP allows it
* Expect: [Fatal Error] access denied by RESOURCE_ACCESS
*/
{fileDTDNotInC, Properties.FSP, PropertyState.API, null, null, new Properties[]{Properties.ACCESS1, Properties.AED0}, null, true, SP_ACCESS},
/**
* Case 2-3: ACCESS_EXTERNAL_DTD is set to deny access though RESOURCE_ACCESS allows it
* Expect: [Fatal Error] access denied by ACCESS_EXTERNAL_DTD
*/
{fileDTDNotInC, Properties.FSP, PropertyState.API, null, null, new Properties[]{Properties.ACCESS0, Properties.AED2}, null, true, XMLConstants.ACCESS_EXTERNAL_DTD},
/**
* Case 2-4: System properties override FSP secure values.
*
* Expect: error as the parser continues and tries to access an invalid site
*/
{fileDTDNotInC, Properties.FSP, PropertyState.SYSTEM, null, new Properties[]{Properties.ACCESS0, Properties.AED0}, null, null, isErrExpected, expected1},
/**
* Case 2-5: API property setting overrides system property setting.
*
* Expect: error as the parser continues and tries to access an invalid site
*/
{fileDTDNotInC, Properties.FSP, PropertyState.CONFIG_FILE_SYSTEM_API, null, new Properties[]{Properties.ACCESS1, Properties.AED0}, new Properties[]{Properties.ACCESS0, Properties.AED0}, null, isErrExpected, expected1},
/**
* Case 2-6: API property setting overrides system property setting.
*
* Expect: [Fatal Error] access denied by RESOURCE_ACCESS
*/
{fileDTDNotInC, Properties.FSP, PropertyState.CONFIG_FILE_SYSTEM_API, null, new Properties[]{Properties.ACCESS0, Properties.AED0}, new Properties[]{Properties.ACCESS1, Properties.AED0}, null, true, SP_ACCESS},
/**
* Case 3: Resolvers and Catalogs take precedence in the resource resolution process
*
* Sample Error Message when access is denied by Catalog's Resolve property:
* [Fatal Error] properties1.xml:7:11: JAXP00090001: The CatalogResolver is enabled with the catalog "JDKCatalog.xml", but a CatalogException is returned.
* org.xml.sax.SAXException: javax.xml.catalog.CatalogException: JAXP09040001: No match found for publicId 'null' and systemId 'http://invalid.site.com/dtd/properties1.dtd'.
*
*/
/**
* Case 3-1: the built-in catalog's Resolve property is set to "strict", both Resource Access (jdk.xml.resource.access) and External Access Properties (EAPs) have no effect,
* regardless of their configured values
*
* Expect: error as access is denied by the Catalog's Resolve property
*/
{fileDTDNotInC, null, PropertyState.CONFIG_FILE_SYSTEM_API, Properties.CONFIG_FILE_CATALOG_STRICT, null, new Properties[]{Properties.ACCESS0, Properties.AED0}, null, true, errCode},
/**
* Case 3-2: the reference is resolved by the built-in catalog before direct fetch.
* FSP sets EAP to deny direct fetch, but catalog resolution completes first.
*
* Expect: no error
*/
{javaDTD, Properties.FSP, PropertyState.CONFIG_FILE, Properties.CONFIG_FILE_CATALOG_STRICT, null, null, null, false, expected1},
/**
* Case 3-3: the reference is resolved by a custom catalog before direct fetch.
* FSP sets EAP to deny direct fetch, but catalog resolution completes first.
*
* Expect: no error
*/
{fileDTDInCC, Properties.FSP, PropertyState.CONFIG_FILE, Properties.CONFIG_FILE_CATALOG_STRICT, null, null, CustomCatalog.STRICT, false, expected2}
};
}
/*
* Test scenarios for XInclude. XInclude direct fetches are controlled by
* RESOURCE_ACCESS, while resolver/catalog results take precedence.
*/
public Object[][] getXIncludeConfigs(Processor processor) {
String xinclude = "XI_roottest.xml";
return new Object[][]{
/**
* Case 1-1: by default, RESOURCE_ACCESS allows direct XInclude access.
*/
{xinclude, null, null, null, null, null, null, false, ""},
/**
* Case 1-2: FSP is set, RESOURCE_ACCESS is explicitly set to allow.
*/
{xinclude, Properties.FSP, PropertyState.API, null, null,
new Properties[]{Properties.ACCESS0}, null, false, ""},
/**
* Case 2-1: RESOURCE_ACCESS is set to deny direct XInclude access.
*
* Expect: access denied by RESOURCE_ACCESS
*/
{xinclude, Properties.FSP, PropertyState.API, null, null,
new Properties[]{Properties.ACCESS1}, null, true, SP_ACCESS},
/**
* Case 2-2: system properties override FSP.
*/
{xinclude, Properties.FSP, PropertyState.SYSTEM, null,
new Properties[]{Properties.ACCESS0}, null, null, false, ""},
/**
* Case 2-3: API property setting overrides system property setting.
*/
{xinclude, Properties.FSP, PropertyState.CONFIG_FILE_SYSTEM_API, null,
new Properties[]{Properties.ACCESS1},
new Properties[]{Properties.ACCESS0}, null, false, ""},
/**
* Case 2-4: API property setting overrides system property setting.
*
* Expect: access denied by RESOURCE_ACCESS
*/
{xinclude, Properties.FSP, PropertyState.CONFIG_FILE_SYSTEM_API, null,
new Properties[]{Properties.ACCESS0},
new Properties[]{Properties.ACCESS1}, null, true, SP_ACCESS},
/**
* Case 3-1: custom catalog resolves the reference before direct fetch.
* FSP sets EAP to deny direct fetch, but catalog resolution completes first.
*
* Expect: no error
*/
{xinclude, Properties.FSP, PropertyState.CONFIG_FILE,
Properties.CONFIG_FILE_CATALOG_STRICT, null, null,
CustomCatalog.STRICT, false, ""},
};
}
/*
* Test scenarios for configuring properties for validation or transform.
*
* Fields:
* xml file, xsd or xsl file, FSP, state of setting, config file, system property,
* api property, Custom Catalog, error expected, error code or expected result
*/
public Object[][] getConfig(String m) {
// Schema Import
String xmlFile = "XSDImport_company.xsd";
String xsdOrXsl = null;
String expected = "";
String errCode = "JAXP00090001";
Properties eapAllow = Properties.AES0;
Properties eapDeny = Properties.AES2;
String eapName = "accessExternalDTD,accessExternalSchema";
switch (m) {
case "SchemaTest2":
// Schema Include
xmlFile = "XSDInclude_company.xsd";
break;
case "Validation":
// Schema Location
xmlFile = "val_test.xml";
break;
case "Stylesheet":
errCode = "JAXP09040001";
xmlFile = "XSLDTD.xsl";
eapAllow = Properties.AED0;
eapDeny = Properties.AED2;
eapName = XMLConstants.ACCESS_EXTERNAL_DTD;
break;
case "Transform":
xmlFile = "XSLPI.xml";
errCode = "JAXP00090001";
xsdOrXsl = "<?xml version='1.0'?>"
+ "<xsl:stylesheet "
+ " xmlns:xsl='http://www.w3.org/1999/XSL/Transform' "
+ " version='1.0'>"
+ "<xsl:include href='XSLPI_target.xsl'/>"
+ "<xsl:template match='/'>"
+ "<out/>"
+ "</xsl:template>"
+ "</xsl:stylesheet> ";
eapAllow = Properties.AEX0;
eapDeny = Properties.AEX2;
eapName = XMLConstants.ACCESS_EXTERNAL_STYLESHEET;
break;
default:
break;
}
return new Object[][]{
/**
* Case 1: all properties must permit.
*
* Case 1-1: by default, both RESOURCE_ACCESS and EAP allow access.
*/
{xmlFile, xsdOrXsl, null, null, null, null, null, null, false, expected},
/**
* Case 1-2: FSP is set, both RESOURCE_ACCESS and EAP are set to allow.
*/
{xmlFile, xsdOrXsl, Properties.FSP, PropertyState.CONFIG_FILE_SYSTEM_API, null, null, new Properties[]{Properties.ACCESS0, Properties.AED0, eapAllow}, null, false, expected},
/**
* Case 2: access is denied unless all properties permit the operation.
*
* Case 2-1: FSP is set. RESOURCE_ACCESS is unchanged, and EAP denies access.
*
* Expect: access denied by EAP
*/
{xmlFile, xsdOrXsl, Properties.FSP, PropertyState.CONFIG_FILE, null, null, null, null, true, eapName},
/**
* Case 2-2: RESOURCE_ACCESS is set to deny access though EAP allows it.
*
* Expect: access denied by RESOURCE_ACCESS
*/
{xmlFile, xsdOrXsl, Properties.FSP, PropertyState.API, null, null, new Properties[]{Properties.ACCESS1, Properties.AED0, eapAllow}, null, true, SP_ACCESS},
/**
* Case 2-3: EAP is set to deny access though RESOURCE_ACCESS allows it.
*
* Expect: access denied by EAP
*/
{xmlFile, xsdOrXsl, Properties.FSP, PropertyState.API, null, null, new Properties[]{Properties.ACCESS0, Properties.AED0, eapDeny}, null, true, eapName},
/**
* Case 2-4: system properties override FSP secure values.
*/
{xmlFile, xsdOrXsl, Properties.FSP, PropertyState.SYSTEM, null, new Properties[]{Properties.ACCESS0, Properties.AED0, eapAllow}, null, null, false, expected},
/**
* Case 2-5: API property setting overrides system property setting.
*/
{xmlFile, xsdOrXsl, Properties.FSP, PropertyState.CONFIG_FILE_SYSTEM_API, null, new Properties[]{Properties.ACCESS1, Properties.AED0, eapAllow}, new Properties[]{Properties.ACCESS0, Properties.AED0, eapAllow}, null, false, expected},
/**
* Case 2-6: API property setting overrides system property setting.
*
* Expect: access denied by RESOURCE_ACCESS
*/
{xmlFile, xsdOrXsl, Properties.FSP, PropertyState.CONFIG_FILE_SYSTEM_API, null, new Properties[]{Properties.ACCESS0, Properties.AED0, eapAllow}, new Properties[]{Properties.ACCESS1, Properties.AED0, eapAllow}, null, true, SP_ACCESS},
/**
* Case 3: Catalogs take precedence in the resource resolution process.
*
* Case 3-1: the built-in catalog's Resolve property is set to "strict",
* and the reference is not in the built-in catalog.
*
* Expect: error as access is denied by the Catalog's Resolve property
*/
{xmlFile, xsdOrXsl, null, PropertyState.CONFIG_FILE_SYSTEM_API, Properties.CONFIG_FILE_CATALOG_STRICT, null, new Properties[]{Properties.ACCESS0, Properties.AED0, eapAllow}, null, true, errCode},
/**
* Case 3-2: custom catalog resolves the reference before direct fetch.
* FSP sets EAP to deny direct fetch, but catalog resolution completes first.
*
* Expect: no error
*/
{xmlFile, xsdOrXsl, Properties.FSP, PropertyState.CONFIG_FILE, Properties.CONFIG_FILE_CATALOG_STRICT, null, null, CustomCatalog.STRICT, false, expected},
};
}
public void testDOM(String filename, Properties fsp, PropertyState state,
Properties config, Properties[] sysProp, Properties[] apiProp, CustomCatalog cc,
boolean expectError, String error) throws Exception {
DocumentBuilderFactory dbf = getDBF(fsp, state, config, sysProp, apiProp, cc);
process(filename, dbf, expectError, error);
}
public void testSAX(String filename, Properties fsp, PropertyState state,
Properties config, Properties[] sysProp, Properties[] apiProp, CustomCatalog cc,
boolean expectError, String error) throws Exception {
SAXParser parser = getSAXParser(fsp, state, config, sysProp, apiProp, cc);
process(filename, parser, expectError, error);
}
public void testStAX(String filename, Properties fsp, PropertyState state,
Properties config, Properties[] sysProp, Properties[] apiProp, CustomCatalog cc,
boolean expectError, String error) throws Exception {
XMLInputFactory xif = getXMLInputFactory(state, config, sysProp, apiProp, cc);
process(filename, xif, expectError, error);
}
public void testSchema1(String filename, String xsd, Properties fsp, PropertyState state,
Properties config, Properties[] sysProp, Properties[] apiProp, CustomCatalog cc,
boolean expectError, String error) throws Exception {
SchemaFactory sf = getSchemaFactory(fsp, state, config, sysProp, apiProp, cc);
process(filename, sf, expectError, error);
}
public void testSchema2(String filename, String xsd, Properties fsp, PropertyState state,
Properties config, Properties[] sysProp, Properties[] apiProp, CustomCatalog cc,
boolean expectError, String error) throws Exception {
testSchema1(filename, xsd, fsp, state, config, sysProp, apiProp, cc, expectError, error);
}
public void testValidation(String filename, String xsd, Properties fsp, PropertyState state,
Properties config, Properties[] sysProp, Properties[] apiProp, CustomCatalog cc,
boolean expectError, String error) throws Exception {
SchemaFactory sf = getSchemaFactory(fsp, state, config, sysProp, apiProp, cc);
validate(filename, sf, expectError, error);
}
public void testStylesheet(String filename, String xsl, Properties fsp, PropertyState state,
Properties config, Properties[] sysProp, Properties[] apiProp, CustomCatalog cc,
boolean expectError, String error) throws Exception {
TransformerFactory tf = getTransformerFactory(fsp, state, config, sysProp, apiProp, cc);
process(filename, tf, expectError, error);
}
public void testTransform(String filename, String xsl, Properties fsp, PropertyState state,
Properties config, Properties[] sysProp, Properties[] apiProp, CustomCatalog cc,
boolean expectError, String error) throws Exception {
TransformerFactory tf = getTransformerFactory(fsp, state, config, sysProp, apiProp, cc);
transform(filename, xsl, tf, expectError, error);
}
// parameters in the same order as the test method
String filename; String xsd; String xsl; Properties fsp; PropertyState state;
Properties config; Properties[] sysProp; Properties[] apiProp; CustomCatalog cc;
boolean expectError; String error;
// Maps the scenario array to individual parameters
public void paramMap(Processor processor, String method, String index) {
int i = 0;
Object[][] params;
if (processor == Processor.VALIDATOR ||
processor == Processor.TRANSFORMER) {
params = getConfig(method);
i = 1;
} else {
params = getConfigs(processor);
}
Object[] param = params[Integer.parseInt(index)];
filename = (String)param[0];
if (processor == Processor.VALIDATOR) {
xsd = (String)param[i];
} else if (processor == Processor.TRANSFORMER) {
xsl = (String)param[i];
}
fsp = (Properties)param[i + 1];
state = (PropertyState)param[i + 2];
config = (Properties)param[i + 3];
sysProp = (Properties[])param[i + 4];
apiProp = (Properties[])param[i + 5];
cc = (CustomCatalog)param[i + 6];
expectError = (boolean)param[i + 7];
error = (String)param[i + 8];
}
public void paramMapXInclude(Processor processor, String index) {
Object[] param = getXIncludeConfigs(processor)[Integer.parseInt(index)];
filename = (String)param[0];
fsp = (Properties)param[1];
state = (PropertyState)param[2];
config = (Properties)param[3];
sysProp = (Properties[])param[4];
apiProp = (Properties[])param[5];
cc = (CustomCatalog)param[6];
expectError = (boolean)param[7];
error = (String)param[8];
}
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2026, 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 common.access;
import java.net.ProxySelector;
/**
* @test @bug 8357394
* @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
* @modules java.xml/jdk.xml.internal
* @run driver common.access.DOMTest 0 // by default, both RESOURCE_ACCESS and EAP allow access
* @run driver common.access.DOMTest 1 // FSP is set, both RESOURCE_ACCESS and EAP are set to allow
* @run driver common.access.DOMTest 2 // FSP is set, RESOURCE_ACCESS is unchanged, EAP denies access
* @run driver common.access.DOMTest 3 // RESOURCE_ACCESS denies access though EAP allows it
* @run driver common.access.DOMTest 4 // ACCESS_EXTERNAL_DTD denies access though RESOURCE_ACCESS allows it
* @run driver common.access.DOMTest 5 // system properties override FSP secure values
* @run driver common.access.DOMTest 6 // API RESOURCE_ACCESS allow overrides system RESOURCE_ACCESS deny
* @run driver common.access.DOMTest 7 // API RESOURCE_ACCESS deny overrides system RESOURCE_ACCESS allow
* @run driver common.access.DOMTest 8 // the built-in catalog's Resolve property is strict
* @run driver common.access.DOMTest 9 // the built-in catalog resolves the reference before direct fetch
* @run driver common.access.DOMTest 10 // the custom catalog resolves the reference before direct fetch
* @summary Tests the interaction between Resource Access (jdk.xml.resource.access),
* External Access Properties (EAPs), and the built-in catalog's Resolve setting,
* ensuring correct precedence and behavior across different combinations of these
* configuration mechanisms
*/
public class DOMTest extends AccessTestBase {
public static void main(String[] args) throws Exception {
final ProxySelector previous = ProxySelector.getDefault();
// disable proxy
ProxySelector.setDefault(ProxySelector.of(null));
try {
new DOMTest().run(args[0]);
} finally {
// reset to the previous proxy selector
ProxySelector.setDefault(previous);
}
}
public void run(String index) throws Exception {
paramMap(Processor.DOM, null, index);
super.testDOM(filename, fsp, state, config, sysProp, apiProp, cc, expectError, error);
}
}

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2026, 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 common.access;
import common.util.TestBase;
import java.net.ProxySelector;
/**
* @test @bug 8357394
* @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
* @modules java.xml/jdk.xml.internal
* @run driver common.access.SAXTest 0 // by default, both RESOURCE_ACCESS and EAP allow access
* @run driver common.access.SAXTest 1 // FSP is set, both RESOURCE_ACCESS and EAP are set to allow
* @run driver common.access.SAXTest 2 // FSP is set, RESOURCE_ACCESS is unchanged, EAP denies access
* @run driver common.access.SAXTest 3 // RESOURCE_ACCESS denies access though EAP allows it
* @run driver common.access.SAXTest 4 // ACCESS_EXTERNAL_DTD denies access though RESOURCE_ACCESS allows it
* @run driver common.access.SAXTest 5 // system properties override FSP secure values
* @run driver common.access.SAXTest 6 // API RESOURCE_ACCESS allow overrides system RESOURCE_ACCESS deny
* @run driver common.access.SAXTest 7 // API RESOURCE_ACCESS deny overrides system RESOURCE_ACCESS allow
* @run driver common.access.SAXTest 8 // the built-in catalog's Resolve property is strict
* @run driver common.access.SAXTest 9 // the built-in catalog resolves the reference before direct fetch
* @run driver common.access.SAXTest 10 // the custom catalog resolves the reference before direct fetch
* @summary Tests the interaction between Resource Access (jdk.xml.resource.access),
* External Access Properties (EAPs), and the built-in catalog's Resolve setting,
* ensuring correct precedence and behavior across different combinations of these
* configuration mechanisms
*/
public class SAXTest extends AccessTestBase {
public static void main(String[] args) throws Exception {
final ProxySelector previous = ProxySelector.getDefault();
// disable proxy
ProxySelector.setDefault(ProxySelector.of(null));
try {
new SAXTest().run(args[0]);
} finally {
// reset to the previous proxy selector
ProxySelector.setDefault(previous);
}
}
public void run(String index) throws Exception {
paramMap(TestBase.Processor.SAX, null, index);
super.testSAX(filename, fsp, state, config, sysProp, apiProp, cc, expectError, error);
}
}

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2026, 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 common.access;
import java.net.ProxySelector;
/**
* @test @bug 8306632
* @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
* @modules java.xml/jdk.xml.internal
* @run driver common.access.SchemaTest SchemaTest1 0 // default RESOURCE_ACCESS and ACCESS_EXTERNAL_SCHEMA allow access
* @run driver common.access.SchemaTest SchemaTest1 1 // FSP with explicit RESOURCE_ACCESS and ACCESS_EXTERNAL_SCHEMA allow
* @run driver common.access.SchemaTest SchemaTest1 2 // FSP leaves RESOURCE_ACCESS unchanged, ACCESS_EXTERNAL_SCHEMA denies
* @run driver common.access.SchemaTest SchemaTest1 3 // RESOURCE_ACCESS denies access though ACCESS_EXTERNAL_SCHEMA allows it
* @run driver common.access.SchemaTest SchemaTest1 4 // ACCESS_EXTERNAL_SCHEMA denies access though RESOURCE_ACCESS allows it
* @run driver common.access.SchemaTest SchemaTest1 5 // system properties override FSP secure values
* @run driver common.access.SchemaTest SchemaTest1 6 // API RESOURCE_ACCESS allow overrides system RESOURCE_ACCESS deny
* @run driver common.access.SchemaTest SchemaTest1 7 // API RESOURCE_ACCESS deny overrides system RESOURCE_ACCESS allow
* @run driver common.access.SchemaTest SchemaTest1 8 // built-in catalog resolve=strict denies unresolved reference
* @run driver common.access.SchemaTest SchemaTest1 9 // custom catalog resolves before direct fetch
* @run driver common.access.SchemaTest SchemaTest2 0 // default RESOURCE_ACCESS and ACCESS_EXTERNAL_SCHEMA allow access
* @run driver common.access.SchemaTest SchemaTest2 1 // FSP with explicit RESOURCE_ACCESS and ACCESS_EXTERNAL_SCHEMA allow
* @run driver common.access.SchemaTest SchemaTest2 2 // FSP leaves RESOURCE_ACCESS unchanged, ACCESS_EXTERNAL_SCHEMA denies
* @run driver common.access.SchemaTest SchemaTest2 3 // RESOURCE_ACCESS denies access though ACCESS_EXTERNAL_SCHEMA allows it
* @run driver common.access.SchemaTest SchemaTest2 4 // ACCESS_EXTERNAL_SCHEMA denies access though RESOURCE_ACCESS allows it
* @run driver common.access.SchemaTest SchemaTest2 5 // system properties override FSP secure values
* @run driver common.access.SchemaTest SchemaTest2 6 // API RESOURCE_ACCESS allow overrides system RESOURCE_ACCESS deny
* @run driver common.access.SchemaTest SchemaTest2 7 // API RESOURCE_ACCESS deny overrides system RESOURCE_ACCESS allow
* @run driver common.access.SchemaTest SchemaTest2 8 // built-in catalog resolve=strict denies unresolved reference
* @run driver common.access.SchemaTest SchemaTest2 9 // custom catalog resolves before direct fetch
* @run driver common.access.SchemaTest Validation 0 // default RESOURCE_ACCESS and ACCESS_EXTERNAL_SCHEMA allow access
* @run driver common.access.SchemaTest Validation 1 // FSP with explicit RESOURCE_ACCESS and ACCESS_EXTERNAL_SCHEMA allow
* @run driver common.access.SchemaTest Validation 2 // FSP leaves RESOURCE_ACCESS unchanged, ACCESS_EXTERNAL_SCHEMA denies
* @run driver common.access.SchemaTest Validation 3 // RESOURCE_ACCESS denies access though ACCESS_EXTERNAL_SCHEMA allows it
* @run driver common.access.SchemaTest Validation 4 // ACCESS_EXTERNAL_SCHEMA denies access though RESOURCE_ACCESS allows it
* @run driver common.access.SchemaTest Validation 5 // system properties override FSP secure values
* @run driver common.access.SchemaTest Validation 6 // API RESOURCE_ACCESS allow overrides system RESOURCE_ACCESS deny
* @run driver common.access.SchemaTest Validation 7 // API RESOURCE_ACCESS deny overrides system RESOURCE_ACCESS allow
* @run driver common.access.SchemaTest Validation 8 // built-in catalog resolve=strict denies unresolved reference
* @run driver common.access.SchemaTest Validation 9 // custom catalog resolves before direct fetch
* @summary verifies Schema and Validation support for Resource Access, ACCESS_EXTERNAL_SCHEMA, and catalog precedence.
*/
public class SchemaTest extends AccessTestBase {
public static void main(String args[]) throws Exception {
new SchemaTest().run(args[0], args[1]);
}
public void run(String method, String index) throws Exception {
paramMap(Processor.VALIDATOR, method, index);
switch (method) {
case "SchemaTest1":
super.testSchema1(filename, xsd, fsp, state, config, sysProp, apiProp, cc, expectError, error);
break;
case "SchemaTest2":
super.testSchema2(filename, xsd, fsp, state, config, sysProp, apiProp, cc, expectError, error);
break;
case "Validation":
super.testValidation(filename, xsd, fsp, state, config, sysProp, apiProp, cc, expectError, error);
break;
}
}
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2026, 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 common.access;
import common.util.TestBase;
import java.net.ProxySelector;
/**
* @test @bug 8357394
* @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
* @modules java.xml/jdk.xml.internal
* @run driver common.access.StAXTest 0 // by default, both RESOURCE_ACCESS and EAP allow access
* @run driver common.access.StAXTest 3 // RESOURCE_ACCESS denies access though EAP allows it
* @run driver common.access.StAXTest 4 // ACCESS_EXTERNAL_DTD denies access though RESOURCE_ACCESS allows it
* @run driver common.access.StAXTest 5 // system properties override FSP secure values
* @run driver common.access.StAXTest 6 // API RESOURCE_ACCESS allow overrides system RESOURCE_ACCESS deny
* @run driver common.access.StAXTest 7 // API RESOURCE_ACCESS deny overrides system RESOURCE_ACCESS allow
* @run driver common.access.StAXTest 8 // the built-in catalog's Resolve property is strict
* @run driver common.access.StAXTest 9 // the built-in catalog resolves the reference before direct fetch
* @run driver common.access.StAXTest 10 // the custom catalog resolves the reference before direct fetch
* @summary Tests the interaction between Resource Access (jdk.xml.resource.access),
* External Access Properties (EAPs), and the built-in catalog's Resolve setting,
* ensuring correct precedence and behavior across different combinations of these
* configuration mechanisms
*/
public class StAXTest extends AccessTestBase {
public static void main(String[] args) throws Exception {
new StAXTest().run(args[0]);
}
public void run(String index) throws Exception {
paramMap(TestBase.Processor.STAX, null, index);
super.testStAX(filename, fsp, state, config, sysProp, apiProp, cc, expectError, error);
}
}

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2026, 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 common.access;
/**
* @test @bug 8306632
* @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
* @modules java.xml/jdk.xml.internal
* @run driver common.access.TransformTest Stylesheet 0 // default RESOURCE_ACCESS and ACCESS_EXTERNAL_DTD allow access
* @run driver common.access.TransformTest Stylesheet 1 // FSP with explicit RESOURCE_ACCESS and ACCESS_EXTERNAL_DTD allow
* @run driver common.access.TransformTest Stylesheet 2 // FSP leaves RESOURCE_ACCESS unchanged, ACCESS_EXTERNAL_DTD denies
* @run driver common.access.TransformTest Stylesheet 3 // RESOURCE_ACCESS denies access though ACCESS_EXTERNAL_DTD allows it
* @run driver common.access.TransformTest Stylesheet 4 // ACCESS_EXTERNAL_DTD denies access though RESOURCE_ACCESS allows it
* @run driver common.access.TransformTest Stylesheet 5 // system properties override FSP secure values
* @run driver common.access.TransformTest Stylesheet 6 // API RESOURCE_ACCESS allow overrides system RESOURCE_ACCESS deny
* @run driver common.access.TransformTest Stylesheet 7 // API RESOURCE_ACCESS deny overrides system RESOURCE_ACCESS allow
* @run driver common.access.TransformTest Stylesheet 8 // built-in catalog resolve=strict denies unresolved reference
* @run driver common.access.TransformTest Stylesheet 9 // custom catalog resolves before direct fetch
* @run driver common.access.TransformTest Transform 0 // default RESOURCE_ACCESS and ACCESS_EXTERNAL_STYLESHEET allow access
* @run driver common.access.TransformTest Transform 1 // FSP with explicit RESOURCE_ACCESS and ACCESS_EXTERNAL_STYLESHEET allow
* @run driver common.access.TransformTest Transform 2 // FSP leaves RESOURCE_ACCESS unchanged, ACCESS_EXTERNAL_STYLESHEET denies
* @run driver common.access.TransformTest Transform 3 // RESOURCE_ACCESS denies access though ACCESS_EXTERNAL_STYLESHEET allows it
* @run driver common.access.TransformTest Transform 4 // ACCESS_EXTERNAL_STYLESHEET denies access though RESOURCE_ACCESS allows it
* @run driver common.access.TransformTest Transform 5 // system properties override FSP secure values
* @run driver common.access.TransformTest Transform 6 // API RESOURCE_ACCESS allow overrides system RESOURCE_ACCESS deny
* @run driver common.access.TransformTest Transform 7 // API RESOURCE_ACCESS deny overrides system RESOURCE_ACCESS allow
* @run driver common.access.TransformTest Transform 8 // built-in catalog resolve=strict denies unresolved reference
* @run driver common.access.TransformTest Transform 9 // custom catalog resolves before direct fetch
* @summary verifies Transform support for Resource Access, external access properties, and catalog precedence.
*/
public class TransformTest extends AccessTestBase {
public static void main(String args[]) throws Exception {
new TransformTest().run(args[0], args[1]);
}
public void run(String method, String index) throws Exception {
paramMap(Processor.TRANSFORMER, method, index);
switch (method) {
case "Stylesheet":
super.testStylesheet(filename, xsl, fsp, state, config, sysProp, apiProp, cc, expectError, error);
break;
case "Transform":
super.testTransform(filename, xsl, fsp, state, config, sysProp, apiProp, cc, expectError, error);
break;
}
}
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2026, 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 common.access;
/**
* @test @bug 8306632
* @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
* @modules java.xml/jdk.xml.internal
* @run driver common.access.XIncludeTest DOM 0 // default RESOURCE_ACCESS allows direct XInclude access
* @run driver common.access.XIncludeTest DOM 1 // FSP with explicit RESOURCE_ACCESS allow
* @run driver common.access.XIncludeTest DOM 2 // RESOURCE_ACCESS denies direct XInclude access
* @run driver common.access.XIncludeTest DOM 3 // system properties override FSP
* @run driver common.access.XIncludeTest DOM 4 // API RESOURCE_ACCESS allow overrides system RESOURCE_ACCESS deny
* @run driver common.access.XIncludeTest DOM 5 // API RESOURCE_ACCESS deny overrides system RESOURCE_ACCESS allow
* @run driver common.access.XIncludeTest DOM 6 // custom catalog resolves before direct fetch
* @run driver common.access.XIncludeTest SAX 0 // default RESOURCE_ACCESS allows direct XInclude access
* @run driver common.access.XIncludeTest SAX 1 // FSP with explicit RESOURCE_ACCESS allow
* @run driver common.access.XIncludeTest SAX 2 // RESOURCE_ACCESS denies direct XInclude access
* @run driver common.access.XIncludeTest SAX 3 // system properties override FSP
* @run driver common.access.XIncludeTest SAX 4 // API RESOURCE_ACCESS allow overrides system RESOURCE_ACCESS deny
* @run driver common.access.XIncludeTest SAX 5 // API RESOURCE_ACCESS deny overrides system RESOURCE_ACCESS allow
* @run driver common.access.XIncludeTest SAX 6 // custom catalog resolves before direct fetch
* @summary verifies XInclude support for Resource Access and catalog precedence.
*/
public class XIncludeTest extends AccessTestBase {
public static void main(String args[]) throws Exception {
new XIncludeTest().run(args[0], args[1]);
}
public void run(String processor, String index) throws Exception {
Processor p = Processor.valueOf(processor);
paramMapXInclude(p, index);
switch (p) {
case DOM:
super.testDOM(filename, fsp, state, config, sysProp, apiProp, cc, expectError, error);
break;
case SAX:
super.testSAX(filename, fsp, state, config, sysProp, apiProp, cc, expectError, error);
break;
default:
throw new IllegalArgumentException("Unsupported processor: " + processor);
}
}
}

View File

@ -18,6 +18,9 @@
<!-- file:/path/val_test.xsd -->
<systemSuffix systemIdSuffix="val_test.xsd" uri="val_test.xsd"/>
</group>
<group id="xsls" prefer = "system" xml:base = "../../xmlfiles/">
<uri name="XSLPI_target.xsl" uri="XSLPI_target.xsl"/>
</group>
<group id="xi" prefer = "system" xml:base = "xinclude/">
@ -26,7 +29,7 @@
<system systemId="XI_test2.xml" uri="XI_test2.xml"/>
<system systemId="XI_utf8.xml" uri="XI_utf8.xml"/>
</group>
<!-- additional catalogs can be added a NextCatalog besides registering
<!-- additional catalogs can be added in a NextCatalog besides registering
through the Feature.FILES (javax.xml.catalog.files) property -->
<!-- nextCatalog catalog="pathto/AnotherCatalog.xml"/-->
</catalog>

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package common.dtd;
@ -12,7 +12,7 @@ import javax.xml.validation.SchemaFactory;
import common.util.TestBase;
/**
* @bug 8306632
* @bug 8306632 8357394
* @summary tests the DTD property jdk.xml.dtd.support.
* The DTD property controls how DTDs are processed.
*/
@ -126,7 +126,7 @@ public class DTDTestBase extends TestBase {
* Expect: error as the parser processes DTD and tries to access the invalid site
* Error: JAXP00010008 java.net.UnknownHostException: invalid.site.com
*/
{fileDTDNotInC, null, null, null, null, null, isErrExpected, expected},
{fileDTDNotInC, null, null, null, null, null, isErrExpected, expected1},
/**
* Case 1-2: DTD=deny in config file

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2026, 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
@ -29,7 +29,6 @@ import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Objects;
import java.util.regex.Pattern;
import javax.xml.XMLConstants;
import javax.xml.catalog.CatalogFeatures;
import javax.xml.parsers.DocumentBuilder;
@ -44,6 +43,7 @@ import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXSource;
@ -53,8 +53,8 @@ import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
@ -90,8 +90,8 @@ public class TestBase {
private static final String CONFIG_FILE = "java.xml.config.file";
// CATALOG Abbreviation: C
static final String C_FILE = CatalogFeatures.Feature.FILES.getPropertyName();
static final String C_RESOLVE = CatalogFeatures.Feature.RESOLVE.getPropertyName();
public static final String C_FILE = CatalogFeatures.Feature.FILES.getPropertyName();
public static final String C_RESOLVE = CatalogFeatures.Feature.RESOLVE.getPropertyName();
// Xerces Property
public static final String DISALLOW_DTD = "http://apache.org/xml/features/disallow-doctype-decl";
@ -106,15 +106,31 @@ public class TestBase {
public static final String SP_CATALOG = "jdk.xml.jdkcatalog.resolve";
public static final String OVERRIDE_PARSER = "jdk.xml.overrideDefaultParser";
//System Properties corresponding to ACCESS_EXTERNAL_* properties
public static final String SP_ACCESS_EXTERNAL_STYLESHEET = "javax.xml.accessExternalStylesheet";
public static final String SP_ACCESS_EXTERNAL_DTD = "javax.xml.accessExternalDTD";
public static final String SP_ACCESS_EXTERNAL_SCHEMA = "javax.xml.accessExternalSchema";
//Values for the ACCESS_EXTERNAL_* properties
public static final String ACCESS_EXTERNAL_ALL = "all";
public static final String ACCESS_EXTERNAL_NONE = "";
// JDK 27
public static final String SP_ACCESS = "jdk.xml.resource.access";
// DTD/CATALOG constants
public static final String RESOLVE_CONTINUE = "continue";
public static final String RESOLVE_IGNORE = "ignore";
public static final String RESOLVE_STRICT = "strict";
public static final String RESOLVE_STRICT_NONLOCAL = "strict:non-local";
public static final String DTD_ALLOW = "allow";
public static final String DTD_IGNORE = "ignore";
public static final String DTD_DENY = "deny";
// resource access constants
public static final String ACCESS_ALLOW = "*";
public static final String ACCESS_DENY = "";
// JAXP Configuration File(JCF) location
// DTD = deny
public static final String JCF_DTD2 = "dtd2.properties";
@ -126,6 +142,8 @@ public class TestBase {
public static final String CONFIG_DEFAULT = "jaxp.properties";
public static final String CONFIG_STRICT = "jaxp-strict.properties";
public static final String CONFIG_TEMPLATE_STRICT = "jaxp-strict.properties.template";
public static final String CONFIG_COMPAT = "jaxp-compat.properties";
public static final String CONFIG_TEMPLATE_COMPAT = "jaxp-compat.properties.template";
public static final String UNKNOWN_HOST = "invalid.site.com";
@ -150,6 +168,16 @@ public class TestBase {
CATALOG0(SP_CATALOG, "ditto", Type.PROPERTY, RESOLVE_CONTINUE),
CATALOG1(SP_CATALOG, "ditto", Type.PROPERTY, RESOLVE_IGNORE),
CATALOG2(SP_CATALOG, "ditto", Type.PROPERTY, RESOLVE_STRICT),
CATALOG_NONLOCAL(SP_CATALOG, "ditto", Type.PROPERTY, RESOLVE_STRICT_NONLOCAL),
AED0(XMLConstants.ACCESS_EXTERNAL_DTD, SP_ACCESS_EXTERNAL_DTD, Type.PROPERTY, ACCESS_EXTERNAL_ALL),
AED2(XMLConstants.ACCESS_EXTERNAL_DTD, SP_ACCESS_EXTERNAL_DTD, Type.PROPERTY, ACCESS_EXTERNAL_NONE),
AES0(XMLConstants.ACCESS_EXTERNAL_SCHEMA, SP_ACCESS_EXTERNAL_SCHEMA, Type.PROPERTY, ACCESS_EXTERNAL_ALL),
AES2(XMLConstants.ACCESS_EXTERNAL_SCHEMA, SP_ACCESS_EXTERNAL_SCHEMA, Type.PROPERTY, ACCESS_EXTERNAL_NONE),
AEX0(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, SP_ACCESS_EXTERNAL_STYLESHEET, Type.PROPERTY, ACCESS_EXTERNAL_ALL),
AEX2(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, SP_ACCESS_EXTERNAL_STYLESHEET, Type.PROPERTY, ACCESS_EXTERNAL_NONE),
ACCESS0(SP_ACCESS, "ditto", Type.PROPERTY, ACCESS_ALLOW),
ACCESS1(SP_ACCESS, "ditto", Type.PROPERTY, ACCESS_DENY),
// StAX properties
SUPPORT_DTD(XMLInputFactory.SUPPORT_DTD, null, Type.FEATURE, "true"),
@ -243,10 +271,21 @@ public class TestBase {
String error) throws Exception {
//dbf.setAttribute(CatalogFeatures.Feature.RESOLVE.getPropertyName(), "continue");
DocumentBuilder builder = dbf.newDocumentBuilder();
builder.setEntityResolver((String publicId, String systemId) -> {
InputSource dtd = null;
InputStream is = null;
if ("http://foo.bar/dtd/test.dtd".equals(systemId)) {
is = getClass().getResourceAsStream("/local/store/path/test.dtd");
}
if (is != null) {
dtd = new InputSource(is);
}
return dtd;
});
File file = new File(getPath(TEST_SOURCE_DIR, filename));
try {
Document document = builder.parse(file);
Assert.assertTrue(!expectError);
builder.parse(file);
processResult(expectError, error);
} catch (Exception e) {
e.printStackTrace();
processError(expectError, error, e);
@ -259,7 +298,7 @@ public class TestBase {
File file = new File(getPath(TEST_SOURCE_DIR, filename));
try {
parser.parse(file, new DefaultHandler());
Assert.assertTrue(!expectError);
processResult(expectError, error);
} catch (Exception e) {
//e.printStackTrace();
processError(expectError, error, e);
@ -275,8 +314,7 @@ public class TestBase {
XMLStreamReader streamReader = xif.createXMLStreamReader(xml, entityxml);
String text = getText(streamReader, XMLStreamConstants.CHARACTERS);
System.out.println("Text: [" + text.trim() + "]");
Assert.assertTrue(Pattern.matches(expected, text.trim()));
Assert.assertTrue(!expectError);
processResult(expectError, expected);
} catch (Exception e) {
e.printStackTrace();
processError(expectError, expected, e);
@ -289,8 +327,8 @@ public class TestBase {
String xsd = getPath(TEST_SOURCE_DIR, filename);
try {
Schema schema = sf.newSchema(new StreamSource(new File(xsd)));
Assert.assertTrue(!expectError);
} catch (Exception e) {
processResult(expectError, expected);
} catch (SAXException e) {
e.printStackTrace();
processError(expectError, expected, e);
}
@ -303,8 +341,8 @@ public class TestBase {
SAXSource xslSource = new SAXSource(new InputSource(xsl));
xslSource.setSystemId(xsl);
Transformer transformer = tf.newTransformer(xslSource);
Assert.assertTrue(!expectError);
} catch (Exception e) {
processResult(expectError, expected);
} catch (TransformerConfigurationException e) {
//e.printStackTrace();
processError(expectError, expected, e);
}
@ -320,7 +358,7 @@ public class TestBase {
Transformer transformer = tf.newTransformer(xslSource);
StringWriter sw = new StringWriter();
transformer.transform(getSource(SourceType.STREAM, xmlSysId), new StreamResult(sw));
Assert.assertTrue(!expectError);
processResult(expectError, expected);
} catch (Exception e) {
processError(expectError, expected, e);
}
@ -333,16 +371,23 @@ public class TestBase {
Schema schema = sf.newSchema();
Validator validator = schema.newValidator();
validator.validate(new StreamSource(new File(xml)));
Assert.assertTrue(!expectError);
processResult(expectError, expected);
} catch (Exception e) {
e.printStackTrace();
processError(expectError, expected, e);
}
}
protected void processResult(boolean expectError, String expected) {
if (expectError) {
Assert.assertTrue(false, "Expected error, but processing succeeded.");
}
}
protected void processError(boolean expectError, String error, Exception e)
throws Exception {
String str = e.getMessage();
String errorText = getErrorText(e);
if (!expectError) {
Assert.assertTrue(false, "Expected pass, but Exception is thrown " + str);
} else {
@ -351,11 +396,33 @@ public class TestBase {
if (UNKNOWN_HOST.equals(error)) {
Assert.assertTrue((str != null) && str.equals(error));
} else {
Assert.assertTrue((str != null) && str.contains(error));
String matched = null;
for (String err : error.split(",")) {
String trimmed = err.trim();
if (!trimmed.isEmpty() && errorText.contains(trimmed)) {
matched = trimmed;
break;
}
}
if (matched == null) {
Assert.assertTrue(false,"Missing expected error code(s): " + error);
}
Assert.assertTrue(true, "Found expected error code: " + matched);
}
}
}
private String getErrorText(Throwable t) {
StringBuilder sb = new StringBuilder();
while (t != null) {
if (t.getMessage() != null) {
sb.append(t.getMessage()).append('\n');
}
t = t.getCause();
}
return sb.toString();
}
/**
* Returns a DocumentBuilderFactory with settings as specified.
*
@ -667,11 +734,15 @@ public class TestBase {
System.setProperty(property.spName, property.value);
break;
case CONFIG_FILE:
System.setProperty(CONFIG_FILE, config.value);
if (config != null) {
System.setProperty(CONFIG_FILE, config.value);
}
break;
case CONFIG_FILE_SYSTEM:
case CONFIG_FILE_SYSTEM_API:
System.setProperty(CONFIG_FILE, config.value);
if (config != null) {
System.setProperty(CONFIG_FILE, config.value);
}
if (property != null) {
System.setProperty(property.spName, property.value);
}
@ -714,7 +785,7 @@ public class TestBase {
}
}
static String getPath(String base, String file) {
public static String getPath(String base, String file) {
String temp = base + file;
if (IS_WINDOWS) {
temp = "/" + temp;
@ -734,6 +805,8 @@ public class TestBase {
} else {
throw new RuntimeException("Expected true but was false. ");
}
} else if (message != null && !message.isEmpty()) {
System.out.println("Passed: " + message);
}
}

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<included>123</included>