changeset 1191:398edfc4c67b

8040228: TransformerConfigurationException occurs with security manager, FSP and XSLT Ext Reviewed-by: joehw, lancea, ahgross
author aefimov
date Thu, 05 Mar 2015 19:49:12 +0300
parents 4218b6ac2157
children 62b76ee35108
files src/com/sun/org/apache/xalan/internal/XalanConstants.java src/com/sun/org/apache/xalan/internal/xsltc/compiler/FunctionCall.java src/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMsg.java src/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java
diffstat 7 files changed, 174 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- 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" ;
--- 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 =
--- 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<String, Class> _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<String, Class> 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();
     }
 
     /**
--- 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.
--- 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";
--- 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<String,Class> _loadedExternalExtensionFunctions;
+
         TransletClassLoader(ClassLoader parent) {
             super(parent);
+            _loadedExternalExtensionFunctions = null;
+        }
+
+        TransletClassLoader(ClassLoader parent,Map<String, Class> 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());
                 }
             });
 
--- 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<String, Class> _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<String,Class> 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);