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("uri == null");
    137         }
    138         if (uri.length() == 0) {
    139             throw new IllegalArgumentException(
    140                 "XPathFactory#newInstance(String uri) cannot be called with uri == \"\""
    141             );
    142         }
    143         ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    144         if (classLoader == null) {
    145             //use the current class loader
    146             classLoader = XPathFactory.class.getClassLoader();
    147         }
    148         XPathFactory xpathFactory = new XPathFactoryFinder(classLoader).newFactory(uri);
    149         if (xpathFactory == null) {
    150             throw new XPathFactoryConfigurationException(
    151                 "No XPathFactory implementation found for the object model: "
    152                 + uri
    153             );
    154         }
    155         return xpathFactory;
    156     }
    157 
    158     /**
    159      * @return Instance of an <code>XPathFactory</code>.
    160      *
    161      * @throws XPathFactoryConfigurationException If the specified object model is unavailable.
    162      * @throws NullPointerException If <code>uri</code> is <code>null</code>.
    163      * @throws IllegalArgumentException If <code>uri.length() == 0</code>.
    164      */
    165     public static XPathFactory newInstance(String uri, String factoryClassName,
    166             ClassLoader classLoader) throws XPathFactoryConfigurationException {
    167         if (uri == null) {
    168             throw new NullPointerException("uri == null");
    169         }
    170         if (uri.length() == 0) {
    171             throw new IllegalArgumentException(
    172                 "XPathFactory#newInstance(String uri) cannot be called with uri == \"\""
    173             );
    174         }
    175         if (factoryClassName == null) {
    176             throw new XPathFactoryConfigurationException("factoryClassName cannot be null.");
    177         }
    178         if (classLoader == null) {
    179             classLoader = Thread.currentThread().getContextClassLoader();
    180         }
    181         XPathFactory xpathFactory = new XPathFactoryFinder(classLoader).createInstance(factoryClassName);
    182         if (xpathFactory == null || !xpathFactory.isObjectModelSupported(uri)) {
    183             throw new XPathFactoryConfigurationException(
    184                 "No XPathFactory implementation found for the object model: "
    185                 + uri
    186             );
    187         }
    188         return xpathFactory;
    189     }
    190 
    191     /**
    192      * <p>Is specified object model supported by this <code>XPathFactory</code>?</p>
    193      *
    194      * @param objectModel Specifies the object model which the returned <code>XPathFactory</code> will understand.
    195      *
    196      * @return <code>true</code> if <code>XPathFactory</code> supports <code>objectModel</code>, else <code>false</code>.
    197      *
    198      * @throws NullPointerException If <code>objectModel</code> is <code>null</code>.
    199      * @throws IllegalArgumentException If <code>objectModel.length() == 0</code>.
    200      */
    201     public abstract boolean isObjectModelSupported(String objectModel);
    202 
    203     /**
    204      * <p>Set a feature for this <code>XPathFactory</code> and <code>XPath</code>s created by this factory.</p>
    205      *
    206      * <p>
    207      * Feature names are fully qualified {@link java.net.URI}s.
    208      * Implementations may define their own features.
    209      * An {@link XPathFactoryConfigurationException} is thrown if this <code>XPathFactory</code> or the <code>XPath</code>s
    210      *  it creates cannot support the feature.
    211      * It is possible for an <code>XPathFactory</code> to expose a feature value but be unable to change its state.
    212      * </p>
    213      *
    214      * <p>
    215      * All implementations are required to support the {@link javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING} feature.
    216      * When the feature is <code>true</code>, any reference to  an external function is an error.
    217      * Under these conditions, the implementation must not call the {@link XPathFunctionResolver}
    218      * and must throw an {@link XPathFunctionException}.
    219      * </p>
    220      *
    221      * @param name Feature name.
    222      * @param value Is feature state <code>true</code> or <code>false</code>.
    223      *
    224      * @throws XPathFactoryConfigurationException if this <code>XPathFactory</code> or the <code>XPath</code>s
    225      *   it creates cannot support this feature.
    226      * @throws NullPointerException if <code>name</code> is <code>null</code>.
    227      */
    228     public abstract void setFeature(String name, boolean value)
    229         throws XPathFactoryConfigurationException;
    230 
    231     /**
    232      * <p>Get the state of the named feature.</p>
    233      *
    234      * <p>
    235      * Feature names are fully qualified {@link java.net.URI}s.
    236      * Implementations may define their own features.
    237      * An {@link XPathFactoryConfigurationException} is thrown if this <code>XPathFactory</code> or the <code>XPath</code>s
    238      * it creates cannot support the feature.
    239      * It is possible for an <code>XPathFactory</code> to expose a feature value but be unable to change its state.
    240      * </p>
    241      *
    242      * @param name Feature name.
    243      *
    244      * @return State of the named feature.
    245      *
    246      * @throws XPathFactoryConfigurationException if this <code>XPathFactory</code> or the <code>XPath</code>s
    247      *   it creates cannot support this feature.
    248      * @throws NullPointerException if <code>name</code> is <code>null</code>.
    249      */
    250     public abstract boolean getFeature(String name)
    251         throws XPathFactoryConfigurationException;
    252 
    253     /**
    254      * <p>Establish a default variable resolver.</p>
    255      *
    256      * <p>Any <code>XPath</code> objects constructed from this factory will use
    257      * the specified resolver by default.</p>
    258      *
    259      * <p>A <code>NullPointerException</code> is thrown if <code>resolver</code> is <code>null</code>.</p>
    260      *
    261      * @param resolver Variable resolver.
    262      *
    263      *  @throws NullPointerException If <code>resolver</code> is <code>null</code>.
    264      */
    265     public abstract void setXPathVariableResolver(XPathVariableResolver resolver);
    266 
    267     /**
    268        * <p>Establish a default function resolver.</p>
    269        *
    270        * <p>Any <code>XPath</code> objects constructed from this factory will use
    271        * the specified resolver by default.</p>
    272        *
    273        * <p>A <code>NullPointerException</code> is thrown if <code>resolver</code> is <code>null</code>.</p>
    274        *
    275        * @param resolver XPath function resolver.
    276        *
    277        * @throws NullPointerException If <code>resolver</code> is <code>null</code>.
    278        */
    279     public abstract void setXPathFunctionResolver(XPathFunctionResolver resolver);
    280 
    281     /**
    282     * <p>Return a new <code>XPath</code> using the underlying object
    283     * model determined when the <code>XPathFactory</code> was instantiated.</p>
    284     *
    285     * @return New instance of an <code>XPath</code>.
    286     */
    287     public abstract XPath newXPath();
    288 }
    289