• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@Sun.com">Norman Walsh</a>
28   * @author  <a href="mailto:Jeff.Suttor@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       */
XPathFactory()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       */
newInstance()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      */
newInstance(final String uri)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       */
newInstance(String uri, String factoryClassName, ClassLoader classLoader)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       */
isObjectModelSupported(String objectModel)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       */
setFeature(String name, boolean value)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       */
getFeature(String name)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       */
setXPathVariableResolver(XPathVariableResolver resolver)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         */
setXPathFunctionResolver(XPathFunctionResolver resolver)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      */
newXPath()287      public abstract XPath newXPath();
288  }
289