Mercurial > hg > release > icedtea7-forest-2.5 > jaxp
changeset 644:9186b6efd2b2 jdk7u40-b28
Merge
author | lana |
---|---|
date | Fri, 31 May 2013 15:42:06 -0700 |
parents | c7596f69febb (current diff) d6d20248f406 (diff) |
children | 740942c76fb6 |
files | src/com/sun/org/apache/xerces/internal/xinclude/ObjectFactory.java src/com/sun/org/apache/xml/internal/serialize/ObjectFactory.java |
diffstat | 5 files changed, 238 insertions(+), 1244 deletions(-) [+] |
line wrap: on
line diff
--- a/src/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderImpl.java Wed May 29 13:24:29 2013 -0700 +++ b/src/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderImpl.java Fri May 31 15:42:06 2013 -0700 @@ -236,10 +236,6 @@ String feature = (String) entry.getKey(); boolean value = ((Boolean) entry.getValue()).booleanValue(); domParser.setFeature(feature, value); - if (feature.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) { - domParser.setProperty(ACCESS_EXTERNAL_DTD, ""); - domParser.setProperty(ACCESS_EXTERNAL_SCHEMA, ""); - } } } }
--- a/src/com/sun/org/apache/xerces/internal/jaxp/SAXParserImpl.java Wed May 29 13:24:29 2013 -0700 +++ b/src/com/sun/org/apache/xerces/internal/jaxp/SAXParserImpl.java Fri May 31 15:42:06 2013 -0700 @@ -242,10 +242,6 @@ String feature = (String) entry.getKey(); boolean value = ((Boolean) entry.getValue()).booleanValue(); xmlReader.setFeature0(feature, value); - if (feature.equals(XMLConstants.FEATURE_SECURE_PROCESSING) && value) { - xmlReader.setProperty0(ACCESS_EXTERNAL_DTD, ""); - xmlReader.setProperty0(ACCESS_EXTERNAL_SCHEMA, ""); - } } } }
--- a/src/com/sun/org/apache/xerces/internal/xinclude/ObjectFactory.java Wed May 29 13:24:29 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,553 +0,0 @@ -/* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * Copyright 2001-2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.sun.org.apache.xerces.internal.xinclude; - -import java.io.InputStream; -import java.io.IOException; -import java.io.File; -import java.io.FileInputStream; - -import java.util.Properties; -import java.io.BufferedReader; -import java.io.InputStreamReader; - -/** - * This class is duplicated for each JAXP subpackage so keep it in sync. - * It is package private and therefore is not exposed as part of the JAXP - * API. - * <p> - * This code is designed to implement the JAXP 1.1 spec pluggability - * feature and is designed to run on JDK version 1.1 and - * later, and to compile on JDK 1.2 and onward. - * The code also runs both as part of an unbundled jar file and - * when bundled as part of the JDK. - * <p> - * - */ -final class ObjectFactory { - - // - // Constants - // - - // name of default properties file to look for in JDK's jre/lib directory - private static final String DEFAULT_PROPERTIES_FILENAME = "xerces.properties"; - - /** Set to true for debugging */ - private static final boolean DEBUG = false; - - /** - * Default columns per line. - */ - private static final int DEFAULT_LINE_LENGTH = 80; - - /** cache the contents of the xerces.properties file. - * Until an attempt has been made to read this file, this will - * be null; if the file does not exist or we encounter some other error - * during the read, this will be empty. - */ - private static Properties fXercesProperties = null; - - /*** - * Cache the time stamp of the xerces.properties file so - * that we know if it's been modified and can invalidate - * the cache when necessary. - */ - private static long fLastModified = -1; - - // - // static methods - // - - /** - * Finds the implementation Class object in the specified order. The - * specified order is the following: - * <ol> - * <li>query the system property using <code>System.getProperty</code> - * <li>read <code>META-INF/services/<i>factoryId</i></code> file - * <li>use fallback classname - * </ol> - * - * @return Class object of factory, never null - * - * @param factoryId Name of the factory to find, same as - * a property name - * @param fallbackClassName Implementation class name, if nothing else - * is found. Use null to mean no fallback. - * - * @exception ObjectFactory.ConfigurationError - */ - static Object createObject(String factoryId, String fallbackClassName) - throws ConfigurationError { - return createObject(factoryId, null, fallbackClassName); - } // createObject(String,String):Object - - /** - * Finds the implementation Class object in the specified order. The - * specified order is the following: - * <ol> - * <li>query the system property using <code>System.getProperty</code> - * <li>read <code>$java.home/lib/<i>propertiesFilename</i></code> file - * <li>read <code>META-INF/services/<i>factoryId</i></code> file - * <li>use fallback classname - * </ol> - * - * @return Class object of factory, never null - * - * @param factoryId Name of the factory to find, same as - * a property name - * @param propertiesFilename The filename in the $java.home/lib directory - * of the properties file. If none specified, - * ${java.home}/lib/xerces.properties will be used. - * @param fallbackClassName Implementation class name, if nothing else - * is found. Use null to mean no fallback. - * - * @exception ObjectFactory.ConfigurationError - */ - static Object createObject(String factoryId, - String propertiesFilename, - String fallbackClassName) - throws ConfigurationError - { - if (DEBUG) debugPrintln("debug is on"); - - SecuritySupport ss = SecuritySupport.getInstance(); - ClassLoader cl = findClassLoader(); - - // Use the system property first - try { - String systemProp = ss.getSystemProperty(factoryId); - if (systemProp != null) { - if (DEBUG) debugPrintln("found system property, value=" + systemProp); - return newInstance(systemProp, cl, true); - } - } catch (SecurityException se) { - // Ignore and continue w/ next location - } - - // JAXP specific change - // always use fallback class to avoid the expense of constantly - // "stat"ing a non-existent "xerces.properties" and jar SPI entry - // see CR 6400863: Expensive creating of SAX parser in Mustang - if (true) { - if (fallbackClassName == null) { - throw new ConfigurationError( - "Provider for " + factoryId + " cannot be found", null); - } - - if (DEBUG) debugPrintln("using fallback, value=" + fallbackClassName); - return newInstance(fallbackClassName, cl, true); - } - - // Try to read from propertiesFilename, or $java.home/lib/xerces.properties - String factoryClassName = null; - // no properties file name specified; use $JAVA_HOME/lib/xerces.properties: - if (propertiesFilename == null) { - File propertiesFile = null; - boolean propertiesFileExists = false; - try { - String javah = ss.getSystemProperty("java.home"); - propertiesFilename = javah + File.separator + - "lib" + File.separator + DEFAULT_PROPERTIES_FILENAME; - propertiesFile = new File(propertiesFilename); - propertiesFileExists = ss.getFileExists(propertiesFile); - } catch (SecurityException e) { - // try again... - fLastModified = -1; - fXercesProperties = null; - } - - synchronized (ObjectFactory.class) { - boolean loadProperties = false; - FileInputStream fis = null; - try { - // file existed last time - if(fLastModified >= 0) { - if(propertiesFileExists && - (fLastModified < (fLastModified = ss.getLastModified(propertiesFile)))) { - loadProperties = true; - } else { - // file has stopped existing... - if(!propertiesFileExists) { - fLastModified = -1; - fXercesProperties = null; - } // else, file wasn't modified! - } - } else { - // file has started to exist: - if(propertiesFileExists) { - loadProperties = true; - fLastModified = ss.getLastModified(propertiesFile); - } // else, nothing's changed - } - if(loadProperties) { - // must never have attempted to read xerces.properties before (or it's outdeated) - fXercesProperties = new Properties(); - fis = ss.getFileInputStream(propertiesFile); - fXercesProperties.load(fis); - } - } catch (Exception x) { - fXercesProperties = null; - fLastModified = -1; - // assert(x instanceof FileNotFoundException - // || x instanceof SecurityException) - // In both cases, ignore and continue w/ next location - } - finally { - // try to close the input stream if one was opened. - if (fis != null) { - try { - fis.close(); - } - // Ignore the exception. - catch (IOException exc) {} - } - } - } - if(fXercesProperties != null) { - factoryClassName = fXercesProperties.getProperty(factoryId); - } - } else { - FileInputStream fis = null; - try { - fis = ss.getFileInputStream(new File(propertiesFilename)); - Properties props = new Properties(); - props.load(fis); - factoryClassName = props.getProperty(factoryId); - } catch (Exception x) { - // assert(x instanceof FileNotFoundException - // || x instanceof SecurityException) - // In both cases, ignore and continue w/ next location - } - finally { - // try to close the input stream if one was opened. - if (fis != null) { - try { - fis.close(); - } - // Ignore the exception. - catch (IOException exc) {} - } - } - } - if (factoryClassName != null) { - if (DEBUG) debugPrintln("found in " + propertiesFilename + ", value=" + factoryClassName); - return newInstance(factoryClassName, cl, true); - } - - // Try Jar Service Provider Mechanism - Object provider = findJarServiceProvider(factoryId); - if (provider != null) { - return provider; - } - - if (fallbackClassName == null) { - throw new ConfigurationError( - "Provider for " + factoryId + " cannot be found", null); - } - - if (DEBUG) debugPrintln("using fallback, value=" + fallbackClassName); - return newInstance(fallbackClassName, cl, true); - } // createObject(String,String,String):Object - - // - // Private static methods - // - - /** Prints a message to standard error if debugging is enabled. */ - private static void debugPrintln(String msg) { - if (DEBUG) { - System.err.println("JAXP: " + msg); - } - } // debugPrintln(String) - - /** - * Figure out which ClassLoader to use. For JDK 1.2 and later use - * the context ClassLoader. - */ - static ClassLoader findClassLoader() - throws ConfigurationError - { - SecuritySupport ss = SecuritySupport.getInstance(); - - // Figure out which ClassLoader to use for loading the provider - // class. If there is a Context ClassLoader then use it. - ClassLoader context = ss.getContextClassLoader(); - ClassLoader system = ss.getSystemClassLoader(); - - ClassLoader chain = system; - while (true) { - if (context == chain) { - // Assert: we are on JDK 1.1 or we have no Context ClassLoader - // or any Context ClassLoader in chain of system classloader - // (including extension ClassLoader) so extend to widest - // ClassLoader (always look in system ClassLoader if Xerces - // is in boot/extension/system classpath and in current - // ClassLoader otherwise); normal classloaders delegate - // back to system ClassLoader first so this widening doesn't - // change the fact that context ClassLoader will be consulted - ClassLoader current = ObjectFactory.class.getClassLoader(); - - chain = system; - while (true) { - if (current == chain) { - // Assert: Current ClassLoader in chain of - // boot/extension/system ClassLoaders - return system; - } - if (chain == null) { - break; - } - chain = ss.getParentClassLoader(chain); - } - - // Assert: Current ClassLoader not in chain of - // boot/extension/system ClassLoaders - return current; - } - - if (chain == null) { - // boot ClassLoader reached - break; - } - - // Check for any extension ClassLoaders in chain up to - // boot ClassLoader - chain = ss.getParentClassLoader(chain); - }; - - // Assert: Context ClassLoader not in chain of - // boot/extension/system ClassLoaders - return context; - } // findClassLoader():ClassLoader - - /** - * Create an instance of a class using the specified ClassLoader - */ - static Object newInstance(String className, ClassLoader cl, - boolean doFallback) - throws ConfigurationError - { - // assert(className != null); - try{ - Class providerClass = findProviderClass(className, cl, doFallback); - Object instance = providerClass.newInstance(); - if (DEBUG) debugPrintln("created new instance of " + providerClass + - " using ClassLoader: " + cl); - return instance; - } catch (ClassNotFoundException x) { - throw new ConfigurationError( - "Provider " + className + " not found", x); - } catch (Exception x) { - throw new ConfigurationError( - "Provider " + className + " could not be instantiated: " + x, - x); - } - } - - /** - * Find a Class using the specified ClassLoader - */ - static Class findProviderClass(String className, ClassLoader cl, - boolean doFallback) - throws ClassNotFoundException, ConfigurationError - { - //throw security exception if the calling thread is not allowed to access the package - //restrict the access to package as speicified in java.security policy - SecurityManager security = System.getSecurityManager(); - if (security != null) { - final int lastDot = className.lastIndexOf("."); - String packageName = className; - if (lastDot != -1) packageName = className.substring(0, lastDot); - security.checkPackageAccess(packageName); - } - Class providerClass; - if (cl == null) { - // XXX Use the bootstrap ClassLoader. There is no way to - // load a class using the bootstrap ClassLoader that works - // in both JDK 1.1 and Java 2. However, this should still - // work b/c the following should be true: - // - // (cl == null) iff current ClassLoader == null - // - // Thus Class.forName(String) will use the current - // ClassLoader which will be the bootstrap ClassLoader. - providerClass = Class.forName(className); - } else { - try { - providerClass = cl.loadClass(className); - } catch (ClassNotFoundException x) { - if (doFallback) { - // Fall back to current classloader - ClassLoader current = ObjectFactory.class.getClassLoader(); - if (current == null) { - providerClass = Class.forName(className); - } else if (cl != current) { - cl = current; - providerClass = cl.loadClass(className); - } else { - throw x; - } - } else { - throw x; - } - } - } - - return providerClass; - } - - /* - * Try to find provider using Jar Service Provider Mechanism - * - * @return instance of provider class if found or null - */ - private static Object findJarServiceProvider(String factoryId) - throws ConfigurationError - { - SecuritySupport ss = SecuritySupport.getInstance(); - String serviceId = "META-INF/services/" + factoryId; - InputStream is = null; - - // First try the Context ClassLoader - ClassLoader cl = findClassLoader(); - - is = ss.getResourceAsStream(cl, serviceId); - - // If no provider found then try the current ClassLoader - if (is == null) { - ClassLoader current = ObjectFactory.class.getClassLoader(); - if (cl != current) { - cl = current; - is = ss.getResourceAsStream(cl, serviceId); - } - } - - if (is == null) { - // No provider found - return null; - } - - if (DEBUG) debugPrintln("found jar resource=" + serviceId + - " using ClassLoader: " + cl); - - // Read the service provider name in UTF-8 as specified in - // the jar spec. Unfortunately this fails in Microsoft - // VJ++, which does not implement the UTF-8 - // encoding. Theoretically, we should simply let it fail in - // that case, since the JVM is obviously broken if it - // doesn't support such a basic standard. But since there - // are still some users attempting to use VJ++ for - // development, we have dropped in a fallback which makes a - // second attempt using the platform's default encoding. In - // VJ++ this is apparently ASCII, which is a subset of - // UTF-8... and since the strings we'll be reading here are - // also primarily limited to the 7-bit ASCII range (at - // least, in English versions), this should work well - // enough to keep us on the air until we're ready to - // officially decommit from VJ++. [Edited comment from - // jkesselm] - BufferedReader rd; - try { - rd = new BufferedReader(new InputStreamReader(is, "UTF-8"), DEFAULT_LINE_LENGTH); - } catch (java.io.UnsupportedEncodingException e) { - rd = new BufferedReader(new InputStreamReader(is), DEFAULT_LINE_LENGTH); - } - - String factoryClassName = null; - try { - // XXX Does not handle all possible input as specified by the - // Jar Service Provider specification - factoryClassName = rd.readLine(); - } catch (IOException x) { - // No provider found - return null; - } - finally { - try { - // try to close the reader. - rd.close(); - } - // Ignore the exception. - catch (IOException exc) {} - } - - if (factoryClassName != null && - ! "".equals(factoryClassName)) { - if (DEBUG) debugPrintln("found in resource, value=" - + factoryClassName); - - // Note: here we do not want to fall back to the current - // ClassLoader because we want to avoid the case where the - // resource file was found using one ClassLoader and the - // provider class was instantiated using a different one. - return newInstance(factoryClassName, cl, false); - } - - // No provider found - return null; - } - - // - // Classes - // - - /** - * A configuration error. - */ - static final class ConfigurationError - extends Error { - - /** Serialization version. */ - static final long serialVersionUID = 5061904944269807898L; - - // - // Data - // - - /** Exception. */ - private Exception exception; - - // - // Constructors - // - - /** - * Construct a new instance with the specified detail string and - * exception. - */ - ConfigurationError(String msg, Exception x) { - super(msg); - this.exception = x; - } // <init>(String,Exception) - - // - // methods - // - - /** Returns the exception associated to this error. */ - Exception getException() { - return exception; - } // getException():Exception - - } // class ConfigurationError - -} // class ObjectFactory
--- a/src/com/sun/org/apache/xml/internal/serialize/ObjectFactory.java Wed May 29 13:24:29 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,553 +0,0 @@ -/* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * Copyright 2001-2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.sun.org.apache.xml.internal.serialize; - -import java.io.InputStream; -import java.io.IOException; -import java.io.File; -import java.io.FileInputStream; - -import java.util.Properties; -import java.io.BufferedReader; -import java.io.InputStreamReader; - -/** - * This class is duplicated for each JAXP subpackage so keep it in sync. - * It is package private and therefore is not exposed as part of the JAXP - * API. - * <p> - * This code is designed to implement the JAXP 1.1 spec pluggability - * feature and is designed to run on JDK version 1.1 and - * later, and to compile on JDK 1.2 and onward. - * The code also runs both as part of an unbundled jar file and - * when bundled as part of the JDK. - * <p> - * - */ -final class ObjectFactory { - - // - // Constants - // - - // name of default properties file to look for in JDK's jre/lib directory - private static final String DEFAULT_PROPERTIES_FILENAME = "xerces.properties"; - - /** Set to true for debugging */ - private static final boolean DEBUG = false; - - /** - * Default columns per line. - */ - private static final int DEFAULT_LINE_LENGTH = 80; - - /** cache the contents of the xerces.properties file. - * Until an attempt has been made to read this file, this will - * be null; if the file does not exist or we encounter some other error - * during the read, this will be empty. - */ - private static Properties fXercesProperties = null; - - /*** - * Cache the time stamp of the xerces.properties file so - * that we know if it's been modified and can invalidate - * the cache when necessary. - */ - private static long fLastModified = -1; - - // - // static methods - // - - /** - * Finds the implementation Class object in the specified order. The - * specified order is the following: - * <ol> - * <li>query the system property using <code>System.getProperty</code> - * <li>read <code>META-INF/services/<i>factoryId</i></code> file - * <li>use fallback classname - * </ol> - * - * @return Class object of factory, never null - * - * @param factoryId Name of the factory to find, same as - * a property name - * @param fallbackClassName Implementation class name, if nothing else - * is found. Use null to mean no fallback. - * - * @exception ObjectFactory.ConfigurationError - */ - static Object createObject(String factoryId, String fallbackClassName) - throws ConfigurationError { - return createObject(factoryId, null, fallbackClassName); - } // createObject(String,String):Object - - /** - * Finds the implementation Class object in the specified order. The - * specified order is the following: - * <ol> - * <li>query the system property using <code>System.getProperty</code> - * <li>read <code>$java.home/lib/<i>propertiesFilename</i></code> file - * <li>read <code>META-INF/services/<i>factoryId</i></code> file - * <li>use fallback classname - * </ol> - * - * @return Class object of factory, never null - * - * @param factoryId Name of the factory to find, same as - * a property name - * @param propertiesFilename The filename in the $java.home/lib directory - * of the properties file. If none specified, - * ${java.home}/lib/xerces.properties will be used. - * @param fallbackClassName Implementation class name, if nothing else - * is found. Use null to mean no fallback. - * - * @exception ObjectFactory.ConfigurationError - */ - static Object createObject(String factoryId, - String propertiesFilename, - String fallbackClassName) - throws ConfigurationError - { - if (DEBUG) debugPrintln("debug is on"); - - SecuritySupport ss = SecuritySupport.getInstance(); - ClassLoader cl = findClassLoader(); - - // Use the system property first - try { - String systemProp = ss.getSystemProperty(factoryId); - if (systemProp != null) { - if (DEBUG) debugPrintln("found system property, value=" + systemProp); - return newInstance(systemProp, cl, true); - } - } catch (SecurityException se) { - // Ignore and continue w/ next location - } - - // JAXP specific change - // always use fallback class to avoid the expense of constantly - // "stat"ing a non-existent "xerces.properties" and jar SPI entry - // see CR 6400863: Expensive creating of SAX parser in Mustang - if (true) { - if (fallbackClassName == null) { - throw new ConfigurationError( - "Provider for " + factoryId + " cannot be found", null); - } - - if (DEBUG) debugPrintln("using fallback, value=" + fallbackClassName); - return newInstance(fallbackClassName, cl, true); - } - - // Try to read from propertiesFilename, or $java.home/lib/xerces.properties - String factoryClassName = null; - // no properties file name specified; use $JAVA_HOME/lib/xerces.properties: - if (propertiesFilename == null) { - File propertiesFile = null; - boolean propertiesFileExists = false; - try { - String javah = ss.getSystemProperty("java.home"); - propertiesFilename = javah + File.separator + - "lib" + File.separator + DEFAULT_PROPERTIES_FILENAME; - propertiesFile = new File(propertiesFilename); - propertiesFileExists = ss.getFileExists(propertiesFile); - } catch (SecurityException e) { - // try again... - fLastModified = -1; - fXercesProperties = null; - } - - synchronized (ObjectFactory.class) { - boolean loadProperties = false; - FileInputStream fis = null; - try { - // file existed last time - if(fLastModified >= 0) { - if(propertiesFileExists && - (fLastModified < (fLastModified = ss.getLastModified(propertiesFile)))) { - loadProperties = true; - } else { - // file has stopped existing... - if(!propertiesFileExists) { - fLastModified = -1; - fXercesProperties = null; - } // else, file wasn't modified! - } - } else { - // file has started to exist: - if(propertiesFileExists) { - loadProperties = true; - fLastModified = ss.getLastModified(propertiesFile); - } // else, nothing's changed - } - if(loadProperties) { - // must never have attempted to read xerces.properties before (or it's outdeated) - fXercesProperties = new Properties(); - fis = ss.getFileInputStream(propertiesFile); - fXercesProperties.load(fis); - } - } catch (Exception x) { - fXercesProperties = null; - fLastModified = -1; - // assert(x instanceof FileNotFoundException - // || x instanceof SecurityException) - // In both cases, ignore and continue w/ next location - } - finally { - // try to close the input stream if one was opened. - if (fis != null) { - try { - fis.close(); - } - // Ignore the exception. - catch (IOException exc) {} - } - } - } - if(fXercesProperties != null) { - factoryClassName = fXercesProperties.getProperty(factoryId); - } - } else { - FileInputStream fis = null; - try { - fis = ss.getFileInputStream(new File(propertiesFilename)); - Properties props = new Properties(); - props.load(fis); - factoryClassName = props.getProperty(factoryId); - } catch (Exception x) { - // assert(x instanceof FileNotFoundException - // || x instanceof SecurityException) - // In both cases, ignore and continue w/ next location - } - finally { - // try to close the input stream if one was opened. - if (fis != null) { - try { - fis.close(); - } - // Ignore the exception. - catch (IOException exc) {} - } - } - } - if (factoryClassName != null) { - if (DEBUG) debugPrintln("found in " + propertiesFilename + ", value=" + factoryClassName); - return newInstance(factoryClassName, cl, true); - } - - // Try Jar Service Provider Mechanism - Object provider = findJarServiceProvider(factoryId); - if (provider != null) { - return provider; - } - - if (fallbackClassName == null) { - throw new ConfigurationError( - "Provider for " + factoryId + " cannot be found", null); - } - - if (DEBUG) debugPrintln("using fallback, value=" + fallbackClassName); - return newInstance(fallbackClassName, cl, true); - } // createObject(String,String,String):Object - - // - // Private static methods - // - - /** Prints a message to standard error if debugging is enabled. */ - private static void debugPrintln(String msg) { - if (DEBUG) { - System.err.println("JAXP: " + msg); - } - } // debugPrintln(String) - - /** - * Figure out which ClassLoader to use. For JDK 1.2 and later use - * the context ClassLoader. - */ - static ClassLoader findClassLoader() - throws ConfigurationError - { - SecuritySupport ss = SecuritySupport.getInstance(); - - // Figure out which ClassLoader to use for loading the provider - // class. If there is a Context ClassLoader then use it. - ClassLoader context = ss.getContextClassLoader(); - ClassLoader system = ss.getSystemClassLoader(); - - ClassLoader chain = system; - while (true) { - if (context == chain) { - // Assert: we are on JDK 1.1 or we have no Context ClassLoader - // or any Context ClassLoader in chain of system classloader - // (including extension ClassLoader) so extend to widest - // ClassLoader (always look in system ClassLoader if Xerces - // is in boot/extension/system classpath and in current - // ClassLoader otherwise); normal classloaders delegate - // back to system ClassLoader first so this widening doesn't - // change the fact that context ClassLoader will be consulted - ClassLoader current = ObjectFactory.class.getClassLoader(); - - chain = system; - while (true) { - if (current == chain) { - // Assert: Current ClassLoader in chain of - // boot/extension/system ClassLoaders - return system; - } - if (chain == null) { - break; - } - chain = ss.getParentClassLoader(chain); - } - - // Assert: Current ClassLoader not in chain of - // boot/extension/system ClassLoaders - return current; - } - - if (chain == null) { - // boot ClassLoader reached - break; - } - - // Check for any extension ClassLoaders in chain up to - // boot ClassLoader - chain = ss.getParentClassLoader(chain); - }; - - // Assert: Context ClassLoader not in chain of - // boot/extension/system ClassLoaders - return context; - } // findClassLoader():ClassLoader - - /** - * Create an instance of a class using the specified ClassLoader - */ - static Object newInstance(String className, ClassLoader cl, - boolean doFallback) - throws ConfigurationError - { - // assert(className != null); - try{ - Class providerClass = findProviderClass(className, cl, doFallback); - Object instance = providerClass.newInstance(); - if (DEBUG) debugPrintln("created new instance of " + providerClass + - " using ClassLoader: " + cl); - return instance; - } catch (ClassNotFoundException x) { - throw new ConfigurationError( - "Provider " + className + " not found", x); - } catch (Exception x) { - throw new ConfigurationError( - "Provider " + className + " could not be instantiated: " + x, - x); - } - } - - /** - * Find a Class using the specified ClassLoader - */ - static Class findProviderClass(String className, ClassLoader cl, - boolean doFallback) - throws ClassNotFoundException, ConfigurationError - { - //throw security exception if the calling thread is not allowed to access the package - //restrict the access to package as speicified in java.security policy - SecurityManager security = System.getSecurityManager(); - if (security != null) { - final int lastDot = className.lastIndexOf("."); - String packageName = className; - if (lastDot != -1) packageName = className.substring(0, lastDot); - security.checkPackageAccess(packageName); - } - Class providerClass; - if (cl == null) { - // XXX Use the bootstrap ClassLoader. There is no way to - // load a class using the bootstrap ClassLoader that works - // in both JDK 1.1 and Java 2. However, this should still - // work b/c the following should be true: - // - // (cl == null) iff current ClassLoader == null - // - // Thus Class.forName(String) will use the current - // ClassLoader which will be the bootstrap ClassLoader. - providerClass = Class.forName(className); - } else { - try { - providerClass = cl.loadClass(className); - } catch (ClassNotFoundException x) { - if (doFallback) { - // Fall back to current classloader - ClassLoader current = ObjectFactory.class.getClassLoader(); - if (current == null) { - providerClass = Class.forName(className); - } else if (cl != current) { - cl = current; - providerClass = cl.loadClass(className); - } else { - throw x; - } - } else { - throw x; - } - } - } - - return providerClass; - } - - /* - * Try to find provider using Jar Service Provider Mechanism - * - * @return instance of provider class if found or null - */ - private static Object findJarServiceProvider(String factoryId) - throws ConfigurationError - { - SecuritySupport ss = SecuritySupport.getInstance(); - String serviceId = "META-INF/services/" + factoryId; - InputStream is = null; - - // First try the Context ClassLoader - ClassLoader cl = findClassLoader(); - - is = ss.getResourceAsStream(cl, serviceId); - - // If no provider found then try the current ClassLoader - if (is == null) { - ClassLoader current = ObjectFactory.class.getClassLoader(); - if (cl != current) { - cl = current; - is = ss.getResourceAsStream(cl, serviceId); - } - } - - if (is == null) { - // No provider found - return null; - } - - if (DEBUG) debugPrintln("found jar resource=" + serviceId + - " using ClassLoader: " + cl); - - // Read the service provider name in UTF-8 as specified in - // the jar spec. Unfortunately this fails in Microsoft - // VJ++, which does not implement the UTF-8 - // encoding. Theoretically, we should simply let it fail in - // that case, since the JVM is obviously broken if it - // doesn't support such a basic standard. But since there - // are still some users attempting to use VJ++ for - // development, we have dropped in a fallback which makes a - // second attempt using the platform's default encoding. In - // VJ++ this is apparently ASCII, which is a subset of - // UTF-8... and since the strings we'll be reading here are - // also primarily limited to the 7-bit ASCII range (at - // least, in English versions), this should work well - // enough to keep us on the air until we're ready to - // officially decommit from VJ++. [Edited comment from - // jkesselm] - BufferedReader rd; - try { - rd = new BufferedReader(new InputStreamReader(is, "UTF-8"), DEFAULT_LINE_LENGTH); - } catch (java.io.UnsupportedEncodingException e) { - rd = new BufferedReader(new InputStreamReader(is), DEFAULT_LINE_LENGTH); - } - - String factoryClassName = null; - try { - // XXX Does not handle all possible input as specified by the - // Jar Service Provider specification - factoryClassName = rd.readLine(); - } catch (IOException x) { - // No provider found - return null; - } - finally { - try { - // try to close the reader. - rd.close(); - } - // Ignore the exception. - catch (IOException exc) {} - } - - if (factoryClassName != null && - ! "".equals(factoryClassName)) { - if (DEBUG) debugPrintln("found in resource, value=" - + factoryClassName); - - // Note: here we do not want to fall back to the current - // ClassLoader because we want to avoid the case where the - // resource file was found using one ClassLoader and the - // provider class was instantiated using a different one. - return newInstance(factoryClassName, cl, false); - } - - // No provider found - return null; - } - - // - // Classes - // - - /** - * A configuration error. - */ - static final class ConfigurationError - extends Error { - - /** Serialization version. */ - static final long serialVersionUID = 937647395548533254L; - - // - // Data - // - - /** Exception. */ - private Exception exception; - - // - // Constructors - // - - /** - * Construct a new instance with the specified detail string and - * exception. - */ - ConfigurationError(String msg, Exception x) { - super(msg); - this.exception = x; - } // <init>(String,Exception) - - // - // methods - // - - /** Returns the exception associated to this error. */ - Exception getException() { - return exception; - } // getException():Exception - - } // class ConfigurationError - -} // class ObjectFactory
--- a/src/com/sun/org/apache/xml/internal/serializer/Encodings.java Wed May 29 13:24:29 2013 -0700 +++ b/src/com/sun/org/apache/xml/internal/serializer/Encodings.java Fri May 31 15:42:06 2013 -0700 @@ -33,6 +33,14 @@ import java.util.HashMap; import java.util.Properties; import java.util.StringTokenizer; +import java.io.IOException; +import java.net.MalformedURLException; +import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; +import java.nio.charset.UnsupportedCharsetException; +import java.util.Collections; +import java.util.Map; +import java.util.Map.Entry; import com.sun.org.apache.xalan.internal.utils.SecuritySupport; @@ -79,36 +87,17 @@ throws UnsupportedEncodingException { - for (int i = 0; i < _encodings.length; ++i) - { - if (_encodings[i].name.equalsIgnoreCase(encoding)) - { - try - { - return new BufferedWriter(new OutputStreamWriter( - output, - _encodings[i].javaName)); - } - catch (java.lang.IllegalArgumentException iae) // java 1.1.8 - { - // keep trying - } - catch (UnsupportedEncodingException usee) - { - - // keep trying - } + final EncodingInfo ei = _encodingInfos.findEncoding(toUpperCaseFast(encoding)); + if (ei != null) { + try { + return new BufferedWriter(new OutputStreamWriter( + output, ei.javaName)); + } catch (UnsupportedEncodingException usee) { + // keep trying } } - try - { - return new BufferedWriter(new OutputStreamWriter(output, encoding)); - } - catch (java.lang.IllegalArgumentException iae) // java 1.1.8 - { - throw new UnsupportedEncodingException(encoding); - } + return new BufferedWriter(new OutputStreamWriter(output, encoding)); } @@ -141,12 +130,24 @@ EncodingInfo ei; String normalizedEncoding = toUpperCaseFast(encoding); - ei = (EncodingInfo) _encodingTableKeyJava.get(normalizedEncoding); - if (ei == null) - ei = (EncodingInfo) _encodingTableKeyMime.get(normalizedEncoding); + ei = _encodingInfos.findEncoding(normalizedEncoding); if (ei == null) { // We shouldn't have to do this, but just in case. - ei = new EncodingInfo(null,null); + try { + // This may happen if the caller tries to use + // an encoding that wasn't registered in the + // (java name)->(preferred mime name) mapping file. + // In that case we attempt to load the charset for the + // given encoding, and if that succeeds - we create a new + // EncodingInfo instance - assuming the canonical name + // of the charset can be used as the mime name. + final Charset c = Charset.forName(encoding); + final String name = c.name(); + ei = new EncodingInfo(name, name); + _encodingInfos.putEncoding(normalizedEncoding, ei); + } catch (IllegalCharsetNameException | UnsupportedCharsetException x) { + ei = new EncodingInfo(null,null); + } } return ei; @@ -269,8 +270,8 @@ */ private static String convertJava2MimeEncoding(String encoding) { - EncodingInfo enc = - (EncodingInfo) _encodingTableKeyJava.get(encoding.toUpperCase()); + final EncodingInfo enc = + _encodingInfos.getEncodingFromJavaKey(toUpperCaseFast(encoding)); if (null != enc) return enc.name; return encoding; @@ -285,38 +286,37 @@ */ public static String convertMime2JavaEncoding(String encoding) { - - for (int i = 0; i < _encodings.length; ++i) - { - if (_encodings[i].name.equalsIgnoreCase(encoding)) - { - return _encodings[i].javaName; - } - } - - return encoding; + final EncodingInfo info = _encodingInfos.findEncoding(toUpperCaseFast(encoding)); + return info != null ? info.javaName : encoding; } - /** - * Load a list of all the supported encodings. - * - * System property "encodings" formatted using URL syntax may define an - * external encodings list. Thanks to Sergey Ushakov for the code - * contribution! - */ - private static EncodingInfo[] loadEncodingInfo() - { - try - { + // Using an inner static class here prevent initialization races + // where the hash maps could be used before they were populated. + // + private final static class EncodingInfos { + // These maps are final and not modified after initialization. + private final Map<String, EncodingInfo> _encodingTableKeyJava = new HashMap<>(); + private final Map<String, EncodingInfo> _encodingTableKeyMime = new HashMap<>(); + // This map will be added to after initialization: make sure it's + // thread-safe. This map should not be used frequently - only in cases + // where the mapping requested was not declared in the Encodings.properties + // file. + private final Map<String, EncodingInfo> _encodingDynamicTable = + Collections.synchronizedMap(new HashMap<String, EncodingInfo>()); + + private EncodingInfos() { + loadEncodingInfo(); + } + + // Opens the file/resource containing java charset name -> preferred mime + // name mapping and returns it as an InputStream. + private InputStream openEncodingsFileStream() throws MalformedURLException, IOException { String urlString = null; InputStream is = null; - try - { + try { urlString = SecuritySupport.getSystemProperty(ENCODINGS_PROP, ""); - } - catch (SecurityException e) - { + } catch (SecurityException e) { } if (urlString != null && urlString.length() > 0) { @@ -327,84 +327,193 @@ if (is == null) { is = SecuritySupport.getResourceAsStream(ENCODINGS_FILE); } + return is; + } + // Loads the Properties resource containing the mapping: + // java charset name -> preferred mime name + // and returns it. + private Properties loadProperties() throws MalformedURLException, IOException { Properties props = new Properties(); - if (is != null) { - props.load(is); - is.close(); - } else { - // Seems to be no real need to force failure here, let the - // system do its best... The issue is not really very critical, - // and the output will be in any case _correct_ though maybe not - // always human-friendly... :) - // But maybe report/log the resource problem? - // Any standard ways to report/log errors (in static context)? + final InputStream is = openEncodingsFileStream(); + try { + if (is != null) { + props.load(is); + } else { + // Seems to be no real need to force failure here, let the + // system do its best... The issue is not really very critical, + // and the output will be in any case _correct_ though maybe not + // always human-friendly... :) + // But maybe report/log the resource problem? + // Any standard ways to report/log errors (in static context)? + } + } finally { + if (is != null) { + is.close(); + } } + return props; + } - int totalEntries = props.size(); - int totalMimeNames = 0; - Enumeration keys = props.keys(); - for (int i = 0; i < totalEntries; ++i) - { - String javaName = (String) keys.nextElement(); - String val = props.getProperty(javaName); - totalMimeNames++; - int pos = val.indexOf(' '); - for (int j = 0; j < pos; ++j) - if (val.charAt(j) == ',') - totalMimeNames++; + // Parses the mime list associated to a java charset name. + // The first mime name in the list is supposed to be the preferred + // mime name. + private String[] parseMimeTypes(String val) { + int pos = val.indexOf(' '); + //int lastPrintable; + if (pos < 0) { + // Maybe report/log this problem? + // "Last printable character not defined for encoding " + + // mimeName + " (" + val + ")" ... + return new String[] { val }; + //lastPrintable = 0x00FF; + } + //lastPrintable = + // Integer.decode(val.substring(pos).trim()).intValue(); + StringTokenizer st = + new StringTokenizer(val.substring(0, pos), ","); + String[] values = new String[st.countTokens()]; + for (int i=0; st.hasMoreTokens(); i++) { + values[i] = st.nextToken(); + } + return values; + } + + // This method here attempts to find the canonical charset name for the + // the given name - which is supposed to be either a java name or a mime + // name. + // For that, it attempts to load the charset using the given name, and + // then returns the charset's canonical name. + // If the charset could not be loaded from the given name, + // the method returns null. + private String findCharsetNameFor(String name) { + try { + return Charset.forName(name).name(); + } catch (Exception x) { + return null; } - EncodingInfo[] ret = new EncodingInfo[totalMimeNames]; - int j = 0; - keys = props.keys(); - for (int i = 0; i < totalEntries; ++i) - { - String javaName = (String) keys.nextElement(); - String val = props.getProperty(javaName); - int pos = val.indexOf(' '); - String mimeName; - //int lastPrintable; - if (pos < 0) - { - // Maybe report/log this problem? - // "Last printable character not defined for encoding " + - // mimeName + " (" + val + ")" ... - mimeName = val; - //lastPrintable = 0x00FF; - } - else - { - //lastPrintable = - // Integer.decode(val.substring(pos).trim()).intValue(); - StringTokenizer st = - new StringTokenizer(val.substring(0, pos), ","); - for (boolean first = true; - st.hasMoreTokens(); - first = false) - { - mimeName = st.nextToken(); - ret[j] = - new EncodingInfo(mimeName, javaName); - _encodingTableKeyMime.put( - mimeName.toUpperCase(), - ret[j]); - if (first) - _encodingTableKeyJava.put( - javaName.toUpperCase(), - ret[j]); - j++; + } + + // This method here attempts to find the canonical charset name for the + // the set javaName+mimeNames - which are supposed to all refer to the + // same charset. + // For that it attempts to load the charset using the javaName, and if + // not found, attempts again using each of the mime names in turn. + // If the charset could be loaded from the javaName, then the javaName + // itself is returned as charset name. Otherwise, each of the mime names + // is tried in turn, until a charset can be loaded from one of the names, + // and the loaded charset's canonical name is returned. + // If no charset can be loaded from either the javaName or one of the + // mime names, then null is returned. + // + // Note that the returned name is the 'java' name that will be used in + // instances of EncodingInfo. + // This is important because EncodingInfo uses that 'java name' later on + // in calls to String.getBytes(javaName). + // As it happens, sometimes only one element of the set mime names/javaName + // is known by Charset: sometimes only one of the mime names is known, + // sometime only the javaName is known, sometimes all are known. + // + // By using this method here, we fix the problem where one of the mime + // names is known but the javaName is unknown, by associating the charset + // loaded from one of the mime names with the unrecognized javaName. + // + // When none of the mime names or javaName are known - there's not much we can + // do... It can mean that this encoding is not supported for this + // OS. If such a charset is ever use it will result in having all characters + // escaped. + // + private String findCharsetNameFor(String javaName, String[] mimes) { + String cs = findCharsetNameFor(javaName); + if (cs != null) return javaName; + for (String m : mimes) { + cs = findCharsetNameFor(m); + if (cs != null) break; + } + return cs; + } + + /** + * Loads a list of all the supported encodings. + * + * System property "encodings" formatted using URL syntax may define an + * external encodings list. Thanks to Sergey Ushakov for the code + * contribution! + */ + private void loadEncodingInfo() { + try { + // load (java name)->(preferred mime name) mapping. + final Properties props = loadProperties(); + + // create instances of EncodingInfo from the loaded mapping + Enumeration keys = props.keys(); + Map<String, EncodingInfo> canonicals = new HashMap<>(); + while (keys.hasMoreElements()) { + final String javaName = (String) keys.nextElement(); + final String[] mimes = parseMimeTypes(props.getProperty(javaName)); + + final String charsetName = findCharsetNameFor(javaName, mimes); + if (charsetName != null) { + final String kj = toUpperCaseFast(javaName); + final String kc = toUpperCaseFast(charsetName); + for (int i = 0; i < mimes.length; ++i) { + final String mimeName = mimes[i]; + final String km = toUpperCaseFast(mimeName); + EncodingInfo info = new EncodingInfo(mimeName, charsetName); + _encodingTableKeyMime.put(km, info); + if (!canonicals.containsKey(kc)) { + // canonicals will map the charset name to + // the info containing the prefered mime name + // (the preferred mime name is the first mime + // name in the list). + canonicals.put(kc, info); + _encodingTableKeyJava.put(kc, info); + } + _encodingTableKeyJava.put(kj, info); + } + } else { + // None of the java or mime names on the line were + // recognized => this charset is not supported? } } + + // Fix up the _encodingTableKeyJava so that the info mapped to + // the java name contains the preferred mime name. + // (a given java name can correspond to several mime name, + // but we want the _encodingTableKeyJava to point to the + // preferred mime name). + for (Entry<String, EncodingInfo> e : _encodingTableKeyJava.entrySet()) { + e.setValue(canonicals.get(toUpperCaseFast(e.getValue().javaName))); + } + + } catch (java.net.MalformedURLException mue) { + throw new com.sun.org.apache.xml.internal.serializer.utils.WrappedRuntimeException(mue); + } catch (java.io.IOException ioe) { + throw new com.sun.org.apache.xml.internal.serializer.utils.WrappedRuntimeException(ioe); } - return ret; } - catch (java.net.MalformedURLException mue) - { - throw new com.sun.org.apache.xml.internal.serializer.utils.WrappedRuntimeException(mue); + + EncodingInfo findEncoding(String normalizedEncoding) { + EncodingInfo info = _encodingTableKeyJava.get(normalizedEncoding); + if (info == null) { + info = _encodingTableKeyMime.get(normalizedEncoding); + } + if (info == null) { + info = _encodingDynamicTable.get(normalizedEncoding); + } + return info; } - catch (java.io.IOException ioe) - { - throw new com.sun.org.apache.xml.internal.serializer.utils.WrappedRuntimeException(ioe); + + EncodingInfo getEncodingFromMimeKey(String normalizedMimeName) { + return _encodingTableKeyMime.get(normalizedMimeName); + } + + EncodingInfo getEncodingFromJavaKey(String normalizedJavaName) { + return _encodingTableKeyJava.get(normalizedJavaName); + } + + void putEncoding(String key, EncodingInfo info) { + _encodingDynamicTable.put(key, info); } } @@ -457,7 +566,6 @@ return codePoint; } - private static final HashMap _encodingTableKeyJava = new HashMap(); - private static final HashMap _encodingTableKeyMime = new HashMap(); - private static final EncodingInfo[] _encodings = loadEncodingInfo(); + private final static EncodingInfos _encodingInfos = new EncodingInfos(); + }