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