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