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