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