# HG changeset patch # User aefimov # Date 1425574152 -10800 # Node ID 398edfc4c67bc4bfb8f32bba8c98c2dd6693fbf4 # Parent 4218b6ac2157d9d11bbb18bee55b6150459bd862 8040228: TransformerConfigurationException occurs with security manager, FSP and XSLT Ext Reviewed-by: joehw, lancea, ahgross diff -r 4218b6ac2157 -r 398edfc4c67b src/com/sun/org/apache/xalan/internal/XalanConstants.java --- a/src/com/sun/org/apache/xalan/internal/XalanConstants.java Fri Apr 03 23:27:33 2015 +0100 +++ b/src/com/sun/org/apache/xalan/internal/XalanConstants.java Thu Mar 05 19:49:12 2015 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -151,6 +151,16 @@ */ public static final String SP_MAX_ELEMENT_DEPTH = "jdk.xml.maxElementDepth"; + /** + * JDK TransformerFactory and Transformer attribute that specifies a class + * loader that will be used for extension functions class loading + * Value: a "null", the default value, means that the default EF class loading + * path will be used. + * Instance of ClassLoader: the specified instance of ClassLoader will be used + * for extension functions loading during translation process + */ + public static final String JDK_EXTENSION_CLASSLOADER = "jdk.xml.transform.extensionClassLoader"; + //legacy System Properties public final static String ENTITY_EXPANSION_LIMIT = "entityExpansionLimit"; public static final String ELEMENT_ATTRIBUTE_LIMIT = "elementAttributeLimit" ; diff -r 4218b6ac2157 -r 398edfc4c67b src/com/sun/org/apache/xalan/internal/xsltc/compiler/FunctionCall.java --- a/src/com/sun/org/apache/xalan/internal/xsltc/compiler/FunctionCall.java Fri Apr 03 23:27:33 2015 +0100 +++ b/src/com/sun/org/apache/xalan/internal/xsltc/compiler/FunctionCall.java Thu Mar 05 19:49:12 2015 +0300 @@ -104,6 +104,9 @@ protected final static String EXSLT_STRINGS = "http://exslt.org/strings"; + protected final static String XALAN_CLASSPACKAGE_NAMESPACE = + "xalan://"; + // Namespace format constants protected final static int NAMESPACE_FORMAT_JAVA = 0; protected final static int NAMESPACE_FORMAT_CLASS = 1; @@ -900,8 +903,22 @@ if (_className != null && _className.length() > 0) { final int nArgs = _arguments.size(); try { - if (_clazz == null) { - _clazz = ObjectFactory.findProviderClass(_className, true); + if (_clazz == null) { + final boolean isSecureProcessing = getXSLTC().isSecureProcessing(); + final boolean isExtensionFunctionEnabled = getXSLTC() + .getFeature(FeatureManager.Feature.ORACLE_ENABLE_EXTENSION_FUNCTION); + + //Check if FSP and SM - only then proceed with loading + if (namespace != null && isSecureProcessing + && isExtensionFunctionEnabled + && (namespace.equals(JAVA_EXT_XALAN) + || namespace.equals(JAVA_EXT_XSLTC) + || namespace.equals(JAVA_EXT_XALAN_OLD) + || namespace.startsWith(XALAN_CLASSPACKAGE_NAMESPACE))) { + _clazz = getXSLTC().loadExternalFunction(_className); + } else { + _clazz = ObjectFactory.findProviderClass(_className, true); + } if (_clazz == null) { final ErrorMsg msg = diff -r 4218b6ac2157 -r 398edfc4c67b src/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java --- a/src/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java Fri Apr 03 23:27:33 2015 +0100 +++ b/src/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java Thu Mar 05 19:49:12 2015 +0300 @@ -23,24 +23,6 @@ package com.sun.org.apache.xalan.internal.xsltc.compiler; -import java.io.BufferedOutputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.Date; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Map; -import java.util.Properties; -import java.util.Vector; -import java.util.jar.JarEntry; -import java.util.jar.JarOutputStream; -import java.util.jar.Manifest; -import javax.xml.XMLConstants; - import com.sun.org.apache.bcel.internal.classfile.JavaClass; import com.sun.org.apache.xalan.internal.XalanConstants; import com.sun.org.apache.xalan.internal.utils.FeatureManager; @@ -50,7 +32,27 @@ import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util; import com.sun.org.apache.xml.internal.dtm.DTM; - +import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Collections; +import java.util.Date; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; +import java.util.Properties; +import java.util.Vector; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; +import javax.xml.XMLConstants; import org.xml.sax.InputSource; import org.xml.sax.XMLReader; @@ -153,11 +155,25 @@ private final FeatureManager _featureManager; /** + * Extension function class loader variables + */ + + /* Class loader reference that will be used for external extension functions loading */ + private ClassLoader _extensionClassLoader; + + /** + * HashMap with the loaded classes + */ + private final Map _externalExtensionFunctions; + + /** * XSLTC compiler constructor */ public XSLTC(boolean useServicesMechanism, FeatureManager featureManager) { _parser = new Parser(this, useServicesMechanism); _featureManager = featureManager; + _extensionClassLoader = null; + _externalExtensionFunctions = new HashMap<>(); } /** @@ -207,6 +223,8 @@ return _accessExternalDTD; } else if (name.equals(XalanConstants.SECURITY_MANAGER)) { return _xmlSecurityManager; + } else if (name.equals(XalanConstants.JDK_EXTENSION_CLASSLOADER)) { + return _extensionClassLoader; } return null; } @@ -222,6 +240,11 @@ _accessExternalDTD = (String)value; } else if (name.equals(XalanConstants.SECURITY_MANAGER)) { _xmlSecurityManager = (XMLSecurityManager)value; + } else if (name.equals(XalanConstants.JDK_EXTENSION_CLASSLOADER)) { + _extensionClassLoader = (ClassLoader) value; + /* Clear the external extension functions HashMap if extension class + loader was changed */ + _externalExtensionFunctions.clear(); } } @@ -256,6 +279,41 @@ _bcelClasses = new Vector(); } + private void setExternalExtensionFunctions(String name, Class clazz) { + if (_isSecureProcessing && clazz != null && !_externalExtensionFunctions.containsKey(name)) { + _externalExtensionFunctions.put(name, clazz); + } + } + + /* + * Function loads an external extension functions. + * The filtering of function types (external,internal) takes place in FunctionCall class + * + */ + Class loadExternalFunction(String name) throws ClassNotFoundException { + Class loaded = null; + //Check if the function is not loaded already + if (_externalExtensionFunctions.containsKey(name)) { + loaded = _externalExtensionFunctions.get(name); + } else if (_extensionClassLoader != null) { + loaded = Class.forName(name, true, _extensionClassLoader); + setExternalExtensionFunctions(name, loaded); + } + if (loaded == null) { + throw new ClassNotFoundException(name); + } + //Return loaded class + return (Class) loaded; + } + + /* + * Returns unmodifiable view of HashMap with loaded external extension + * functions - will be needed for the TransformerImpl + */ + public Map getExternalExtensionFunctions() { + return Collections.unmodifiableMap(_externalExtensionFunctions); + } + /** * Initializes the compiler to produce a new translet */ @@ -283,6 +341,7 @@ -1, // LEVEL_MULTIPLE -1 // LEVEL_ANY }; + _externalExtensionFunctions.clear(); } /** diff -r 4218b6ac2157 -r 398edfc4c67b src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java --- a/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java Fri Apr 03 23:27:33 2015 +0100 +++ b/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java Thu Mar 05 19:49:12 2015 +0300 @@ -602,6 +602,9 @@ {ErrorMsg.JAXP_INVALID_ATTR_ERR, "TransformerFactory does not recognise attribute ''{0}''."}, + {ErrorMsg.JAXP_INVALID_ATTR_VALUE_ERR, + "Incorrect value specified for ''{0}'' attribute."}, + /* * Note to translators: "setResult()" and "startDocument()" are Java * method names that should not be translated. diff -r 4218b6ac2157 -r 398edfc4c67b src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMsg.java --- a/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMsg.java Fri Apr 03 23:27:33 2015 +0100 +++ b/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMsg.java Thu Mar 05 19:49:12 2015 +0300 @@ -117,6 +117,7 @@ public static final String JAXP_NO_SOURCE_ERR = "JAXP_NO_SOURCE_ERR"; public static final String JAXP_COMPILE_ERR = "JAXP_COMPILE_ERR"; public static final String JAXP_INVALID_ATTR_ERR = "JAXP_INVALID_ATTR_ERR"; + public static final String JAXP_INVALID_ATTR_VALUE_ERR = "JAXP_INVALID_ATTR_VALUE_ERR"; public static final String JAXP_SET_RESULT_ERR = "JAXP_SET_RESULT_ERR"; public static final String JAXP_NO_TRANSLET_ERR = "JAXP_NO_TRANSLET_ERR"; public static final String JAXP_NO_HANDLER_ERR = "JAXP_NO_HANDLER_ERR"; diff -r 4218b6ac2157 -r 398edfc4c67b src/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java --- a/src/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java Fri Apr 03 23:27:33 2015 +0100 +++ b/src/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java Thu Mar 05 19:49:12 2015 +0300 @@ -24,28 +24,27 @@ package com.sun.org.apache.xalan.internal.xsltc.trax; import com.sun.org.apache.xalan.internal.XalanConstants; +import com.sun.org.apache.xalan.internal.utils.ObjectFactory; +import com.sun.org.apache.xalan.internal.utils.SecuritySupport; +import com.sun.org.apache.xalan.internal.xsltc.DOM; +import com.sun.org.apache.xalan.internal.xsltc.Translet; +import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; +import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; +import com.sun.org.apache.xalan.internal.xsltc.runtime.Hashtable; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; -import java.util.Properties; import java.security.AccessController; import java.security.PrivilegedAction; - +import java.util.Map; +import java.util.Properties; import javax.xml.XMLConstants; import javax.xml.transform.Templates; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.URIResolver; -import com.sun.org.apache.xalan.internal.xsltc.DOM; -import com.sun.org.apache.xalan.internal.xsltc.Translet; -import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; -import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; -import com.sun.org.apache.xalan.internal.xsltc.runtime.Hashtable; -import com.sun.org.apache.xalan.internal.utils.ObjectFactory; -import com.sun.org.apache.xalan.internal.utils.SecuritySupport; - /** * @author Morten Jorgensen * @author G. Todd Millerj @@ -131,8 +130,30 @@ private String _accessExternalStylesheet = XalanConstants.EXTERNAL_ACCESS_DEFAULT; static final class TransletClassLoader extends ClassLoader { + + private final Map _loadedExternalExtensionFunctions; + TransletClassLoader(ClassLoader parent) { super(parent); + _loadedExternalExtensionFunctions = null; + } + + TransletClassLoader(ClassLoader parent,Map mapEF) { + super(parent); + _loadedExternalExtensionFunctions = mapEF; + } + + public Class loadClass(String name) throws ClassNotFoundException { + Class ret = null; + // The _loadedExternalExtensionFunctions will be empty when the + // SecurityManager is not set and the FSP is turned off + if (_loadedExternalExtensionFunctions != null) { + ret = _loadedExternalExtensionFunctions.get(name); + } + if (ret == null) { + ret = super.loadClass(name); + } + return ret; } /** @@ -330,7 +351,7 @@ TransletClassLoader loader = (TransletClassLoader) AccessController.doPrivileged(new PrivilegedAction() { public Object run() { - return new TransletClassLoader(ObjectFactory.findClassLoader()); + return new TransletClassLoader(ObjectFactory.findClassLoader(),_tfactory.getExternalExtensionsMap()); } }); diff -r 4218b6ac2157 -r 398edfc4c67b src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java --- a/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java Fri Apr 03 23:27:33 2015 +0100 +++ b/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java Thu Mar 05 19:49:12 2015 +0300 @@ -27,12 +27,12 @@ import com.sun.org.apache.xalan.internal.utils.FactoryImpl; import com.sun.org.apache.xalan.internal.utils.FeatureManager; import com.sun.org.apache.xalan.internal.utils.FeaturePropertyBase; +import com.sun.org.apache.xalan.internal.utils.FeaturePropertyBase.State; import com.sun.org.apache.xalan.internal.utils.ObjectFactory; import com.sun.org.apache.xalan.internal.utils.SecuritySupport; import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager; import com.sun.org.apache.xalan.internal.utils.XMLSecurityPropertyManager; import com.sun.org.apache.xalan.internal.utils.XMLSecurityPropertyManager.Property; -import com.sun.org.apache.xalan.internal.utils.FeaturePropertyBase.State; import com.sun.org.apache.xalan.internal.xsltc.compiler.Constants; import com.sun.org.apache.xalan.internal.xsltc.compiler.SourceLoader; import com.sun.org.apache.xalan.internal.xsltc.compiler.XSLTC; @@ -50,6 +50,7 @@ import java.net.URL; import java.util.Enumeration; import java.util.Hashtable; +import java.util.Map; import java.util.Properties; import java.util.Vector; import java.util.zip.ZipEntry; @@ -57,7 +58,6 @@ import javax.xml.XMLConstants; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; - import javax.xml.transform.ErrorListener; import javax.xml.transform.Source; import javax.xml.transform.Templates; @@ -239,6 +239,13 @@ private final FeatureManager _featureManager; + private ClassLoader _extensionClassLoader = null; + + // Unmodifiable view of external extension function from xslt compiler + // It will be populated by user-specified extension functions during the + // type checking + private Map _xsltcExtensionFunctions; + /** * javax.xml.transform.sax.TransformerFactory implementation. */ @@ -270,6 +277,12 @@ //Parser's security manager _xmlSecurityManager = new XMLSecurityManager(true); + //Unmodifiable hash map with loaded external extension functions + _xsltcExtensionFunctions = null; + } + + public Map getExternalExtensionsMap() { + return _xsltcExtensionFunctions; } /** @@ -330,6 +343,8 @@ return Boolean.FALSE; } else if (name.equals(XalanConstants.SECURITY_MANAGER)) { return _xmlSecurityManager; + } else if (name.equals(XalanConstants.JDK_EXTENSION_CLASSLOADER)) { + return _extensionClassLoader; } /** Check to see if the property is managed by the security manager **/ @@ -444,6 +459,16 @@ return; } } + else if ( name.equals(XalanConstants.JDK_EXTENSION_CLASSLOADER)) { + if (value instanceof ClassLoader) { + _extensionClassLoader = (ClassLoader) value; + return; + } else { + final ErrorMsg err + = new ErrorMsg(ErrorMsg.JAXP_INVALID_ATTR_VALUE_ERR, "Extension Functions ClassLoader"); + throw new IllegalArgumentException(err.toString()); + } + } if (_xmlSecurityManager != null && _xmlSecurityManager.setLimit(name, XMLSecurityManager.State.APIPROPERTY, value)) { @@ -878,7 +903,6 @@ // Reset the per-session attributes to their default values // after each newTemplates() call. resetTransientAttributes(); - return new TemplatesImpl(bytecodes, transletClassName, null, _indentNumber, this); } } @@ -895,8 +919,10 @@ xsltc.setProperty(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, _accessExternalStylesheet); xsltc.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, _accessExternalDTD); xsltc.setProperty(XalanConstants.SECURITY_MANAGER, _xmlSecurityManager); + xsltc.setProperty(XalanConstants.JDK_EXTENSION_CLASSLOADER, _extensionClassLoader); xsltc.init(); - + if (!_isNotSecureProcessing) + _xsltcExtensionFunctions = xsltc.getExternalExtensionFunctions(); // Set a document loader (for xsl:include/import) if defined if (_uriResolver != null) { xsltc.setSourceLoader(this);