Home | History | Annotate | Download | only in xpath
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one or more
      3  * contributor license agreements.  See the NOTICE file distributed with
      4  * this work for additional information regarding copyright ownership.
      5  * The ASF licenses this file to You under the Apache License, Version 2.0
      6  * (the "License"); you may not use this file except in compliance with
      7  * the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 // $Id: XPathFactory.java 888889 2009-12-09 17:43:18Z mrglavas $
     18 
     19 package javax.xml.xpath;
     20 
     21 /**
     22  * <p>An <code>XPathFactory</code> instance can be used to create
     23  * {@link javax.xml.xpath.XPath} objects.</p>
     24  *
     25  *<p>See {@link #newInstance(String uri)} for lookup mechanism.</p>
     26  *
     27  * @author  <a href="mailto:Norman.Walsh (at) Sun.com">Norman Walsh</a>
     28  * @author  <a href="mailto:Jeff.Suttor (at) Sun.com">Jeff Suttor</a>
     29  * @version $Revision: 888889 $, $Date: 2009-12-09 09:43:18 -0800 (Wed, 09 Dec 2009) $
     30  * @since 1.5
     31  */
     32 public abstract class XPathFactory {
     33 
     34 
     35     /**
     36      * <p>The default property name according to the JAXP spec.</p>
     37      */
     38     public static final String DEFAULT_PROPERTY_NAME = "javax.xml.xpath.XPathFactory";
     39 
     40     /**
     41      * <p>Default Object Model URI.</p>
     42      */
     43     public static final String DEFAULT_OBJECT_MODEL_URI = "http://java.sun.com/jaxp/xpath/dom";
     44 
     45     /**
     46      * <p>Protected constructor as {@link #newInstance()}, {@link #newInstance(String uri)}
     47      * or {@link #newInstance(String uri, String factoryClassName, ClassLoader classLoader)}
     48      * should be used to create a new instance of an <code>XPathFactory</code>.</p>
     49      */
     50     protected XPathFactory() {
     51     }
     52 
     53     /**
     54      * <p>Get a new <code>XPathFactory</code> instance using the default object model,
     55      * {@link #DEFAULT_OBJECT_MODEL_URI},
     56      * the W3C DOM.</p>
     57      *
     58      * <p>This method is functionally equivalent to:</p>
     59      * <pre>
     60      *   newInstance(DEFAULT_OBJECT_MODEL_URI)
     61      * </pre>
     62      *
     63      * <p>Since the implementation for the W3C DOM is always available, this method will never fail.</p>
     64      *
     65      * @return Instance of an <code>XPathFactory</code>.
     66      */
     67     public static final XPathFactory newInstance() {
     68         try {
     69             return newInstance(DEFAULT_OBJECT_MODEL_URI);
     70         }
     71         catch (XPathFactoryConfigurationException xpathFactoryConfigurationException) {
     72             throw new RuntimeException(
     73                 "XPathFactory#newInstance() failed to create an XPathFactory for the default object model: "
     74                 + DEFAULT_OBJECT_MODEL_URI
     75                 + " with the XPathFactoryConfigurationException: "
     76                 + xpathFactoryConfigurationException.toString()
     77             );
     78         }
     79     }
     80 
     81     /**
     82     * <p>Get a new <code>XPathFactory</code> instance using the specified object model.</p>
     83     *
     84     * <p>To find a <code>XPathFactory</code> object,
     85     * this method looks the following places in the following order where "the class loader" refers to the context class loader:</p>
     86     * <ol>
     87     *   <li>
     88     *     If the system property {@link #DEFAULT_PROPERTY_NAME} + ":uri" is present,
     89     *     where uri is the parameter to this method, then its value is read as a class name.
     90     *     The method will try to create a new instance of this class by using the class loader,
     91     *     and returns it if it is successfully created.
     92     *   </li>
     93     *   <li>
     94     *     ${java.home}/lib/jaxp.properties is read and the value associated with the key being the system property above is looked for.
     95     *     If present, the value is processed just like above.
     96     *   </li>
     97     *   <li>
     98     *     The class loader is asked for service provider provider-configuration files matching <code>javax.xml.xpath.XPathFactory</code>
     99     *     in the resource directory META-INF/services.
    100     *     See the JAR File Specification for file format and parsing rules.
    101     *     Each potential service provider is required to implement the method:
    102     *     <pre>
    103     *       {@link #isObjectModelSupported(String objectModel)}
    104     *     </pre>
    105     *     The first service provider found in class loader order that supports the specified object model is returned.
    106     *   </li>
    107     *   <li>
    108     *     Platform default <code>XPathFactory</code> is located in a platform specific way.
    109     *     There must be a platform default XPathFactory for the W3C DOM, i.e. {@link #DEFAULT_OBJECT_MODEL_URI}.
    110     *   </li>
    111     * </ol>
    112     * <p>If everything fails, an <code>XPathFactoryConfigurationException</code> will be thrown.</p>
    113     *
    114     * <p>Tip for Trouble-shooting:</p>
    115     * <p>See {@link java.util.Properties#load(java.io.InputStream)} for exactly how a property file is parsed.
    116     * In particular, colons ':' need to be escaped in a property file, so make sure the URIs are properly escaped in it.
    117     * For example:</p>
    118     * <pre>
    119     *   http\://java.sun.com/jaxp/xpath/dom=org.acme.DomXPathFactory
    120     * </pre>
    121     *
    122     * @param uri Identifies the underlying object model.
    123     *   The specification only defines the URI {@link #DEFAULT_OBJECT_MODEL_URI},
    124     *   <code>http://java.sun.com/jaxp/xpath/dom</code> for the W3C DOM,
    125     *   the org.w3c.dom package, and implementations are free to introduce other URIs for other object models.
    126     *
    127     * @return Instance of an <code>XPathFactory</code>.
    128     *
    129     * @throws XPathFactoryConfigurationException If the specified object model is unavailable.
    130     * @throws NullPointerException If <code>uri</code> is <code>null</code>.
    131     * @throws IllegalArgumentException If <code>uri.length() == 0</code>.
    132     */
    133     public static final XPathFactory newInstance(final String uri)
    134         throws XPathFactoryConfigurationException {
    135         if (uri == null) {
    136             throw new NullPointerException(
    137                 "XPathFactory#newInstance(String uri) cannot be called with uri == null"
    138             );
    139         }
    140         if (uri.length() == 0) {
    141             throw new IllegalArgumentException(
    142                 "XPathFactory#newInstance(String uri) cannot be called with uri == \"\""
    143             );
    144         }
    145         ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    146         if (classLoader == null) {
    147             //use the current class loader
    148             classLoader = XPathFactory.class.getClassLoader();
    149         }
    150         XPathFactory xpathFactory = new XPathFactoryFinder(classLoader).newFactory(uri);
    151         if (xpathFactory == null) {
    152             throw new XPathFactoryConfigurationException(
    153                 "No XPathFactory implementation found for the object model: "
    154                 + uri
    155             );
    156         }
    157         return xpathFactory;
    158     }
    159 
    160     /**
    161      * @return Instance of an <code>XPathFactory</code>.
    162      *
    163      * @throws XPathFactoryConfigurationException If the specified object model is unavailable.
    164      * @throws NullPointerException If <code>uri</code> is <code>null</code>.
    165      * @throws IllegalArgumentException If <code>uri.length() == 0</code>.
    166      */
    167     public static XPathFactory newInstance(String uri, String factoryClassName,
    168             ClassLoader classLoader) throws XPathFactoryConfigurationException {
    169         if (uri == null) {
    170             throw new NullPointerException(
    171                 "XPathFactory#newInstance(String uri) cannot be called with uri == null"
    172             );
    173         }
    174         if (uri.length() == 0) {
    175             throw new IllegalArgumentException(
    176                 "XPathFactory#newInstance(String uri) cannot be called with uri == \"\""
    177             );
    178         }
    179         if (factoryClassName == null) {
    180             throw new XPathFactoryConfigurationException("factoryClassName cannot be null.");
    181         }
    182         if (classLoader == null) {
    183             classLoader = Thread.currentThread().getContextClassLoader();
    184         }
    185         XPathFactory xpathFactory = new XPathFactoryFinder(classLoader).createInstance(factoryClassName);
    186         if (xpathFactory == null || !xpathFactory.isObjectModelSupported(uri)) {
    187             throw new XPathFactoryConfigurationException(
    188                 "No XPathFactory implementation found for the object model: "
    189                 + uri
    190             );
    191         }
    192         return xpathFactory;
    193     }
    194 
    195     /**
    196      * <p>Is specified object model supported by this <code>XPathFactory</code>?</p>
    197      *
    198      * @param objectModel Specifies the object model which the returned <code>XPathFactory</code> will understand.
    199      *
    200      * @return <code>true</code> if <code>XPathFactory</code> supports <code>objectModel</code>, else <code>false</code>.
    201      *
    202      * @throws NullPointerException If <code>objectModel</code> is <code>null</code>.
    203      * @throws IllegalArgumentException If <code>objectModel.length() == 0</code>.
    204      */
    205     public abstract boolean isObjectModelSupported(String objectModel);
    206 
    207     /**
    208      * <p>Set a feature for this <code>XPathFactory</code> and <code>XPath</code>s created by this factory.</p>
    209      *
    210      * <p>
    211      * Feature names are fully qualified {@link java.net.URI}s.
    212      * Implementations may define their own features.
    213      * An {@link XPathFactoryConfigurationException} is thrown if this <code>XPathFactory</code> or the <code>XPath</code>s
    214      *  it creates cannot support the feature.
    215      * It is possible for an <code>XPathFactory</code> to expose a feature value but be unable to change its state.
    216      * </p>
    217      *
    218      * <p>
    219      * All implementations are required to support the {@link javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING} feature.
    220      * When the feature is <code>true</code>, any reference to  an external function is an error.
    221      * Under these conditions, the implementation must not call the {@link XPathFunctionResolver}
    222      * and must throw an {@link XPathFunctionException}.
    223      * </p>
    224      *
    225      * @param name Feature name.
    226      * @param value Is feature state <code>true</code> or <code>false</code>.
    227      *
    228      * @throws XPathFactoryConfigurationException if this <code>XPathFactory</code> or the <code>XPath</code>s
    229      *   it creates cannot support this feature.
    230      * @throws NullPointerException if <code>name</code> is <code>null</code>.
    231      */
    232     public abstract void setFeature(String name, boolean value)
    233         throws XPathFactoryConfigurationException;
    234 
    235     /**
    236      * <p>Get the state of the named feature.</p>
    237      *
    238      * <p>
    239      * Feature names are fully qualified {@link java.net.URI}s.
    240      * Implementations may define their own features.
    241      * An {@link XPathFactoryConfigurationException} is thrown if this <code>XPathFactory</code> or the <code>XPath</code>s
    242      * it creates cannot support the feature.
    243      * It is possible for an <code>XPathFactory</code> to expose a feature value but be unable to change its state.
    244      * </p>
    245      *
    246      * @param name Feature name.
    247      *
    248      * @return State of the named feature.
    249      *
    250      * @throws XPathFactoryConfigurationException if this <code>XPathFactory</code> or the <code>XPath</code>s
    251      *   it creates cannot support this feature.
    252      * @throws NullPointerException if <code>name</code> is <code>null</code>.
    253      */
    254     public abstract boolean getFeature(String name)
    255         throws XPathFactoryConfigurationException;
    256 
    257     /**
    258      * <p>Establish a default variable resolver.</p>
    259      *
    260      * <p>Any <code>XPath</code> objects constructed from this factory will use
    261      * the specified resolver by default.</p>
    262      *
    263      * <p>A <code>NullPointerException</code> is thrown if <code>resolver</code> is <code>null</code>.</p>
    264      *
    265      * @param resolver Variable resolver.
    266      *
    267      *  @throws NullPointerException If <code>resolver</code> is <code>null</code>.
    268      */
    269     public abstract void setXPathVariableResolver(XPathVariableResolver resolver);
    270 
    271     /**
    272        * <p>Establish a default function resolver.</p>
    273        *
    274        * <p>Any <code>XPath</code> objects constructed from this factory will use
    275        * the specified resolver by default.</p>
    276        *
    277        * <p>A <code>NullPointerException</code> is thrown if <code>resolver</code> is <code>null</code>.</p>
    278        *
    279        * @param resolver XPath function resolver.
    280        *
    281        * @throws NullPointerException If <code>resolver</code> is <code>null</code>.
    282        */
    283     public abstract void setXPathFunctionResolver(XPathFunctionResolver resolver);
    284 
    285     /**
    286     * <p>Return a new <code>XPath</code> using the underlying object
    287     * model determined when the <code>XPathFactory</code> was instantiated.</p>
    288     *
    289     * @return New instance of an <code>XPath</code>.
    290     */
    291     public abstract XPath newXPath();
    292 }
    293