changeset 444:fad6560cb32a

8005954: JAXP Plugability Layer should use java.util.ServiceLoader Summary: This fix replaces manual processing of files under META-INF/services in JAXP factories by calls to java.util.ServiceLoader. Reviewed-by: alanb, joehw, mchung
author dfuchs
date Wed, 17 Apr 2013 15:23:19 +0200
parents 3f9817b8b0e0
children 1c2079d11a79
files src/javax/xml/datatype/DatatypeFactory.java src/javax/xml/datatype/FactoryFinder.java src/javax/xml/parsers/DocumentBuilderFactory.java src/javax/xml/parsers/FactoryFinder.java src/javax/xml/parsers/SAXParserFactory.java src/javax/xml/stream/FactoryFinder.java src/javax/xml/stream/XMLEventFactory.java src/javax/xml/stream/XMLInputFactory.java src/javax/xml/stream/XMLOutputFactory.java src/javax/xml/transform/FactoryFinder.java src/javax/xml/transform/TransformerFactory.java src/javax/xml/validation/SchemaFactory.java src/javax/xml/validation/SchemaFactoryConfigurationError.java src/javax/xml/validation/SchemaFactoryFinder.java src/javax/xml/xpath/XPathFactory.java src/javax/xml/xpath/XPathFactoryFinder.java
diffstat 16 files changed, 1828 insertions(+), 2135 deletions(-) [+]
line wrap: on
line diff
--- a/src/javax/xml/datatype/DatatypeFactory.java	Fri Apr 12 10:20:32 2013 +0100
+++ b/src/javax/xml/datatype/DatatypeFactory.java	Wed Apr 17 15:23:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,8 @@
 
 package javax.xml.datatype;
 
+import java.math.BigDecimal;
 import java.math.BigInteger;
-import java.math.BigDecimal;
 import java.util.GregorianCalendar;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -34,12 +34,12 @@
 /**
  * <p>Factory that creates new <code>javax.xml.datatype</code> <code>Object</code>s that map XML to/from Java <code>Object</code>s.</p>
  *
- * <p><a name="DatatypeFactory.newInstance"/>{@link #newInstance()} is used to create a new <code>DatatypeFactory</code>.
- * The following implementation resolution mechanisms are used in the following order:</p>
+ * <p>A new instance of the <code>DatatypeFactory</code> is created through the {@link #newInstance()} method
+ * that uses the following implementation resolution mechanisms to determine an implementation:</p>
  * <ol>
  *    <li>
  *      If the system property specified by {@link #DATATYPEFACTORY_PROPERTY}, "<code>javax.xml.datatype.DatatypeFactory</code>",
- *      exists, a class with the name of the property's value is instantiated.
+ *      exists, a class with the name of the property value is instantiated.
  *      Any Exception thrown during the instantiation process is wrapped as a {@link DatatypeConfigurationException}.
  *    </li>
  *    <li>
@@ -48,8 +48,12 @@
  *      and processed as documented in the prior step.
  *    </li>
  *    <li>
- *      The services resolution mechanism is used, e.g. <code>META-INF/services/java.xml.datatype.DatatypeFactory</code>.
- *      Any Exception thrown during the instantiation process is wrapped as a {@link DatatypeConfigurationException}.
+ *     Uses the service-provider loading facilities, defined by the {@link java.util.ServiceLoader} class, to attempt
+ *     to locate and load an implementation of the service.
+ *     <br>
+ *     In case of {@link java.util.ServiceConfigurationError service
+ *     configuration error} a {@link javax.xml.datatype.DatatypeConfigurationException}
+ *     will be thrown.
  *    </li>
  *    <li>
  *      The final mechanism is to attempt to instantiate the <code>Class</code> specified by
@@ -67,26 +71,33 @@
  */
 public abstract class DatatypeFactory {
 
-        /**
-         * <p>Default property name as defined in JSR 206: Java(TM) API for XML Processing (JAXP) 1.3.</p>
-         *
-         * <p>Default value is <code>javax.xml.datatype.DatatypeFactory</code>.</p>
-         */
-        public static final String DATATYPEFACTORY_PROPERTY = "javax.xml.datatype.DatatypeFactory";
+    /**
+     * <p>Default property name as defined in JSR 206: Java(TM) API for XML Processing (JAXP) 1.3.</p>
+     *
+     * <p>Default value is <code>javax.xml.datatype.DatatypeFactory</code>.</p>
+     */
+    public static final String DATATYPEFACTORY_PROPERTY =
+            // We use a String constant here, rather than calling
+            // DatatypeFactory.class.getName() - in order to make javadoc
+            // generate a See Also: Constant Field Value link.
+            "javax.xml.datatype.DatatypeFactory";
 
-        /**
-         * <p>Default implementation class name as defined in
-         * <em>JSR 206: Java(TM) API for XML Processing (JAXP) 1.3</em>.</p>
-         *
-         * <p>Implementers should specify the name of an appropriate class
-         * to be instantiated if no other implementation resolution mechanism
-         * succeeds.</p>
-         *
-         * <p>Users should not refer to this field; it is intended only to
-         * document a factory implementation detail.
-         * </p>
-         */
-        public static final String DATATYPEFACTORY_IMPLEMENTATION_CLASS = new String("com.sun.org.apache.xerces.internal.jaxp.datatype.DatatypeFactoryImpl");
+    /**
+     * <p>Default implementation class name as defined in
+     * <em>JSR 206: Java(TM) API for XML Processing (JAXP) 1.3</em>.</p>
+     *
+     * <p>Implementers should specify the name of an appropriate class
+     * to be instantiated if no other implementation resolution mechanism
+     * succeeds.</p>
+     *
+     * <p>Users should not refer to this field; it is intended only to
+     * document a factory implementation detail.
+     * </p>
+     */
+    public static final String DATATYPEFACTORY_IMPLEMENTATION_CLASS =
+        // We use new String() here to prevent javadoc from generating
+        // a See Also: Constant Field Value link.
+        new String("com.sun.org.apache.xerces.internal.jaxp.datatype.DatatypeFactoryImpl");
 
     /**
      * http://www.w3.org/TR/xpath-datamodel/#xdtschema defines two regexps
@@ -101,40 +112,36 @@
     private static final Pattern XDTSCHEMA_DTD =
         Pattern.compile("[^YM]*[DT].*");
 
-        /**
-         * <p>Protected constructor to prevent instaniation outside of package.</p>
-         *
-         * <p>Use {@link #newInstance()} to create a <code>DatatypeFactory</code>.</p>
-         */
-        protected DatatypeFactory() {
-        }
+    /**
+     * <p>Protected constructor to prevent instaniation outside of package.</p>
+     *
+     * <p>Use {@link #newInstance()} to create a <code>DatatypeFactory</code>.</p>
+     */
+    protected DatatypeFactory() {
+    }
 
-        /**
-         * <p>Obtain a new instance of a <code>DatatypeFactory</code>.</p>
-         *
+    /**
+     * <p>Obtain a new instance of a <code>DatatypeFactory</code>.</p>
+     *
      * <p>The implementation resolution mechanisms are <a href="#DatatypeFactory.newInstance">defined</a> in this
      * <code>Class</code>'s documentation.</p>
-         *
-         * @return New instance of a <code>DatatypeFactory</code>
-         *
-         * @throws DatatypeConfigurationException If the implementation is not
-         *   available or cannot be instantiated.
+     *
+     * @return New instance of a <code>DatatypeFactory</code>
+     *
+     * @throws DatatypeConfigurationException If the implementation is not
+     *   available or cannot be instantiated.
      *
      * @see #newInstance(String factoryClassName, ClassLoader classLoader)
-         */
-        public static DatatypeFactory newInstance()
-                throws DatatypeConfigurationException {
+     */
+    public static DatatypeFactory newInstance()
+            throws DatatypeConfigurationException {
 
-                try {
-                        return (DatatypeFactory) FactoryFinder.find(
-                                /* The default property name according to the JAXP spec */
-                                 DATATYPEFACTORY_PROPERTY,
-                                /* The fallback implementation class name */
-                                DATATYPEFACTORY_IMPLEMENTATION_CLASS);
-                } catch (FactoryFinder.ConfigurationError e) {
-                        throw new DatatypeConfigurationException(e.getMessage(), e.getException());
-                }
-        }
+            return FactoryFinder.find(
+                    /* The default property name according to the JAXP spec */
+                    DatatypeFactory.class,
+                    /* The fallback implementation class name */
+                    DATATYPEFACTORY_IMPLEMENTATION_CLASS);
+    }
 
     /**
      * <p>Obtain a new instance of a <code>DatatypeFactory</code> from class name.
@@ -172,57 +179,54 @@
      */
     public static DatatypeFactory newInstance(String factoryClassName, ClassLoader classLoader)
         throws DatatypeConfigurationException {
-        try {
-            return (DatatypeFactory) FactoryFinder.newInstance(factoryClassName, classLoader, false);
-        } catch (FactoryFinder.ConfigurationError e) {
-            throw new DatatypeConfigurationException(e.getMessage(), e.getException());
-        }
-    }
+        return FactoryFinder.newInstance(DatatypeFactory.class,
+                    factoryClassName, classLoader, false);
+     }
 
-        /**
-         * <p>Obtain a new instance of a <code>Duration</code>
-         * specifying the <code>Duration</code> as its string representation, "PnYnMnDTnHnMnS",
-         * as defined in XML Schema 1.0 section 3.2.6.1.</p>
-         *
-         * <p>XML Schema Part 2: Datatypes, 3.2.6 duration, defines <code>duration</code> as:</p>
-         * <blockquote>
-         * duration represents a duration of time.
-         * The value space of duration is a six-dimensional space where the coordinates designate the
-         * Gregorian year, month, day, hour, minute, and second components defined in Section 5.5.3.2 of [ISO 8601], respectively.
-         * These components are ordered in their significance by their order of appearance i.e. as
-         * year, month, day, hour, minute, and second.
-         * </blockquote>
-     * <p>All six values are set and availabe from the created {@link Duration}</p>
+    /**
+     * <p>Obtain a new instance of a <code>Duration</code>
+     * specifying the <code>Duration</code> as its string representation, "PnYnMnDTnHnMnS",
+     * as defined in XML Schema 1.0 section 3.2.6.1.</p>
+     *
+     * <p>XML Schema Part 2: Datatypes, 3.2.6 duration, defines <code>duration</code> as:</p>
+     * <blockquote>
+     * duration represents a duration of time.
+     * The value space of duration is a six-dimensional space where the coordinates designate the
+     * Gregorian year, month, day, hour, minute, and second components defined in Section 5.5.3.2 of [ISO 8601], respectively.
+     * These components are ordered in their significance by their order of appearance i.e. as
+     * year, month, day, hour, minute, and second.
+     * </blockquote>
+     * <p>All six values are set and available from the created {@link Duration}</p>
      *
      * <p>The XML Schema specification states that values can be of an arbitrary size.
      * Implementations may chose not to or be incapable of supporting arbitrarily large and/or small values.
      * An {@link UnsupportedOperationException} will be thrown with a message indicating implementation limits
      * if implementation capacities are exceeded.</p>
-         *
-         * @param lexicalRepresentation <code>String</code> representation of a <code>Duration</code>.
-         *
-         * @return New <code>Duration</code> created from parsing the <code>lexicalRepresentation</code>.
-         *
-         * @throws IllegalArgumentException If <code>lexicalRepresentation</code> is not a valid representation of a <code>Duration</code>.
-         * @throws UnsupportedOperationException If implementation cannot support requested values.
-         * @throws NullPointerException if <code>lexicalRepresentation</code> is <code>null</code>.
-         */
-        public abstract Duration newDuration(final String lexicalRepresentation);
+     *
+     * @param lexicalRepresentation <code>String</code> representation of a <code>Duration</code>.
+     *
+     * @return New <code>Duration</code> created from parsing the <code>lexicalRepresentation</code>.
+     *
+     * @throws IllegalArgumentException If <code>lexicalRepresentation</code> is not a valid representation of a <code>Duration</code>.
+     * @throws UnsupportedOperationException If implementation cannot support requested values.
+     * @throws NullPointerException if <code>lexicalRepresentation</code> is <code>null</code>.
+     */
+    public abstract Duration newDuration(final String lexicalRepresentation);
 
