1/* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 */ 4/* 5 * Licensed to the Apache Software Foundation (ASF) under one or more 6 * contributor license agreements. See the NOTICE file distributed with 7 * this work for additional information regarding copyright ownership. 8 * The ASF licenses this file to You under the Apache License, Version 2.0 9 * (the "License"); you may not use this file except in compliance with 10 * the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21package com.sun.org.apache.xpath.internal.jaxp; 22 23import com.sun.org.apache.xalan.internal.XalanConstants; 24import com.sun.org.apache.xalan.internal.res.XSLMessages; 25import com.sun.org.apache.xpath.internal.res.XPATHErrorResources; 26import javax.xml.XMLConstants; 27import javax.xml.xpath.XPathFactory; 28import javax.xml.xpath.XPathFactoryConfigurationException; 29import javax.xml.xpath.XPathFunctionResolver; 30import javax.xml.xpath.XPathVariableResolver; 31import jdk.xml.internal.JdkXmlFeatures; 32 33/** 34 * The XPathFactory builds XPaths. 35 * 36 * @author Ramesh Mandava 37 */ 38public class XPathFactoryImpl extends XPathFactory { 39 40 /** 41 * <p>Name of class as a constant to use for debugging.</p> 42 */ 43 private static final String CLASS_NAME = "XPathFactoryImpl"; 44 45 /** 46 *<p>XPathFunctionResolver for this XPathFactory and created XPaths.</p> 47 */ 48 private XPathFunctionResolver xPathFunctionResolver = null; 49 50 /** 51 * <p>XPathVariableResolver for this XPathFactory and created XPaths</p> 52 */ 53 private XPathVariableResolver xPathVariableResolver = null; 54 55 /** 56 * <p>State of secure processing feature.</p> 57 */ 58 private boolean _isNotSecureProcessing = true; 59 /** 60 * <p>State of secure mode.</p> 61 */ 62 private boolean _isSecureMode = false; 63 /** 64 * javax.xml.xpath.XPathFactory implementation. 65 */ 66 67 private boolean _useServicesMechanism = true; 68 69 private final JdkXmlFeatures _featureManager; 70 71 public XPathFactoryImpl() { 72 this(true); 73 } 74 75 public static XPathFactory newXPathFactoryNoServiceLoader() { 76 return new XPathFactoryImpl(false); 77 } 78 79 public XPathFactoryImpl(boolean useServicesMechanism) { 80 if (System.getSecurityManager() != null) { 81 _isSecureMode = true; 82 _isNotSecureProcessing = false; 83 } 84 _featureManager = new JdkXmlFeatures(!_isNotSecureProcessing); 85 this._useServicesMechanism = useServicesMechanism; 86 } 87 /** 88 * <p>Is specified object model supported by this 89 * <code>XPathFactory</code>?</p> 90 * 91 * @param objectModel Specifies the object model which the returned 92 * <code>XPathFactory</code> will understand. 93 * 94 * @return <code>true</code> if <code>XPathFactory</code> supports 95 * <code>objectModel</code>, else <code>false</code>. 96 * 97 * @throws NullPointerException If <code>objectModel</code> is <code>null</code>. 98 * @throws IllegalArgumentException If <code>objectModel.length() == 0</code>. 99 */ 100 public boolean isObjectModelSupported(String objectModel) { 101 102 if (objectModel == null) { 103 String fmsg = XSLMessages.createXPATHMessage( 104 XPATHErrorResources.ER_OBJECT_MODEL_NULL, 105 new Object[] { this.getClass().getName() } ); 106 107 throw new NullPointerException( fmsg ); 108 } 109 110 if (objectModel.length() == 0) { 111 String fmsg = XSLMessages.createXPATHMessage( 112 XPATHErrorResources.ER_OBJECT_MODEL_EMPTY, 113 new Object[] { this.getClass().getName() } ); 114 throw new IllegalArgumentException( fmsg ); 115 } 116 117 // know how to support default object model, W3C DOM 118 if (objectModel.equals(XPathFactory.DEFAULT_OBJECT_MODEL_URI)) { 119 return true; 120 } 121 122 // don't know how to support anything else 123 return false; 124 } 125 126 /** 127 * <p>Returns a new <code>XPath</code> object using the underlying 128 * object model determined when the factory was instantiated.</p> 129 * 130 * @return New <code>XPath</code> 131 */ 132 public javax.xml.xpath.XPath newXPath() { 133 return new com.sun.org.apache.xpath.internal.jaxp.XPathImpl( 134 xPathVariableResolver, xPathFunctionResolver, 135 !_isNotSecureProcessing, _useServicesMechanism, 136 _featureManager ); 137 } 138 139 /** 140 * <p>Set a feature for this <code>XPathFactory</code> and 141 * <code>XPath</code>s created by this factory.</p> 142 * 143 * <p> 144 * Feature names are fully qualified {@link java.net.URI}s. 145 * Implementations may define their own features. 146 * An {@link XPathFactoryConfigurationException} is thrown if this 147 * <code>XPathFactory</code> or the <code>XPath</code>s 148 * it creates cannot support the feature. 149 * It is possible for an <code>XPathFactory</code> to expose a feature 150 * value but be unable to change its state. 151 * </p> 152 * 153 * <p>See {@link javax.xml.xpath.XPathFactory} for full documentation 154 * of specific features.</p> 155 * 156 * @param name Feature name. 157 * @param value Is feature state <code>true</code> or <code>false</code>. 158 * 159 * @throws XPathFactoryConfigurationException if this 160 * <code>XPathFactory</code> or the <code>XPath</code>s 161 * it creates cannot support this feature. 162 * @throws NullPointerException if <code>name</code> is 163 * <code>null</code>. 164 */ 165 public void setFeature(String name, boolean value) 166 throws XPathFactoryConfigurationException { 167 168 // feature name cannot be null 169 if (name == null) { 170 String fmsg = XSLMessages.createXPATHMessage( 171 XPATHErrorResources.ER_FEATURE_NAME_NULL, 172 new Object[] { CLASS_NAME, value } ); 173 throw new NullPointerException( fmsg ); 174 } 175 176 // secure processing? 177 if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) { 178 if ((_isSecureMode) && (!value)) { 179 String fmsg = XSLMessages.createXPATHMessage( 180 XPATHErrorResources.ER_SECUREPROCESSING_FEATURE, 181 new Object[] { name, CLASS_NAME, value } ); 182 throw new XPathFactoryConfigurationException( fmsg ); 183 } 184 185 _isNotSecureProcessing = !value; 186 if (value && _featureManager != null) { 187 _featureManager.setFeature(JdkXmlFeatures.XmlFeature.ENABLE_EXTENSION_FUNCTION, 188 JdkXmlFeatures.State.FSP, false); 189 } 190 191 // all done processing feature 192 return; 193 } 194 if (name.equals(XalanConstants.ORACLE_FEATURE_SERVICE_MECHANISM)) { 195 //in secure mode, let _useServicesMechanism be determined by the constructor 196 if (!_isSecureMode) 197 _useServicesMechanism = value; 198 return; 199 } 200 201 if (_featureManager != null && 202 _featureManager.setFeature(name, JdkXmlFeatures.State.APIPROPERTY, value)) { 203 return; 204 } 205 206 // unknown feature 207 String fmsg = XSLMessages.createXPATHMessage( 208 XPATHErrorResources.ER_FEATURE_UNKNOWN, 209 new Object[] { name, CLASS_NAME, value } ); 210 throw new XPathFactoryConfigurationException( fmsg ); 211 } 212 213 /** 214 * <p>Get the state of the named feature.</p> 215 * 216 * <p> 217 * Feature names are fully qualified {@link java.net.URI}s. 218 * Implementations may define their own features. 219 * An {@link XPathFactoryConfigurationException} is thrown if this 220 * <code>XPathFactory</code> or the <code>XPath</code>s 221 * it creates cannot support the feature. 222 * It is possible for an <code>XPathFactory</code> to expose a feature 223 * value but be unable to change its state. 224 * </p> 225 * 226 * @param name Feature name. 227 * 228 * @return State of the named feature. 229 * 230 * @throws XPathFactoryConfigurationException if this 231 * <code>XPathFactory</code> or the <code>XPath</code>s 232 * it creates cannot support this feature. 233 * @throws NullPointerException if <code>name</code> is 234 * <code>null</code>. 235 */ 236 public boolean getFeature(String name) 237 throws XPathFactoryConfigurationException { 238 239 // feature name cannot be null 240 if (name == null) { 241 String fmsg = XSLMessages.createXPATHMessage( 242 XPATHErrorResources.ER_GETTING_NULL_FEATURE, 243 new Object[] { CLASS_NAME } ); 244 throw new NullPointerException( fmsg ); 245 } 246 247 // secure processing? 248 if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) { 249 return !_isNotSecureProcessing; 250 } 251 if (name.equals(XalanConstants.ORACLE_FEATURE_SERVICE_MECHANISM)) { 252 return _useServicesMechanism; 253 } 254 255 /** Check to see if the property is managed by the feature manager **/ 256 int index = _featureManager.getIndex(name); 257 if (index > -1) { 258 return _featureManager.getFeature(index); 259 } 260 261 // unknown feature 262 String fmsg = XSLMessages.createXPATHMessage( 263 XPATHErrorResources.ER_GETTING_UNKNOWN_FEATURE, 264 new Object[] { name, CLASS_NAME } ); 265 266 throw new XPathFactoryConfigurationException( fmsg ); 267 } 268 269 /** 270 * <p>Establish a default function resolver.</p> 271 * 272 * <p>Any <code>XPath</code> objects constructed from this factory will use 273 * the specified resolver by default.</p> 274 * 275 * <p>A <code>NullPointerException</code> is thrown if 276 * <code>resolver</code> is <code>null</code>.</p> 277 * 278 * @param resolver XPath function resolver. 279 * 280 * @throws NullPointerException If <code>resolver</code> is 281 * <code>null</code>. 282 */ 283 public void setXPathFunctionResolver(XPathFunctionResolver resolver) { 284 285 // resolver cannot be null 286 if (resolver == null) { 287 String fmsg = XSLMessages.createXPATHMessage( 288 XPATHErrorResources.ER_NULL_XPATH_FUNCTION_RESOLVER, 289 new Object[] { CLASS_NAME } ); 290 throw new NullPointerException( fmsg ); 291 } 292 293 xPathFunctionResolver = resolver; 294 } 295 296 /** 297 * <p>Establish a default variable resolver.</p> 298 * 299 * <p>Any <code>XPath</code> objects constructed from this factory will use 300 * the specified resolver by default.</p> 301 * 302 * <p>A <code>NullPointerException</code> is thrown if <code>resolver</code> is <code>null</code>.</p> 303 * 304 * @param resolver Variable resolver. 305 * 306 * @throws NullPointerException If <code>resolver</code> is 307 * <code>null</code>. 308 */ 309 public void setXPathVariableResolver(XPathVariableResolver resolver) { 310 311 // resolver cannot be null 312 if (resolver == null) { 313 String fmsg = XSLMessages.createXPATHMessage( 314 XPATHErrorResources.ER_NULL_XPATH_VARIABLE_RESOLVER, 315 new Object[] { CLASS_NAME } ); 316 throw new NullPointerException( fmsg ); 317 } 318 319 xPathVariableResolver = resolver; 320 } 321} 322