1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Copyright 2005 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 21 package com.sun.org.apache.xerces.internal.jaxp.validation; 22 23 import java.util.HashMap; 24 import java.util.Locale; 25 import java.util.Iterator; 26 import java.util.Map; 27 28 import javax.xml.XMLConstants; 29 30 import com.sun.org.apache.xerces.internal.impl.Constants; 31 import com.sun.org.apache.xerces.internal.impl.XMLEntityManager; 32 import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter; 33 import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager; 34 import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator; 35 import com.sun.org.apache.xerces.internal.impl.xs.XSMessageFormatter; 36 import com.sun.org.apache.xerces.internal.util.DOMEntityResolverWrapper; 37 import com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper; 38 import com.sun.org.apache.xerces.internal.util.FeatureState; 39 import com.sun.org.apache.xerces.internal.util.NamespaceSupport; 40 import com.sun.org.apache.xerces.internal.util.ParserConfigurationSettings; 41 import com.sun.org.apache.xerces.internal.util.PropertyState; 42 import com.sun.org.apache.xerces.internal.util.SecurityManager; 43 import com.sun.org.apache.xerces.internal.util.Status; 44 import com.sun.org.apache.xerces.internal.util.SymbolTable; 45 import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager; 46 import com.sun.org.apache.xerces.internal.xni.NamespaceContext; 47 import com.sun.org.apache.xerces.internal.xni.XNIException; 48 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent; 49 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager; 50 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; 51 import org.w3c.dom.ls.LSResourceResolver; 52 import org.xml.sax.ErrorHandler; 53 54 /** 55 * <p>An implementation of XMLComponentManager for a schema validator.</p> 56 * 57 * @author Michael Glavassevich, IBM 58 * @version $Id: XMLSchemaValidatorComponentManager.java,v 1.9 2010-11-01 04:40:08 joehw Exp $ 59 */ 60 final class XMLSchemaValidatorComponentManager extends ParserConfigurationSettings implements 61 XMLComponentManager { 62 63 // feature identifiers 64 65 /** Feature identifier: schema validation. */ 66 private static final String SCHEMA_VALIDATION = 67 Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE; 68 69 /** Feature identifier: validation. */ 70 private static final String VALIDATION = 71 Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE; 72 73 /** Feature identifier: send element default value via characters() */ 74 private static final String SCHEMA_ELEMENT_DEFAULT = 75 Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_ELEMENT_DEFAULT; 76 77 /** Feature identifier: use grammar pool only. */ 78 private static final String USE_GRAMMAR_POOL_ONLY = 79 Constants.XERCES_FEATURE_PREFIX + Constants.USE_GRAMMAR_POOL_ONLY_FEATURE; 80 81 // property identifiers 82 83 /** Property identifier: entity manager. */ 84 private static final String ENTITY_MANAGER = 85 Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY; 86 87 /** Property identifier: entity resolver. */ 88 private static final String ENTITY_RESOLVER = 89 Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY; 90 91 /** Property identifier: error handler. */ 92 private static final String ERROR_HANDLER = 93 Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY; 94 95 /** Property identifier: error reporter. */ 96 private static final String ERROR_REPORTER = 97 Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY; 98 99 /** Property identifier: namespace context. */ 100 private static final String NAMESPACE_CONTEXT = 101 Constants.XERCES_PROPERTY_PREFIX + Constants.NAMESPACE_CONTEXT_PROPERTY; 102 103 /** Property identifier: XML Schema validator. */ 104 private static final String SCHEMA_VALIDATOR = 105 Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_VALIDATOR_PROPERTY; 106 107 /** Property identifier: security manager. */ 108 private static final String SECURITY_MANAGER = 109 Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY; 110 111 /** Property identifier: security property manager. */ 112 private static final String XML_SECURITY_PROPERTY_MANAGER = 113 Constants.XML_SECURITY_PROPERTY_MANAGER; 114 115 /** Property identifier: symbol table. */ 116 private static final String SYMBOL_TABLE = 117 Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY; 118 119 /** Property identifier: validation manager. */ 120 private static final String VALIDATION_MANAGER = 121 Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY; 122 123 /** Property identifier: grammar pool. */ 124 private static final String XMLGRAMMAR_POOL = 125 Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY; 126 127 /** Property identifier: locale. */ 128 private static final String LOCALE = 129 Constants.XERCES_PROPERTY_PREFIX + Constants.LOCALE_PROPERTY; 130 131 // 132 // Data 133 // 134 /** 135 * <p>State of secure mode.</p> 136 */ 137 private boolean _isSecureMode = false; 138 139 /** 140 * fConfigUpdated is set to true if there has been any change to the configuration settings, 141 * i.e a feature or a property was changed. 142 */ 143 private boolean fConfigUpdated = true; 144 145 /** 146 * Tracks whether the validator should use components from 147 * the grammar pool to the exclusion of all others. 148 */ 149 private boolean fUseGrammarPoolOnly; 150 151 /** Lookup map for components required for validation. **/ 152 private final HashMap fComponents = new HashMap(); 153 154 // 155 // Components 156 // 157 158 /** Entity manager. */ 159 private XMLEntityManager fEntityManager; 160 161 /** Error reporter. */ 162 private XMLErrorReporter fErrorReporter; 163 164 /** Namespace context. */ 165 private NamespaceContext fNamespaceContext; 166 167 /** XML Schema validator. */ 168 private XMLSchemaValidator fSchemaValidator; 169 170 /** Validation manager. */ 171 private ValidationManager fValidationManager; 172 173 // 174 // Configuration 175 // 176 177 /** Stores initial feature values for validator reset. */ 178 private final HashMap fInitFeatures = new HashMap(); 179 180 /** Stores initial property values for validator reset. */ 181 private final HashMap fInitProperties = new HashMap(); 182 183 /** Stores the initial security manager. */ 184 private final SecurityManager fInitSecurityManager; 185 186 /** Stores the initial security property manager. */ 187 private final XMLSecurityPropertyManager fSecurityPropertyMgr; 188 189 // 190 // User Objects 191 // 192 193 /** Application's ErrorHandler. **/ 194 private ErrorHandler fErrorHandler = null; 195 196 /** Application's LSResourceResolver. */ 197 private LSResourceResolver fResourceResolver = null; 198 199 /** Locale chosen by the application. */ 200 private Locale fLocale = null; 201 202 /** Constructs a component manager suitable for Xerces' schema validator. */ 203 public XMLSchemaValidatorComponentManager(XSGrammarPoolContainer grammarContainer) { 204 // setup components 205 fEntityManager = new XMLEntityManager(); 206 fComponents.put(ENTITY_MANAGER, fEntityManager); 207 208 fErrorReporter = new XMLErrorReporter(); 209 fComponents.put(ERROR_REPORTER, fErrorReporter); 210 211 fNamespaceContext = new NamespaceSupport(); 212 fComponents.put(NAMESPACE_CONTEXT, fNamespaceContext); 213 214 fSchemaValidator = new XMLSchemaValidator(); 215 fComponents.put(SCHEMA_VALIDATOR, fSchemaValidator); 216 217 fValidationManager = new ValidationManager(); 218 fComponents.put(VALIDATION_MANAGER, fValidationManager); 219 220 // setup other properties 221 fComponents.put(ENTITY_RESOLVER, null); 222 fComponents.put(ERROR_HANDLER, null); 223 224 if (System.getSecurityManager() != null) { 225 _isSecureMode = true; 226 setProperty(SECURITY_MANAGER, new SecurityManager()); 227 } else { 228 fComponents.put(SECURITY_MANAGER, null); 229 } 230 fComponents.put(SYMBOL_TABLE, new SymbolTable()); 231 232 // setup grammar pool 233 fComponents.put(XMLGRAMMAR_POOL, grammarContainer.getGrammarPool()); 234 fUseGrammarPoolOnly = grammarContainer.isFullyComposed(); 235 236 // add schema message formatter to error reporter 237 fErrorReporter.putMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN, new XSMessageFormatter()); 238 239 // add all recognized features and properties and apply their defaults 240 addRecognizedParamsAndSetDefaults(fEntityManager, grammarContainer); 241 addRecognizedParamsAndSetDefaults(fErrorReporter, grammarContainer); 242 addRecognizedParamsAndSetDefaults(fSchemaValidator, grammarContainer); 243 244 // if the secure processing feature is set to true, add a security manager to the configuration 245 Boolean secureProcessing = grammarContainer.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING); 246 if (Boolean.TRUE.equals(secureProcessing)) { 247 fInitSecurityManager = new SecurityManager(); 248 } 249 else { 250 fInitSecurityManager = null; 251 } 252 fComponents.put(SECURITY_MANAGER, fInitSecurityManager); 253 254 //pass on properties set on SchemaFactory 255 fSecurityPropertyMgr = (XMLSecurityPropertyManager) 256 grammarContainer.getProperty(Constants.XML_SECURITY_PROPERTY_MANAGER); 257 setProperty(XML_SECURITY_PROPERTY_MANAGER, fSecurityPropertyMgr); 258 } 259 260 /** 261 * Returns the state of a feature. 262 * 263 * @param featureId The feature identifier. 264 * @return true if the feature is supported 265 * 266 * @throws XMLConfigurationException Thrown for configuration error. 267 * In general, components should 268 * only throw this exception if 269 * it is <strong>really</strong> 270 * a critical error. 271 */ 272 public FeatureState getFeatureState(String featureId) 273 throws XMLConfigurationException { 274 if (PARSER_SETTINGS.equals(featureId)) { 275 return FeatureState.is(fConfigUpdated); 276 } 277 else if (VALIDATION.equals(featureId) || SCHEMA_VALIDATION.equals(featureId)) { 278 return FeatureState.is(true); 279 } 280 else if (USE_GRAMMAR_POOL_ONLY.equals(featureId)) { 281 return FeatureState.is(fUseGrammarPoolOnly); 282 } 283 else if (XMLConstants.FEATURE_SECURE_PROCESSING.equals(featureId)) { 284 return FeatureState.is(getProperty(SECURITY_MANAGER) != null); 285 } 286 else if (SCHEMA_ELEMENT_DEFAULT.equals(featureId)) { 287 return FeatureState.is(true); //pre-condition: VALIDATION and SCHEMA_VALIDATION are always true 288 } 289 return super.getFeatureState(featureId); 290 } 291 292 /** 293 * Set the state of a feature. 294 * 295 * @param featureId The unique identifier (URI) of the feature. 296 * @param state The requested state of the feature (true or false). 297 * 298 * @exception XMLConfigurationException If the requested feature is not known. 299 */ 300 public void setFeature(String featureId, boolean value) throws XMLConfigurationException { 301 if (PARSER_SETTINGS.equals(featureId)) { 302 throw new XMLConfigurationException(Status.NOT_SUPPORTED, featureId); 303 } 304 else if (value == false && (VALIDATION.equals(featureId) || SCHEMA_VALIDATION.equals(featureId))) { 305 throw new XMLConfigurationException(Status.NOT_SUPPORTED, featureId); 306 } 307 else if (USE_GRAMMAR_POOL_ONLY.equals(featureId) && value != fUseGrammarPoolOnly) { 308 throw new XMLConfigurationException(Status.NOT_SUPPORTED, featureId); 309 } 310 if (XMLConstants.FEATURE_SECURE_PROCESSING.equals(featureId)) { 311 if (_isSecureMode && !value) { 312 throw new XMLConfigurationException(Status.NOT_ALLOWED, XMLConstants.FEATURE_SECURE_PROCESSING); 313 } 314 setProperty(SECURITY_MANAGER, value ? new SecurityManager() : null); 315 316 if (value && Constants.IS_JDK8_OR_ABOVE) { 317 fSecurityPropertyMgr.setValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD, 318 XMLSecurityPropertyManager.State.FSP, Constants.EXTERNAL_ACCESS_DEFAULT_FSP); 319 fSecurityPropertyMgr.setValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA, 320 XMLSecurityPropertyManager.State.FSP, Constants.EXTERNAL_ACCESS_DEFAULT_FSP); 321 setProperty(XML_SECURITY_PROPERTY_MANAGER, fSecurityPropertyMgr); 322 } 323 324 return; 325 } 326 fConfigUpdated = true; 327 fEntityManager.setFeature(featureId, value); 328 fErrorReporter.setFeature(featureId, value); 329 fSchemaValidator.setFeature(featureId, value); 330 if (!fInitFeatures.containsKey(featureId)) { 331 boolean current = super.getFeature(featureId); 332 fInitFeatures.put(featureId, current ? Boolean.TRUE : Boolean.FALSE); 333 } 334 super.setFeature(featureId, value); 335 } 336 337 /** 338 * Returns the value of a property. 339 * 340 * @param propertyId The property identifier. 341 * @return the value of the property 342 * 343 * @throws XMLConfigurationException Thrown for configuration error. 344 * In general, components should 345 * only throw this exception if 346 * it is <strong>really</strong> 347 * a critical error. 348 */ 349 public PropertyState getPropertyState(String propertyId) 350 throws XMLConfigurationException { 351 if (LOCALE.equals(propertyId)) { 352 return PropertyState.is(getLocale()); 353 } 354 final Object component = fComponents.get(propertyId); 355 if (component != null) { 356 return PropertyState.is(component); 357 } 358 else if (fComponents.containsKey(propertyId)) { 359 return PropertyState.is(null); 360 } 361 return super.getPropertyState(propertyId); 362 } 363 364 /** 365 * Sets the state of a property. 366 * 367 * @param propertyId The unique identifier (URI) of the property. 368 * @param value The requested state of the property. 369 * 370 * @exception XMLConfigurationException If the requested property is not known. 371 */ 372 public void setProperty(String propertyId, Object value) throws XMLConfigurationException { 373 if ( ENTITY_MANAGER.equals(propertyId) || ERROR_REPORTER.equals(propertyId) || 374 NAMESPACE_CONTEXT.equals(propertyId) || SCHEMA_VALIDATOR.equals(propertyId) || 375 SYMBOL_TABLE.equals(propertyId) || VALIDATION_MANAGER.equals(propertyId) || 376 XMLGRAMMAR_POOL.equals(propertyId)) { 377 throw new XMLConfigurationException(Status.NOT_SUPPORTED, propertyId); 378 } 379 fConfigUpdated = true; 380 fEntityManager.setProperty(propertyId, value); 381 fErrorReporter.setProperty(propertyId, value); 382 fSchemaValidator.setProperty(propertyId, value); 383 if (ENTITY_RESOLVER.equals(propertyId) || ERROR_HANDLER.equals(propertyId) || 384 SECURITY_MANAGER.equals(propertyId)) { 385 fComponents.put(propertyId, value); 386 return; 387 } 388 else if (LOCALE.equals(propertyId)) { 389 setLocale((Locale) value); 390 fComponents.put(propertyId, value); 391 return; 392 } 393 if (!fInitProperties.containsKey(propertyId)) { 394 fInitProperties.put(propertyId, super.getProperty(propertyId)); 395 } 396 super.setProperty(propertyId, value); 397 } 398 399 /** 400 * Adds all of the component's recognized features and properties 401 * to the list of default recognized features and properties, and 402 * sets default values on the configuration for features and 403 * properties which were previously absent from the configuration. 404 * 405 * @param component The component whose recognized features 406 * and properties will be added to the configuration 407 */ 408 public void addRecognizedParamsAndSetDefaults(XMLComponent component, XSGrammarPoolContainer grammarContainer) { 409 410 // register component's recognized features 411 final String[] recognizedFeatures = component.getRecognizedFeatures(); 412 addRecognizedFeatures(recognizedFeatures); 413 414 // register component's recognized properties 415 final String[] recognizedProperties = component.getRecognizedProperties(); 416 addRecognizedProperties(recognizedProperties); 417 418 // set default values 419 setFeatureDefaults(component, recognizedFeatures, grammarContainer); 420 setPropertyDefaults(component, recognizedProperties); 421 } 422 423 /** Calls reset on each of the components owned by this component manager. **/ 424 public void reset() throws XNIException { 425 fNamespaceContext.reset(); 426 fValidationManager.reset(); 427 fEntityManager.reset(this); 428 fErrorReporter.reset(this); 429 fSchemaValidator.reset(this); 430 // Mark configuration as fixed. 431 fConfigUpdated = false; 432 } 433 434 void setErrorHandler(ErrorHandler errorHandler) { 435 fErrorHandler = errorHandler; 436 setProperty(ERROR_HANDLER, (errorHandler != null) ? new ErrorHandlerWrapper(errorHandler) : 437 new ErrorHandlerWrapper(DraconianErrorHandler.getInstance())); 438 } 439 440 ErrorHandler getErrorHandler() { 441 return fErrorHandler; 442 } 443 444 void setResourceResolver(LSResourceResolver resourceResolver) { 445 fResourceResolver = resourceResolver; 446 setProperty(ENTITY_RESOLVER, new DOMEntityResolverWrapper(resourceResolver)); 447 } 448 449 LSResourceResolver getResourceResolver() { 450 return fResourceResolver; 451 } 452 453 void setLocale(Locale locale) { 454 fLocale = locale; 455 fErrorReporter.setLocale(locale); 456 } 457 458 Locale getLocale() { 459 return fLocale; 460 } 461 462 /** Cleans out configuration, restoring it to its initial state. */ 463 void restoreInitialState() { 464 fConfigUpdated = true; 465 466 // Remove error resolver and error handler 467 fComponents.put(ENTITY_RESOLVER, null); 468 fComponents.put(ERROR_HANDLER, null); 469 470 // Set the Locale back to null. 471 setLocale(null); 472 fComponents.put(LOCALE, null); 473 474 // Restore initial security manager 475 fComponents.put(SECURITY_MANAGER, fInitSecurityManager); 476 477 // Set the Locale back to null. 478 setLocale(null); 479 fComponents.put(LOCALE, null); 480 481 // Reset feature and property values to their initial values 482 if (!fInitFeatures.isEmpty()) { 483 Iterator iter = fInitFeatures.entrySet().iterator(); 484 while (iter.hasNext()) { 485 Map.Entry entry = (Map.Entry) iter.next(); 486 String name = (String) entry.getKey(); 487 boolean value = ((Boolean) entry.getValue()).booleanValue(); 488 super.setFeature(name, value); 489 } 490 fInitFeatures.clear(); 491 } 492 if (!fInitProperties.isEmpty()) { 493 Iterator iter = fInitProperties.entrySet().iterator(); 494 while (iter.hasNext()) { 495 Map.Entry entry = (Map.Entry) iter.next(); 496 String name = (String) entry.getKey(); 497 Object value = entry.getValue(); 498 super.setProperty(name, value); 499 } 500 fInitProperties.clear(); 501 } 502 } 503 504 /** Sets feature defaults for the given component on this configuration. */ 505 private void setFeatureDefaults(final XMLComponent component, 506 final String [] recognizedFeatures, XSGrammarPoolContainer grammarContainer) { 507 if (recognizedFeatures != null) { 508 for (int i = 0; i < recognizedFeatures.length; ++i) { 509 String featureId = recognizedFeatures[i]; 510 Boolean state = grammarContainer.getFeature(featureId); 511 if (state == null) { 512 state = component.getFeatureDefault(featureId); 513 } 514 if (state != null) { 515 // Do not overwrite values already set on the configuration. 516 if (!fFeatures.containsKey(featureId)) { 517 fFeatures.put(featureId, state); 518 // For newly added components who recognize this feature 519 // but did not offer a default value, we need to make 520 // sure these components will get an opportunity to read 521 // the value before parsing begins. 522 fConfigUpdated = true; 523 } 524 } 525 } 526 } 527 } 528 529 /** Sets property defaults for the given component on this configuration. */ 530 private void setPropertyDefaults(final XMLComponent component, final String [] recognizedProperties) { 531 if (recognizedProperties != null) { 532 for (int i = 0; i < recognizedProperties.length; ++i) { 533 String propertyId = recognizedProperties[i]; 534 Object value = component.getPropertyDefault(propertyId); 535 if (value != null) { 536 // Do not overwrite values already set on the configuration. 537 if (!fProperties.containsKey(propertyId)) { 538 fProperties.put(propertyId, value); 539 // For newly added components who recognize this property 540 // but did not offer a default value, we need to make 541 // sure these components will get an opportunity to read 542 // the value before parsing begins. 543 fConfigUpdated = true; 544 } 545 } 546 } 547 } 548 } 549 550 } // XMLSchemaValidatorComponentManager