-        /**
-         * <p>Obtain a new instance of a <code>Duration</code>
-         * specifying the <code>Duration</code> as milliseconds.</p>
-         *
-         * <p>XML Schema Part 2: Datatypes, 3.2.6 duration, defines <code>duration</code> as:</p>
-         * <blockquote>
-         * duration represents a duration of time.
-         * The value space of duration is a six-dimensional space where the coordinates designate the
-         * Gregorian year, month, day, hour, minute, and second components defined in Section 5.5.3.2 of [ISO 8601], respectively.
-         * These components are ordered in their significance by their order of appearance i.e. as
-         * year, month, day, hour, minute, and second.
-         * </blockquote>
+    /**
+     * <p>Obtain a new instance of a <code>Duration</code>
+     * specifying the <code>Duration</code> as milliseconds.</p>
+     *
+     * <p>XML Schema Part 2: Datatypes, 3.2.6 duration, defines <code>duration</code> as:</p>
+     * <blockquote>
+     * duration represents a duration of time.
+     * The value space of duration is a six-dimensional space where the coordinates designate the
+     * Gregorian year, month, day, hour, minute, and second components defined in Section 5.5.3.2 of [ISO 8601], respectively.
+     * These components are ordered in their significance by their order of appearance i.e. as
+     * year, month, day, hour, minute, and second.
+     * </blockquote>
      * <p>All six values are set by computing their values from the specified milliseconds
-     * and are availabe using the <code>get</code> methods of  the created {@link Duration}.
+     * and are available using the <code>get</code> methods of  the created {@link Duration}.
      * The values conform to and are defined by:</p>
      * <ul>
      *   <li>ISO 8601:2000(E) Section 5.5.3.2 Alternative format</li>
@@ -231,25 +235,25 @@
      *   </li>
      *   <li>{@link XMLGregorianCalendar}  Date/Time Datatype Field Mapping Between XML Schema 1.0 and Java Representation</li>
      * </ul>
-         *
-         * <p>The default start instance is defined by {@link GregorianCalendar}'s use of the start of the epoch: i.e.,
-         * {@link java.util.Calendar#YEAR} = 1970,
-         * {@link java.util.Calendar#MONTH} = {@link java.util.Calendar#JANUARY},
-         * {@link java.util.Calendar#DATE} = 1, etc.
-         * This is important as there are variations in the Gregorian Calendar,
-         * e.g. leap years have different days in the month = {@link java.util.Calendar#FEBRUARY}
-         * so the result of {@link Duration#getMonths()} and {@link Duration#getDays()} can be influenced.</p>
-         *
-         * @param durationInMilliSeconds Duration in milliseconds to create.
-         *
-         * @return New <code>Duration</code> representing <code>durationInMilliSeconds</code>.
-         */
-        public abstract Duration newDuration(final long durationInMilliSeconds);
+     *
+     * <p>The default start instance is defined by {@link GregorianCalendar}'s use of the start of the epoch: i.e.,
+     * {@link java.util.Calendar#YEAR} = 1970,
+     * {@link java.util.Calendar#MONTH} = {@link java.util.Calendar#JANUARY},
+     * {@link java.util.Calendar#DATE} = 1, etc.
+     * This is important as there are variations in the Gregorian Calendar,
+     * e.g. leap years have different days in the month = {@link java.util.Calendar#FEBRUARY}
+     * so the result of {@link Duration#getMonths()} and {@link Duration#getDays()} can be influenced.</p>
+     *
+     * @param durationInMilliSeconds Duration in milliseconds to create.
+     *
+     * @return New <code>Duration</code> representing <code>durationInMilliSeconds</code>.
+     */
+    public abstract Duration newDuration(final long durationInMilliSeconds);
 
-        /**
-         * <p>Obtain a new instance of a <code>Duration</code>
-         * specifying the <code>Duration</code> as isPositive, years, months, days, hours, minutes, seconds.</p>
-         *
+    /**
+     * <p>Obtain a new instance of a <code>Duration</code>
+     * specifying the <code>Duration</code> as isPositive, years, months, days, hours, minutes, seconds.</p>
+     *
      * <p>The XML Schema specification states that values can be of an arbitrary size.
      * Implementations may chose not to or be incapable of supporting arbitrarily large and/or small values.
      * An {@link UnsupportedOperationException} will be thrown with a message indicating implementation limits
@@ -257,35 +261,35 @@
      *
      * <p>A <code>null</code> value indicates that field is not set.</p>
      *
-         * @param isPositive Set to <code>false</code> to create a negative duration. When the length
-         *   of the duration is zero, this parameter will be ignored.
-         * @param years of this <code>Duration</code>
-         * @param months of this <code>Duration</code>
-         * @param days of this <code>Duration</code>
-         * @param hours of this <code>Duration</code>
-         * @param minutes of this <code>Duration</code>
-         * @param seconds of this <code>Duration</code>
-         *
-         * @return New <code>Duration</code> created from the specified values.
-         *
-         * @throws IllegalArgumentException If the values are not a valid representation of a
-         * <code>Duration</code>: if all the fields (years, months, ...) are null or
-         * if any of the fields is negative.
-         * @throws UnsupportedOperationException If implementation cannot support requested values.
-         */
-        public abstract Duration newDuration(
-                final boolean isPositive,
-                final BigInteger years,
-                final BigInteger months,
-                final BigInteger days,
-                final BigInteger hours,
-                final BigInteger minutes,
-                final BigDecimal seconds);
+     * @param isPositive Set to <code>false</code> to create a negative duration. When the length
+     *   of the duration is zero, this parameter will be ignored.
+     * @param years of this <code>Duration</code>
+     * @param months of this <code>Duration</code>
+     * @param days of this <code>Duration</code>
+     * @param hours of this <code>Duration</code>
+     * @param minutes of this <code>Duration</code>
+     * @param seconds of this <code>Duration</code>
+     *
+     * @return New <code>Duration</code> created from the specified values.
+     *
+     * @throws IllegalArgumentException If the values are not a valid representation of a
+     * <code>Duration</code>: if all the fields (years, months, ...) are null or
+     * if any of the fields is negative.
+     * @throws UnsupportedOperationException If implementation cannot support requested values.
+     */
+    public abstract Duration newDuration(
+            final boolean isPositive,
+            final BigInteger years,
+            final BigInteger months,
+            final BigInteger days,
+            final BigInteger hours,
+            final BigInteger minutes,
+            final BigDecimal seconds);
 
-        /**
-         * <p>Obtain a new instance of a <code>Duration</code>
-         * specifying the <code>Duration</code> as isPositive, years, months, days, hours, minutes, seconds.</p>
-         *
+    /**
+     * <p>Obtain a new instance of a <code>Duration</code>
+     * specifying the <code>Duration</code> as isPositive, years, months, days, hours, minutes, seconds.</p>
+     *
      * <p>A {@link DatatypeConstants#FIELD_UNDEFINED} value indicates that field is not set.</p>
      *
      * @param isPositive Set to <code>false</code> to create a negative duration. When the length
@@ -297,113 +301,113 @@
      * @param minutes of this <code>Duration</code>
      * @param seconds of this <code>Duration</code>
      *
-         * @return New <code>Duration</code> created from the specified values.
-         *
-         * @throws IllegalArgumentException If the values are not a valid representation of a
-         * <code>Duration</code>: if any of the fields is negative.
-         *
-         * @see #newDuration(
-         *   boolean isPositive,
-         *   BigInteger years,
-         *   BigInteger months,
-         *   BigInteger days,
-         *   BigInteger hours,
-         *   BigInteger minutes,
-         *   BigDecimal seconds)
-         */
-        public Duration newDuration(
-                final boolean isPositive,
-                final int years,
-                final int months,
-                final int days,
-                final int hours,
-                final int minutes,
-                final int seconds) {
+     * @return New <code>Duration</code> created from the specified values.
+     *
+     * @throws IllegalArgumentException If the values are not a valid representation of a
+     * <code>Duration</code>: if any of the fields is negative.
+     *
+     * @see #newDuration(
+     *   boolean isPositive,
+     *   BigInteger years,
+     *   BigInteger months,
+     *   BigInteger days,
+     *   BigInteger hours,
+     *   BigInteger minutes,
+     *   BigDecimal seconds)
+     */
+    public Duration newDuration(
+            final boolean isPositive,
+            final int years,
+            final int months,
+            final int days,
+            final int hours,
+            final int minutes,
+            final int seconds) {
 
-                // years may not be set
-                BigInteger realYears = (years != DatatypeConstants.FIELD_UNDEFINED) ? BigInteger.valueOf((long) years) : null;
+            // years may not be set
+            BigInteger realYears = (years != DatatypeConstants.FIELD_UNDEFINED) ? BigInteger.valueOf((long) years) : null;
 
-                // months may not be set
-                BigInteger realMonths = (months != DatatypeConstants.FIELD_UNDEFINED) ? BigInteger.valueOf((long) months) : null;
+            // months may not be set
+            BigInteger realMonths = (months != DatatypeConstants.FIELD_UNDEFINED) ? BigInteger.valueOf((long) months) : null;
 
-                // days may not be set
-                BigInteger realDays = (days != DatatypeConstants.FIELD_UNDEFINED) ? BigInteger.valueOf((long) days) : null;
+            // days may not be set
+            BigInteger realDays = (days != DatatypeConstants.FIELD_UNDEFINED) ? BigInteger.valueOf((long) days) : null;
 
-                // hours may not be set
-                BigInteger realHours = (hours != DatatypeConstants.FIELD_UNDEFINED) ? BigInteger.valueOf((long) hours) : null;
+            // hours may not be set
+            BigInteger realHours = (hours != DatatypeConstants.FIELD_UNDEFINED) ? BigInteger.valueOf((long) hours) : null;
 
-                // minutes may not be set
-                BigInteger realMinutes = (minutes != DatatypeConstants.FIELD_UNDEFINED) ? BigInteger.valueOf((long) minutes) : null;
+            // minutes may not be set
+            BigInteger realMinutes = (minutes != DatatypeConstants.FIELD_UNDEFINED) ? BigInteger.valueOf((long) minutes) : null;
 
-                // seconds may not be set
-                BigDecimal realSeconds = (seconds != DatatypeConstants.FIELD_UNDEFINED) ? BigDecimal.valueOf((long) seconds) : null;
+            // seconds may not be set
+            BigDecimal realSeconds = (seconds != DatatypeConstants.FIELD_UNDEFINED) ? BigDecimal.valueOf((long) seconds) : null;
 
-                        return newDuration(
-                                isPositive,
-                                realYears,
-                                realMonths,
-                                realDays,
-                                realHours,
-                                realMinutes,
-                                realSeconds
-                        );
-                }
+                    return newDuration(
+                            isPositive,
+                            realYears,
+                            realMonths,
+                            realDays,
+                            realHours,
+                            realMinutes,
+                            realSeconds
+                    );
+            }
 
-        /**
-         * <p>Create a <code>Duration</code> of type <code>xdt:dayTimeDuration</code> by parsing its <code>String</code> representation,
-         * "<em>PnDTnHnMnS</em>", <a href="http://www.w3.org/TR/xpath-datamodel#dayTimeDuration">
-         *   XQuery 1.0 and XPath 2.0 Data Model, xdt:dayTimeDuration</a>.</p>
-         *
-         * <p>The datatype <code>xdt:dayTimeDuration</code> is a subtype of <code>xs:duration</code>
-         * whose lexical representation contains only day, hour, minute, and second components.
-         * This datatype resides in the namespace <code>http://www.w3.org/2003/11/xpath-datatypes</code>.</p>
-         *
-     * <p>All four values are set and availabe from the created {@link Duration}</p>
-         *
+    /**
+     * <p>Create a <code>Duration</code> of type <code>xdt:dayTimeDuration</code> by parsing its <code>String</code> representation,
+     * "<em>PnDTnHnMnS</em>", <a href="http://www.w3.org/TR/xpath-datamodel#dayTimeDuration">
+     *   XQuery 1.0 and XPath 2.0 Data Model, xdt:dayTimeDuration</a>.</p>
+     *
+     * <p>The datatype <code>xdt:dayTimeDuration</code> is a subtype of <code>xs:duration</code>
+     * whose lexical representation contains only day, hour, minute, and second components.
+     * This datatype resides in the namespace <code>http://www.w3.org/2003/11/xpath-datatypes</code>.</p>
+     *
+     * <p>All four values are set and available from the created {@link Duration}</p>
+     *
      * <p>The XML Schema specification states that values can be of an arbitrary size.
      * Implementations may chose not to or be incapable of supporting arbitrarily large and/or small values.
      * An {@link UnsupportedOperationException} will be thrown with a message indicating implementation limits
      * if implementation capacities are exceeded.</p>
      *
-         * @param lexicalRepresentation Lexical representation of a duration.
-         *
-         * @return New <code>Duration</code> created using the specified <code>lexicalRepresentation</code>.
-         *
-         * @throws IllegalArgumentException If <code>lexicalRepresentation</code> is not a valid representation of a <code>Duration</code> expressed only in terms of days and time.
-         * @throws UnsupportedOperationException If implementation cannot support requested values.
-         * @throws NullPointerException If <code>lexicalRepresentation</code> is <code>null</code>.
-         */
-        public Duration newDurationDayTime(final String lexicalRepresentation) {
-            // lexicalRepresentation must be non-null
-            if (lexicalRepresentation == null) {
-                throw new NullPointerException(
-                    "Trying to create an xdt:dayTimeDuration with an invalid"
-                    + " lexical representation of \"null\"");
-            }
-
-            // test lexicalRepresentation against spec regex
-            Matcher matcher = XDTSCHEMA_DTD.matcher(lexicalRepresentation);
-            if (!matcher.matches()) {
-                throw new IllegalArgumentException(
-                    "Trying to create an xdt:dayTimeDuration with an invalid"
-                    + " lexical representation of \"" + lexicalRepresentation
-                    + "\", data model requires years and months only.");
-            }
-
-            return newDuration(lexicalRepresentation);
+     * @param lexicalRepresentation Lexical representation of a duration.
+     *
+     * @return New <code>Duration</code> created using the specified <code>lexicalRepresentation</code>.
+     *
+     * @throws IllegalArgumentException If <code>lexicalRepresentation</code> is not a valid representation of a <code>Duration</code> expressed only in terms of days and time.
+     * @throws UnsupportedOperationException If implementation cannot support requested values.
+     * @throws NullPointerException If <code>lexicalRepresentation</code> is <code>null</code>.
+     */
+    public Duration newDurationDayTime(final String lexicalRepresentation) {
+        // lexicalRepresentation must be non-null
+        if (lexicalRepresentation == null) {
+            throw new NullPointerException(
+                "Trying to create an xdt:dayTimeDuration with an invalid"
+                + " lexical representation of \"null\"");
         }
 
-        /**
-         * <p>Create a <code>Duration</code> of type <code>xdt:dayTimeDuration</code> using the specified milliseconds as defined in
-         * <a href="http://www.w3.org/TR/xpath-datamodel#dayTimeDuration">
-         *   XQuery 1.0 and XPath 2.0 Data Model, xdt:dayTimeDuration</a>.</p>
-         *
-         * <p>The datatype <code>xdt:dayTimeDuration</code> is a subtype of <code>xs:duration</code>
-         * whose lexical representation contains only day, hour, minute, and second components.
-         * This datatype resides in the namespace <code>http://www.w3.org/2003/11/xpath-datatypes</code>.</p>
-         *
+        // test lexicalRepresentation against spec regex
+        Matcher matcher = XDTSCHEMA_DTD.matcher(lexicalRepresentation);
+        if (!matcher.matches()) {
+            throw new IllegalArgumentException(
+                "Trying to create an xdt:dayTimeDuration with an invalid"
+                + " lexical representation of \"" + lexicalRepresentation
+                + "\", data model requires years and months only.");
+        }
+
+        return newDuration(lexicalRepresentation);
+    }
+
+    /**
+     * <p>Create a <code>Duration</code> of type <code>xdt:dayTimeDuration</code> using the specified milliseconds as defined in
+     * <a href="http://www.w3.org/TR/xpath-datamodel#dayTimeDuration">
+     *   XQuery 1.0 and XPath 2.0 Data Model, xdt:dayTimeDuration</a>.</p>
+     *
+     * <p>The datatype <code>xdt:dayTimeDuration</code> is a subtype of <code>xs:duration</code>
+     * whose lexical representation contains only day, hour, minute, and second components.
+     * This datatype resides in the namespace <code>http://www.w3.org/2003/11/xpath-datatypes</code>.</p>
+     *
      * <p>All four values are set by computing their values from the specified milliseconds
-     * and are availabe using the <code>get</code> methods of  the created {@link Duration}.
+     * and are available using the <code>get</code> methods of  the created {@link Duration}.
      * The values conform to and are defined by:</p>
      * <ul>
      *   <li>ISO 8601:2000(E) Section 5.5.3.2 Alternative format</li>
@@ -412,39 +416,39 @@
      *   </li>
      *   <li>{@link XMLGregorianCalendar}  Date/Time Datatype Field Mapping Between XML Schema 1.0 and Java Representation</li>
      * </ul>
-         *
-         * <p>The default start instance is defined by {@link GregorianCalendar}'s use of the start of the epoch: i.e.,
-         * {@link java.util.Calendar#YEAR} = 1970,
-         * {@link java.util.Calendar#MONTH} = {@link java.util.Calendar#JANUARY},
-         * {@link java.util.Calendar#DATE} = 1, etc.
-         * This is important as there are variations in the Gregorian Calendar,
-         * e.g. leap years have different days in the month = {@link java.util.Calendar#FEBRUARY}
-         * so the result of {@link Duration#getDays()} can be influenced.</p>
-         *
+     *
+     * <p>The default start instance is defined by {@link GregorianCalendar}'s use of the start of the epoch: i.e.,
+     * {@link java.util.Calendar#YEAR} = 1970,
+     * {@link java.util.Calendar#MONTH} = {@link java.util.Calendar#JANUARY},
+     * {@link java.util.Calendar#DATE} = 1, etc.
+     * This is important as there are variations in the Gregorian Calendar,
+     * e.g. leap years have different days in the month = {@link java.util.Calendar#FEBRUARY}
+     * so the result of {@link Duration#getDays()} can be influenced.</p>
+     *
      * <p>Any remaining milliseconds after determining the day, hour, minute and second are discarded.</p>
      *
-         * @param durationInMilliseconds Milliseconds of <code>Duration</code> to create.
-         *
-         * @return New <code>Duration</code> created with the specified <code>durationInMilliseconds</code>.
-         *
-         * @see <a href="http://www.w3.org/TR/xpath-datamodel#dayTimeDuration">
-         *   XQuery 1.0 and XPath 2.0 Data Model, xdt:dayTimeDuration</a>
-         */
-        public Duration newDurationDayTime(final long durationInMilliseconds) {
+     * @param durationInMilliseconds Milliseconds of <code>Duration</code> to create.
+     *
+     * @return New <code>Duration</code> created with the specified <code>durationInMilliseconds</code>.
+     *
+     * @see <a href="http://www.w3.org/TR/xpath-datamodel#dayTimeDuration">
+     *   XQuery 1.0 and XPath 2.0 Data Model, xdt:dayTimeDuration</a>
+     */
+    public Duration newDurationDayTime(final long durationInMilliseconds) {
 
-                return newDuration(durationInMilliseconds);
-        }
+            return newDuration(durationInMilliseconds);
+    }
 
-        /**
-         * <p>Create a <code>Duration</code> of type <code>xdt:dayTimeDuration</code> using the specified
-         * <code>day</code>, <code>hour</code>, <code>minute</code> and <code>second</code> as defined in
-         * <a href="http://www.w3.org/TR/xpath-datamodel#dayTimeDuration">
-         *   XQuery 1.0 and XPath 2.0 Data Model, xdt:dayTimeDuration</a>.</p>
-         *
-         * <p>The datatype <code>xdt:dayTimeDuration</code> is a subtype of <code>xs:duration</code>
-         * whose lexical representation contains only day, hour, minute, and second components.
-         * This datatype resides in the namespace <code>http://www.w3.org/2003/11/xpath-datatypes</code>.</p>
-         *
+    /**
+     * <p>Create a <code>Duration</code> of type <code>xdt:dayTimeDuration</code> using the specified
+     * <code>day</code>, <code>hour</code>, <code>minute</code> and <code>second</code> as defined in
+     * <a href="http://www.w3.org/TR/xpath-datamodel#dayTimeDuration">
+     *   XQuery 1.0 and XPath 2.0 Data Model, xdt:dayTimeDuration</a>.</p>
+     *
+     * <p>The datatype <code>xdt:dayTimeDuration</code> is a subtype of <code>xs:duration</code>
+     * whose lexical representation contains only day, hour, minute, and second components.
+     * This datatype resides in the namespace <code>http://www.w3.org/2003/11/xpath-datatypes</code>.</p>
+     *
      * <p>The XML Schema specification states that values can be of an arbitrary size.
      * Implementations may chose not to or be incapable of supporting arbitrarily large and/or small values.
      * An {@link UnsupportedOperationException} will be thrown with a message indicating implementation limits
@@ -454,102 +458,102 @@
      *
      * @param isPositive Set to <code>false</code> to create a negative duration. When the length
      *   of the duration is zero, this parameter will be ignored.
-         * @param day Day of <code>Duration</code>.
-         * @param hour Hour of <code>Duration</code>.
-         * @param minute Minute of <code>Duration</code>.
-         * @param second Second of <code>Duration</code>.
-         *
-         * @return New <code>Duration</code> created with the specified <code>day</code>, <code>hour</code>, <code>minute</code>
-         * and <code>second</code>.
-         *
-         * @throws IllegalArgumentException If the values are not a valid representation of a
-         * <code>Duration</code>: if all the fields (day, hour, ...) are null or
-         * if any of the fields is negative.
-         * @throws UnsupportedOperationException If implementation cannot support requested values.
-         */
-        public Duration newDurationDayTime(
-                final boolean isPositive,
-                final BigInteger day,
-                final BigInteger hour,
-                final BigInteger minute,
-                final BigInteger second) {
+     * @param day Day of <code>Duration</code>.
+     * @param hour Hour of <code>Duration</code>.
+     * @param minute Minute of <code>Duration</code>.
+     * @param second Second of <code>Duration</code>.
+     *
+     * @return New <code>Duration</code> created with the specified <code>day</code>, <code>hour</code>, <code>minute</code>
+     * and <code>second</code>.
+     *
+     * @throws IllegalArgumentException If the values are not a valid representation of a
+     * <code>Duration</code>: if all the fields (day, hour, ...) are null or
+     * if any of the fields is negative.
+     * @throws UnsupportedOperationException If implementation cannot support requested values.
+     */
+    public Duration newDurationDayTime(
+            final boolean isPositive,
+            final BigInteger day,
+            final BigInteger hour,
+            final BigInteger minute,
+            final BigInteger second) {
 
-                return newDuration(
-                        isPositive,
-                        null,  // years
-                        null, // months
-                        day,
-                        hour,
-                        minute,
-                        (second != null)? new BigDecimal(second):null
-                );
-        }
+            return newDuration(
+                    isPositive,
+                    null,  // years
+                    null, // months
+                    day,
+                    hour,
+                    minute,
+                    (second != null)? new BigDecimal(second):null
+            );
+    }
 
-        /**
-         * <p>Create a <code>Duration</code> of type <code>xdt:dayTimeDuration</code> using the specified
-         * <code>day</code>, <code>hour</code>, <code>minute</code> and <code>second</code> as defined in
-         * <a href="http://www.w3.org/TR/xpath-datamodel#dayTimeDuration">
-         *   XQuery 1.0 and XPath 2.0 Data Model, xdt:dayTimeDuration</a>.</p>
-         *
-         * <p>The datatype <code>xdt:dayTimeDuration</code> is a subtype of <code>xs:duration</code>
-         * whose lexical representation contains only day, hour, minute, and second components.
-         * This datatype resides in the namespace <code>http://www.w3.org/2003/11/xpath-datatypes</code>.</p>
-         *
+    /**
+     * <p>Create a <code>Duration</code> of type <code>xdt:dayTimeDuration</code> using the specified
+     * <code>day</code>, <code>hour</code>, <code>minute</code> and <code>second</code> as defined in
+     * <a href="http://www.w3.org/TR/xpath-datamodel#dayTimeDuration">
+     *   XQuery 1.0 and XPath 2.0 Data Model, xdt:dayTimeDuration</a>.</p>
+     *
+     * <p>The datatype <code>xdt:dayTimeDuration</code> is a subtype of <code>xs:duration</code>
+     * whose lexical representation contains only day, hour, minute, and second components.
+     * This datatype resides in the namespace <code>http://www.w3.org/2003/11/xpath-datatypes</code>.</p>
+     *
      * <p>A {@link DatatypeConstants#FIELD_UNDEFINED} value indicates that field is not set.</p>
      *
      * @param isPositive Set to <code>false</code> to create a negative duration. When the length
      *   of the duration is zero, this parameter will be ignored.
-         * @param day Day of <code>Duration</code>.
-         * @param hour Hour of <code>Duration</code>.
-         * @param minute Minute of <code>Duration</code>.
-         * @param second Second of <code>Duration</code>.
-         *
-         * @return New <code>Duration</code> created with the specified <code>day</code>, <code>hour</code>, <code>minute</code>
-         * and <code>second</code>.
-         *
-         * @throws IllegalArgumentException If the values are not a valid representation of a
-         * <code>Duration</code>: if any of the fields (day, hour, ...) is negative.
-         */
-        public Duration newDurationDayTime(
-                final boolean isPositive,
-                final int day,
-                final int hour,
-                final int minute,
-                final int second) {
+     * @param day Day of <code>Duration</code>.
+     * @param hour Hour of <code>Duration</code>.
+     * @param minute Minute of <code>Duration</code>.
+     * @param second Second of <code>Duration</code>.
+     *
+     * @return New <code>Duration</code> created with the specified <code>day</code>, <code>hour</code>, <code>minute</code>
+     * and <code>second</code>.
+     *
+     * @throws IllegalArgumentException If the values are not a valid representation of a
+     * <code>Duration</code>: if any of the fields (day, hour, ...) is negative.
+     */
+    public Duration newDurationDayTime(
+            final boolean isPositive,
+            final int day,
+            final int hour,
+            final int minute,
+            final int second) {
 
-                        return newDurationDayTime(
-                                isPositive,
-                                BigInteger.valueOf((long) day),
-                                BigInteger.valueOf((long) hour),
-                                BigInteger.valueOf((long) minute),
-                                BigInteger.valueOf((long) second)
-                                );
-                }
+                    return newDurationDayTime(
+                            isPositive,
+                            BigInteger.valueOf((long) day),
+                            BigInteger.valueOf((long) hour),
+                            BigInteger.valueOf((long) minute),
+                            BigInteger.valueOf((long) second)
+                            );
+            }
 
-        /**
-         * <p>Create a <code>Duration</code> of type <code>xdt:yearMonthDuration</code> by parsing its <code>String</code> representation,
-         * "<em>PnYnM</em>", <a href="http://www.w3.org/TR/xpath-datamodel#yearMonthDuration">
-         *   XQuery 1.0 and XPath 2.0 Data Model, xdt:yearMonthDuration</a>.</p>
-         *
-         * <p>The datatype <code>xdt:yearMonthDuration</code> is a subtype of <code>xs:duration</code>
-         * whose lexical representation contains only year and month components.
-         * This datatype resides in the namespace {@link javax.xml.XMLConstants#W3C_XPATH_DATATYPE_NS_URI}.</p>
-         *
-     * <p>Both values are set and availabe from the created {@link Duration}</p>
-         *
+    /**
+     * <p>Create a <code>Duration</code> of type <code>xdt:yearMonthDuration</code> by parsing its <code>String</code> representation,
+     * "<em>PnYnM</em>", <a href="http://www.w3.org/TR/xpath-datamodel#yearMonthDuration">
+     *   XQuery 1.0 and XPath 2.0 Data Model, xdt:yearMonthDuration</a>.</p>
+     *
+     * <p>The datatype <code>xdt:yearMonthDuration</code> is a subtype of <code>xs:duration</code>
+     * whose lexical representation contains only year and month components.
+     * This datatype resides in the namespace {@link javax.xml.XMLConstants#W3C_XPATH_DATATYPE_NS_URI}.</p>
+     *
+     * <p>Both values are set and available from the created {@link Duration}</p>
+     *
      * <p>The XML Schema specification states that values can be of an arbitrary size.
      * Implementations may chose not to or be incapable of supporting arbitrarily large and/or small values.
      * An {@link UnsupportedOperationException} will be thrown with a message indicating implementation limits
      * if implementation capacities are exceeded.</p>
      *
-         * @param lexicalRepresentation Lexical representation of a duration.
-         *
-         * @return New <code>Duration</code> created using the specified <code>lexicalRepresentation</code>.
-         *
-         * @throws IllegalArgumentException If <code>lexicalRepresentation</code> is not a valid representation of a <code>Duration</code> expressed only in terms of years and months.
-         * @throws UnsupportedOperationException If implementation cannot support requested values.
-         * @throws NullPointerException If <code>lexicalRepresentation</code> is <code>null</code>.
-         */
+     * @param lexicalRepresentation Lexical representation of a duration.
+     *
+     * @return New <code>Duration</code> created using the specified <code>lexicalRepresentation</code>.
+     *
+     * @throws IllegalArgumentException If <code>lexicalRepresentation</code> is not a valid representation of a <code>Duration</code> expressed only in terms of years and months.
+     * @throws UnsupportedOperationException If implementation cannot support requested values.
+     * @throws NullPointerException If <code>lexicalRepresentation</code> is <code>null</code>.
+     */
     public Duration newDurationYearMonth(
             final String lexicalRepresentation) {
 
@@ -572,17 +576,17 @@
         return newDuration(lexicalRepresentation);
     }
 
-        /**
-         * <p>Create a <code>Duration</code> of type <code>xdt:yearMonthDuration</code> using the specified milliseconds as defined in
-         * <a href="http://www.w3.org/TR/xpath-datamodel#yearMonthDuration">
-         *   XQuery 1.0 and XPath 2.0 Data Model, xdt:yearMonthDuration</a>.</p>
-         *
-         * <p>The datatype <code>xdt:yearMonthDuration</code> is a subtype of <code>xs:duration</code>
-         * whose lexical representation contains only year and month components.
-         * This datatype resides in the namespace {@link javax.xml.XMLConstants#W3C_XPATH_DATATYPE_NS_URI}.</p>
-         *
+    /**
+     * <p>Create a <code>Duration</code> of type <code>xdt:yearMonthDuration</code> using the specified milliseconds as defined in
+     * <a href="http://www.w3.org/TR/xpath-datamodel#yearMonthDuration">
+     *   XQuery 1.0 and XPath 2.0 Data Model, xdt:yearMonthDuration</a>.</p>
+     *
+     * <p>The datatype <code>xdt:yearMonthDuration</code> is a subtype of <code>xs:duration</code>
+     * whose lexical representation contains only year and month components.
+     * This datatype resides in the namespace {@link javax.xml.XMLConstants#W3C_XPATH_DATATYPE_NS_URI}.</p>
+     *
      * <p>Both values are set by computing their values from the specified milliseconds
-     * and are availabe using the <code>get</code> methods of  the created {@link Duration}.
+     * and are available using the <code>get</code> methods of  the created {@link Duration}.
      * The values conform to and are defined by:</p>
      * <ul>
      *   <li>ISO 8601:2000(E) Section 5.5.3.2 Alternative format</li>
@@ -592,20 +596,20 @@
      *   <li>{@link XMLGregorianCalendar}  Date/Time Datatype Field Mapping Between XML Schema 1.0 and Java Representation</li>
      * </ul>
      *
-         * <p>The default start instance is defined by {@link GregorianCalendar}'s use of the start of the epoch: i.e.,
-         * {@link java.util.Calendar#YEAR} = 1970,
-         * {@link java.util.Calendar#MONTH} = {@link java.util.Calendar#JANUARY},
-         * {@link java.util.Calendar#DATE} = 1, etc.
-         * This is important as there are variations in the Gregorian Calendar,
-         * e.g. leap years have different days in the month = {@link java.util.Calendar#FEBRUARY}
-         * so the result of {@link Duration#getMonths()} can be influenced.</p>
-         *
+     * <p>The default start instance is defined by {@link GregorianCalendar}'s use of the start of the epoch: i.e.,
+     * {@link java.util.Calendar#YEAR} = 1970,
+     * {@link java.util.Calendar#MONTH} = {@link java.util.Calendar#JANUARY},
+     * {@link java.util.Calendar#DATE} = 1, etc.
+     * This is important as there are variations in the Gregorian Calendar,
+     * e.g. leap years have different days in the month = {@link java.util.Calendar#FEBRUARY}
+     * so the result of {@link Duration#getMonths()} can be influenced.</p>
+     *
      * <p>Any remaining milliseconds after determining the year and month are discarded.</p>
-         *
-         * @param durationInMilliseconds Milliseconds of <code>Duration</code> to create.
-         *
-         * @return New <code>Duration</code> created using the specified <code>durationInMilliseconds</code>.
-         */
+     *
+     * @param durationInMilliseconds Milliseconds of <code>Duration</code> to create.
+     *
+     * @return New <code>Duration</code> created using the specified <code>durationInMilliseconds</code>.
+     */
     public Duration newDurationYearMonth(
             final long durationInMilliseconds) {
 
@@ -624,12 +628,12 @@
         return newDurationYearMonth(isPositive, years, months);
     }
 
-        /**
-         * <p>Create a <code>Duration</code> of type <code>xdt:yearMonthDuration</code> using the specified
-         * <code>year</code> and <code>month</code> as defined in
-         * <a href="http://www.w3.org/TR/xpath-datamodel#yearMonthDuration">
-         *   XQuery 1.0 and XPath 2.0 Data Model, xdt:yearMonthDuration</a>.</p>
-         *
+    /**
+     * <p>Create a <code>Duration</code> of type <code>xdt:yearMonthDuration</code> using the specified
+     * <code>year</code> and <code>month</code> as defined in
+     * <a href="http://www.w3.org/TR/xpath-datamodel#yearMonthDuration">
+     *   XQuery 1.0 and XPath 2.0 Data Model, xdt:yearMonthDuration</a>.</p>
+     *
      * <p>The XML Schema specification states that values can be of an arbitrary size.
      * Implementations may chose not to or be incapable of supporting arbitrarily large and/or small values.
      * An {@link UnsupportedOperationException} will be thrown with a message indicating implementation limits
@@ -639,74 +643,74 @@
      *
      * @param isPositive Set to <code>false</code> to create a negative duration. When the length
      *   of the duration is zero, this parameter will be ignored.
-         * @param year Year of <code>Duration</code>.
-         * @param month Month of <code>Duration</code>.
-         *
-         * @return New <code>Duration</code> created using the specified <code>year</code> and <code>month</code>.
-         *
-         * @throws IllegalArgumentException If the values are not a valid representation of a
-         * <code>Duration</code>: if all of the fields (year, month) are null or
-         * if any of the fields is negative.
-         * @throws UnsupportedOperationException If implementation cannot support requested values.
-         */
-        public Duration newDurationYearMonth(
-                final boolean isPositive,
-                final BigInteger year,
-                final BigInteger month) {
+     * @param year Year of <code>Duration</code>.
+     * @param month Month of <code>Duration</code>.
+     *
+     * @return New <code>Duration</code> created using the specified <code>year</code> and <code>month</code>.
+     *
+     * @throws IllegalArgumentException If the values are not a valid representation of a
+     * <code>Duration</code>: if all of the fields (year, month) are null or
+     * if any of the fields is negative.
+     * @throws UnsupportedOperationException If implementation cannot support requested values.
+     */
+    public Duration newDurationYearMonth(
+            final boolean isPositive,
+            final BigInteger year,
+            final BigInteger month) {
 
-                return newDuration(
-                        isPositive,
-                        year,
-                        month,
-                        null, // days
-                        null, // hours
-                        null, // minutes
-                        null  // seconds
-                );
-        }
+            return newDuration(
+                    isPositive,
+                    year,
+                    month,
+                    null, // days
+                    null, // hours
+                    null, // minutes
+                    null  // seconds
+            );
+    }
 
-        /**
-         * <p>Create a <code>Duration</code> of type <code>xdt:yearMonthDuration</code> using the specified
-         * <code>year</code> and <code>month</code> as defined in
-         * <a href="http://www.w3.org/TR/xpath-datamodel#yearMonthDuration">
-         *   XQuery 1.0 and XPath 2.0 Data Model, xdt:yearMonthDuration</a>.</p>
-         *
+    /**
+     * <p>Create a <code>Duration</code> of type <code>xdt:yearMonthDuration</code> using the specified
+     * <code>year</code> and <code>month</code> as defined in
+     * <a href="http://www.w3.org/TR/xpath-datamodel#yearMonthDuration">
+     *   XQuery 1.0 and XPath 2.0 Data Model, xdt:yearMonthDuration</a>.</p>
+     *
      * <p>A {@link DatatypeConstants#FIELD_UNDEFINED} value indicates that field is not set.</p>
      *
      * @param isPositive Set to <code>false</code> to create a negative duration. When the length
      *   of the duration is zero, this parameter will be ignored.
-         * @param year Year of <code>Duration</code>.
-         * @param month Month of <code>Duration</code>.
-         *
-         * @return New <code>Duration</code> created using the specified <code>year</code> and <code>month</code>.
-         *
-         * @throws IllegalArgumentException If the values are not a valid representation of a
-         * <code>Duration</code>: if any of the fields (year, month) is negative.
-         */
-        public Duration newDurationYearMonth(
-                final boolean isPositive,
-                final int year,
-                final int month) {
+     * @param year Year of <code>Duration</code>.
+     * @param month Month of <code>Duration</code>.
+     *
+     * @return New <code>Duration</code> created using the specified <code>year</code> and <code>month</code>.
+     *
+     * @throws IllegalArgumentException If the values are not a valid representation of a
+     * <code>Duration</code>: if any of the fields (year, month) is negative.
+     */
+    public Duration newDurationYearMonth(
+            final boolean isPositive,
+            final int year,
+            final int month) {
 
-                return newDurationYearMonth(
-                        isPositive,
-                        BigInteger.valueOf((long) year),
-                        BigInteger.valueOf((long) month));
-                }
+            return newDurationYearMonth(
+                    isPositive,
+                    BigInteger.valueOf((long) year),
+                    BigInteger.valueOf((long) month));
+            }
 
-        /**
-         * <p>Create a new instance of an <code>XMLGregorianCalendar</code>.</p>
-         *
+    /**
+     * <p>Create a new instance of an <code>XMLGregorianCalendar</code>.</p>
+     *
      * <p>All date/time datatype fields set to {@link DatatypeConstants#FIELD_UNDEFINED} or null.</p>
      *
      * @return New <code>XMLGregorianCalendar</code> with all date/time datatype fields set to
      *   {@link DatatypeConstants#FIELD_UNDEFINED} or null.
-         */
-        public abstract XMLGregorianCalendar newXMLGregorianCalendar();
+     */
+    public abstract XMLGregorianCalendar newXMLGregorianCalendar();
 
-        /**
-         * <p>Create a new XMLGregorianCalendar by parsing the String as a lexical representation.</p>
-         *
+    /**
+     * <p>Create a new XMLGregorianCalendar by parsing the String as a lexical representation.</p>
+     *
      * <p>Parsing the lexical string representation is defined in
      * <a href="http://www.w3.org/TR/xmlschema-2/#dateTime-order">XML Schema 1.0 Part 2, Section 3.2.[7-14].1,
      * <em>Lexical Representation</em>.</a></p>
@@ -721,344 +725,344 @@
      * <p>Except for the noted lexical/canonical representation mismatches
      * listed in <a href="http://www.w3.org/2001/05/xmlschema-errata#e2-45">
      * XML Schema 1.0 errata, Section 3.2.7.2</a>.</p>
-         *
-         * @param lexicalRepresentation Lexical representation of one the eight XML Schema date/time datatypes.
-         *
-         * @return <code>XMLGregorianCalendar</code> created from the <code>lexicalRepresentation</code>.
-         *
-         * @throws IllegalArgumentException If the <code>lexicalRepresentation</code> is not a valid <code>XMLGregorianCalendar</code>.
-         * @throws NullPointerException If <code>lexicalRepresentation</code> is <code>null</code>.
-         */
-        public abstract XMLGregorianCalendar newXMLGregorianCalendar(final String lexicalRepresentation);
+     *
+     * @param lexicalRepresentation Lexical representation of one the eight XML Schema date/time datatypes.
+     *
+     * @return <code>XMLGregorianCalendar</code> created from the <code>lexicalRepresentation</code>.
+     *
+     * @throws IllegalArgumentException If the <code>lexicalRepresentation</code> is not a valid <code>XMLGregorianCalendar</code>.
+     * @throws NullPointerException If <code>lexicalRepresentation</code> is <code>null</code>.
+     */
+    public abstract XMLGregorianCalendar newXMLGregorianCalendar(final String lexicalRepresentation);
 
-        /**
-         * <p>Create an <code>XMLGregorianCalendar</code> from a {@link GregorianCalendar}.</p>
-         *
-         * <table border="2" rules="all" cellpadding="2">
-         *   <thead>
-         *     <tr>
-         *       <th align="center" colspan="2">
-         *          Field by Field Conversion from
-         *          {@link GregorianCalendar} to an {@link XMLGregorianCalendar}
-         *       </th>
-         *     </tr>
-         *     <tr>
-         *        <th><code>java.util.GregorianCalendar</code> field</th>
-         *        <th><code>javax.xml.datatype.XMLGregorianCalendar</code> field</th>
-         *     </tr>
-         *   </thead>
-         *   <tbody>
-         *     <tr>
-         *       <td><code>ERA == GregorianCalendar.BC ? -YEAR : YEAR</code></td>
-         *       <td>{@link XMLGregorianCalendar#setYear(int year)}</td>
-         *     </tr>
-         *     <tr>
-         *       <td><code>MONTH + 1</code></td>
-         *       <td>{@link XMLGregorianCalendar#setMonth(int month)}</td>
-         *     </tr>
-         *     <tr>
-         *       <td><code>DAY_OF_MONTH</code></td>
-         *       <td>{@link XMLGregorianCalendar#setDay(int day)}</td>
-         *     </tr>
-         *     <tr>
-         *       <td><code>HOUR_OF_DAY, MINUTE, SECOND, MILLISECOND</code></td>
-         *       <td>{@link XMLGregorianCalendar#setTime(int hour, int minute, int second, BigDecimal fractional)}</td>
-         *     </tr>
-         *     <tr>
-         *       <td>
-         *         <code>(ZONE_OFFSET + DST_OFFSET) / (60*1000)</code><br/>
-         *         <em>(in minutes)</em>
-         *       </td>
-         *       <td>{@link XMLGregorianCalendar#setTimezone(int offset)}<sup><em>*</em></sup>
-         *       </td>
-         *     </tr>
-         *   </tbody>
-         * </table>
-         * <p><em>*</em>conversion loss of information. It is not possible to represent
-         * a <code>java.util.GregorianCalendar</code> daylight savings timezone id in the
-         * XML Schema 1.0 date/time datatype representation.</p>
-         *
-         * <p>To compute the return value's <code>TimeZone</code> field,
-         * <ul>
-         * <li>when <code>this.getTimezone() != FIELD_UNDEFINED</code>,
-         * create a <code>java.util.TimeZone</code> with a custom timezone id
-         * using the <code>this.getTimezone()</code>.</li>
-         * <li>else use the <code>GregorianCalendar</code> default timezone value
-         * for the host is defined as specified by
-         * <code>java.util.TimeZone.getDefault()</code>.</li></p>
-         *
-         * @param cal <code>java.util.GregorianCalendar</code> used to create <code>XMLGregorianCalendar</code>
-         *
-         * @return <code>XMLGregorianCalendar</code> created from <code>java.util.GregorianCalendar</code>
-         *
-         * @throws NullPointerException If <code>cal</code> is <code>null</code>.
-         */
-        public abstract XMLGregorianCalendar newXMLGregorianCalendar(final GregorianCalendar cal);
+    /**
+     * <p>Create an <code>XMLGregorianCalendar</code> from a {@link GregorianCalendar}.</p>
+     *
+     * <table border="2" rules="all" cellpadding="2">
+     *   <thead>
+     *     <tr>
+     *       <th align="center" colspan="2">
+     *          Field by Field Conversion from
+     *          {@link GregorianCalendar} to an {@link XMLGregorianCalendar}
+     *       </th>
+     *     </tr>
+     *     <tr>
+     *        <th><code>java.util.GregorianCalendar</code> field</th>
+     *        <th><code>javax.xml.datatype.XMLGregorianCalendar</code> field</th>
+     *     </tr>
+     *   </thead>
+     *   <tbody>
+     *     <tr>
+     *       <td><code>ERA == GregorianCalendar.BC ? -YEAR : YEAR</code></td>
+     *       <td>{@link XMLGregorianCalendar#setYear(int year)}</td>
+     *     </tr>
+     *     <tr>
+     *       <td><code>MONTH + 1</code></td>
+     *       <td>{@link XMLGregorianCalendar#setMonth(int month)}</td>
+     *     </tr>
+     *     <tr>
+     *       <td><code>DAY_OF_MONTH</code></td>
+     *       <td>{@link XMLGregorianCalendar#setDay(int day)}</td>
+     *     </tr>
+     *     <tr>
+     *       <td><code>HOUR_OF_DAY, MINUTE, SECOND, MILLISECOND</code></td>
+     *       <td>{@link XMLGregorianCalendar#setTime(int hour, int minute, int second, BigDecimal fractional)}</td>
+     *     </tr>
+     *     <tr>
+     *       <td>
+     *         <code>(ZONE_OFFSET + DST_OFFSET) / (60*1000)</code><br/>
+     *         <em>(in minutes)</em>
+     *       </td>
+     *       <td>{@link XMLGregorianCalendar#setTimezone(int offset)}<sup><em>*</em></sup>
+     *       </td>
+     *     </tr>
+     *   </tbody>
+     * </table>
+     * <p><em>*</em>conversion loss of information. It is not possible to represent
+     * a <code>java.util.GregorianCalendar</code> daylight savings timezone id in the
+     * XML Schema 1.0 date/time datatype representation.</p>
+     *
+     * <p>To compute the return value's <code>TimeZone</code> field,
+     * <ul>
+     * <li>when <code>this.getTimezone() != FIELD_UNDEFINED</code>,
+     * create a <code>java.util.TimeZone</code> with a custom timezone id
+     * using the <code>this.getTimezone()</code>.</li>
+     * <li>else use the <code>GregorianCalendar</code> default timezone value
+     * for the host is defined as specified by
+     * <code>java.util.TimeZone.getDefault()</code>.</li></p>
+     *
+     * @param cal <code>java.util.GregorianCalendar</code> used to create <code>XMLGregorianCalendar</code>
+     *
+     * @return <code>XMLGregorianCalendar</code> created from <code>java.util.GregorianCalendar</code>
+     *
+     * @throws NullPointerException If <code>cal</code> is <code>null</code>.
+     */
+    public abstract XMLGregorianCalendar newXMLGregorianCalendar(final GregorianCalendar cal);
 
-        /**
-         * <p>Constructor allowing for complete value spaces allowed by
-         * W3C XML Schema 1.0 recommendation for xsd:dateTime and related
-         * builtin datatypes. Note that <code>year</code> parameter supports
-         * arbitrarily large numbers and fractionalSecond has infinite
-         * precision.</p>
-         *
+    /**
+     * <p>Constructor allowing for complete value spaces allowed by
+     * W3C XML Schema 1.0 recommendation for xsd:dateTime and related
+     * builtin datatypes. Note that <code>year</code> parameter supports
+     * arbitrarily large numbers and fractionalSecond has infinite
+     * precision.</p>
+     *
      * <p>A <code>null</code> value indicates that field is not set.</p>
      *
-         * @param year of <code>XMLGregorianCalendar</code> to be created.
-         * @param month of <code>XMLGregorianCalendar</code> to be created.
-         * @param day of <code>XMLGregorianCalendar</code> to be created.
-         * @param hour of <code>XMLGregorianCalendar</code> to be created.
-         * @param minute of <code>XMLGregorianCalendar</code> to be created.
-         * @param second of <code>XMLGregorianCalendar</code> to be created.
-         * @param fractionalSecond of <code>XMLGregorianCalendar</code> to be created.
-         * @param timezone of <code>XMLGregorianCalendar</code> to be created.
-         *
-         * @return <code>XMLGregorianCalendar</code> created from specified values.
-         *
-         * @throws IllegalArgumentException If any individual parameter's value is outside the maximum value constraint for the field
-         *   as determined by the Date/Time Data Mapping table in {@link XMLGregorianCalendar}
-         *   or if the composite values constitute an invalid <code>XMLGregorianCalendar</code> instance
-         *   as determined by {@link XMLGregorianCalendar#isValid()}.
-         */
-        public abstract XMLGregorianCalendar newXMLGregorianCalendar(
-                final BigInteger year,
-                final int month,
-                final int day,
-                final int hour,
-                final int minute,
-                final int second,
-                final BigDecimal fractionalSecond,
-                final int timezone);
+     * @param year of <code>XMLGregorianCalendar</code> to be created.
+     * @param month of <code>XMLGregorianCalendar</code> to be created.
+     * @param day of <code>XMLGregorianCalendar</code> to be created.
+     * @param hour of <code>XMLGregorianCalendar</code> to be created.
+     * @param minute of <code>XMLGregorianCalendar</code> to be created.
+     * @param second of <code>XMLGregorianCalendar</code> to be created.
+     * @param fractionalSecond of <code>XMLGregorianCalendar</code> to be created.
+     * @param timezone of <code>XMLGregorianCalendar</code> to be created.
+     *
+     * @return <code>XMLGregorianCalendar</code> created from specified values.
+     *
+     * @throws IllegalArgumentException If any individual parameter's value is outside the maximum value constraint for the field
+     *   as determined by the Date/Time Data Mapping table in {@link XMLGregorianCalendar}
+     *   or if the composite values constitute an invalid <code>XMLGregorianCalendar</code> instance
+     *   as determined by {@link XMLGregorianCalendar#isValid()}.
+     */
+    public abstract XMLGregorianCalendar newXMLGregorianCalendar(
+            final BigInteger year,
+            final int month,
+            final int day,
+            final int hour,
+            final int minute,
+            final int second,
+            final BigDecimal fractionalSecond,
+            final int timezone);
 
-        /**
-         * <p>Constructor of value spaces that a
-         * <code>java.util.GregorianCalendar</code> instance would need to convert to an
-         * <code>XMLGregorianCalendar</code> instance.</p>
-         *
-         * <p><code>XMLGregorianCalendar eon</code> and
-         * <code>fractionalSecond</code> are set to <code>null</code></p>
-         *
+    /**
+     * <p>Constructor of value spaces that a
+     * <code>java.util.GregorianCalendar</code> instance would need to convert to an
+     * <code>XMLGregorianCalendar</code> instance.</p>
+     *
+     * <p><code>XMLGregorianCalendar eon</code> and
+     * <code>fractionalSecond</code> are set to <code>null</code></p>
+     *
      * <p>A {@link DatatypeConstants#FIELD_UNDEFINED} value indicates that field is not set.</p>
      *
-         * @param year of <code>XMLGregorianCalendar</code> to be created.
-         * @param month of <code>XMLGregorianCalendar</code> to be created.
-         * @param day of <code>XMLGregorianCalendar</code> to be created.
-         * @param hour of <code>XMLGregorianCalendar</code> to be created.
-         * @param minute of <code>XMLGregorianCalendar</code> to be created.
-         * @param second of <code>XMLGregorianCalendar</code> to be created.
-         * @param millisecond of <code>XMLGregorianCalendar</code> to be created.
-         * @param timezone of <code>XMLGregorianCalendar</code> to be created.
-         *
-         * @return <code>XMLGregorianCalendar</code> created from specified values.
-         *
-         * @throws IllegalArgumentException If any individual parameter's value is outside the maximum value constraint for the field
-         *   as determined by the Date/Time Data Mapping table in {@link XMLGregorianCalendar}
-         *   or if the composite values constitute an invalid <code>XMLGregorianCalendar</code> instance
-         *   as determined by {@link XMLGregorianCalendar#isValid()}.
-         */
-        public XMLGregorianCalendar newXMLGregorianCalendar(
-                final int year,
-                final int month,
-                final int day,
-                final int hour,
-                final int minute,
-                final int second,
-                final int millisecond,
-                final int timezone) {
+     * @param year of <code>XMLGregorianCalendar</code> to be created.
+     * @param month of <code>XMLGregorianCalendar</code> to be created.
+     * @param day of <code>XMLGregorianCalendar</code> to be created.
+     * @param hour of <code>XMLGregorianCalendar</code> to be created.
+     * @param minute of <code>XMLGregorianCalendar</code> to be created.
+     * @param second of <code>XMLGregorianCalendar</code> to be created.
+     * @param millisecond of <code>XMLGregorianCalendar</code> to be created.
+     * @param timezone of <code>XMLGregorianCalendar</code> to be created.
+     *
+     * @return <code>XMLGregorianCalendar</code> created from specified values.
+     *
+     * @throws IllegalArgumentException If any individual parameter's value is outside the maximum value constraint for the field
+     *   as determined by the Date/Time Data Mapping table in {@link XMLGregorianCalendar}
+     *   or if the composite values constitute an invalid <code>XMLGregorianCalendar</code> instance
+     *   as determined by {@link XMLGregorianCalendar#isValid()}.
+     */
+    public XMLGregorianCalendar newXMLGregorianCalendar(
+            final int year,
+            final int month,
+            final int day,
+            final int hour,
+            final int minute,
+            final int second,
+            final int millisecond,
+            final int timezone) {
 
-                // year may be undefined
-                BigInteger realYear = (year != DatatypeConstants.FIELD_UNDEFINED) ? BigInteger.valueOf((long) year) : null;
+            // year may be undefined
+            BigInteger realYear = (year != DatatypeConstants.FIELD_UNDEFINED) ? BigInteger.valueOf((long) year) : null;
 
-                // millisecond may be undefined
-                // millisecond must be >= 0 millisecond <= 1000
-                BigDecimal realMillisecond = null; // undefined value
-                if (millisecond != DatatypeConstants.FIELD_UNDEFINED) {
-                        if (millisecond < 0 || millisecond > 1000) {
-                                throw new IllegalArgumentException(
-                                                        "javax.xml.datatype.DatatypeFactory#newXMLGregorianCalendar("
-                                                        + "int year, int month, int day, int hour, int minute, int second, int millisecond, int timezone)"
-                                                        + "with invalid millisecond: " + millisecond
-                                                        );
-                        }
+            // millisecond may be undefined
+            // millisecond must be >= 0 millisecond <= 1000
+            BigDecimal realMillisecond = null; // undefined value
+            if (millisecond != DatatypeConstants.FIELD_UNDEFINED) {
+                    if (millisecond < 0 || millisecond > 1000) {
+                            throw new IllegalArgumentException(
+                                                    "javax.xml.datatype.DatatypeFactory#newXMLGregorianCalendar("
+                                                    + "int year, int month, int day, int hour, int minute, int second, int millisecond, int timezone)"
+                                                    + "with invalid millisecond: " + millisecond
+                                                    );
+                    }
 
-                        realMillisecond = BigDecimal.valueOf((long) millisecond).movePointLeft(3);
-                }
+                    realMillisecond = BigDecimal.valueOf((long) millisecond).movePointLeft(3);
+            }
 
-                return newXMLGregorianCalendar(
-                        realYear,
-                        month,
-                        day,
-                        hour,
-                        minute,
-                        second,
-                        realMillisecond,
-                        timezone
-                );
-        }
+            return newXMLGregorianCalendar(
+                    realYear,
+                    month,
+                    day,
+                    hour,
+                    minute,
+                    second,
+                    realMillisecond,
+                    timezone
+            );
+    }
 
-        /**
-         * <p>Create a Java representation of XML Schema builtin datatype <code>date</code> or <code>g*</code>.</p>
-         *
-         * <p>For example, an instance of <code>gYear</code> can be created invoking this factory
-         * with <code>month</code> and <code>day</code> parameters set to
-         * {@link DatatypeConstants#FIELD_UNDEFINED}.</p>
-         *
+    /**
+     * <p>Create a Java representation of XML Schema builtin datatype <code>date</code> or <code>g*</code>.</p>
+     *
+     * <p>For example, an instance of <code>gYear</code> can be created invoking this factory
+     * with <code>month</code> and <code>day</code> parameters set to
+     * {@link DatatypeConstants#FIELD_UNDEFINED}.</p>
+     *
      * <p>A {@link DatatypeConstants#FIELD_UNDEFINED} value indicates that field is not set.</p>
      *
-         * @param year of <code>XMLGregorianCalendar</code> to be created.
-         * @param month of <code>XMLGregorianCalendar</code> to be created.
-         * @param day of <code>XMLGregorianCalendar</code> to be created.
-         * @param timezone offset in minutes. {@link DatatypeConstants#FIELD_UNDEFINED} indicates optional field is not set.
-         *
-         * @return <code>XMLGregorianCalendar</code> created from parameter values.
-         *
-         * @see DatatypeConstants#FIELD_UNDEFINED
-         *
-         * @throws IllegalArgumentException If any individual parameter's value is outside the maximum value constraint for the field
-         *   as determined by the Date/Time Data Mapping table in {@link XMLGregorianCalendar}
-         *   or if the composite values constitute an invalid <code>XMLGregorianCalendar</code> instance
-         *   as determined by {@link XMLGregorianCalendar#isValid()}.
-         */
-        public XMLGregorianCalendar newXMLGregorianCalendarDate(
-                final int year,
-                final int month,
-                final int day,
-                final int timezone) {
+     * @param year of <code>XMLGregorianCalendar</code> to be created.
+     * @param month of <code>XMLGregorianCalendar</code> to be created.
+     * @param day of <code>XMLGregorianCalendar</code> to be created.
+     * @param timezone offset in minutes. {@link DatatypeConstants#FIELD_UNDEFINED} indicates optional field is not set.
+     *
+     * @return <code>XMLGregorianCalendar</code> created from parameter values.
+     *
+     * @see DatatypeConstants#FIELD_UNDEFINED
+     *
+     * @throws IllegalArgumentException If any individual parameter's value is outside the maximum value constraint for the field
+     *   as determined by the Date/Time Data Mapping table in {@link XMLGregorianCalendar}
+     *   or if the composite values constitute an invalid <code>XMLGregorianCalendar</code> instance
+     *   as determined by {@link XMLGregorianCalendar#isValid()}.
+     */
+    public XMLGregorianCalendar newXMLGregorianCalendarDate(
+            final int year,
+            final int month,
+            final int day,
+            final int timezone) {
 
-                return newXMLGregorianCalendar(
-                        year,
-                        month,
-                        day,
-                        DatatypeConstants.FIELD_UNDEFINED, // hour
-                        DatatypeConstants.FIELD_UNDEFINED, // minute
-                        DatatypeConstants.FIELD_UNDEFINED, // second
-                        DatatypeConstants.FIELD_UNDEFINED, // millisecond
-                        timezone);
-                }
+            return newXMLGregorianCalendar(
+                    year,
+                    month,
+                    day,
+                    DatatypeConstants.FIELD_UNDEFINED, // hour
+                    DatatypeConstants.FIELD_UNDEFINED, // minute
+                    DatatypeConstants.FIELD_UNDEFINED, // second
+                    DatatypeConstants.FIELD_UNDEFINED, // millisecond
+                    timezone);
+            }
 
-        /**
-         * <p>Create a Java instance of XML Schema builtin datatype <code>time</code>.</p>
-         *
+    /**
+     * <p>Create a Java instance of XML Schema builtin datatype <code>time</code>.</p>
+     *
      * <p>A {@link DatatypeConstants#FIELD_UNDEFINED} value indicates that field is not set.</p>
      *
-         * @param hours number of hours
-         * @param minutes number of minutes
-         * @param seconds number of seconds
-         * @param timezone offset in minutes. {@link DatatypeConstants#FIELD_UNDEFINED} indicates optional field is not set.
-         *
-         * @return <code>XMLGregorianCalendar</code> created from parameter values.
-         *
-         * @throws IllegalArgumentException If any individual parameter's value is outside the maximum value constraint for the field
-         *   as determined by the Date/Time Data Mapping table in {@link XMLGregorianCalendar}
-         *   or if the composite values constitute an invalid <code>XMLGregorianCalendar</code> instance
-         *   as determined by {@link XMLGregorianCalendar#isValid()}.
-         *
-         * @see DatatypeConstants#FIELD_UNDEFINED
-         */
-        public XMLGregorianCalendar newXMLGregorianCalendarTime(
-                final int hours,
-                final int minutes,
-                final int seconds,
-                final int timezone) {
+     * @param hours number of hours
+     * @param minutes number of minutes
+     * @param seconds number of seconds
+     * @param timezone offset in minutes. {@link DatatypeConstants#FIELD_UNDEFINED} indicates optional field is not set.
+     *
+     * @return <code>XMLGregorianCalendar</code> created from parameter values.
+     *
+     * @throws IllegalArgumentException If any individual parameter's value is outside the maximum value constraint for the field
+     *   as determined by the Date/Time Data Mapping table in {@link XMLGregorianCalendar}
+     *   or if the composite values constitute an invalid <code>XMLGregorianCalendar</code> instance
+     *   as determined by {@link XMLGregorianCalendar#isValid()}.
+     *
+     * @see DatatypeConstants#FIELD_UNDEFINED
+     */
+    public XMLGregorianCalendar newXMLGregorianCalendarTime(
+            final int hours,
+            final int minutes,
+            final int seconds,
+            final int timezone) {
 
-                return newXMLGregorianCalendar(
-                        DatatypeConstants.FIELD_UNDEFINED, // Year
-                        DatatypeConstants.FIELD_UNDEFINED, // Month
-                        DatatypeConstants.FIELD_UNDEFINED, // Day
-                        hours,
-                        minutes,
-                        seconds,
-                        DatatypeConstants.FIELD_UNDEFINED, //Millisecond
-                        timezone);
-        }
+            return newXMLGregorianCalendar(
+                    DatatypeConstants.FIELD_UNDEFINED, // Year
+                    DatatypeConstants.FIELD_UNDEFINED, // Month
+                    DatatypeConstants.FIELD_UNDEFINED, // Day
+                    hours,
+                    minutes,
+                    seconds,
+                    DatatypeConstants.FIELD_UNDEFINED, //Millisecond
+                    timezone);
+    }
 
-        /**
-         * <p>Create a Java instance of XML Schema builtin datatype time.</p>
-         *
+    /**
+     * <p>Create a Java instance of XML Schema builtin datatype time.</p>
+     *
      * <p>A <code>null</code> value indicates that field is not set.</p>
      * <p>A {@link DatatypeConstants#FIELD_UNDEFINED} value indicates that field is not set.</p>
      *
-         * @param hours number of hours
-         * @param minutes number of minutes
-         * @param seconds number of seconds
-         * @param fractionalSecond value of <code>null</code> indicates that this optional field is not set.
-         * @param timezone offset in minutes. {@link DatatypeConstants#FIELD_UNDEFINED} indicates optional field is not set.
-         *
-         * @return <code>XMLGregorianCalendar</code> created from parameter values.
-         *
-         * @see DatatypeConstants#FIELD_UNDEFINED
-         *
-         * @throws IllegalArgumentException If any individual parameter's value is outside the maximum value constraint for the field
-         *   as determined by the Date/Time Data Mapping table in {@link XMLGregorianCalendar}
-         *   or if the composite values constitute an invalid <code>XMLGregorianCalendar</code> instance
-         *   as determined by {@link XMLGregorianCalendar#isValid()}.
-         */
-        public XMLGregorianCalendar newXMLGregorianCalendarTime(
-                final int hours,
-                final int minutes,
-                final int seconds,
-                final BigDecimal fractionalSecond,
-                final int timezone) {
+     * @param hours number of hours
+     * @param minutes number of minutes
+     * @param seconds number of seconds
+     * @param fractionalSecond value of <code>null</code> indicates that this optional field is not set.
+     * @param timezone offset in minutes. {@link DatatypeConstants#FIELD_UNDEFINED} indicates optional field is not set.
+     *
+     * @return <code>XMLGregorianCalendar</code> created from parameter values.
+     *
+     * @see DatatypeConstants#FIELD_UNDEFINED
+     *
+     * @throws IllegalArgumentException If any individual parameter's value is outside the maximum value constraint for the field
+     *   as determined by the Date/Time Data Mapping table in {@link XMLGregorianCalendar}
+     *   or if the composite values constitute an invalid <code>XMLGregorianCalendar</code> instance
+     *   as determined by {@link XMLGregorianCalendar#isValid()}.
+     */
+    public XMLGregorianCalendar newXMLGregorianCalendarTime(
+            final int hours,
+            final int minutes,
+            final int seconds,
+            final BigDecimal fractionalSecond,
+            final int timezone) {
 
-                return newXMLGregorianCalendar(
-                        null, // year
-                        DatatypeConstants.FIELD_UNDEFINED, // month
-                        DatatypeConstants.FIELD_UNDEFINED, // day
-                        hours,
-                        minutes,
-                        seconds,
-                        fractionalSecond,
-                        timezone);
-                }
+            return newXMLGregorianCalendar(
+                    null, // year
+                    DatatypeConstants.FIELD_UNDEFINED, // month
+                    DatatypeConstants.FIELD_UNDEFINED, // day
+                    hours,
+                    minutes,
+                    seconds,
+                    fractionalSecond,
+                    timezone);
+            }
 
-        /**
-         * <p>Create a Java instance of XML Schema builtin datatype time.</p>
-         *
+    /**
+     * <p>Create a Java instance of XML Schema builtin datatype time.</p>
+     *
      * <p>A {@link DatatypeConstants#FIELD_UNDEFINED} value indicates that field is not set.</p>
      *
-         * @param hours number of hours
-         * @param minutes number of minutes
-         * @param seconds number of seconds
-         * @param milliseconds number of milliseconds
-         * @param timezone offset in minutes. {@link DatatypeConstants#FIELD_UNDEFINED} indicates optional field is not set.
-         *
-         * @return <code>XMLGregorianCalendar</code> created from parameter values.
-         *
-         * @see DatatypeConstants#FIELD_UNDEFINED
-         *
-         * @throws IllegalArgumentException If any individual parameter's value is outside the maximum value constraint for the field
-         *   as determined by the Date/Time Data Mapping table in {@link XMLGregorianCalendar}
-         *   or if the composite values constitute an invalid <code>XMLGregorianCalendar</code> instance
-         *   as determined by {@link XMLGregorianCalendar#isValid()}.
-         */
-        public XMLGregorianCalendar newXMLGregorianCalendarTime(
-                final int hours,
-                final int minutes,
-                final int seconds,
-                final int milliseconds,
-                final int timezone) {
+     * @param hours number of hours
+     * @param minutes number of minutes
+     * @param seconds number of seconds
+     * @param milliseconds number of milliseconds
+     * @param timezone offset in minutes. {@link DatatypeConstants#FIELD_UNDEFINED} indicates optional field is not set.
+     *
+     * @return <code>XMLGregorianCalendar</code> created from parameter values.
+     *
+     * @see DatatypeConstants#FIELD_UNDEFINED
+     *
+     * @throws IllegalArgumentException If any individual parameter's value is outside the maximum value constraint for the field
+     *   as determined by the Date/Time Data Mapping table in {@link XMLGregorianCalendar}
+     *   or if the composite values constitute an invalid <code>XMLGregorianCalendar</code> instance
+     *   as determined by {@link XMLGregorianCalendar#isValid()}.
+     */
+    public XMLGregorianCalendar newXMLGregorianCalendarTime(
+            final int hours,
+            final int minutes,
+            final int seconds,
+            final int milliseconds,
+            final int timezone) {
 
-                // millisecond may be undefined
-                // millisecond must be >= 0 millisecond <= 1000
-                BigDecimal realMilliseconds = null; // undefined value
-                if (milliseconds != DatatypeConstants.FIELD_UNDEFINED) {
-                        if (milliseconds < 0 || milliseconds > 1000) {
-                                throw new IllegalArgumentException(
-                                                        "javax.xml.datatype.DatatypeFactory#newXMLGregorianCalendarTime("
-                                                        + "int hours, int minutes, int seconds, int milliseconds, int timezone)"
-                                                        + "with invalid milliseconds: " + milliseconds
-                                                        );
-                        }
+            // millisecond may be undefined
+            // millisecond must be >= 0 millisecond <= 1000
+            BigDecimal realMilliseconds = null; // undefined value
+            if (milliseconds != DatatypeConstants.FIELD_UNDEFINED) {
+                    if (milliseconds < 0 || milliseconds > 1000) {
+                            throw new IllegalArgumentException(
+                                                    "javax.xml.datatype.DatatypeFactory#newXMLGregorianCalendarTime("
+                                                    + "int hours, int minutes, int seconds, int milliseconds, int timezone)"
+                                                    + "with invalid milliseconds: " + milliseconds
+                                                    );
+                    }
 
-                        realMilliseconds = BigDecimal.valueOf((long) milliseconds).movePointLeft(3);
-                }
+                    realMilliseconds = BigDecimal.valueOf((long) milliseconds).movePointLeft(3);
+            }
 
-                return newXMLGregorianCalendarTime(
-                        hours,
-                        minutes,
-                        seconds,
-                        realMilliseconds,
-                        timezone
-                );
-        }
+            return newXMLGregorianCalendarTime(
+                    hours,
+                    minutes,
+                    seconds,
+                    realMilliseconds,
+                    timezone
+            );
+    }
 }
--- a/src/javax/xml/datatype/FactoryFinder.java	Fri Apr 12 10:20:32 2013 +0100
+++ b/src/javax/xml/datatype/FactoryFinder.java	Wed Apr 17 15:23:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,14 +26,12 @@
 package javax.xml.datatype;
 
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Iterator;
 import java.util.Properties;
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.net.URL;
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
 
 /**
  * <p>Implements pluggable Datatypes.</p>
@@ -54,19 +52,19 @@
     /**
      * Cache for properties in java.home/lib/jaxp.properties
      */
-    static Properties cacheProps = new Properties();
+    private final static Properties cacheProps = new Properties();
 
     /**
      * Flag indicating if properties from java.home/lib/jaxp.properties
      * have been cached.
      */
-    static volatile boolean firstTime = true;
+    private static volatile boolean firstTime = true;
 
     /**
      * Security support class use to check access control before
      * getting certain system resources.
      */
-    static SecuritySupport ss = new SecuritySupport();
+    private final static SecuritySupport ss = new SecuritySupport();
 
     // Define system property "jaxp.debug" to get output
     static {
@@ -99,31 +97,31 @@
      *
      * Use bootstrap classLoader if cl = null and useBSClsLoader is true
      */
-    static private Class getProviderClass(String className, ClassLoader cl,
+    static private Class<?> getProviderClass(String className, ClassLoader cl,
             boolean doFallback, boolean useBSClsLoader) throws ClassNotFoundException
     {
         try {
             if (cl == null) {
                 if (useBSClsLoader) {
-                    return Class.forName(className, true, FactoryFinder.class.getClassLoader());
+                    return Class.forName(className, false, FactoryFinder.class.getClassLoader());
                 } else {
                     cl = ss.getContextClassLoader();
                     if (cl == null) {
                         throw new ClassNotFoundException();
                     }
                     else {
-                        return cl.loadClass(className);
+                        return Class.forName(className, false, cl);
                     }
                 }
             }
             else {
-                return cl.loadClass(className);
+                return Class.forName(className, false, cl);
             }
         }
         catch (ClassNotFoundException e1) {
             if (doFallback) {
                 // Use current class loader - should always be bootstrap CL
-                return Class.forName(className, true, FactoryFinder.class.getClassLoader());
+                return Class.forName(className, false, FactoryFinder.class.getClassLoader());
             }
             else {
                 throw e1;
@@ -135,6 +133,9 @@
      * Create an instance of a class. Delegates to method
      * <code>getProviderClass()</code> in order to load the class.
      *
+     * @param type Base class / Service interface  of the factory to
+     *             instantiate.
+     *
      * @param className Name of the concrete class corresponding to the
      * service provider
      *
@@ -144,16 +145,19 @@
      * @param doFallback True if the current ClassLoader should be tried as
      * a fallback if the class is not found using cl
      */
-    static Object newInstance(String className, ClassLoader cl, boolean doFallback)
-        throws ConfigurationError
+    static <T> T newInstance(Class<T> type, String className, ClassLoader cl, boolean doFallback)
+        throws  DatatypeConfigurationException
     {
-        return newInstance(className, cl, doFallback, false);
+        return newInstance(type, className, cl, doFallback, false);
     }
 
     /**
      * Create an instance of a class. Delegates to method
      * <code>getProviderClass()</code> in order to load the class.
      *
+     * @param type Base class / Service interface  of the factory to
+     *             instantiate.
+     *
      * @param className Name of the concrete class corresponding to the
      * service provider
      *
@@ -166,9 +170,12 @@
      * @param useBSClsLoader True if cl=null actually meant bootstrap classLoader. This parameter
      * is needed since DocumentBuilderFactory/SAXParserFactory defined null as context classLoader.
      */
-    static Object newInstance(String className, ClassLoader cl, boolean doFallback, boolean useBSClsLoader)
-        throws ConfigurationError
+    static <T> T newInstance(Class<T> type, String className, ClassLoader cl,
+            boolean doFallback, boolean useBSClsLoader)
+        throws DatatypeConfigurationException
     {
+        assert type != null;
+
         // make sure we have access to restricted packages
         if (System.getSecurityManager() != null) {
             if (className != null && className.startsWith(DEFAULT_PACKAGE)) {
@@ -178,20 +185,23 @@
         }
 
         try {
-            Class providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader);
+            Class<?> providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader);
+            if (!type.isAssignableFrom(providerClass)) {
+                throw new ClassCastException(className + " cannot be cast to " + type.getName());
+            }
             Object instance = providerClass.newInstance();
             if (debug) {    // Extra check to avoid computing cl strings
                 dPrint("created new instance of " + providerClass +
                        " using ClassLoader: " + cl);
             }
-            return instance;
+            return type.cast(instance);
         }
         catch (ClassNotFoundException x) {
-            throw new ConfigurationError(
+            throw new DatatypeConfigurationException(
                 "Provider " + className + " not found", x);
         }
         catch (Exception x) {
-            throw new ConfigurationError(
+            throw new DatatypeConfigurationException(
                 "Provider " + className + " could not be instantiated: " + x,
                 x);
         }
@@ -202,16 +212,17 @@
      * entry point.
      * @return Class object of factory, never null
      *
-     * @param factoryId             Name of the factory to find, same as
-     *                              a property name
+     * @param type                  Base class / Service interface  of the
+     *                              factory to find.
      * @param fallbackClassName     Implementation class name, if nothing else
      *                              is found.  Use null to mean no fallback.
      *
      * Package private so this code can be shared.
      */
-    static Object find(String factoryId, String fallbackClassName)
-        throws ConfigurationError
+    static <T> T find(Class<T> type, String fallbackClassName)
+        throws DatatypeConfigurationException
     {
+        final String factoryId = type.getName();
         dPrint("find factoryId =" + factoryId);
 
         // Use the system property first
@@ -219,7 +230,7 @@
             String systemProp = ss.getSystemProperty(factoryId);
             if (systemProp != null) {
                 dPrint("found system property, value=" + systemProp);
-                return newInstance(systemProp, null, true);
+                return newInstance(type, systemProp, null, true);
             }
         }
         catch (SecurityException se) {
@@ -228,7 +239,6 @@
 
         // try to read from $java.home/lib/jaxp.properties
         try {
-            String factoryClassName = null;
             if (firstTime) {
                 synchronized (cacheProps) {
                     if (firstTime) {
@@ -243,11 +253,11 @@
                     }
                 }
             }
-            factoryClassName = cacheProps.getProperty(factoryId);
+            final String factoryClassName = cacheProps.getProperty(factoryId);
 
             if (factoryClassName != null) {
                 dPrint("found in $java.home/jaxp.properties, value=" + factoryClassName);
-                return newInstance(factoryClassName, null, true);
+                return newInstance(type, factoryClassName, null, true);
             }
         }
         catch (Exception ex) {
@@ -255,112 +265,46 @@
         }
 
         // Try Jar Service Provider Mechanism
-        Object provider = findJarServiceProvider(factoryId);
+        final T provider = findServiceProvider(type);
         if (provider != null) {
             return provider;
         }
         if (fallbackClassName == null) {
-            throw new ConfigurationError(
-                "Provider for " + factoryId + " cannot be found", null);
+            throw new DatatypeConfigurationException(
+                "Provider for " + factoryId + " cannot be found");
         }
 
         dPrint("loaded from fallback value: " + fallbackClassName);
-        return newInstance(fallbackClassName, null, true);
+        return newInstance(type, fallbackClassName, null, true);
     }
 
     /*
-     * Try to find provider using Jar Service Provider Mechanism
+     * Try to find provider using the ServiceLoader API
+     *
+     * @param type Base class / Service interface  of the factory to find.
      *
      * @return instance of provider class if found or null
      */
-    private static Object findJarServiceProvider(String factoryId)
-        throws ConfigurationError
+    private static <T> T findServiceProvider(final Class<T> type)
+            throws DatatypeConfigurationException
     {
-        String serviceId = "META-INF/services/" + factoryId;
-        InputStream is = null;
-
-        // First try the Context ClassLoader
-        ClassLoader cl = ss.getContextClassLoader();
-        boolean useBSClsLoader = false;
-        if (cl != null) {
-            is = ss.getResourceAsStream(cl, serviceId);
-
-            // If no provider found then try the current ClassLoader
-            if (is == null) {
-                cl = FactoryFinder.class.getClassLoader();
-                is = ss.getResourceAsStream(cl, serviceId);
-                useBSClsLoader = true;
-            }
-        } else {
-            // No Context ClassLoader, try the current ClassLoader
-            cl = FactoryFinder.class.getClassLoader();
-            is = ss.getResourceAsStream(cl, serviceId);
-            useBSClsLoader = true;
-        }
-
-        if (is == null) {
-            // No provider found
-            return null;
-        }
-
-        if (debug) {    // Extra check to avoid computing cl strings
-            dPrint("found jar resource=" + serviceId + " using ClassLoader: " + cl);
-        }
-
-        BufferedReader rd;
-        try {
-            rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
-        }
-        catch (java.io.UnsupportedEncodingException e) {
-            rd = new BufferedReader(new InputStreamReader(is));
-        }
-
-        String factoryClassName = null;
         try {
-            // XXX Does not handle all possible input as specified by the
-            // Jar Service Provider specification
-            factoryClassName = rd.readLine();
-            rd.close();
-        } catch (IOException x) {
-            // No provider found
-            return null;
-        }
-
-        if (factoryClassName != null && !"".equals(factoryClassName)) {
-            dPrint("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, useBSClsLoader);
-        }
-
-        // No provider found
-        return null;
-    }
-
-    static class ConfigurationError extends Error {
-        private Exception exception;
-
-        /**
-         * Construct a new instance with the specified detail string and
-         * exception.
-         */
-        ConfigurationError(String msg, Exception x) {
-            super(msg);
-            this.exception = x;
-        }
-
-        Exception getException() {
-            return exception;
-        }
-        /**
-        * use the exception chaining mechanism of JDK1.4
-        */
-        @Override
-        public Throwable getCause() {
-            return exception;
+            return AccessController.doPrivileged(new PrivilegedAction<T>() {
+                public T run() {
+                    final ServiceLoader<T> serviceLoader = ServiceLoader.load(type);
+                    final Iterator<T> iterator = serviceLoader.iterator();
+                    if (iterator.hasNext()) {
+                        return iterator.next();
+                    } else {
+                        return null;
+                    }
+                }
+            });
+        } catch(ServiceConfigurationError e) {
+            final DatatypeConfigurationException error =
+                    new DatatypeConfigurationException(
+                        "Provider for " + type + " cannot be found", e);
+            throw error;
         }
     }
 
--- a/src/javax/xml/parsers/DocumentBuilderFactory.java	Fri Apr 12 10:20:32 2013 +0100
+++ b/src/javax/xml/parsers/DocumentBuilderFactory.java	Wed Apr 17 15:23:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,9 +40,6 @@
 
 public abstract class DocumentBuilderFactory {
 
-    /** The default property name according to the JAXP spec */
-    private static final String DEFAULT_PROPERTY_NAME = "javax.xml.parsers.DocumentBuilderFactory";
-
     private boolean validating = false;
     private boolean namespaceAware = false;
     private boolean whitespace = false;
@@ -50,8 +47,6 @@
     private boolean ignoreComments = false;
     private boolean coalescing = false;
 
-    private boolean canonicalState = false;
-
     /**
      * <p>Protected constructor to prevent instantiation.
      * Use {@link #newInstance()}.</p>
@@ -85,14 +80,12 @@
      * of any property in jaxp.properties after it has been read for the first time.
      * </li>
      * <li>
-     * Use the Services API (as detailed in the JAR specification), if
-     * available, to determine the classname. The Services API will look
-     * for a classname in the file
-     * <code>META-INF/services/javax.xml.parsers.DocumentBuilderFactory</code>
-     * in jars available to the runtime.
+     * Uses the service-provider loading facilities, defined by the
+     * {@link java.util.ServiceLoader} class, to attempt to locate and load an
+     * implementation of the service.
      * </li>
      * <li>
-     * Platform default <code>DocumentBuilderFactory</code> instance.
+     * Otherwise, the system-default implementation is returned.
      * </li>
      * </ul>
      *
@@ -113,21 +106,16 @@
      *
      * @return New instance of a <code>DocumentBuilderFactory</code>
      *
-     * @throws FactoryConfigurationError if the implementation is not
-     *   available or cannot be instantiated.
+     * @throws FactoryConfigurationError in case of {@linkplain
+     * java.util.ServiceConfigurationError service configuration error} or if
+     * the implementation is not available or cannot be instantiated.
      */
     public static DocumentBuilderFactory newInstance() {
-        try {
-            return (DocumentBuilderFactory) FactoryFinder.find(
+        return FactoryFinder.find(
                 /* The default property name according to the JAXP spec */
-                "javax.xml.parsers.DocumentBuilderFactory",
+                DocumentBuilderFactory.class, // "javax.xml.parsers.DocumentBuilderFactory"
                 /* The fallback implementation class name */
                 "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");
-        } catch (FactoryFinder.ConfigurationError e) {
-            throw new FactoryConfigurationError(e.getException(),
-                                                e.getMessage());
-        }
-
     }
 
     /**
@@ -165,13 +153,9 @@
      * @since 1.6
      */
     public static DocumentBuilderFactory newInstance(String factoryClassName, ClassLoader classLoader){
-        try {
             //do not fallback if given classloader can't find the class, throw exception
-            return (DocumentBuilderFactory) FactoryFinder.newInstance(factoryClassName, classLoader, false);
-        } catch (FactoryFinder.ConfigurationError e) {
-            throw new FactoryConfigurationError(e.getException(),
-                                                e.getMessage());
-        }
+            return FactoryFinder.newInstance(DocumentBuilderFactory.class,
+                        factoryClassName, classLoader, false);
     }
 
     /**
@@ -391,75 +375,64 @@
     public abstract Object getAttribute(String name)
                 throws IllegalArgumentException;
 
-        /**
-         * <p>Set a feature for this <code>DocumentBuilderFactory</code> and <code>DocumentBuilder</code>s created by this factory.</p>
-         *
-         * <p>
-         * Feature names are fully qualified {@link java.net.URI}s.
-         * Implementations may define their own features.
-         * A {@link ParserConfigurationException} is thrown if this <code>DocumentBuilderFactory</code> or the
-         * <code>DocumentBuilder</code>s it creates cannot support the feature.
-         * It is possible for a <code>DocumentBuilderFactory</code> to expose a feature value but be unable to change its state.
-         * </p>
-         *
-         * <p>
-         * All implementations are required to support the {@link javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING} feature.
-         * When the feature is:</p>
-         * <ul>
-         *   <li>
-         *     <code>true</code>: the implementation will limit XML processing to conform to implementation limits.
-         *     Examples include enity expansion limits and XML Schema constructs that would consume large amounts of resources.
-         *     If XML processing is limited for security reasons, it will be reported via a call to the registered
-         *    {@link org.xml.sax.ErrorHandler#fatalError(SAXParseException exception)}.
-         *     See {@link  DocumentBuilder#setErrorHandler(org.xml.sax.ErrorHandler errorHandler)}.
-         *   </li>
-         *   <li>
-         *     <code>false</code>: the implementation will processing XML according to the XML specifications without
-         *     regard to possible implementation limits.
-         *   </li>
-         * </ul>
-         *
-         * @param name Feature name.
-         * @param value Is feature state <code>true</code> or <code>false</code>.
-         *
-         * @throws ParserConfigurationException if this <code>DocumentBuilderFactory</code> or the <code>DocumentBuilder</code>s
-         *   it creates cannot support this feature.
+    /**
+     * <p>Set a feature for this <code>DocumentBuilderFactory</code> and <code>DocumentBuilder</code>s created by this factory.</p>
+     *
+     * <p>
+     * Feature names are fully qualified {@link java.net.URI}s.
+     * Implementations may define their own features.
+     * A {@link ParserConfigurationException} is thrown if this <code>DocumentBuilderFactory</code> or the
+     * <code>DocumentBuilder</code>s it creates cannot support the feature.
+     * It is possible for a <code>DocumentBuilderFactory</code> to expose a feature value but be unable to change its state.
+     * </p>
+     *
+     * <p>
+     * All implementations are required to support the {@link javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING} feature.
+     * When the feature is:</p>
+     * <ul>
+     *   <li>
+     *     <code>true</code>: the implementation will limit XML processing to conform to implementation limits.
+     *     Examples include enity expansion limits and XML Schema constructs that would consume large amounts of resources.
+     *     If XML processing is limited for security reasons, it will be reported via a call to the registered
+     *    {@link org.xml.sax.ErrorHandler#fatalError(SAXParseException exception)}.
+     *     See {@link  DocumentBuilder#setErrorHandler(org.xml.sax.ErrorHandler errorHandler)}.
+     *   </li>
+     *   <li>
+     *     <code>false</code>: the implementation will processing XML according to the XML specifications without
+     *     regard to possible implementation limits.
+     *   </li>
+     * </ul>
+     *
+     * @param name Feature name.
+     * @param value Is feature state <code>true</code> or <code>false</code>.
+     *
+     * @throws ParserConfigurationException if this <code>DocumentBuilderFactory</code> or the <code>DocumentBuilder</code>s
+     *   it creates cannot support this feature.
      * @throws NullPointerException If the <code>name</code> parameter is null.
-         */
-        public abstract void setFeature(String name, boolean value)
-                throws ParserConfigurationException;
+     */
+    public abstract void setFeature(String name, boolean value)
+            throws ParserConfigurationException;
 
-        /**
-         * <p>Get the state of the named feature.</p>
-         *
-         * <p>
-         * Feature names are fully qualified {@link java.net.URI}s.
-         * Implementations may define their own features.
-         * An {@link ParserConfigurationException} is thrown if this <code>DocumentBuilderFactory</code> or the
-         * <code>DocumentBuilder</code>s it creates cannot support the feature.
-         * It is possible for an <code>DocumentBuilderFactory</code> to expose a feature value but be unable to change its state.
-         * </p>
-         *
-         * @param name Feature name.
-         *
-         * @return State of the named feature.
-         *
-         * @throws ParserConfigurationException if this <code>DocumentBuilderFactory</code>
-         *   or the <code>DocumentBuilder</code>s it creates cannot support this feature.
-         */
-        public abstract boolean getFeature(String name)
-                throws ParserConfigurationException;
-
-
-    /** <p>Get current state of canonicalization.</p>
+    /**
+     * <p>Get the state of the named feature.</p>
      *
-     * @return current state canonicalization control
+     * <p>
+     * Feature names are fully qualified {@link java.net.URI}s.
+     * Implementations may define their own features.
+     * An {@link ParserConfigurationException} is thrown if this <code>DocumentBuilderFactory</code> or the
+     * <code>DocumentBuilder</code>s it creates cannot support the feature.
+     * It is possible for an <code>DocumentBuilderFactory</code> to expose a feature value but be unable to change its state.
+     * </p>
+     *
+     * @param name Feature name.
+     *
+     * @return State of the named feature.
+     *
+     * @throws ParserConfigurationException if this <code>DocumentBuilderFactory</code>
+     *   or the <code>DocumentBuilder</code>s it creates cannot support this feature.
      */
-    /*
-    public boolean getCanonicalization() {
-        return canonicalState;
-    }
-    */
+    public abstract boolean getFeature(String name)
+            throws ParserConfigurationException;
 
 
     /**
@@ -488,17 +461,6 @@
 
     }
 
-    /* <p>Set canonicalization control to <code>true</code> or
-     * </code>false</code>.</p>
-     *
-     * @param state of canonicalization
-     */
-    /*
-    public void setCanonicalization(boolean state) {
-        canonicalState = state;
-    }
-    */
-
     /**
      * <p>Set the {@link Schema} to be used by parsers created
      * from this factory.
--- a/src/javax/xml/parsers/FactoryFinder.java	Fri Apr 12 10:20:32 2013 +0100
+++ b/src/javax/xml/parsers/FactoryFinder.java	Wed Apr 17 15:23:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,15 +25,16 @@
 
 package javax.xml.parsers;
 
-import java.io.BufferedReader;
 import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Iterator;
 import java.util.Properties;
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
 
 /**
- * <p>Implements pluggable Datatypes.</p>
+ * <p>Implements pluggable Parsers.</p>
  *
  * <p>This class is duplicated for each JAXP subpackage so keep it in
  * sync.  It is package private for secure class loading.</p>
@@ -51,7 +52,7 @@
     /**
      * Cache for properties in java.home/lib/jaxp.properties
      */
-    static Properties cacheProps = new Properties();
+    private static final Properties cacheProps = new Properties();
 
     /**
      * Flag indicating if properties from java.home/lib/jaxp.properties
@@ -63,7 +64,7 @@
      * Security support class use to check access control before
      * getting certain system resources.
      */
-    static SecuritySupport ss = new SecuritySupport();
+    private static final SecuritySupport ss = new SecuritySupport();
 
     // Define system property "jaxp.debug" to get output
     static {
@@ -96,31 +97,31 @@
      *
      * Use bootstrap classLoader if cl = null and useBSClsLoader is true
      */
-    static private Class getProviderClass(String className, ClassLoader cl,
+    static private Class<?> getProviderClass(String className, ClassLoader cl,
             boolean doFallback, boolean useBSClsLoader) throws ClassNotFoundException
     {
         try {
             if (cl == null) {
                 if (useBSClsLoader) {
-                    return Class.forName(className, true, FactoryFinder.class.getClassLoader());
+                    return Class.forName(className, false, FactoryFinder.class.getClassLoader());
                 } else {
                     cl = ss.getContextClassLoader();
                     if (cl == null) {
                         throw new ClassNotFoundException();
                     }
                     else {
-                        return cl.loadClass(className);
+                        return Class.forName(className, false, cl);
                     }
                 }
             }
             else {
-                return cl.loadClass(className);
+                return Class.forName(className, false, cl);
             }
         }
         catch (ClassNotFoundException e1) {
             if (doFallback) {
                 // Use current class loader - should always be bootstrap CL
-                return Class.forName(className, true, FactoryFinder.class.getClassLoader());
+                return Class.forName(className, false, FactoryFinder.class.getClassLoader());
             }
             else {
                 throw e1;
@@ -132,6 +133,9 @@
      * Create an instance of a class. Delegates to method
      * <code>getProviderClass()</code> in order to load the class.
      *
+     * @param type Base class / Service interface  of the factory to
+     *             instantiate.
+     *
      * @param className Name of the concrete class corresponding to the
      * service provider
      *
@@ -141,16 +145,20 @@
      * @param doFallback True if the current ClassLoader should be tried as
      * a fallback if the class is not found using cl
      */
-    static Object newInstance(String className, ClassLoader cl, boolean doFallback)
-        throws ConfigurationError
+    static <T> T newInstance(Class<T> type, String className, ClassLoader cl,
+                             boolean doFallback)
+        throws FactoryConfigurationError
     {
-        return newInstance(className, cl, doFallback, false);
+        return newInstance(type, className, cl, doFallback, false);
     }
 
     /**
      * Create an instance of a class. Delegates to method
      * <code>getProviderClass()</code> in order to load the class.
      *
+     * @param type Base class / Service interface  of the factory to
+     *             instantiate.
+     *
      * @param className Name of the concrete class corresponding to the
      * service provider
      *
@@ -163,9 +171,11 @@
      * @param useBSClsLoader True if cl=null actually meant bootstrap classLoader. This parameter
      * is needed since DocumentBuilderFactory/SAXParserFactory defined null as context classLoader.
      */
-    static Object newInstance(String className, ClassLoader cl, boolean doFallback, boolean useBSClsLoader)
-        throws ConfigurationError
+    static <T> T newInstance(Class<T> type, String className, ClassLoader cl,
+                             boolean doFallback, boolean useBSClsLoader)
+        throws FactoryConfigurationError
     {
+        assert type != null;
         // make sure we have access to restricted packages
         if (System.getSecurityManager() != null) {
             if (className != null && className.startsWith(DEFAULT_PACKAGE)) {
@@ -175,22 +185,24 @@
         }
 
         try {
-            Class providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader);
+            Class<?> providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader);
+            if (!type.isAssignableFrom(providerClass)) {
+                throw new ClassCastException(className + " cannot be cast to " + type.getName());
+            }
             Object instance = providerClass.newInstance();
             if (debug) {    // Extra check to avoid computing cl strings
                 dPrint("created new instance of " + providerClass +
                        " using ClassLoader: " + cl);
             }
-            return instance;
+            return type.cast(instance);
         }
         catch (ClassNotFoundException x) {
-            throw new ConfigurationError(
-                "Provider " + className + " not found", x);
+            throw new FactoryConfigurationError(x,
+                "Provider " + className + " not found");
         }
         catch (Exception x) {
-            throw new ConfigurationError(
-                "Provider " + className + " could not be instantiated: " + x,
-                x);
+            throw new FactoryConfigurationError(x,
+                "Provider " + className + " could not be instantiated: " + x);
         }
     }
 
@@ -199,16 +211,17 @@
      * entry point.
      * @return Class object of factory, never null
      *
-     * @param factoryId             Name of the factory to find, same as
-     *                              a property name
+     * @param type                  Base class / Service interface  of the
+     *                              factory to find.
      * @param fallbackClassName     Implementation class name, if nothing else
      *                              is found.  Use null to mean no fallback.
      *
      * Package private so this code can be shared.
      */
-    static Object find(String factoryId, String fallbackClassName)
-        throws ConfigurationError
+    static <T> T find(Class<T> type, String fallbackClassName)
+        throws FactoryConfigurationError
     {
+        final String factoryId = type.getName();
         dPrint("find factoryId =" + factoryId);
 
         // Use the system property first
@@ -216,7 +229,7 @@
             String systemProp = ss.getSystemProperty(factoryId);
             if (systemProp != null) {
                 dPrint("found system property, value=" + systemProp);
-                return newInstance(systemProp, null, true);
+                return newInstance(type, systemProp, null, true);
             }
         }
         catch (SecurityException se) {
@@ -225,7 +238,6 @@
 
         // try to read from $java.home/lib/jaxp.properties
         try {
-            String factoryClassName = null;
             if (firstTime) {
                 synchronized (cacheProps) {
                     if (firstTime) {
@@ -240,11 +252,11 @@
                     }
                 }
             }
-            factoryClassName = cacheProps.getProperty(factoryId);
+            final String factoryClassName = cacheProps.getProperty(factoryId);
 
             if (factoryClassName != null) {
                 dPrint("found in $java.home/jaxp.properties, value=" + factoryClassName);
-                return newInstance(factoryClassName, null, true);
+                return newInstance(type, factoryClassName, null, true);
             }
         }
         catch (Exception ex) {
@@ -252,112 +264,52 @@
         }
 
         // Try Jar Service Provider Mechanism
-        Object provider = findJarServiceProvider(factoryId);
+        T provider = findServiceProvider(type);
         if (provider != null) {
             return provider;
         }
         if (fallbackClassName == null) {
-            throw new ConfigurationError(
-                "Provider for " + factoryId + " cannot be found", null);
+            throw new FactoryConfigurationError(
+                "Provider for " + factoryId + " cannot be found");
         }
 
         dPrint("loaded from fallback value: " + fallbackClassName);
-        return newInstance(fallbackClassName, null, true);
+        return newInstance(type, fallbackClassName, null, true);
     }
 
     /*
-     * Try to find provider using Jar Service Provider Mechanism
+     * Try to find provider using the ServiceLoader API
+     *
+     * @param type Base class / Service interface  of the factory to find.
      *
      * @return instance of provider class if found or null
      */
-    private static Object findJarServiceProvider(String factoryId)
-        throws ConfigurationError
-    {
-        String serviceId = "META-INF/services/" + factoryId;
-        InputStream is = null;
-
-        // First try the Context ClassLoader
-        ClassLoader cl = ss.getContextClassLoader();
-        boolean useBSClsLoader = false;
-        if (cl != null) {
-            is = ss.getResourceAsStream(cl, serviceId);
-
-            // If no provider found then try the current ClassLoader
-            if (is == null) {
-                cl = FactoryFinder.class.getClassLoader();
-                is = ss.getResourceAsStream(cl, serviceId);
-                useBSClsLoader = true;
-            }
-        } else {
-            // No Context ClassLoader, try the current ClassLoader
-            cl = FactoryFinder.class.getClassLoader();
-            is = ss.getResourceAsStream(cl, serviceId);
-            useBSClsLoader = true;
-        }
-
-        if (is == null) {
-            // No provider found
-            return null;
-        }
-
-        if (debug) {    // Extra check to avoid computing cl strings
-            dPrint("found jar resource=" + serviceId + " using ClassLoader: " + cl);
-        }
-
-        BufferedReader rd;
-        try {
-            rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
-        }
-        catch (java.io.UnsupportedEncodingException e) {
-            rd = new BufferedReader(new InputStreamReader(is));
-        }
-
-        String factoryClassName = null;
+    private static <T> T findServiceProvider(final Class<T> type) {
         try {
-            // XXX Does not handle all possible input as specified by the
-            // Jar Service Provider specification
-            factoryClassName = rd.readLine();
-            rd.close();
-        } catch (IOException x) {
-            // No provider found
-            return null;
-        }
-
-        if (factoryClassName != null && !"".equals(factoryClassName)) {
-            dPrint("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, useBSClsLoader);
-        }
-
-        // No provider found
-        return null;
-    }
-
-    static class ConfigurationError extends Error {
-        private Exception exception;
-
-        /**
-         * Construct a new instance with the specified detail string and
-         * exception.
-         */
-        ConfigurationError(String msg, Exception x) {
-            super(msg);
-            this.exception = x;
-        }
-
-        Exception getException() {
-            return exception;
-        }
-        /**
-        * use the exception chaining mechanism of JDK1.4
-        */
-        @Override
-        public Throwable getCause() {
-            return exception;
+            return AccessController.doPrivileged(new PrivilegedAction<T>() {
+                public T run() {
+                    final ServiceLoader<T> serviceLoader = ServiceLoader.load(type);
+                    final Iterator<T> iterator = serviceLoader.iterator();
+                    if (iterator.hasNext()) {
+                        return iterator.next();
+                    } else {
+                        return null;
+                    }
+                 }
+            });
+        } catch(ServiceConfigurationError e) {
+            // It is not possible to wrap an error directly in
+            // FactoryConfigurationError - so we need to wrap the
+            // ServiceConfigurationError in a RuntimeException.
+            // The alternative would be to modify the logic in
+            // FactoryConfigurationError to allow setting a
+            // Throwable as the cause, but that could cause
+            // compatibility issues down the road.
+            final RuntimeException x = new RuntimeException(
+                    "Provider for " + type + " cannot be created", e);
+            final FactoryConfigurationError error =
+                    new FactoryConfigurationError(x, x.getMessage());
+            throw error;
         }
     }
 
--- a/src/javax/xml/parsers/SAXParserFactory.java	Fri Apr 12 10:20:32 2013 +0100
+++ b/src/javax/xml/parsers/SAXParserFactory.java	Wed Apr 17 15:23:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,6 @@
 package javax.xml.parsers;
 
 import javax.xml.validation.Schema;
-
 import org.xml.sax.SAXException;
 import org.xml.sax.SAXNotRecognizedException;
 import org.xml.sax.SAXNotSupportedException;
@@ -42,8 +41,6 @@
  *
  */
 public abstract class SAXParserFactory {
-    /** The default property name according to the JAXP spec */
-    private static final String DEFAULT_PROPERTY_NAME = "javax.xml.parsers.SAXParserFactory";
 
     /**
      * <p>Should Parsers be validating?</p>
@@ -87,14 +84,12 @@
      * of any property in jaxp.properties after it has been read for the first time.
      * </li>
      * <li>
-     * Use the Services API (as detailed in the JAR specification), if
-     * available, to determine the classname. The Services API will look
-     * for a classname in the file
-     * <code>META-INF/services/javax.xml.parsers.SAXParserFactory</code>
-     * in jars available to the runtime.
+     * Use the service-provider loading facilities, defined by the
+     * {@link java.util.ServiceLoader} class, to attempt to locate and load an
+     * implementation of the service.
      * </li>
      * <li>
-     * Platform default <code>SAXParserFactory</code> instance.
+     * Otherwise the system-default implementation is returned.
      * </li>
      * </ul>
      *
@@ -109,7 +104,7 @@
      * this method to print a lot of debug messages
      * to <code>System.err</code> about what it is doing and where it is looking at.</p>
      *
-     * <p> If you have problems loading {@link DocumentBuilder}s, try:</p>
+     * <p> If you have problems loading {@link SAXParser}s, try:</p>
      * <pre>
      * java -Djaxp.debug=1 YourProgram ....
      * </pre>
@@ -117,21 +112,17 @@
      *
      * @return A new instance of a SAXParserFactory.
      *
-     * @throws FactoryConfigurationError if the implementation is
-     *   not available or cannot be instantiated.
+     * @throws FactoryConfigurationError in case of {@linkplain
+     * java.util.ServiceConfigurationError service configuration error} or if
+     * the implementation is not available or cannot be instantiated.
      */
 
     public static SAXParserFactory newInstance() {
-        try {
-            return (SAXParserFactory) FactoryFinder.find(
+        return FactoryFinder.find(
                 /* The default property name according to the JAXP spec */
-                "javax.xml.parsers.SAXParserFactory",
+                SAXParserFactory.class,
                 /* The fallback implementation class name */
                 "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl");
-        } catch (FactoryFinder.ConfigurationError e) {
-            throw new FactoryConfigurationError(e.getException(),
-                                                e.getMessage());
-        }
     }
 
     /**
@@ -169,13 +160,9 @@
      * @since 1.6
      */
     public static SAXParserFactory newInstance(String factoryClassName, ClassLoader classLoader){
-        try {
             //do not fallback if given classloader can't find the class, throw exception
-            return (SAXParserFactory) FactoryFinder.newInstance(factoryClassName, classLoader, false);
-        } catch (FactoryFinder.ConfigurationError e) {
-            throw new FactoryConfigurationError(e.getException(),
-                                                e.getMessage());
-        }
+            return FactoryFinder.newInstance(SAXParserFactory.class,
+                    factoryClassName, classLoader, false);
     }
 
     /**
@@ -266,22 +253,22 @@
      * A list of the core features and properties can be found at
      * <a href="http://www.saxproject.org/">http://www.saxproject.org/</a></p>
      *
-         * <p>All implementations are required to support the {@link javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING} feature.
-         * When the feature is</p>
-         * <ul>
-         *   <li>
-         *     <code>true</code>: the implementation will limit XML processing to conform to implementation limits.
-         *     Examples include enity expansion limits and XML Schema constructs that would consume large amounts of resources.
-         *     If XML processing is limited for security reasons, it will be reported via a call to the registered
-         *     {@link org.xml.sax.ErrorHandler#fatalError(SAXParseException exception)}.
-         *     See {@link SAXParser} <code>parse</code> methods for handler specification.
-         *   </li>
-         *   <li>
-         *     When the feature is <code>false</code>, the implementation will processing XML according to the XML specifications without
-         *     regard to possible implementation limits.
-         *   </li>
-         * </ul>
-         *
+     * <p>All implementations are required to support the {@link javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING} feature.
+     * When the feature is</p>
+     * <ul>
+     *   <li>
+     *     <code>true</code>: the implementation will limit XML processing to conform to implementation limits.
+     *     Examples include entity expansion limits and XML Schema constructs that would consume large amounts of resources.
+     *     If XML processing is limited for security reasons, it will be reported via a call to the registered
+     *     {@link org.xml.sax.ErrorHandler#fatalError(SAXParseException exception)}.
+     *     See {@link SAXParser} <code>parse</code> methods for handler specification.
+     *   </li>
+     *   <li>
+     *     When the feature is <code>false</code>, the implementation will processing XML according to the XML specifications without
+     *     regard to possible implementation limits.
+     *   </li>
+     * </ul>
+     *
      * @param name The name of the feature to be set.
      * @param value The value of the feature to be set.
      *
@@ -320,17 +307,6 @@
                 SAXNotSupportedException;
 
 
-
-    /* <p>Get current state of canonicalization.</p>
-     *
-     * @return current state canonicalization control
-     */
-    /*
-    public boolean getCanonicalization() {
-        return canonicalState;
-    }
-    */
-
     /**
      * Gets the {@link Schema} object specified through
      * the {@link #setSchema(Schema schema)} method.
@@ -357,17 +333,6 @@
             );
     }
 
-    /** <p>Set canonicalization control to <code>true</code> or
-     * </code>false</code>.</p>
-     *
-     * @param state of canonicalization
-     */
-    /*
-    public void setCanonicalization(boolean state) {
-        canonicalState = state;
-    }
-    */
-
     /**
      * <p>Set the {@link Schema} to be used by parsers created
      * from this factory.</p>
@@ -400,7 +365,7 @@
      * Such configuration will cause a {@link SAXException}
      * exception when those properties are set on a {@link SAXParser}.</p>
      *
-     * <h4>Note for implmentors</h4>
+     * <h4>Note for implementors</h4>
      * <p>
      * A parser must be able to work with any {@link Schema}
      * implementation. However, parsers and schemas are allowed
--- a/src/javax/xml/stream/FactoryFinder.java	Fri Apr 12 10:20:32 2013 +0100
+++ b/src/javax/xml/stream/FactoryFinder.java	Wed Apr 17 15:23:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,15 +25,16 @@
 
 package javax.xml.stream;
 
-import java.io.BufferedReader;
 import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Iterator;
 import java.util.Properties;
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
 
 /**
- * <p>Implements pluggable Datatypes.</p>
+ * <p>Implements pluggable streams.</p>
  *
  * <p>This class is duplicated for each JAXP subpackage so keep it in
  * sync.  It is package private for secure class loading.</p>
@@ -52,19 +53,19 @@
     /**
      * Cache for properties in java.home/lib/jaxp.properties
      */
-    static Properties cacheProps = new Properties();
+    final private static Properties cacheProps = new Properties();
 
     /**
      * Flag indicating if properties from java.home/lib/jaxp.properties
      * have been cached.
      */
-    static volatile boolean firstTime = true;
+    private static volatile boolean firstTime = true;
 
     /**
      * Security support class use to check access control before
      * getting certain system resources.
      */
-    static SecuritySupport ss = new SecuritySupport();
+    final private static SecuritySupport ss = new SecuritySupport();
 
     // Define system property "jaxp.debug" to get output
     static {
@@ -103,25 +104,25 @@
         try {
             if (cl == null) {
                 if (useBSClsLoader) {
-                    return Class.forName(className, true, FactoryFinder.class.getClassLoader());
+                    return Class.forName(className, false, FactoryFinder.class.getClassLoader());
                 } else {
                     cl = ss.getContextClassLoader();
                     if (cl == null) {
                         throw new ClassNotFoundException();
                     }
                     else {
-                        return cl.loadClass(className);
+                        return Class.forName(className, false, cl);
                     }
                 }
             }
             else {
-                return cl.loadClass(className);
+                return Class.forName(className, false, cl);
             }
         }
         catch (ClassNotFoundException e1) {
             if (doFallback) {
                 // Use current class loader - should always be bootstrap CL
-                return Class.forName(className, true, FactoryFinder.class.getClassLoader());
+                return Class.forName(className, false, FactoryFinder.class.getClassLoader());
             }
             else {
                 throw e1;
@@ -133,6 +134,9 @@
      * Create an instance of a class. Delegates to method
      * <code>getProviderClass()</code> in order to load the class.
      *
+     * @param type Base class / Service interface  of the factory to
+     *             instantiate.
+     *
      * @param className Name of the concrete class corresponding to the
      * service provider
      *
@@ -142,16 +146,19 @@
      * @param doFallback True if the current ClassLoader should be tried as
      * a fallback if the class is not found using cl
      */
-    static Object newInstance(String className, ClassLoader cl, boolean doFallback)
-        throws ConfigurationError
+    static <T> T newInstance(Class<T> type, String className, ClassLoader cl, boolean doFallback)
+        throws FactoryConfigurationError
     {
-        return newInstance(className, cl, doFallback, false);
+        return newInstance(type, className, cl, doFallback, false);
     }
 
     /**
      * Create an instance of a class. Delegates to method
      * <code>getProviderClass()</code> in order to load the class.
      *
+     * @param type Base class / Service interface  of the factory to
+     *             instantiate.
+     *
      * @param className Name of the concrete class corresponding to the
      * service provider
      *
@@ -164,9 +171,12 @@
      * @param useBSClsLoader True if cl=null actually meant bootstrap classLoader. This parameter
      * is needed since DocumentBuilderFactory/SAXParserFactory defined null as context classLoader.
      */
-    static Object newInstance(String className, ClassLoader cl, boolean doFallback, boolean useBSClsLoader)
-        throws ConfigurationError
+    static <T> T newInstance(Class<T> type, String className, ClassLoader cl,
+                              boolean doFallback, boolean useBSClsLoader)
+        throws FactoryConfigurationError
     {
+        assert type != null;
+
         // make sure we have access to restricted packages
         if (System.getSecurityManager() != null) {
             if (className != null && className.startsWith(DEFAULT_PACKAGE)) {
@@ -176,20 +186,23 @@
         }
 
         try {
-            Class providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader);
+            Class<?> providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader);
+            if (!type.isAssignableFrom(providerClass)) {
+                throw new ClassCastException(className + " cannot be cast to " + type.getName());
+            }
             Object instance = providerClass.newInstance();
             if (debug) {    // Extra check to avoid computing cl strings
                 dPrint("created new instance of " + providerClass +
                        " using ClassLoader: " + cl);
             }
-            return instance;
+            return type.cast(instance);
         }
         catch (ClassNotFoundException x) {
-            throw new ConfigurationError(
+            throw new FactoryConfigurationError(
                 "Provider " + className + " not found", x);
         }
         catch (Exception x) {
-            throw new ConfigurationError(
+            throw new FactoryConfigurationError(
                 "Provider " + className + " could not be instantiated: " + x,
                 x);
         }
@@ -200,17 +213,18 @@
      *
      * @return Class object of factory, never null
      *
-     * @param factoryId             Name of the factory to find, same as
-     *                              a property name
+     * @param type                  Base class / Service interface  of the
+     *                              factory to find.
+     *
      * @param fallbackClassName     Implementation class name, if nothing else
      *                              is found.  Use null to mean no fallback.
      *
      * Package private so this code can be shared.
      */
-    static Object find(String factoryId, String fallbackClassName)
-        throws ConfigurationError
+    static <T> T find(Class<T> type, String fallbackClassName)
+        throws FactoryConfigurationError
     {
-        return find(factoryId, null, fallbackClassName);
+        return find(type, type.getName(), null, fallbackClassName);
     }
 
     /**
@@ -218,6 +232,9 @@
      * entry point.
      * @return Class object of factory, never null
      *
+     * @param type                  Base class / Service interface  of the
+     *                              factory to find.
+     *
      * @param factoryId             Name of the factory to find, same as
      *                              a property name
      *
@@ -229,8 +246,8 @@
      *
      * Package private so this code can be shared.
      */
-    static Object find(String factoryId, ClassLoader cl, String fallbackClassName)
-        throws ConfigurationError
+    static <T> T find(Class<T> type, String factoryId, ClassLoader cl, String fallbackClassName)
+        throws FactoryConfigurationError
     {
         dPrint("find factoryId =" + factoryId);
 
@@ -239,7 +256,9 @@
             String systemProp = ss.getSystemProperty(factoryId);
             if (systemProp != null) {
                 dPrint("found system property, value=" + systemProp);
-                return newInstance(systemProp, null, true);
+                // There's a bug here - because 'cl' is ignored.
+                // This will be handled separately.
+                return newInstance(type, systemProp, null, true);
             }
         }
         catch (SecurityException se) {
@@ -250,7 +269,6 @@
         // $java.home/lib/jaxp.properties if former not present
         String configFile = null;
         try {
-            String factoryClassName = null;
             if (firstTime) {
                 synchronized (cacheProps) {
                     if (firstTime) {
@@ -269,130 +287,80 @@
                             if (ss.doesFileExist(f)) {
                                 dPrint("Read properties file "+f);
                                 cacheProps.load(ss.getFileInputStream(f));
+                            }
+                        }
                     }
                 }
             }
-                }
-            }
-            factoryClassName = cacheProps.getProperty(factoryId);
+            final String factoryClassName = cacheProps.getProperty(factoryId);
 
             if (factoryClassName != null) {
                 dPrint("found in " + configFile + " value=" + factoryClassName);
-                return newInstance(factoryClassName, null, true);
+                // There's a bug here - because 'cl' is ignored.
+                // This will be handled separately.
+                return newInstance(type, factoryClassName, null, true);
             }
         }
         catch (Exception ex) {
             if (debug) ex.printStackTrace();
         }
 
-        // Try Jar Service Provider Mechanism
-        Object provider = findJarServiceProvider(factoryId);
-        if (provider != null) {
-            return provider;
+        if (type.getName().equals(factoryId)) {
+            // Try Jar Service Provider Mechanism
+            final T provider = findServiceProvider(type);
+            if (provider != null) {
+                return provider;
+            }
+        } else {
+            // We're in the case where a 'custom' factoryId was provided,
+            // and in every case where that happens, we expect that
+            // fallbackClassName will be null.
+            assert fallbackClassName == null;
         }
         if (fallbackClassName == null) {
-            throw new ConfigurationError(
+            throw new FactoryConfigurationError(
                 "Provider for " + factoryId + " cannot be found", null);
         }
 
         dPrint("loaded from fallback value: " + fallbackClassName);
-        return newInstance(fallbackClassName, cl, true);
+        return newInstance(type, fallbackClassName, cl, true);
     }
 
     /*
-     * Try to find provider using Jar Service Provider Mechanism
+     * Try to find provider using the ServiceLoader API
+     *
+     * @param type Base class / Service interface  of the factory to find.
      *
      * @return instance of provider class if found or null
      */
-    private static Object findJarServiceProvider(String factoryId)
-        throws ConfigurationError
-    {
-        String serviceId = "META-INF/services/" + factoryId;
-        InputStream is = null;
-
-        // First try the Context ClassLoader
-        ClassLoader cl = ss.getContextClassLoader();
-        boolean useBSClsLoader = false;
-        if (cl != null) {
-            is = ss.getResourceAsStream(cl, serviceId);
-
-            // If no provider found then try the current ClassLoader
-            if (is == null) {
-                cl = FactoryFinder.class.getClassLoader();
-                is = ss.getResourceAsStream(cl, serviceId);
-                useBSClsLoader = true;
-            }
-        } else {
-            // No Context ClassLoader, try the current ClassLoader
-            cl = FactoryFinder.class.getClassLoader();
-            is = ss.getResourceAsStream(cl, serviceId);
-            useBSClsLoader = true;
-        }
-
-        if (is == null) {
-            // No provider found
-            return null;
-        }
-
-        if (debug) {    // Extra check to avoid computing cl strings
-            dPrint("found jar resource=" + serviceId + " using ClassLoader: " + cl);
-        }
-
-        BufferedReader rd;
-        try {
-            rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
-        }
-        catch (java.io.UnsupportedEncodingException e) {
-            rd = new BufferedReader(new InputStreamReader(is));
-        }
-
-        String factoryClassName = null;
+    private static <T> T findServiceProvider(final Class<T> type) {
         try {
-            // XXX Does not handle all possible input as specified by the
-            // Jar Service Provider specification
-            factoryClassName = rd.readLine();
-            rd.close();
-        } catch (IOException x) {
-            // No provider found
-            return null;
-        }
-
-        if (factoryClassName != null && !"".equals(factoryClassName)) {
-            dPrint("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, useBSClsLoader);
-        }
-
-        // No provider found
-        return null;
-    }
-
-    static class ConfigurationError extends Error {
-        private Exception exception;
-
-        /**
-         * Construct a new instance with the specified detail string and
-         * exception.
-         */
-        ConfigurationError(String msg, Exception x) {
-            super(msg);
-            this.exception = x;
-        }
-
-        Exception getException() {
-            return exception;
-        }
-        /**
-        * use the exception chaining mechanism of JDK1.4
-        */
-        @Override
-        public Throwable getCause() {
-            return exception;
-        }
-    }
+            return AccessController.doPrivileged(new PrivilegedAction<T>() {
+                @Override
+                public T run() {
+                    final ServiceLoader<T> serviceLoader = ServiceLoader.load(type);
+                    final Iterator<T> iterator = serviceLoader.iterator();
+                    if (iterator.hasNext()) {
+                        return iterator.next();
+                    } else {
+                        return null;
+                    }
+                }
+            });
+        } catch(ServiceConfigurationError e) {
+            // It is not possible to wrap an error directly in
+            // FactoryConfigurationError - so we need to wrap the
+            // ServiceConfigurationError in a RuntimeException.
+            // The alternative would be to modify the logic in
+            // FactoryConfigurationError to allow setting a
+            // Throwable as the cause, but that could cause
+            // compatibility issues down the road.
+            final RuntimeException x = new RuntimeException(
+                    "Provider for " + type + " cannot be created", e);
+            final FactoryConfigurationError error =
+                    new FactoryConfigurationError(x, x.getMessage());
+            throw error;
+          }
+      }
 
 }
--- a/src/javax/xml/stream/XMLEventFactory.java	Fri Apr 12 10:20:32 2013 +0100
+++ b/src/javax/xml/stream/XMLEventFactory.java	Wed Apr 17 15:23:19 2013 +0200
@@ -23,14 +23,14 @@
  */
 
 /*
- * Copyright (c) 2009 by Oracle Corporation. All Rights Reserved.
+ * Copyright (c) 2009, 2013, by Oracle Corporation. All Rights Reserved.
  */
 
 package javax.xml.stream;
-import javax.xml.stream.events.*;
+import java.util.Iterator;
 import javax.xml.namespace.NamespaceContext;
 import javax.xml.namespace.QName;
-import java.util.Iterator;
+import javax.xml.stream.events.*;
 /**
  * This interface defines a utility class for creating instances of
  * XMLEvents
@@ -54,48 +54,59 @@
 
 
   /**
-   * Create a new instance of the factory
+   * Creates a new instance of the factory in exactly the same manner as the
+   * {@link #newFactory()} method.
    * @throws FactoryConfigurationError if an instance of this factory cannot be loaded
    */
   public static XMLEventFactory newInstance()
     throws FactoryConfigurationError
   {
-    return (XMLEventFactory) FactoryFinder.find(
-      JAXPFACTORYID,
-      DEFAULIMPL);
+    return FactoryFinder.find(XMLEventFactory.class, DEFAULIMPL);
   }
 
   /**
    * Create a new instance of the factory.
+   * <p>
    * This static method creates a new factory instance.
    * This method uses the following ordered lookup procedure to determine
    * the XMLEventFactory implementation class to load:
+   * </p>
+   * <ul>
+   * <li>
    *   Use the javax.xml.stream.XMLEventFactory system property.
+   * </li>
+   * <li>
    *   Use the properties file "lib/stax.properties" in the JRE directory.
    *     This configuration file is in standard java.util.Properties format
    *     and contains the fully qualified name of the implementation class
    *     with the key being the system property defined above.
-   *   Use the Services API (as detailed in the JAR specification), if available,
-   *     to determine the classname. The Services API will look for a classname
-   *     in the file META-INF/services/javax.xml.stream.XMLEventFactory in jars
-   *     available to the runtime.
-   *   Platform default XMLEventFactory instance.
-   *
+   * </li>
+   * <li>
+   *   Use the service-provider loading facilities, defined by the
+   *   {@link java.util.ServiceLoader} class, to attempt to locate and load an
+   *   implementation of the service.
+   * </li>
+   * <li>
+   *   Otherwise, the system-default implementation is returned.
+   * </li>
+   * </ul>
+   * <p>
    *   Once an application has obtained a reference to a XMLEventFactory it
    *   can use the factory to configure and obtain stream instances.
-   *
+   * </p>
+   * <p>
    *   Note that this is a new method that replaces the deprecated newInstance() method.
    *     No changes in behavior are defined by this replacement method relative to
    *     the deprecated method.
-   *
-   * @throws FactoryConfigurationError if an instance of this factory cannot be loaded
+   * </p>
+   * @throws FactoryConfigurationError in case of {@linkplain
+   *   java.util.ServiceConfigurationError service configuration error} or if
+   *   the implementation is not available or cannot be instantiated.
    */
   public static XMLEventFactory newFactory()
     throws FactoryConfigurationError
   {
-    return (XMLEventFactory) FactoryFinder.find(
-      JAXPFACTORYID,
-      DEFAULIMPL);
+    return FactoryFinder.find(XMLEventFactory.class, DEFAULIMPL);
   }
 
   /**
@@ -116,40 +127,59 @@
   public static XMLEventFactory newInstance(String factoryId,
           ClassLoader classLoader)
           throws FactoryConfigurationError {
-      try {
-          //do not fallback if given classloader can't find the class, throw exception
-          return (XMLEventFactory) FactoryFinder.find(factoryId, classLoader, null);
-      } catch (FactoryFinder.ConfigurationError e) {
-          throw new FactoryConfigurationError(e.getException(),
-                  e.getMessage());
-      }
+      //do not fallback if given classloader can't find the class, throw exception
+      return FactoryFinder.find(XMLEventFactory.class, factoryId, classLoader, null);
   }
 
   /**
    * Create a new instance of the factory.
    * If the classLoader argument is null, then the ContextClassLoader is used.
+   * <p>
+   * This method uses the following ordered lookup procedure to determine
+   * the XMLEventFactory implementation class to load:
+   * </p>
+   * <ul>
+   * <li>
+   *   Use the value of the system property identified by {@code factoryId}.
+   * </li>
+   * <li>
+   *   Use the properties file "lib/stax.properties" in the JRE directory.
+   *     This configuration file is in standard java.util.Properties format
+   *     and contains the fully qualified name of the implementation class
+   *     with the key being the given {@code factoryId}.
+   * </li>
+   * <li>
+   *   If {@code factoryId} is "javax.xml.stream.XMLEventFactory",
+   *   use the service-provider loading facilities, defined by the
+   *   {@link java.util.ServiceLoader} class, to attempt to locate and load an
+   *   implementation of the service.
+   * </li>
+   * <li>
+   *   Otherwise, throws a {@link FactoryConfigurationError}.
+   * </li>
+   * </ul>
    *
+   * <p>
    * Note that this is a new method that replaces the deprecated
-   *   newInstance(String factoryId, ClassLoader classLoader) method.
+   *   {@link #newInstance(java.lang.String, java.lang.ClassLoader)
+   *   newInstance(String factoryId, ClassLoader classLoader)} method.
    * No changes in behavior are defined by this replacement method relative
    * to the deprecated method.
+   * </p>
    *
    * @param factoryId             Name of the factory to find, same as
    *                              a property name
    * @param classLoader           classLoader to use
    * @return the factory implementation
-   * @throws FactoryConfigurationError if an instance of this factory cannot be loaded
+   * @throws FactoryConfigurationError in case of {@linkplain
+   *   java.util.ServiceConfigurationError service configuration error} or if
+   *   the implementation is not available or cannot be instantiated.
    */
   public static XMLEventFactory newFactory(String factoryId,
-          ClassLoader classLoader)
+                                           ClassLoader classLoader)
           throws FactoryConfigurationError {
-      try {
-          //do not fallback if given classloader can't find the class, throw exception
-          return (XMLEventFactory) FactoryFinder.find(factoryId, classLoader, null);
-      } catch (FactoryFinder.ConfigurationError e) {
-          throw new FactoryConfigurationError(e.getException(),
-                  e.getMessage());
-      }
+      //do not fallback if given classloader can't find the class, throw exception
+      return FactoryFinder.find(XMLEventFactory.class, factoryId, classLoader, null);
   }
 
  /**
--- a/src/javax/xml/stream/XMLInputFactory.java	Fri Apr 12 10:20:32 2013 +0100
+++ b/src/javax/xml/stream/XMLInputFactory.java	Wed Apr 17 15:23:19 2013 +0200
@@ -23,13 +23,13 @@
  */
 
 /*
- * Copyright (c) 2009 by Oracle Corporation. All Rights Reserved.
+ * Copyright (c) 2009, 2013, by Oracle Corporation. All Rights Reserved.
  */
 
 package javax.xml.stream;
 
+import javax.xml.stream.util.XMLEventAllocator;
 import javax.xml.transform.Source;
-import javax.xml.stream.util.XMLEventAllocator;
 
 /**
  * Defines an abstract implementation of a factory for getting streams.
@@ -144,48 +144,59 @@
   protected XMLInputFactory(){}
 
   /**
-   * Create a new instance of the factory.
+   * Creates a new instance of the factory in exactly the same manner as the
+   * {@link #newFactory()} method.
    * @throws FactoryConfigurationError if an instance of this factory cannot be loaded
    */
   public static XMLInputFactory newInstance()
     throws FactoryConfigurationError
   {
-    return (XMLInputFactory) FactoryFinder.find(
-      "javax.xml.stream.XMLInputFactory",
-      DEFAULIMPL);
+    return FactoryFinder.find(XMLInputFactory.class, DEFAULIMPL);
   }
 
   /**
    * Create a new instance of the factory.
+   * <p>
    * This static method creates a new factory instance.
    * This method uses the following ordered lookup procedure to determine
    * the XMLInputFactory implementation class to load:
+   * </p>
+   * <ul>
+   * <li>
    *   Use the javax.xml.stream.XMLInputFactory system property.
+   * </li>
+   * <li>
    *   Use the properties file "lib/stax.properties" in the JRE directory.
    *     This configuration file is in standard java.util.Properties format
    *     and contains the fully qualified name of the implementation class
    *     with the key being the system property defined above.
-   *   Use the Services API (as detailed in the JAR specification), if available,
-   *     to determine the classname. The Services API will look for a classname
-   *     in the file META-INF/services/javax.xml.stream.XMLInputFactory in jars
-   *     available to the runtime.
-   *   Platform default XMLInputFactory instance.
-   *
+   * </li>
+   * <li>
+   *   Use the service-provider loading facilities, defined by the
+   *   {@link java.util.ServiceLoader} class, to attempt to locate and load an
+   *   implementation of the service.
+   * </li>
+   * <li>
+   * Otherwise, the system-default implementation is returned.
+   * </li>
+   * </ul>
+   * <p>
    *   Once an application has obtained a reference to a XMLInputFactory it
    *   can use the factory to configure and obtain stream instances.
-   *
+   * </p>
+   * <p>
    *   Note that this is a new method that replaces the deprecated newInstance() method.
    *     No changes in behavior are defined by this replacement method relative to
    *     the deprecated method.
-   *
-   * @throws FactoryConfigurationError if an instance of this factory cannot be loaded
+   * </p>
+   * @throws FactoryConfigurationError in case of {@linkplain
+   *   java.util.ServiceConfigurationError service configuration error} or if
+   *   the implementation is not available or cannot be instantiated.
    */
   public static XMLInputFactory newFactory()
     throws FactoryConfigurationError
   {
-    return (XMLInputFactory) FactoryFinder.find(
-      "javax.xml.stream.XMLInputFactory",
-      DEFAULIMPL);
+    return FactoryFinder.find(XMLInputFactory.class, DEFAULIMPL);
   }
 
   /**
@@ -206,40 +217,60 @@
   public static XMLInputFactory newInstance(String factoryId,
           ClassLoader classLoader)
           throws FactoryConfigurationError {
-      try {
-          //do not fallback if given classloader can't find the class, throw exception
-          return (XMLInputFactory) FactoryFinder.find(factoryId, classLoader, null);
-      } catch (FactoryFinder.ConfigurationError e) {
-          throw new FactoryConfigurationError(e.getException(),
-                  e.getMessage());
-      }
+      //do not fallback if given classloader can't find the class, throw exception
+      return FactoryFinder.find(XMLInputFactory.class, factoryId, classLoader, null);
   }
 
   /**
    * Create a new instance of the factory.
    * If the classLoader argument is null, then the ContextClassLoader is used.
+   * <p>
+   * This method uses the following ordered lookup procedure to determine
+   * the XMLInputFactory implementation class to load:
+   * </p>
+   * <ul>
+   * <li>
+   *   Use the value of the system property identified by {@code factoryId}.
+   * </li>
+   * <li>
+   *   Use the properties file "lib/stax.properties" in the JRE directory.
+   *     This configuration file is in standard java.util.Properties format
+   *     and contains the fully qualified name of the implementation class
+   *     with the key being the given {@code factoryId}.
+   * </li>
+   * <li>
+   *   If {@code factoryId} is "javax.xml.stream.XMLInputFactory",
+   *   use the service-provider loading facilities, defined by the
+   *   {@link java.util.ServiceLoader} class, to attempt to locate and load an
+   *   implementation of the service.
+   * </li>
+   * <li>
+   *   Otherwise, throws a {@link FactoryConfigurationError}.
+   * </li>
+   * </ul>
    *
+   * <p>
    * Note that this is a new method that replaces the deprecated
-   *   newInstance(String factoryId, ClassLoader classLoader) method.
+   *   {@link #newInstance(java.lang.String, java.lang.ClassLoader)
+   *   newInstance(String factoryId, ClassLoader classLoader)} method.
    * No changes in behavior are defined by this replacement method relative
    * to the deprecated method.
+   * </p>
    *
    * @param factoryId             Name of the factory to find, same as
    *                              a property name
    * @param classLoader           classLoader to use
    * @return the factory implementation
+   * @throws FactoryConfigurationError in case of {@linkplain
+   *   java.util.ServiceConfigurationError service configuration error} or if
+   *   the implementation is not available or cannot be instantiated.
    * @throws FactoryConfigurationError if an instance of this factory cannot be loaded
    */
   public static XMLInputFactory newFactory(String factoryId,
           ClassLoader classLoader)
           throws FactoryConfigurationError {
-      try {
-          //do not fallback if given classloader can't find the class, throw exception
-          return (XMLInputFactory) FactoryFinder.find(factoryId, classLoader, null);
-      } catch (FactoryFinder.ConfigurationError e) {
-          throw new FactoryConfigurationError(e.getException(),
-                  e.getMessage());
-      }
+      //do not fallback if given classloader can't find the class, throw exception
+      return FactoryFinder.find(XMLInputFactory.class, factoryId, classLoader, null);
   }
 
   /**
--- a/src/javax/xml/stream/XMLOutputFactory.java	Fri Apr 12 10:20:32 2013 +0100
+++ b/src/javax/xml/stream/XMLOutputFactory.java	Wed Apr 17 15:23:19 2013 +0200
@@ -23,7 +23,7 @@
  */
 
 /*
- * Copyright (c) 2009 by Oracle Corporation. All Rights Reserved.
+ * Copyright (c) 2009, 2013, by Oracle Corporation. All Rights Reserved.
  */
 
 package javax.xml.stream;
@@ -120,46 +120,58 @@
   protected XMLOutputFactory(){}
 
   /**
-   * Create a new instance of the factory.
+   * Creates a new instance of the factory in exactly the same manner as the
+   * {@link #newFactory()} method.
    * @throws FactoryConfigurationError if an instance of this factory cannot be loaded
    */
   public static XMLOutputFactory newInstance()
     throws FactoryConfigurationError
   {
-    return (XMLOutputFactory) FactoryFinder.find("javax.xml.stream.XMLOutputFactory",
-                                                 DEFAULIMPL);
+    return FactoryFinder.find(XMLOutputFactory.class, DEFAULIMPL);
   }
 
   /**
    * Create a new instance of the factory.
+   * <p>
    * This static method creates a new factory instance. This method uses the
    * following ordered lookup procedure to determine the XMLOutputFactory
    * implementation class to load:
+   * </p>
+   * <ul>
+   * <li>
    *   Use the javax.xml.stream.XMLOutputFactory system property.
+   * </li>
+   * <li>
    *   Use the properties file "lib/stax.properties" in the JRE directory.
    *     This configuration file is in standard java.util.Properties format
    *     and contains the fully qualified name of the implementation class
    *     with the key being the system property defined above.
-   *   Use the Services API (as detailed in the JAR specification), if available,
-   *     to determine the classname. The Services API will look for a classname
-   *     in the file META-INF/services/javax.xml.stream.XMLOutputFactory in jars
-   *     available to the runtime.
-   *   Platform default XMLOutputFactory instance.
-   *
+   * </li>
+   * <li>
+   *   Use the service-provider loading facilities, defined by the
+   *   {@link java.util.ServiceLoader} class, to attempt to locate and load an
+   *   implementation of the service.
+   * </li>
+   * <li>
+   *   Otherwise, the system-default implementation is returned.
+   * </li>
+   * <p>
    * Once an application has obtained a reference to a XMLOutputFactory it
    * can use the factory to configure and obtain stream instances.
-   *
+   * </p>
+   * <p>
    * Note that this is a new method that replaces the deprecated newInstance() method.
    *   No changes in behavior are defined by this replacement method relative to the
    *   deprecated method.
-   *
-   * @throws FactoryConfigurationError if an instance of this factory cannot be loaded
+   * </p>
+   * @throws FactoryConfigurationError in case of {@linkplain
+   *   java.util.ServiceConfigurationError service configuration error} or if
+   *   the implementation is not available or cannot be instantiated.
    */
   public static XMLOutputFactory newFactory()
     throws FactoryConfigurationError
   {
-    return (XMLOutputFactory) FactoryFinder.find("javax.xml.stream.XMLOutputFactory",
-                                                 DEFAULIMPL);
+    return FactoryFinder.find(XMLOutputFactory.class, DEFAULIMPL);
   }
 
   /**
@@ -179,42 +191,59 @@
   public static XMLInputFactory newInstance(String factoryId,
           ClassLoader classLoader)
           throws FactoryConfigurationError {
-      try {
-          //do not fallback if given classloader can't find the class, throw exception
-          return (XMLInputFactory) FactoryFinder.find(factoryId, classLoader, null);
-      } catch (FactoryFinder.ConfigurationError e) {
-          throw new FactoryConfigurationError(e.getException(),
-                  e.getMessage());
-      }
+      //do not fallback if given classloader can't find the class, throw exception
+      return FactoryFinder.find(XMLInputFactory.class, factoryId, classLoader, null);
   }
 
   /**
    * Create a new instance of the factory.
    * If the classLoader argument is null, then the ContextClassLoader is used.
-   *
-   * Note that this is a new method that replaces the deprecated
-   *   newInstance(String factoryId, ClassLoader classLoader) method.
+   * <p>
+   * This method uses the following ordered lookup procedure to determine
+   * the XMLOutputFactory implementation class to load:
+   * </p>
+   * <ul>
+   * <li>
+   *   Use the value of the system property identified by {@code factoryId}.
+   * </li>
+   * <li>
+   *   Use the properties file "lib/stax.properties" in the JRE directory.
+   *     This configuration file is in standard java.util.Properties format
+   *     and contains the fully qualified name of the implementation class
+   *     with the key being the given {@code factoryId}.
+   * </li>
+   * <li>
+   *   If {@code factoryId} is "javax.xml.stream.XMLOutputFactory",
+   *   use the service-provider loading facilities, defined by the
+   *   {@link java.util.ServiceLoader} class, to attempt to locate and load an
+   *   implementation of the service.
+   * </li>
+   * <li>
+   *   Otherwise, throws a {@link FactoryConfigurationError}.
+   * </li>
+   * </ul>
    *
-   *   No changes in behavior are defined by this replacement method relative
-   *   to the deprecated method.
-   *
+   * <p>
+   * Note that this is a new method that replaces the deprecated
+   *   {@link #newInstance(java.lang.String, java.lang.ClassLoader)
+   *   newInstance(String factoryId, ClassLoader classLoader)} method.
+   * No changes in behavior are defined by this replacement method relative
+   * to the deprecated method.
+   * </p>
    *
    * @param factoryId             Name of the factory to find, same as
    *                              a property name
    * @param classLoader           classLoader to use
    * @return the factory implementation
-   * @throws FactoryConfigurationError if an instance of this factory cannot be loaded
+   * @throws FactoryConfigurationError in case of {@linkplain
+   *   java.util.ServiceConfigurationError service configuration error} or if
+   *   the implementation is not available or cannot be instantiated.
    */
   public static XMLOutputFactory newFactory(String factoryId,
           ClassLoader classLoader)
           throws FactoryConfigurationError {
-      try {
-          //do not fallback if given classloader can't find the class, throw exception
-          return (XMLOutputFactory) FactoryFinder.find(factoryId, classLoader, null);
-      } catch (FactoryFinder.ConfigurationError e) {
-          throw new FactoryConfigurationError(e.getException(),
-                  e.getMessage());
-      }
+      //do not fallback if given classloader can't find the class, throw exception
+      return FactoryFinder.find(XMLOutputFactory.class, factoryId, classLoader, null);
   }
 
   /**
--- a/src/javax/xml/transform/FactoryFinder.java	Fri Apr 12 10:20:32 2013 +0100
+++ b/src/javax/xml/transform/FactoryFinder.java	Wed Apr 17 15:23:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,13 +25,15 @@
 
 package javax.xml.transform;
 
-import java.io.BufferedReader;
 import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
 import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Iterator;
 import java.util.Properties;
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
 
 /**
  * <p>Implements pluggable Datatypes.</p>
@@ -53,7 +55,7 @@
     /**
      * Cache for properties in java.home/lib/jaxp.properties
      */
-    static Properties cacheProps = new Properties();
+    private final static Properties cacheProps = new Properties();
 
     /**
      * Flag indicating if properties from java.home/lib/jaxp.properties
@@ -65,7 +67,7 @@
      * Security support class use to check access control before
      * getting certain system resources.
      */
-    static SecuritySupport ss = new SecuritySupport();
+    private final static SecuritySupport ss = new SecuritySupport();
 
     // Define system property "jaxp.debug" to get output
     static {
@@ -98,31 +100,31 @@
      *
      * Use bootstrap classLoader if cl = null and useBSClsLoader is true
      */
-    static private Class getProviderClass(String className, ClassLoader cl,
+    static private Class<?> getProviderClass(String className, ClassLoader cl,
             boolean doFallback, boolean useBSClsLoader) throws ClassNotFoundException
     {
         try {
             if (cl == null) {
                 if (useBSClsLoader) {
-                    return Class.forName(className, true, FactoryFinder.class.getClassLoader());
+                    return Class.forName(className, false, FactoryFinder.class.getClassLoader());
                 } else {
                     cl = ss.getContextClassLoader();
                     if (cl == null) {
                         throw new ClassNotFoundException();
                     }
                     else {
-                        return cl.loadClass(className);
+                        return Class.forName(className, false, cl);
                     }
                 }
             }
             else {
-                return cl.loadClass(className);
+                return Class.forName(className, false, cl);
             }
         }
         catch (ClassNotFoundException e1) {
             if (doFallback) {
                 // Use current class loader - should always be bootstrap CL
-                return Class.forName(className, true, FactoryFinder.class.getClassLoader());
+                return Class.forName(className, false, FactoryFinder.class.getClassLoader());
             }
             else {
                 throw e1;
@@ -134,24 +136,8 @@
      * Create an instance of a class. Delegates to method
      * <code>getProviderClass()</code> in order to load the class.
      *
-     * @param className Name of the concrete class corresponding to the
-     * service provider
-     *
-     * @param cl <code>ClassLoader</code> used to load the factory class. If <code>null</code>
-     * current <code>Thread</code>'s context classLoader is used to load the factory class.
-     *
-     * @param doFallback True if the current ClassLoader should be tried as
-     * a fallback if the class is not found using cl
-     */
-    static Object newInstance(String className, ClassLoader cl, boolean doFallback)
-        throws ConfigurationError
-    {
-        return newInstance(className, cl, doFallback, false, false);
-    }
-
-    /**
-     * Create an instance of a class. Delegates to method
-     * <code>getProviderClass()</code> in order to load the class.
+     * @param type Base class / Service interface  of the factory to
+     *             instantiate.
      *
      * @param className Name of the concrete class corresponding to the
      * service provider
@@ -162,14 +148,15 @@
      * @param doFallback True if the current ClassLoader should be tried as
      * a fallback if the class is not found using cl
      *
-     * @param useBSClsLoader True if cl=null actually meant bootstrap classLoader. This parameter
-     * is needed since DocumentBuilderFactory/SAXParserFactory defined null as context classLoader.
-     *
      * @param useServicesMechanism True use services mechanism
      */
-    static Object newInstance(String className, ClassLoader cl, boolean doFallback, boolean useBSClsLoader, boolean useServicesMechanism)
-        throws ConfigurationError
+    static <T> T newInstance(Class<T> type, String className, ClassLoader cl,
+                             boolean doFallback, boolean useServicesMechanism)
+        throws TransformerFactoryConfigurationError
     {
+        assert type != null;
+
+        boolean useBSClsLoader = false;
         // make sure we have access to restricted packages
         if (System.getSecurityManager() != null) {
             if (className != null && className.startsWith(DEFAULT_PACKAGE)) {
@@ -179,10 +166,13 @@
         }
 
         try {
-            Class providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader);
+            Class<?> providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader);
+            if (!type.isAssignableFrom(providerClass)) {
+                throw new ClassCastException(className + " cannot be cast to " + type.getName());
+            }
             Object instance = null;
             if (!useServicesMechanism) {
-                instance = newInstanceNoServiceLoader(providerClass);
+                instance = newInstanceNoServiceLoader(type, providerClass);
             }
             if (instance == null) {
                 instance = providerClass.newInstance();
@@ -191,63 +181,87 @@
                 dPrint("created new instance of " + providerClass +
                        " using ClassLoader: " + cl);
             }
-            return instance;
+            return type.cast(instance);
         }
         catch (ClassNotFoundException x) {
-            throw new ConfigurationError(
-                "Provider " + className + " not found", x);
+            throw new TransformerFactoryConfigurationError(x,
+                "Provider " + className + " not found");
         }
         catch (Exception x) {
-            throw new ConfigurationError(
-                "Provider " + className + " could not be instantiated: " + x,
-                x);
+            throw new TransformerFactoryConfigurationError(x,
+                "Provider " + className + " could not be instantiated: " + x);
         }
     }
+
     /**
      * Try to construct using newTransformerFactoryNoServiceLoader
      *   method if available.
      */
-    private static Object newInstanceNoServiceLoader(
-         Class<?> providerClass
-    ) {
+    private static <T> T newInstanceNoServiceLoader(Class<T> type, Class<?> providerClass) {
         // Retain maximum compatibility if no security manager.
         if (System.getSecurityManager() == null) {
             return null;
         }
         try {
-            Method creationMethod =
-                providerClass.getDeclaredMethod(
-                    "newTransformerFactoryNoServiceLoader"
-                );
-                return creationMethod.invoke(null, (Object[])null);
-            } catch (NoSuchMethodException exc) {
+            final Method creationMethod =
+                    providerClass.getDeclaredMethod(
+                        "newTransformerFactoryNoServiceLoader"
+                    );
+            final int modifiers = creationMethod.getModifiers();
+
+            // Do not call the method if it's not public static.
+            if (!Modifier.isPublic(modifiers) || !Modifier.isStatic(modifiers)) {
                 return null;
-            } catch (Exception exc) {
-                return null;
+            }
+
+            // Only call the method if it's declared to return an instance of
+            // TransformerFactory
+            final Class<?> returnType = creationMethod.getReturnType();
+            if (type.isAssignableFrom(returnType)) {
+                final Object result = creationMethod.invoke(null, (Object[])null);
+                return type.cast(result);
+            } else {
+                // This should not happen, as
+                // TransformerFactoryImpl.newTransformerFactoryNoServiceLoader is
+                // declared to return TransformerFactory.
+                throw new ClassCastException(returnType + " cannot be cast to " + type);
+            }
+        } catch (ClassCastException e) {
+            throw new TransformerFactoryConfigurationError(e, e.getMessage());
+        } catch (NoSuchMethodException exc) {
+            return null;
+        } catch (Exception exc) {
+            return null;
         }
     }
+
     /**
      * Finds the implementation Class object in the specified order.  Main
      * entry point.
      * @return Class object of factory, never null
      *
-     * @param factoryId             Name of the factory to find, same as
-     *                              a property name
+     * @param type                  Base class / Service interface  of the
+     *                              factory to find.
+     *
      * @param fallbackClassName     Implementation class name, if nothing else
      *                              is found.  Use null to mean no fallback.
      *
      * Package private so this code can be shared.
      */
-    static Object find(String factoryId, String fallbackClassName)
-        throws ConfigurationError
+    static <T> T find(Class<T> type, String fallbackClassName)
+        throws TransformerFactoryConfigurationError
     {
+        assert type != null;
+
+        final String factoryId = type.getName();
+
         dPrint("find factoryId =" + factoryId);
         // Use the system property first
         try {
             String systemProp = ss.getSystemProperty(factoryId);
             if (systemProp != null) {
                 dPrint("found system property, value=" + systemProp);
-                return newInstance(systemProp, null, true, false, true);
+                return newInstance(type, systemProp, null, true, true);
             }
         }
         catch (SecurityException se) {
@@ -256,7 +270,6 @@
 
         // try to read from $java.home/lib/jaxp.properties
         try {
-            String factoryClassName = null;
             if (firstTime) {
                 synchronized (cacheProps) {
                     if (firstTime) {
@@ -271,11 +284,11 @@
                     }
                 }
             }
-            factoryClassName = cacheProps.getProperty(factoryId);
+            final String factoryClassName = cacheProps.getProperty(factoryId);
 
             if (factoryClassName != null) {
                 dPrint("found in $java.home/jaxp.properties, value=" + factoryClassName);
-                return newInstance(factoryClassName, null, true, false, true);
+                return newInstance(type, factoryClassName, null, true, true);
             }
         }
         catch (Exception ex) {
@@ -283,113 +296,54 @@
         }
 
         // Try Jar Service Provider Mechanism
-        Object provider = findJarServiceProvider(factoryId);
+        T provider = findServiceProvider(type);
         if (provider != null) {
             return provider;
         }
         if (fallbackClassName == null) {
-            throw new ConfigurationError(
-                "Provider for " + factoryId + " cannot be found", null);
+            throw new TransformerFactoryConfigurationError(null,
+                "Provider for " + factoryId + " cannot be found");
         }
 
         dPrint("loaded from fallback value: " + fallbackClassName);
-        return newInstance(fallbackClassName, null, true, false, true);
+        return newInstance(type, fallbackClassName, null, true, true);
     }
 
     /*
-     * Try to find provider using Jar Service Provider Mechanism
+     * Try to find provider using the ServiceLoader.
+     *
+     * @param type Base class / Service interface  of the factory to find.
      *
      * @return instance of provider class if found or null
      */
-    private static Object findJarServiceProvider(String factoryId)
-        throws ConfigurationError
+    private static <T> T findServiceProvider(final Class<T> type)
+        throws TransformerFactoryConfigurationError
     {
-        String serviceId = "META-INF/services/" + factoryId;
-        InputStream is = null;
-
-        // First try the Context ClassLoader
-        ClassLoader cl = ss.getContextClassLoader();
-        boolean useBSClsLoader = false;
-        if (cl != null) {
-            is = ss.getResourceAsStream(cl, serviceId);
-
-            // If no provider found then try the current ClassLoader
-            if (is == null) {
-                cl = FactoryFinder.class.getClassLoader();
-                is = ss.getResourceAsStream(cl, serviceId);
-                useBSClsLoader = true;
-           }
-        } else {
-            // No Context ClassLoader, try the current ClassLoader
-            cl = FactoryFinder.class.getClassLoader();
-            is = ss.getResourceAsStream(cl, serviceId);
-            useBSClsLoader = true;
-        }
-
-        if (is == null) {
-            // No provider found
-            return null;
-        }
-
-        if (debug) {    // Extra check to avoid computing cl strings
-            dPrint("found jar resource=" + serviceId + " using ClassLoader: " + cl);
-        }
-
-        BufferedReader rd;
-        try {
-            rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
-        }
-        catch (java.io.UnsupportedEncodingException e) {
-            rd = new BufferedReader(new InputStreamReader(is));
-        }
-
-        String factoryClassName = null;
-        try {
-            // XXX Does not handle all possible input as specified by the
-            // Jar Service Provider specification
-            factoryClassName = rd.readLine();
-            rd.close();
-        } catch (IOException x) {
-            // No provider found
-            return null;
-        }
-
-        if (factoryClassName != null && !"".equals(factoryClassName)) {
-            dPrint("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, useBSClsLoader, true);
-        }
-
-        // No provider found
-        return null;
-    }
-
-    static class ConfigurationError extends Error {
-        private Exception exception;
-
-        /**
-         * Construct a new instance with the specified detail string and
-         * exception.
-         */
-        ConfigurationError(String msg, Exception x) {
-            super(msg);
-            this.exception = x;
-        }
-
-        Exception getException() {
-            return exception;
-        }
-        /**
-        * use the exception chaining mechanism of JDK1.4
-        */
-        @Override
-        public Throwable getCause() {
-            return exception;
+      try {
+            return AccessController.doPrivileged(new PrivilegedAction<T>() {
+                public T run() {
+                    final ServiceLoader<T> serviceLoader = ServiceLoader.load(type);
+                    final Iterator<T> iterator = serviceLoader.iterator();
+                    if (iterator.hasNext()) {
+                        return iterator.next();
+                    } else {
+                        return null;
+                    }
+                 }
+            });
+        } catch(ServiceConfigurationError e) {
+            // It is not possible to wrap an error directly in
+            // FactoryConfigurationError - so we need to wrap the
+            // ServiceConfigurationError in a RuntimeException.
+            // The alternative would be to modify the logic in
+            // FactoryConfigurationError to allow setting a
+            // Throwable as the cause, but that could cause
+            // compatibility issues down the road.
+            final RuntimeException x = new RuntimeException(
+                    "Provider for " + type + " cannot be created", e);
+            final TransformerFactoryConfigurationError error =
+                    new TransformerFactoryConfigurationError(x, x.getMessage());
+            throw error;
         }
     }
-
 }
--- a/src/javax/xml/transform/TransformerFactory.java	Fri Apr 12 10:20:32 2013 +0100
+++ b/src/javax/xml/transform/TransformerFactory.java	Wed Apr 17 15:23:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -52,8 +52,8 @@
 
     /**
      * <p>Obtain a new instance of a <code>TransformerFactory</code>.
-     * This static method creates a new factory instance
-     * This method uses the following ordered lookup procedure to determine
+     * This static method creates a new factory instance.</p>
+     * <p>This method uses the following ordered lookup procedure to determine
      * the <code>TransformerFactory</code> implementation class to
      * load:</p>
      * <ul>
@@ -67,7 +67,7 @@
      * </code> format and contains the fully qualified name of the
      * implementation class with the key being the system property defined
      * above.
-     *
+     * <br>
      * The jaxp.properties file is read only once by the JAXP implementation
      * and it's values are then cached for future use.  If the file does not exist
      * when the first attempt is made to read from it, no further attempts are
@@ -75,14 +75,12 @@
      * of any property in jaxp.properties after it has been read for the first time.
      * </li>
      * <li>
-     * Use the Services API (as detailed in the JAR specification), if
-     * available, to determine the classname. The Services API will look
-     * for a classname in the file
-     * <code>META-INF/services/javax.xml.transform.TransformerFactory</code>
-     * in jars available to the runtime.
+     *   Use the service-provider loading facilities, defined by the
+     *   {@link java.util.ServiceLoader} class, to attempt to locate and load an
+     *   implementation of the service.
      * </li>
      * <li>
-     * Platform default <code>TransformerFactory</code> instance.
+     *   Otherwise, the system-default implementation is returned.
      * </li>
      * </ul>
      *
@@ -92,22 +90,18 @@
      *
      * @return new TransformerFactory instance, never null.
      *
-     * @throws TransformerFactoryConfigurationError Thrown if the implementation
-     *    is not available or cannot be instantiated.
+     * @throws TransformerFactoryConfigurationError Thrown in case of {@linkplain
+     * java.util.ServiceConfigurationError service configuration error} or if
+     * the implementation is not available or cannot be instantiated.
      */
     public static TransformerFactory newInstance()
         throws TransformerFactoryConfigurationError {
-        try {
-            return (TransformerFactory) FactoryFinder.find(
+
+        return FactoryFinder.find(
             /* The default property name according to the JAXP spec */
-            "javax.xml.transform.TransformerFactory",
+            TransformerFactory.class,
             /* The fallback implementation class name, XSLTC */
             "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");
-        } catch (FactoryFinder.ConfigurationError e) {
-            throw new TransformerFactoryConfigurationError(
-                e.getException(),
-                e.getMessage());
-        }
     }
 
     /**
@@ -147,14 +141,10 @@
      */
     public static TransformerFactory newInstance(String factoryClassName, ClassLoader classLoader)
         throws TransformerFactoryConfigurationError{
-        try {
-            //do not fallback if given classloader can't find the class, throw exception
-            return (TransformerFactory) FactoryFinder.newInstance(factoryClassName, classLoader, false);
-        } catch (FactoryFinder.ConfigurationError e) {
-            throw new TransformerFactoryConfigurationError(
-                e.getException(),
-                e.getMessage());
-        }
+
+        //do not fallback if given classloader can't find the class, throw exception
+        return  FactoryFinder.newInstance(TransformerFactory.class,
+                    factoryClassName, classLoader, false, false);
     }
     /**
      * <p>Process the <code>Source</code> into a <code>Transformer</code>
--- a/src/javax/xml/validation/SchemaFactory.java	Fri Apr 12 10:20:32 2013 +0100
+++ b/src/javax/xml/validation/SchemaFactory.java	Wed Apr 17 15:23:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,15 +27,14 @@
 
 import java.io.File;
 import java.net.URL;
-
 import javax.xml.transform.Source;
 import javax.xml.transform.stream.StreamSource;
-
 import org.w3c.dom.ls.LSResourceResolver;
 import org.xml.sax.ErrorHandler;
 import org.xml.sax.SAXException;
 import org.xml.sax.SAXNotRecognizedException;
 import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.SAXParseException;
 
 /**
  * Factory that creates {@link Schema} objects&#x2E; Entry-point to
@@ -79,7 +78,7 @@
  * and has a significant effect on the parsing process, it is impossible
  * to define the DTD validation as a process independent from parsing.
  * For this reason, this specification does not define the semantics for
- * the XML DTD. This doesn't prohibit implentors from implementing it
+ * the XML DTD. This doesn't prohibit implementors from implementing it
  * in a way they see fit, but <em>users are warned that any DTD
  * validation implemented on this interface necessarily deviate from
  * the XML DTD semantics as defined in the XML 1.0</em>.
@@ -147,14 +146,17 @@
      *     is looked for. If present, the value is processed just like above.
      *   </li>
      *   <li>
-     *     <p>The class loader is asked for service provider provider-configuration files matching
-     *     <code>javax.xml.validation.SchemaFactory</code> in the resource directory META-INF/services.
-     *     See the JAR File Specification for file format and parsing rules.
-     *     Each potential service provider is required to implement the method:</p>
-     *     <pre>
-     *        {@link #isSchemaLanguageSupported(String schemaLanguage)}
-     *     </pre>
-     *     The first service provider found in class loader order that supports the specified schema language is returned.
+     *   Use the service-provider loading facilities, defined by the
+     *   {@link java.util.ServiceLoader} class, to attempt to locate and load an
+     *   implementation of the service.<br>
+     *   Each potential service provider is required to implement the method
+     *        {@link #isSchemaLanguageSupported(String schemaLanguage)}.
+     *   <br>
+     *   The first service provider found that supports the specified schema
+     *   language is returned.
+     *   <br>
+     *   In case of {@link java.util.ServiceConfigurationError} a
+     *   {@link SchemaFactoryConfigurationError} will be thrown.
      *   </li>
      *   <li>
      *     Platform default <code>SchemaFactory</code> is located
@@ -186,10 +188,12 @@
      *      If no implementation of the schema language is available.
      * @throws NullPointerException
      *      If the <code>schemaLanguage</code> parameter is null.
+     * @throws SchemaFactoryConfigurationError
+     *      If a configuration error is encountered.
      *
      * @see #newInstance(String schemaLanguage, String factoryClassName, ClassLoader classLoader)
      */
-    public static final SchemaFactory newInstance(String schemaLanguage) {
+    public static SchemaFactory newInstance(String schemaLanguage) {
         ClassLoader cl;
         cl = ss.getContextClassLoader();
 
@@ -275,19 +279,19 @@
 
     }
 
-        /**
-         * <p>Is specified schema supported by this <code>SchemaFactory</code>?</p>
-         *
-         * @param schemaLanguage Specifies the schema language which the returned <code>SchemaFactory</code> will understand.
+    /**
+     * <p>Is specified schema supported by this <code>SchemaFactory</code>?</p>
+     *
+     * @param schemaLanguage Specifies the schema language which the returned <code>SchemaFactory</code> will understand.
      *    <code>schemaLanguage</code> must specify a <a href="#schemaLanguage">valid</a> schema language.
-         *
-         * @return <code>true</code> if <code>SchemaFactory</code> supports <code>schemaLanguage</code>, else <code>false</code>.
-         *
-         * @throws NullPointerException If <code>schemaLanguage</code> is <code>null</code>.
-         * @throws IllegalArgumentException If <code>schemaLanguage.length() == 0</code>
-         *   or <code>schemaLanguage</code> does not specify a <a href="#schemaLanguage">valid</a> schema language.
-         */
-        public abstract boolean isSchemaLanguageSupported(String schemaLanguage);
+     *
+     * @return <code>true</code> if <code>SchemaFactory</code> supports <code>schemaLanguage</code>, else <code>false</code>.
+     *
+     * @throws NullPointerException If <code>schemaLanguage</code> is <code>null</code>.
+     * @throws IllegalArgumentException If <code>schemaLanguage.length() == 0</code>
+     *   or <code>schemaLanguage</code> does not specify a <a href="#schemaLanguage">valid</a> schema language.
+     */
+    public abstract boolean isSchemaLanguageSupported(String schemaLanguage);
 
     /**
      * Look up the value of a feature flag.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/javax/xml/validation/SchemaFactoryConfigurationError.java	Wed Apr 17 15:23:19 2013 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.xml.validation;
+
+/**
+ * Thrown when a problem with configuration with the Schema Factories
+ * exists. This error will typically be thrown when the class of a
+ * schema factory specified in the system properties cannot be found
+ * or instantiated.
+ * @since 1.8
+ */
+public final class SchemaFactoryConfigurationError extends Error {
+
+    static final long serialVersionUID = 3531438703147750126L;
+
+    /**
+     * Create a new <code>SchemaFactoryConfigurationError</code> with no
+     * detail message.
+     */
+    public SchemaFactoryConfigurationError() {
+    }
+
+
+    /**
+     * Create a new <code>SchemaFactoryConfigurationError</code> with
+     * the <code>String</code> specified as an error message.
+     *
+     * @param message The error message for the exception.
+     */
+    public SchemaFactoryConfigurationError(String message) {
+        super(message);
+    }
+
+    /**
+     * Create a new <code>SchemaFactoryConfigurationError</code> with the
+     * given <code>Throwable</code> base cause.
+     *
+     * @param cause The exception or error to be encapsulated in a
+     * SchemaFactoryConfigurationError.
+     */
+    public SchemaFactoryConfigurationError(Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * Create a new <code>SchemaFactoryConfigurationError</code> with the
+     * given <code>Throwable</code> base cause and detail message.
+     *
+     * @param cause The exception or error to be encapsulated in a
+     * SchemaFactoryConfigurationError.
+     * @param message The detail message.
+     */
+    public SchemaFactoryConfigurationError(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+}
--- a/src/javax/xml/validation/SchemaFactoryFinder.java	Fri Apr 12 10:20:32 2013 +0100
+++ b/src/javax/xml/validation/SchemaFactoryFinder.java	Wed Apr 17 15:23:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,19 +25,16 @@
 
 package javax.xml.validation;
 
-import java.io.BufferedReader;
 import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
 import java.lang.reflect.Method;
-import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
 import java.net.URL;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.Properties;
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
 
 /**
  * Implementation of {@link SchemaFactory#newInstance(String)}.
@@ -53,17 +50,17 @@
     /**
      *<p> Take care of restrictions imposed by java security model </p>
      */
-    private static SecuritySupport ss = new SecuritySupport();
+    private static final SecuritySupport ss = new SecuritySupport();
     private static final String DEFAULT_PACKAGE = "com.sun.org.apache.xerces.internal";
     /**
      * <p>Cache properties for performance.</p>
      */
-        private static Properties cacheProps = new Properties();
+    private static final Properties cacheProps = new Properties();
 
-        /**
-         * <p>First time requires initialization overhead.</p>
-         */
-        private static volatile boolean firstTime = true;
+    /**
+     * <p>First time requires initialization overhead.</p>
+     */
+    private static volatile boolean firstTime = true;
 
     static {
         // Use try/catch block to support applets
@@ -115,7 +112,7 @@
                 return;
             }
         } catch( Throwable unused ) {
-            ; // getContextClassLoader() undefined in JDK1.1
+            // getContextClassLoader() undefined in JDK1.1
         }
 
         if( classLoader==ClassLoader.getSystemClassLoader() ) {
@@ -138,9 +135,13 @@
      *
      * @throws NullPointerException
      *      If the <code>schemaLanguage</code> parameter is null.
+     * @throws SchemaFactoryConfigurationError
+     *      If a configuration error is encountered.
      */
     public SchemaFactory newFactory(String schemaLanguage) {
-        if(schemaLanguage==null)        throw new NullPointerException();
+        if(schemaLanguage==null) {
+            throw new NullPointerException();
+        }
         SchemaFactory f = _newFactory(schemaLanguage);
         if (f != null) {
             debugPrintln("factory '" + f.getClass().getName() + "' was found for " + schemaLanguage);
@@ -183,7 +184,6 @@
         String configFile = javah + File.separator +
         "lib" + File.separator + "jaxp.properties";
 
-        String factoryClassName = null ;
 
         // try to read from $java.home/lib/jaxp.properties
         try {
@@ -199,7 +199,7 @@
                     }
                 }
             }
-            factoryClassName = cacheProps.getProperty(propertyName);
+            final String factoryClassName = cacheProps.getProperty(propertyName);
             debugPrintln("found " + factoryClassName + " in $java.home/jaxp.properties");
 
             if (factoryClassName != null) {
@@ -214,21 +214,15 @@
             }
         }
 
-        // try META-INF/services files
-        Iterator sitr = createServiceFileIterator();
-        while(sitr.hasNext()) {
-            URL resource = (URL)sitr.next();
-            debugPrintln("looking into " + resource);
-            try {
-                sf = loadFromService(schemaLanguage,resource.toExternalForm(),
-                                                ss.getURLInputStream(resource));
-                if(sf!=null)    return sf;
-            } catch(IOException e) {
-                if( debug ) {
-                    debugPrintln("failed to read "+resource);
-                    e.printStackTrace();
-                }
-            }
+        // Try with ServiceLoader
+        final SchemaFactory factoryImpl = findServiceProvider(schemaLanguage);
+
+        // The following assertion should always be true.
+        // Uncomment it, recompile, and run with -ea in case of doubts:
+        // assert factoryImpl == null || factoryImpl.isSchemaLanguageSupported(schemaLanguage);
+
+        if (factoryImpl != null) {
+            return factoryImpl;
         }
 
         // platform default
@@ -246,8 +240,8 @@
      * @param className Name of class to create.
      * @return Created class or <code>null</code>.
      */
-    private Class createClass(String className) {
-            Class clazz;
+    private Class<?> createClass(String className) {
+        Class<?> clazz;
         // make sure we have access to restricted packages
         boolean internal = false;
         if (System.getSecurityManager() != null) {
@@ -256,25 +250,27 @@
             }
         }
 
-            try {
-                if (classLoader != null && !internal) {
-                        clazz = classLoader.loadClass(className);
-                } else {
-                        clazz = Class.forName(className);
-                }
-            } catch (Throwable t) {
-                if(debug)   t.printStackTrace();
-                    return null;
+        try {
+            if (classLoader != null && !internal) {
+                clazz = Class.forName(className, false, classLoader);
+            } else {
+                clazz = Class.forName(className);
             }
+        } catch (Throwable t) {
+            if(debug)  {
+                t.printStackTrace();
+            }
+            return null;
+        }
 
-            return clazz;
+        return clazz;
     }
 
     /**
      * <p>Creates an instance of the specified and returns it.</p>
      *
      * @param className
-     *      fully qualified class name to be instanciated.
+     *      fully qualified class name to be instantiated.
      *
      * @return null
      *      if it fails. Error messages will be printed by this method.
@@ -289,7 +285,7 @@
         debugPrintln("createInstance(" + className + ")");
 
         // get Class from className
-        Class clazz = createClass(className);
+        Class<?> clazz = createClass(className);
         if (clazz == null) {
                 debugPrintln("failed to getClass(" + className + ")");
                 return null;
@@ -298,9 +294,13 @@
 
         // instantiate Class as a SchemaFactory
         try {
-            if (!useServicesMechanism) {
-                schemaFactory = (SchemaFactory) newInstanceNoServiceLoader(clazz);
-            }
+                if (!SchemaFactory.class.isAssignableFrom(clazz)) {
+                    throw new ClassCastException(clazz.getName()
+                                + " cannot be cast to " + SchemaFactory.class);
+                }
+                if (!useServicesMechanism) {
+                    schemaFactory = newInstanceNoServiceLoader(clazz);
+                }
                 if (schemaFactory == null) {
                     schemaFactory = (SchemaFactory) clazz.newInstance();
                 }
@@ -326,11 +326,12 @@
 
         return schemaFactory;
     }
+
     /**
-     * Try to construct using newTransformerFactoryNoServiceLoader
+     * Try to construct using newXMLSchemaFactoryNoServiceLoader
      *   method if available.
      */
-    private static Object newInstanceNoServiceLoader(
+    private static SchemaFactory newInstanceNoServiceLoader(
          Class<?> providerClass
     ) {
         // Retain maximum compatibility if no security manager.
@@ -338,196 +339,87 @@
             return null;
         }
         try {
-            Method creationMethod =
+            final Method creationMethod =
                 providerClass.getDeclaredMethod(
                     "newXMLSchemaFactoryNoServiceLoader"
                 );
-                return creationMethod.invoke(null, (Object[])null);
-            } catch (NoSuchMethodException exc) {
-                return null;
-            } catch (Exception exc) {
-                return null;
-        }
-    }
+            final int modifiers = creationMethod.getModifiers();
 
-    /** Iterator that lazily computes one value and returns it. */
-    private static abstract class SingleIterator implements Iterator {
-        private boolean seen = false;
-
-        public final void remove() { throw new UnsupportedOperationException(); }
-        public final boolean hasNext() { return !seen; }
-        public final Object next() {
-            if(seen)    throw new NoSuchElementException();
-            seen = true;
-            return value();
-        }
+            // Do not call the method if it's not public static.
+            if (!Modifier.isStatic(modifiers) || !Modifier.isPublic(modifiers)) {
+                return null;
+            }
 
-        protected abstract Object value();
-    }
-
-    /**
-     * Looks up a value in a property file
-     * while producing all sorts of debug messages.
-     *
-     * @return null
-     *      if there was an error.
-     */
-    private SchemaFactory loadFromProperty( String keyName, String resourceName, InputStream in )
-        throws IOException {
-        debugPrintln("Reading "+resourceName );
-
-        Properties props=new Properties();
-        props.load(in);
-        in.close();
-        String factoryClassName = props.getProperty(keyName);
-        if(factoryClassName != null){
-            debugPrintln("found "+keyName+" = " + factoryClassName);
-            return createInstance(factoryClassName);
-        } else {
-            debugPrintln(keyName+" is not in the property file");
+            // Only calls "newXMLSchemaFactoryNoServiceLoader" if it's
+            // declared to return an instance of SchemaFactory.
+            final Class<?> returnType = creationMethod.getReturnType();
+            if (SERVICE_CLASS.isAssignableFrom(returnType)) {
+                return SERVICE_CLASS.cast(creationMethod.invoke(null, (Object[])null));
+            } else {
+                // Should not happen since
+                // XMLSchemaFactory.newXMLSchemaFactoryNoServiceLoader is
+                // declared to return XMLSchemaFactory.
+                throw new ClassCastException(returnType
+                            + " cannot be cast to " + SERVICE_CLASS);
+            }
+        } catch(ClassCastException e) {
+            throw new SchemaFactoryConfigurationError(e.getMessage(), e);
+        } catch (NoSuchMethodException exc) {
+            return null;
+        } catch (Exception exc) {
             return null;
         }
     }
 
-    /**
-     * <p>Look up a value in a property file.</p>
-     *
-     * <p>Set <code>debug</code> to <code>true</code> to trace property evaluation.</p>
-     *
-     * @param schemaLanguage Schema Language to support.
-     * @param inputName Name of <code>InputStream</code>.
-     * @param in <code>InputStream</code> of properties.
-     *
-     * @return <code>SchemaFactory</code> as determined by <code>keyName</code> value or <code>null</code> if there was an error.
-     *
-     * @throws IOException If IO error reading from <code>in</code>.
-     */
-    private SchemaFactory loadFromService(
-            String schemaLanguage,
-            String inputName,
-            InputStream in)
-            throws IOException {
-
-            SchemaFactory schemaFactory = null;
-            final Class[] stringClassArray = {"".getClass()};
-            final Object[] schemaLanguageObjectArray = {schemaLanguage};
-            final String isSchemaLanguageSupportedMethod = "isSchemaLanguageSupported";
-
-            debugPrintln("Reading " + inputName);
-
-            // read from InputStream until a match is found
-            BufferedReader configFile = new BufferedReader(new InputStreamReader(in));
-            String line = null;
-            while ((line = configFile.readLine()) != null) {
-                    // '#' is comment char
-                    int comment = line.indexOf("#");
-                    switch (comment) {
-                            case -1: break; // no comment
-                            case 0: line = ""; break; // entire line is a comment
-                            default: line = line.substring(0, comment); break; // trim comment
-                    }
-
-                    // trim whitespace
-                    line = line.trim();
-
-                    // any content left on line?
-                    if (line.length() == 0) {
-                            continue;
-                    }
-
-                    // line content is now the name of the class
-                    Class clazz = createClass(line);
-                    if (clazz == null) {
-                            continue;
-                    }
-
-                    // create an instance of the Class
-                    try {
-                            schemaFactory = (SchemaFactory) clazz.newInstance();
-                    } catch (ClassCastException classCastExcpetion) {
-                            schemaFactory = null;
-                            continue;
-                    } catch (InstantiationException instantiationException) {
-                            schemaFactory = null;
-                            continue;
-                    } catch (IllegalAccessException illegalAccessException) {
-                            schemaFactory = null;
-                            continue;
-                    }
-
-                    // does this Class support desired Schema?
-                    try {
-                            Method isSchemaLanguageSupported = clazz.getMethod(isSchemaLanguageSupportedMethod, stringClassArray);
-                            Boolean supported = (Boolean) isSchemaLanguageSupported.invoke(schemaFactory, schemaLanguageObjectArray);
-                            if (supported.booleanValue()) {
-                                    break;
-                            }
-                    } catch (NoSuchMethodException noSuchMethodException) {
-
-                    } catch (IllegalAccessException illegalAccessException) {
-
-                    } catch (InvocationTargetException invocationTargetException) {
-
-                    }
-                    schemaFactory = null;
+    // Call isSchemaLanguageSupported with initial context.
+    private boolean isSchemaLanguageSupportedBy(final SchemaFactory factory,
+            final String schemaLanguage,
+            AccessControlContext acc) {
+        return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+            public Boolean run() {
+                return factory.isSchemaLanguageSupported(schemaLanguage);
             }
-
-            // clean up
-            configFile.close();
-
-            // return new instance of SchemaFactory or null
-            return schemaFactory;
+        }, acc);
     }
 
     /**
-     * Returns an {@link Iterator} that enumerates all
-     * the META-INF/services files that we care.
+     * Finds a service provider subclass of SchemaFactory that supports the
+     * given schema language using the ServiceLoader.
+     *
+     * @param schemaLanguage The schema language for which we seek a factory.
+     * @return A SchemaFactory supporting the specified schema language, or null
+     *         if none is found.
+     * @throws SchemaFactoryConfigurationError if a configuration error is found.
      */
-    private Iterator createServiceFileIterator() {
-        if (classLoader == null) {
-            return new SingleIterator() {
-                protected Object value() {
-                    ClassLoader classLoader = SchemaFactoryFinder.class.getClassLoader();
-                    //return (ClassLoader.getSystemResource( SERVICE_ID ));
-                    return ss.getResourceAsURL(classLoader, SERVICE_ID);
-                }
-            };
-        } else {
-            try {
-                //final Enumeration e = classLoader.getResources(SERVICE_ID);
-                final Enumeration e = ss.getResources(classLoader, SERVICE_ID);
-                if(!e.hasMoreElements()) {
-                    debugPrintln("no "+SERVICE_ID+" file was found");
+    private SchemaFactory findServiceProvider(final String schemaLanguage) {
+        assert schemaLanguage != null;
+        // store current context.
+        final AccessControlContext acc = AccessController.getContext();
+        try {
+            return AccessController.doPrivileged(new PrivilegedAction<SchemaFactory>() {
+                public SchemaFactory run() {
+                    final ServiceLoader<SchemaFactory> loader =
+                            ServiceLoader.load(SERVICE_CLASS);
+                    for (SchemaFactory factory : loader) {
+                        // restore initial context to call
+                        // factory.isSchemaLanguageSupported
+                        if (isSchemaLanguageSupportedBy(factory, schemaLanguage, acc)) {
+                            return factory;
+                        }
+                    }
+                    return null; // no factory found.
                 }
-
-                // wrap it into an Iterator.
-                return new Iterator() {
-                    public void remove() {
-                        throw new UnsupportedOperationException();
-                    }
-
-                    public boolean hasNext() {
-                        return e.hasMoreElements();
-                    }
-
-                    public Object next() {
-                        return e.nextElement();
-                    }
-                };
-            } catch (IOException e) {
-                debugPrintln("failed to enumerate resources "+SERVICE_ID);
-                if(debug)   e.printStackTrace();
-                return new ArrayList().iterator();  // empty iterator
-            }
+            });
+        } catch (ServiceConfigurationError error) {
+            throw new SchemaFactoryConfigurationError(
+                    "Provider for " + SERVICE_CLASS + " cannot be created", error);
         }
     }
 
-    private static final Class SERVICE_CLASS = SchemaFactory.class;
-    private static final String SERVICE_ID = "META-INF/services/" + SERVICE_CLASS.getName();
+    private static final Class<SchemaFactory> SERVICE_CLASS = SchemaFactory.class;
 
 
-
-    private static String which( Class clazz ) {
+    private static String which( Class<?> clazz ) {
         return which( clazz.getName(), clazz.getClassLoader() );
     }
 
--- a/src/javax/xml/xpath/XPathFactory.java	Fri Apr 12 10:20:32 2013 +0100
+++ b/src/javax/xml/xpath/XPathFactory.java	Wed Apr 17 15:23:19 2013 +0200
@@ -90,7 +90,7 @@
      * @throws RuntimeException When there is a failure in creating an
      *   <code>XPathFactory</code> for the default object model.
      */
-    public static final XPathFactory newInstance() {
+    public static XPathFactory newInstance() {
 
         try {
                 return newInstance(DEFAULT_OBJECT_MODEL_URI);
@@ -121,14 +121,17 @@
     *     If present, the value is processed just like above.
     *   </li>
     *   <li>
-    *     The class loader is asked for service provider provider-configuration files matching <code>javax.xml.xpath.XPathFactory</code>
-    *     in the resource directory META-INF/services.
-    *     See the JAR File Specification for file format and parsing rules.
-    *     Each potential service provider is required to implement the method:
-    *     <pre>
-    *       {@link #isObjectModelSupported(String objectModel)}
-    *     </pre>
-    *     The first service provider found in class loader order that supports the specified object model is returned.
+    *     Use the service-provider loading facilities, defined by the
+    *     {@link java.util.ServiceLoader} class, to attempt to locate and load an
+    *     implementation of the service.
+    *     <br>
+    *     Each potential service provider is required to implement the method
+    *     {@link #isObjectModelSupported(String objectModel)}.
+    *     The first service provider found that supports the specified object
+    *     model is returned.
+    *     <br>
+    *     In case of {@link java.util.ServiceConfigurationError} an
+    *     {@link XPathFactoryConfigurationException} will be thrown.
     *   </li>
     *   <li>
     *     Platform default <code>XPathFactory</code> is located in a platform specific way.
@@ -152,43 +155,41 @@
     *
     * @return Instance of an <code>XPathFactory</code>.
     *
-    * @throws XPathFactoryConfigurationException If the specified object model is unavailable.
+    * @throws XPathFactoryConfigurationException If the specified object model
+    *      is unavailable, or if there is a configuration error.
     * @throws NullPointerException If <code>uri</code> is <code>null</code>.
-        * @throws IllegalArgumentException If <code>uri</code> is <code>null</code>
+    * @throws IllegalArgumentException If <code>uri</code> is <code>null</code>
     *   or <code>uri.length() == 0</code>.
     */
-    public static final XPathFactory newInstance(final String uri)
+    public static XPathFactory newInstance(final String uri)
         throws XPathFactoryConfigurationException {
 
         if (uri == null) {
-                throw new NullPointerException(
-                        "XPathFactory#newInstance(String uri) cannot be called with uri == null"
-                );
+            throw new NullPointerException(
+                    "XPathFactory#newInstance(String uri) cannot be called with uri == null");
         }
 
-                if (uri.length() == 0) {
-                        throw new IllegalArgumentException(
-                                "XPathFactory#newInstance(String uri) cannot be called with uri == \"\""
-                        );
-                }
+        if (uri.length() == 0) {
+            throw new IllegalArgumentException(
+                    "XPathFactory#newInstance(String uri) cannot be called with uri == \"\"");
+        }
 
-                ClassLoader classLoader = ss.getContextClassLoader();
+        ClassLoader classLoader = ss.getContextClassLoader();
 
         if (classLoader == null) {
             //use the current class loader
             classLoader = XPathFactory.class.getClassLoader();
         }
 
-                XPathFactory xpathFactory = new XPathFactoryFinder(classLoader).newFactory(uri);
+        XPathFactory xpathFactory = new XPathFactoryFinder(classLoader).newFactory(uri);
 
-                if (xpathFactory == null) {
-                        throw new XPathFactoryConfigurationException(
-                                "No XPathFactory implementation found for the object model: "
-                                + uri
-                        );
-                }
+        if (xpathFactory == null) {
+            throw new XPathFactoryConfigurationException(
+                    "No XPathFactory implementation found for the object model: "
+                    + uri);
+        }
 
-                return xpathFactory;
+        return xpathFactory;
     }
 
     /**
@@ -242,16 +243,14 @@
         ClassLoader cl = classLoader;
 
         if (uri == null) {
-                throw new NullPointerException(
-                        "XPathFactory#newInstance(String uri) cannot be called with uri == null"
-                );
+            throw new NullPointerException(
+                    "XPathFactory#newInstance(String uri) cannot be called with uri == null");
         }
 
-                if (uri.length() == 0) {
-                        throw new IllegalArgumentException(
-                                "XPathFactory#newInstance(String uri) cannot be called with uri == \"\""
-                        );
-                }
+        if (uri.length() == 0) {
+            throw new IllegalArgumentException(
+                    "XPathFactory#newInstance(String uri) cannot be called with uri == \"\"");
+        }
 
         if (cl == null) {
             cl = ss.getContextClassLoader();
@@ -260,31 +259,32 @@
         XPathFactory f = new XPathFactoryFinder(cl).createInstance(factoryClassName);
 
         if (f == null) {
-                        throw new XPathFactoryConfigurationException(
-                                "No XPathFactory implementation found for the object model: "
-                                + uri
-                        );
+            throw new XPathFactoryConfigurationException(
+                    "No XPathFactory implementation found for the object model: "
+                    + uri);
         }
         //if this factory supports the given schemalanguage return this factory else thrown exception
-        if(f.isObjectModelSupported(uri)){
+        if (f.isObjectModelSupported(uri)) {
             return f;
-        }else{
-            throw new XPathFactoryConfigurationException("Factory " + factoryClassName + " doesn't support given " + uri + " object model");
+        } else {
+            throw new XPathFactoryConfigurationException("Factory "
+                    + factoryClassName + " doesn't support given " + uri
+                    + " object model");
         }
 
     }
 
-        /**
-         * <p>Is specified object model supported by this <code>XPathFactory</code>?</p>
-         *
-         * @param objectModel Specifies the object model which the returned <code>XPathFactory</code> will understand.
-         *
-         * @return <code>true</code> if <code>XPathFactory</code> supports <code>objectModel</code>, else <code>false</code>.
-         *
-         * @throws NullPointerException If <code>objectModel</code> is <code>null</code>.
-         * @throws IllegalArgumentException If <code>objectModel.length() == 0</code>.
-         */
-        public abstract boolean isObjectModelSupported(String objectModel);
+    /**
+     * <p>Is specified object model supported by this <code>XPathFactory</code>?</p>
+     *
+     * @param objectModel Specifies the object model which the returned <code>XPathFactory</code> will understand.
+     *
+     * @return <code>true</code> if <code>XPathFactory</code> supports <code>objectModel</code>, else <code>false</code>.
+     *
+     * @throws NullPointerException If <code>objectModel</code> is <code>null</code>.
+     * @throws IllegalArgumentException If <code>objectModel.length() == 0</code>.
+     */
+    public abstract boolean isObjectModelSupported(String objectModel);
 
     /**
      * <p>Set a feature for this <code>XPathFactory</code> and
@@ -314,8 +314,8 @@
      *   it creates cannot support this feature.
      * @throws NullPointerException if <code>name</code> is <code>null</code>.
      */
-        public abstract void setFeature(String name, boolean value)
-                throws XPathFactoryConfigurationException;
+    public abstract void setFeature(String name, boolean value)
+            throws XPathFactoryConfigurationException;
 
     /**
      * <p>Get the state of the named feature.</p>
@@ -339,8 +339,8 @@
      *   it creates cannot support this feature.
      * @throws NullPointerException if <code>name</code> is <code>null</code>.
      */
-        public abstract boolean getFeature(String name)
-                throws XPathFactoryConfigurationException;
+    public abstract boolean getFeature(String name)
+            throws XPathFactoryConfigurationException;
 
     /**
      * <p>Establish a default variable resolver.</p>
@@ -359,19 +359,19 @@
     public abstract void setXPathVariableResolver(XPathVariableResolver resolver);
 
     /**
-       * <p>Establish a default function resolver.</p>
-       *
-       * <p>Any <code>XPath</code> objects constructed from this factory will
-       * use the specified resolver by default.</p>
-       *
-       * <p>A <code>NullPointerException</code> is thrown if
-       * <code>resolver</code> is <code>null</code>.</p>
-       *
-       * @param resolver XPath function resolver.
-       *
-       * @throws NullPointerException If <code>resolver</code> is
-       *   <code>null</code>.
-       */
+     * <p>Establish a default function resolver.</p>
+     *
+     * <p>Any <code>XPath</code> objects constructed from this factory will
+     * use the specified resolver by default.</p>
+     *
+     * <p>A <code>NullPointerException</code> is thrown if
+     * <code>resolver</code> is <code>null</code>.</p>
+     *
+     * @param resolver XPath function resolver.
+     *
+     * @throws NullPointerException If <code>resolver</code> is
+     *   <code>null</code>.
+     */
     public abstract void setXPathFunctionResolver(XPathFunctionResolver resolver);
 
     /**
--- a/src/javax/xml/xpath/XPathFactoryFinder.java	Fri Apr 12 10:20:32 2013 +0100
+++ b/src/javax/xml/xpath/XPathFactoryFinder.java	Wed Apr 17 15:23:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,20 +25,16 @@
 
 package javax.xml.xpath;
 
-import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
 import java.lang.reflect.Method;
-import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
 import java.net.URL;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.Properties;
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
 
 /**
  * Implementation of {@link XPathFactory#newInstance(String)}.
@@ -50,7 +46,7 @@
 class XPathFactoryFinder  {
     private static final String DEFAULT_PACKAGE = "com.sun.org.apache.xpath.internal";
 
-    private static SecuritySupport ss = new SecuritySupport() ;
+    private static final SecuritySupport ss = new SecuritySupport() ;
     /** debug support code. */
     private static boolean debug = false;
     static {
@@ -65,12 +61,12 @@
     /**
      * <p>Cache properties for performance.</p>
      */
-        private static Properties cacheProps = new Properties();
+    private static final Properties cacheProps = new Properties();
 
-        /**
-         * <p>First time requires initialization overhead.</p>
-         */
-        private volatile static boolean firstTime = true;
+    /**
+     * <p>First time requires initialization overhead.</p>
+     */
+    private volatile static boolean firstTime = true;
 
     /**
      * <p>Conditional debug printing.</p>
@@ -93,9 +89,8 @@
      * to find <code>XPathFactory</code>.</p>
      *
      * @param loader
-     *      to be used to load resource, {@link XPathFactory}, and
-     *      {@link SchemaFactoryLoader} implementations during
-     *      the resolution process.
+     *      to be used to load resource and {@link XPathFactory}
+     *      implementations during the resolution process.
      *      If this parameter is null, the default system class loader
      *      will be used.
      */
@@ -113,7 +108,7 @@
                 return;
             }
         } catch( Throwable unused ) {
-            ; // getContextClassLoader() undefined in JDK1.1
+             // getContextClassLoader() undefined in JDK1.1
         }
 
         if( classLoader==ClassLoader.getSystemClassLoader() ) {
@@ -126,7 +121,7 @@
 
     /**
      * <p>Creates a new {@link XPathFactory} object for the specified
-     * schema language.</p>
+     * object model.</p>
      *
      * @param uri
      *       Identifies the underlying object model.
@@ -136,8 +131,10 @@
      * @throws NullPointerException
      *      If the parameter is null.
      */
-    public XPathFactory newFactory(String uri) {
-        if(uri==null)        throw new NullPointerException();
+    public XPathFactory newFactory(String uri) throws XPathFactoryConfigurationException {
+        if (uri == null) {
+            throw new NullPointerException();
+        }
         XPathFactory f = _newFactory(uri);
         if (f != null) {
             debugPrintln("factory '" + f.getClass().getName() + "' was found for " + uri);
@@ -154,8 +151,8 @@
      *
      * @return {@link XPathFactory} for the given object model.
      */
-    private XPathFactory _newFactory(String uri) {
-        XPathFactory xpathFactory;
+    private XPathFactory _newFactory(String uri) throws XPathFactoryConfigurationException {
+        XPathFactory xpathFactory = null;
 
         String propertyName = SERVICE_CLASS.getName() + ":" + uri;
 
@@ -166,7 +163,9 @@
             if(r!=null) {
                 debugPrintln("The value is '"+r+"'");
                 xpathFactory = createInstance(r, true);
-                if(xpathFactory != null)    return xpathFactory;
+                if (xpathFactory != null) {
+                    return xpathFactory;
+                }
             } else
                 debugPrintln("The property is undefined.");
         } catch( Throwable t ) {
@@ -180,8 +179,6 @@
         String configFile = javah + File.separator +
         "lib" + File.separator + "jaxp.properties";
 
-        String factoryClassName = null ;
-
         // try to read from $java.home/lib/jaxp.properties
         try {
             if(firstTime){
@@ -196,7 +193,7 @@
                     }
                 }
             }
-            factoryClassName = cacheProps.getProperty(propertyName);
+            final String factoryClassName = cacheProps.getProperty(propertyName);
             debugPrintln("found " + factoryClassName + " in $java.home/jaxp.properties");
 
             if (factoryClassName != null) {
@@ -211,23 +208,16 @@
             }
         }
 
-        // try META-INF/services files
-        Iterator sitr = createServiceFileIterator();
-        while(sitr.hasNext()) {
-            URL resource = (URL)sitr.next();
-            debugPrintln("looking into " + resource);
-            try {
-                xpathFactory = loadFromService(uri, resource.toExternalForm(),
-                                                ss.getURLInputStream(resource));
-                if (xpathFactory != null) {
-                    return xpathFactory;
-                }
-            } catch(IOException e) {
-                if( debug ) {
-                    debugPrintln("failed to read "+resource);
-                    e.printStackTrace();
-                }
-            }
+        // Try with ServiceLoader
+        assert xpathFactory == null;
+        xpathFactory = findServiceProvider(uri);
+
+        // The following assertion should always be true.
+        // Uncomment it, recompile, and run with -ea in case of doubts:
+        // assert xpathFactory == null || xpathFactory.isObjectModelSupported(uri);
+
+        if (xpathFactory != null) {
+            return xpathFactory;
         }
 
         // platform default
@@ -245,8 +235,8 @@
      * @param className Name of class to create.
      * @return Created class or <code>null</code>.
      */
-    private Class createClass(String className) {
-            Class clazz;
+    private Class<?> createClass(String className) {
+        Class clazz;
         // make sure we have access to restricted packages
         boolean internal = false;
         if (System.getSecurityManager() != null) {
@@ -258,47 +248,54 @@
         // use approprite ClassLoader
         try {
             if (classLoader != null && !internal) {
-                    clazz = classLoader.loadClass(className);
+                    clazz = Class.forName(className, false, classLoader);
             } else {
                     clazz = Class.forName(className);
             }
         } catch (Throwable t) {
-            if(debug)   t.printStackTrace();
-                return null;
+            if(debug) {
+                t.printStackTrace();
+            }
+            return null;
         }
 
-            return clazz;
+        return clazz;
     }
 
     /**
      * <p>Creates an instance of the specified and returns it.</p>
      *
      * @param className
-     *      fully qualified class name to be instanciated.
+     *      fully qualified class name to be instantiated.
      *
      * @return null
      *      if it fails. Error messages will be printed by this method.
      */
-    XPathFactory createInstance( String className ) {
+    XPathFactory createInstance( String className )
+            throws XPathFactoryConfigurationException
+    {
         return createInstance( className, false );
     }
-    XPathFactory createInstance( String className, boolean useServicesMechanism  ) {
+
+    XPathFactory createInstance( String className, boolean useServicesMechanism  )
+            throws XPathFactoryConfigurationException
+    {
         XPathFactory xPathFactory = null;
 
         debugPrintln("createInstance(" + className + ")");
 
         // get Class from className
-        Class clazz = createClass(className);
+        Class<?> clazz = createClass(className);
         if (clazz == null) {
-                debugPrintln("failed to getClass(" + className + ")");
-                return null;
+            debugPrintln("failed to getClass(" + className + ")");
+            return null;
         }
         debugPrintln("loaded " + className + " from " + which(clazz));
 
         // instantiate Class as a XPathFactory
         try {
             if (!useServicesMechanism) {
-                xPathFactory = (XPathFactory) newInstanceNoServiceLoader(clazz);
+                xPathFactory = newInstanceNoServiceLoader(clazz);
             }
             if (xPathFactory == null) {
                 xPathFactory = (XPathFactory) clazz.newInstance();
@@ -329,203 +326,94 @@
      * Try to construct using newXPathFactoryNoServiceLoader
      *   method if available.
      */
-    private static Object newInstanceNoServiceLoader(
+    private static XPathFactory newInstanceNoServiceLoader(
          Class<?> providerClass
-    ) {
+    ) throws XPathFactoryConfigurationException {
         // Retain maximum compatibility if no security manager.
         if (System.getSecurityManager() == null) {
             return null;
         }
         try {
             Method creationMethod =
-                providerClass.getDeclaredMethod(
-                    "newXPathFactoryNoServiceLoader"
-                );
-                return creationMethod.invoke(null, (Object[])null);
-            } catch (NoSuchMethodException exc) {
-                return null;
-            } catch (Exception exc) {
-                return null;
-        }
-    }
-
-    /**
-     * <p>Look up a value in a property file.</p>
-     *
-     * <p>Set <code>debug</code> to <code>true</code> to trace property evaluation.</p>
-     *
-     * @param objectModel URI of object model to support.
-     * @param inputName Name of <code>InputStream</code>.
-     * @param in <code>InputStream</code> of properties.
-     *
-     * @return <code>XPathFactory</code> as determined by <code>keyName</code> value or <code>null</code> if there was an error.
-     *
-     * @throws IOException If IO error reading from <code>in</code>.
-     */
-    private XPathFactory loadFromService(
-            String objectModel,
-            String inputName,
-            InputStream in)
-            throws IOException {
-
-            XPathFactory xPathFactory = null;
-            final Class[] stringClassArray = {"".getClass()};
-            final Object[] objectModelObjectArray = {objectModel};
-            final String isObjectModelSupportedMethod = "isObjectModelSupported";
-
-            debugPrintln("Reading " + inputName);
+                    providerClass.getDeclaredMethod(
+                        "newXPathFactoryNoServiceLoader"
+                    );
+            final int modifiers = creationMethod.getModifiers();
 
-            // read from InputStream until a match is found
-            BufferedReader configFile = new BufferedReader(new InputStreamReader(in));
-            String line = null;
-            while ((line = configFile.readLine()) != null) {
-                    // '#' is comment char
-                    int comment = line.indexOf("#");
-                    switch (comment) {
-                            case -1: break; // no comment
-                            case 0: line = ""; break; // entire line is a comment
-                            default: line = line.substring(0, comment); break; // trim comment
-                    }
-
-                    // trim whitespace
-                    line = line.trim();
-
-                    // any content left on line?
-                    if (line.length() == 0) {
-                            continue;
-                    }
-
-                    // line content is now the name of the class
-                    Class clazz = createClass(line);
-                    if (clazz == null) {
-                            continue;
-                    }
-
-                    // create an instance of the Class
-                    try {
-                            xPathFactory = (XPathFactory) clazz.newInstance();
-                    } catch (ClassCastException classCastExcpetion) {
-                            xPathFactory = null;
-                            continue;
-                    } catch (InstantiationException instantiationException) {
-                            xPathFactory = null;
-                            continue;
-                    } catch (IllegalAccessException illegalAccessException) {
-                            xPathFactory = null;
-                            continue;
-                    }
-
-                    // does this Class support desired object model?
-                    try {
-                            Method isObjectModelSupported = clazz.getMethod(isObjectModelSupportedMethod, stringClassArray);
-                            Boolean supported = (Boolean) isObjectModelSupported.invoke(xPathFactory, objectModelObjectArray);
-                            if (supported.booleanValue()) {
-                                    break;
-                            }
-
-                    } catch (NoSuchMethodException noSuchMethodException) {
-
-                    } catch (IllegalAccessException illegalAccessException) {
-
-                    } catch (InvocationTargetException invocationTargetException) {
-
-                    }
-                    xPathFactory = null;
+            // Do not call "newXPathFactoryNoServiceLoader" if it's
+            // not public static.
+            if (!Modifier.isStatic(modifiers) || !Modifier.isPublic(modifiers)) {
+                return null;
             }
 
-            // clean up
-            configFile.close();
-
-            // return new instance of XPathFactory or null
-            return xPathFactory;
-    }
-
-    /** Iterator that lazily computes one value and returns it. */
-    private static abstract class SingleIterator implements Iterator {
-        private boolean seen = false;
-
-        public final void remove() { throw new UnsupportedOperationException(); }
-        public final boolean hasNext() { return !seen; }
-        public final Object next() {
-            if(seen)    throw new NoSuchElementException();
-            seen = true;
-            return value();
-        }
-
-        protected abstract Object value();
-    }
-
-    /**
-     * Looks up a value in a property file
-     * while producing all sorts of debug messages.
-     *
-     * @return null
-     *      if there was an error.
-     */
-    private XPathFactory loadFromProperty( String keyName, String resourceName, InputStream in )
-        throws IOException {
-        debugPrintln("Reading "+resourceName );
-
-        Properties props = new Properties();
-        props.load(in);
-        in.close();
-        String factoryClassName = props.getProperty(keyName);
-        if(factoryClassName != null){
-            debugPrintln("found "+keyName+" = " + factoryClassName);
-            return createInstance(factoryClassName, true);
-        } else {
-            debugPrintln(keyName+" is not in the property file");
+            // Only calls "newXPathFactoryNoServiceLoader" if it's
+            // declared to return an instance of XPathFactory.
+            final Class<?> returnType = creationMethod.getReturnType();
+            if (SERVICE_CLASS.isAssignableFrom(returnType)) {
+                return SERVICE_CLASS.cast(creationMethod.invoke(null, (Object[])null));
+            } else {
+                // Should not happen since
+                // XPathFactoryImpl.newXPathFactoryNoServiceLoader is
+                // declared to return XPathFactory.
+                throw new ClassCastException(returnType
+                            + " cannot be cast to " + SERVICE_CLASS);
+            }
+        } catch (ClassCastException e) {
+            throw new XPathFactoryConfigurationException(e);
+        } catch (NoSuchMethodException exc) {
+            return null;
+        } catch (Exception exc) {
             return null;
         }
     }
 
+    // Call isObjectModelSupportedBy with initial context.
+    private boolean isObjectModelSupportedBy(final XPathFactory factory,
+            final String objectModel,
+            AccessControlContext acc) {
+        return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+                    public Boolean run() {
+                        return factory.isObjectModelSupported(objectModel);
+                    }
+                }, acc);
+    }
+
     /**
-     * Returns an {@link Iterator} that enumerates all
-     * the META-INF/services files that we care.
+     * Finds a service provider subclass of XPathFactory that supports the
+     * given object model using the ServiceLoader.
+     *
+     * @param objectModel URI of object model to support.
+     * @return An XPathFactory supporting the specified object model, or null
+     *         if none is found.
+     * @throws XPathFactoryConfigurationException if a configuration error is found.
      */
-    private Iterator createServiceFileIterator() {
-        if (classLoader == null) {
-            return new SingleIterator() {
-                protected Object value() {
-                    ClassLoader classLoader = XPathFactoryFinder.class.getClassLoader();
-                    return ss.getResourceAsURL(classLoader, SERVICE_ID);
-                    //return (ClassLoader.getSystemResource( SERVICE_ID ));
-                }
-            };
-        } else {
-            try {
-                //final Enumeration e = classLoader.getResources(SERVICE_ID);
-                final Enumeration e = ss.getResources(classLoader, SERVICE_ID);
-                if(!e.hasMoreElements()) {
-                    debugPrintln("no "+SERVICE_ID+" file was found");
+    private XPathFactory findServiceProvider(final String objectModel)
+            throws XPathFactoryConfigurationException {
+
+        assert objectModel != null;
+        // store current context.
+        final AccessControlContext acc = AccessController.getContext();
+        try {
+            return AccessController.doPrivileged(new PrivilegedAction<XPathFactory>() {
+                public XPathFactory run() {
+                    final ServiceLoader<XPathFactory> loader =
+                            ServiceLoader.load(SERVICE_CLASS);
+                    for (XPathFactory factory : loader) {
+                        // restore initial context to call
+                        // factory.isObjectModelSupportedBy
+                        if (isObjectModelSupportedBy(factory, objectModel, acc)) {
+                            return factory;
+                        }
+                    }
+                    return null; // no factory found.
                 }
-
-                // wrap it into an Iterator.
-                return new Iterator() {
-                    public void remove() {
-                        throw new UnsupportedOperationException();
-                    }
-
-                    public boolean hasNext() {
-                        return e.hasMoreElements();
-                    }
-
-                    public Object next() {
-                        return e.nextElement();
-                    }
-                };
-            } catch (IOException e) {
-                debugPrintln("failed to enumerate resources "+SERVICE_ID);
-                if(debug)   e.printStackTrace();
-                return new ArrayList().iterator();  // empty iterator
-            }
+            });
+        } catch (ServiceConfigurationError error) {
+            throw new XPathFactoryConfigurationException(error);
         }
     }
 
-    private static final Class SERVICE_CLASS = XPathFactory.class;
-    private static final String SERVICE_ID = "META-INF/services/" + SERVICE_CLASS.getName();
-
-
+    private static final Class<XPathFactory> SERVICE_CLASS = XPathFactory.class;
 
     private static String which( Class clazz ) {
         return which( clazz.getName(), clazz.getClassLoader() );