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();
+
 }