1 /* 2 * Copyright (c) 2010, 2019, 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 21 package com.sun.org.apache.xerces.internal.util; 22 23 import com.sun.org.apache.xerces.internal.impl.Constants; 24 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager; 25 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; 26 import java.util.ArrayList; 27 import java.util.Arrays; 28 import java.util.HashMap; 29 import java.util.List; 30 import java.util.Map; 31 32 /** 33 * This class implements the basic operations for managing parser 34 * configuration features and properties. This utility class can 35 * be used as a base class for parser configurations or separately 36 * to encapsulate a number of parser settings as a component 37 * manager. 38 * <p> 39 * This class can be constructed with a "parent" settings object 40 * (in the form of an <code>XMLComponentManager</code>) that allows 41 * parser configuration settings to be "chained" together. 42 * 43 * @author Andy Clark, IBM 44 * 45 * @LastModified: Apr 2019 46 */ 47 public class ParserConfigurationSettings 48 implements XMLComponentManager { 49 50 protected static final String PARSER_SETTINGS = 51 Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS; 52 53 // 54 // Data 55 // 56 57 // data 58 59 /** Recognized properties. */ 60 protected List<String> fRecognizedProperties; 61 62 /** Properties. */ 63 protected Map<String, Object> fProperties; 64 65 /** Recognized features. */ 66 protected List<String> fRecognizedFeatures; 67 68 /** Features. */ 69 protected Map<String, Boolean> fFeatures; 70 71 /** Parent parser configuration settings. */ 72 protected XMLComponentManager fParentSettings; 73 74 // 75 // Constructors 76 // 77 78 /** Default Constructor. */ ParserConfigurationSettings()79 public ParserConfigurationSettings() { 80 this(null); 81 } // <init>() 82 83 /** 84 * Constructs a parser configuration settings object with a 85 * parent settings object. 86 */ ParserConfigurationSettings(XMLComponentManager parent)87 public ParserConfigurationSettings(XMLComponentManager parent) { 88 89 // create storage for recognized features and properties 90 fRecognizedFeatures = new ArrayList<>(); 91 fRecognizedProperties = new ArrayList<>(); 92 93 // create table for features and properties 94 fFeatures = new HashMap<>(); 95 fProperties = new HashMap<>(); 96 97 // save parent 98 fParentSettings = parent; 99 100 } // <init>(XMLComponentManager) 101 102 // 103 // XMLParserConfiguration methods 104 // 105 106 /** 107 * Allows a parser to add parser specific features to be recognized 108 * and managed by the parser configuration. 109 * 110 * @param featureIds An array of the additional feature identifiers 111 * to be recognized. 112 */ addRecognizedFeatures(String[] featureIds)113 public void addRecognizedFeatures(String[] featureIds) { 114 115 // add recognized features 116 int featureIdsCount = featureIds != null ? featureIds.length : 0; 117 for (int i = 0; i < featureIdsCount; i++) { 118 String featureId = featureIds[i]; 119 if (!fRecognizedFeatures.contains(featureId)) { 120 fRecognizedFeatures.add(featureId); 121 } 122 } 123 124 } // addRecognizedFeatures(String[]) 125 126 /** 127 * Set the state of a feature. 128 * 129 * Set the state of any feature in a SAX2 parser. The parser 130 * might not recognize the feature, and if it does recognize 131 * it, it might not be able to fulfill the request. 132 * 133 * @param featureId The unique identifier (URI) of the feature. 134 * @param state The requested state of the feature (true or false). 135 * 136 * @exception com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException If the 137 * requested feature is not known. 138 */ setFeature(String featureId, boolean state)139 public void setFeature(String featureId, boolean state) 140 throws XMLConfigurationException { 141 142 // check and store 143 FeatureState checkState = checkFeature(featureId); 144 if (checkState.isExceptional()) { 145 throw new XMLConfigurationException(checkState.status, featureId); 146 } 147 148 fFeatures.put(featureId, state); 149 } // setFeature(String,boolean) 150 151 /** 152 * Allows a parser to add parser specific properties to be recognized 153 * and managed by the parser configuration. 154 * 155 * @param propertyIds An array of the additional property identifiers 156 * to be recognized. 157 */ addRecognizedProperties(String[] propertyIds)158 public void addRecognizedProperties(String[] propertyIds) { 159 fRecognizedProperties.addAll(Arrays.asList(propertyIds)); 160 } // addRecognizedProperties(String[]) 161 162 /** 163 * setProperty 164 * 165 * @param propertyId 166 * @param value 167 * @exception com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException If the 168 * requested feature is not known. 169 */ setProperty(String propertyId, Object value)170 public void setProperty(String propertyId, Object value) 171 throws XMLConfigurationException { 172 173 // check and store 174 PropertyState checkState = checkProperty(propertyId); 175 if (checkState.isExceptional()) { 176 throw new XMLConfigurationException(checkState.status, propertyId); 177 } 178 fProperties.put(propertyId, value); 179 180 } // setProperty(String,Object) 181 182 // 183 // XMLComponentManager methods 184 // 185 186 /** 187 * Returns the state of a feature. 188 * 189 * @param featureId The feature identifier. 190 * @return true if the feature is supported 191 * 192 * @throws XMLConfigurationException Thrown for configuration error. 193 * In general, components should 194 * only throw this exception if 195 * it is <strong>really</strong> 196 * a critical error. 197 */ 198 @Override getFeature(String featureId)199 public boolean getFeature(String featureId) 200 throws XMLConfigurationException { 201 202 FeatureState state = getFeatureState(featureId); 203 if (state.isExceptional()) { 204 throw new XMLConfigurationException(state.status, featureId); 205 } 206 return state.state; 207 } // getFeature(String):boolean 208 209 @Override getFeature(String featureId, boolean defaultValue)210 public final boolean getFeature(String featureId, boolean defaultValue) { 211 FeatureState state = getFeatureState(featureId); 212 if (state.isExceptional()) { 213 return defaultValue; 214 } 215 return state.state; 216 } 217 218 @Override getFeatureState(String featureId)219 public FeatureState getFeatureState(String featureId) { 220 Boolean state = fFeatures.get(featureId); 221 222 if (state == null) { 223 FeatureState checkState = checkFeature(featureId); 224 if (checkState.isExceptional()) { 225 return checkState; 226 } 227 return FeatureState.is(false); 228 } 229 return FeatureState.is(state); 230 } 231 232 /** 233 * Returns the value of a property. 234 * 235 * @param propertyId The property identifier. 236 * @return the value of the property 237 * 238 * @throws XMLConfigurationException Thrown for configuration error. 239 * In general, components should 240 * only throw this exception if 241 * it is <strong>really</strong> 242 * a critical error. 243 */ 244 @Override getProperty(String propertyId)245 public Object getProperty(String propertyId) 246 throws XMLConfigurationException { 247 248 PropertyState state = getPropertyState(propertyId); 249 if (state.isExceptional()) { 250 throw new XMLConfigurationException(state.status, propertyId); 251 } 252 253 return state.state; 254 } // getProperty(String):Object 255 256 @Override getProperty(String propertyId, Object defaultValue)257 public final Object getProperty(String propertyId, Object defaultValue) { 258 PropertyState state = getPropertyState(propertyId); 259 if (state.isExceptional()) { 260 return defaultValue; 261 } 262 263 return state.state; 264 } 265 266 @Override getPropertyState(String propertyId)267 public PropertyState getPropertyState(String propertyId) { 268 Object propertyValue = fProperties.get(propertyId); 269 270 if (propertyValue == null) { 271 PropertyState state = checkProperty(propertyId); 272 if (state.isExceptional()) { 273 return state; 274 } 275 } 276 277 return PropertyState.is(propertyValue); 278 } 279 280 // 281 // Protected methods 282 // 283 284 /** 285 * Check a feature. If feature is known and supported, this method simply 286 * returns. Otherwise, the appropriate exception is thrown. 287 * 288 * @param featureId The unique identifier (URI) of the feature. 289 * 290 * @exception com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException If the 291 * requested feature is not known. 292 */ checkFeature(String featureId)293 protected FeatureState checkFeature(String featureId) 294 throws XMLConfigurationException { 295 296 // check feature 297 if (!fRecognizedFeatures.contains(featureId)) { 298 if (fParentSettings != null) { 299 return fParentSettings.getFeatureState(featureId); 300 } 301 else { 302 return FeatureState.NOT_RECOGNIZED; 303 } 304 } 305 306 // TODO: reasonable default? 307 return FeatureState.RECOGNIZED; 308 } // checkFeature(String) 309 310 /** 311 * Check a property. If the property is known and supported, this method 312 * simply returns. Otherwise, the appropriate exception is thrown. 313 * 314 * @param propertyId The unique identifier (URI) of the property 315 * being set. 316 * @return the PropertyState 317 * @exception com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException If the 318 * requested feature is not known. 319 */ checkProperty(String propertyId)320 protected PropertyState checkProperty(String propertyId) 321 throws XMLConfigurationException { 322 323 // check property 324 if (!fRecognizedProperties.contains(propertyId)) { 325 if (fParentSettings != null) { 326 PropertyState state = fParentSettings.getPropertyState(propertyId); 327 if (state.isExceptional()) { 328 return state; 329 } 330 } 331 else { 332 return PropertyState.NOT_RECOGNIZED; 333 } 334 } 335 return PropertyState.RECOGNIZED; 336 } // checkProperty(String) 337 338 } // class ParserConfigurationSettings 339