1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Copyright 2000-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; 22 23 import java.io.IOException; 24 import java.util.Hashtable; 25 import java.util.Iterator; 26 import java.util.Map; 27 28 import javax.xml.parsers.DocumentBuilder; 29 import javax.xml.validation.Schema; 30 31 import com.sun.org.apache.xerces.internal.dom.DOMImplementationImpl; 32 import com.sun.org.apache.xerces.internal.dom.DOMMessageFormatter; 33 import com.sun.org.apache.xerces.internal.impl.Constants; 34 import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager; 35 import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator; 36 import com.sun.org.apache.xerces.internal.jaxp.validation.XSGrammarPoolContainer; 37 import com.sun.org.apache.xerces.internal.parsers.DOMParser; 38 import com.sun.org.apache.xerces.internal.util.SecurityManager; 39 import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler; 40 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent; 41 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager; 42 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; 43 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource; 44 import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration; 45 import org.w3c.dom.DOMImplementation; 46 import org.w3c.dom.Document; 47 import org.xml.sax.EntityResolver; 48 import org.xml.sax.ErrorHandler; 49 import org.xml.sax.InputSource; 50 import org.xml.sax.SAXException; 51 import org.xml.sax.SAXNotRecognizedException; 52 import org.xml.sax.SAXNotSupportedException; 53 54 /** 55 * @author Rajiv Mordani 56 * @author Edwin Goei 57 * @version $Id: DocumentBuilderImpl.java,v 1.8 2010-11-01 04:40:06 joehw Exp $ 58 */ 59 public class DocumentBuilderImpl extends DocumentBuilder 60 implements JAXPConstants 61 { 62 /** Feature identifier: namespaces. */ 63 private static final String NAMESPACES_FEATURE = 64 Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE; 65 66 /** Feature identifier: include ignorable white space. */ 67 private static final String INCLUDE_IGNORABLE_WHITESPACE = 68 Constants.XERCES_FEATURE_PREFIX + Constants.INCLUDE_IGNORABLE_WHITESPACE; 69 70 /** Feature identifier: create entiry ref nodes feature. */ 71 private static final String CREATE_ENTITY_REF_NODES_FEATURE = 72 Constants.XERCES_FEATURE_PREFIX + Constants.CREATE_ENTITY_REF_NODES_FEATURE; 73 74 /** Feature identifier: include comments feature. */ 75 private static final String INCLUDE_COMMENTS_FEATURE = 76 Constants.XERCES_FEATURE_PREFIX + Constants.INCLUDE_COMMENTS_FEATURE; 77 78 /** Feature identifier: create cdata nodes feature. */ 79 private static final String CREATE_CDATA_NODES_FEATURE = 80 Constants.XERCES_FEATURE_PREFIX + Constants.CREATE_CDATA_NODES_FEATURE; 81 82 /** Feature identifier: XInclude processing */ 83 private static final String XINCLUDE_FEATURE = 84 Constants.XERCES_FEATURE_PREFIX + Constants.XINCLUDE_FEATURE; 85 86 /** feature identifier: XML Schema validation */ 87 private static final String XMLSCHEMA_VALIDATION_FEATURE = 88 Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE; 89 90 /** Feature identifier: validation */ 91 private static final String VALIDATION_FEATURE = 92 Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE; 93 94 /** Property identifier: security manager. */ 95 private static final String SECURITY_MANAGER = 96 Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY; 97 98 private final DOMParser domParser; 99 private final Schema grammar; 100 101 private final XMLComponent fSchemaValidator; 102 private final XMLComponentManager fSchemaValidatorComponentManager; 103 private final ValidationManager fSchemaValidationManager; 104 private final UnparsedEntityHandler fUnparsedEntityHandler; 105 106 /** Initial ErrorHandler */ 107 private final ErrorHandler fInitErrorHandler; 108 109 /** Initial EntityResolver */ 110 private final EntityResolver fInitEntityResolver; 111 112 DocumentBuilderImpl(DocumentBuilderFactoryImpl dbf, Hashtable dbfAttrs, Hashtable features) 113 throws SAXNotRecognizedException, SAXNotSupportedException { 114 this(dbf, dbfAttrs, features, false); 115 } 116 117 DocumentBuilderImpl(DocumentBuilderFactoryImpl dbf, Hashtable dbfAttrs, Hashtable features, boolean secureProcessing) 118 throws SAXNotRecognizedException, SAXNotSupportedException 119 { 120 domParser = new DOMParser(); 121 122 // If validating, provide a default ErrorHandler that prints 123 // validation errors with a warning telling the user to set an 124 // ErrorHandler 125 if (dbf.isValidating()) { 126 fInitErrorHandler = new DefaultValidationErrorHandler(); 127 setErrorHandler(fInitErrorHandler); 128 } 129 else { 130 fInitErrorHandler = domParser.getErrorHandler(); 131 } 132 133 domParser.setFeature(VALIDATION_FEATURE, dbf.isValidating()); 134 135 // "namespaceAware" == SAX Namespaces feature 136 domParser.setFeature(NAMESPACES_FEATURE, dbf.isNamespaceAware()); 137 138 // Set various parameters obtained from DocumentBuilderFactory 139 domParser.setFeature(INCLUDE_IGNORABLE_WHITESPACE, 140 !dbf.isIgnoringElementContentWhitespace()); 141 domParser.setFeature(CREATE_ENTITY_REF_NODES_FEATURE, 142 !dbf.isExpandEntityReferences()); 143 domParser.setFeature(INCLUDE_COMMENTS_FEATURE, 144 !dbf.isIgnoringComments()); 145 domParser.setFeature(CREATE_CDATA_NODES_FEATURE, 146 !dbf.isCoalescing()); 147 148 // Avoid setting the XInclude processing feature if the value is false. 149 // This will keep the configuration from throwing an exception if it 150 // does not support XInclude. 151 if (dbf.isXIncludeAware()) { 152 domParser.setFeature(XINCLUDE_FEATURE, true); 153 } 154 155 // If the secure processing feature is on set a security manager. 156 if (secureProcessing) { 157 domParser.setProperty(SECURITY_MANAGER, new SecurityManager()); 158 } 159 160 this.grammar = dbf.getSchema(); 161 if (grammar != null) { 162 XMLParserConfiguration config = domParser.getXMLParserConfiguration(); 163 XMLComponent validatorComponent = null; 164 /** For Xerces grammars, use built-in schema validator. **/ 165 if (grammar instanceof XSGrammarPoolContainer) { 166 validatorComponent = new XMLSchemaValidator(); 167 fSchemaValidationManager = new ValidationManager(); 168 fUnparsedEntityHandler = new UnparsedEntityHandler(fSchemaValidationManager); 169 config.setDTDHandler(fUnparsedEntityHandler); 170 fUnparsedEntityHandler.setDTDHandler(domParser); 171 domParser.setDTDSource(fUnparsedEntityHandler); 172 fSchemaValidatorComponentManager = new SchemaValidatorConfiguration(config, 173 (XSGrammarPoolContainer) grammar, fSchemaValidationManager); 174 } 175 /** For third party grammars, use the JAXP validator component. **/ 176 else { 177 validatorComponent = new JAXPValidatorComponent(grammar.newValidatorHandler()); 178 fSchemaValidationManager = null; 179 fUnparsedEntityHandler = null; 180 fSchemaValidatorComponentManager = config; 181 } 182 config.addRecognizedFeatures(validatorComponent.getRecognizedFeatures()); 183 config.addRecognizedProperties(validatorComponent.getRecognizedProperties()); 184 setFeatures(features); // Must set before calling setDocumentHandler() 185 config.setDocumentHandler((XMLDocumentHandler) validatorComponent); 186 ((XMLDocumentSource)validatorComponent).setDocumentHandler(domParser); 187 domParser.setDocumentSource((XMLDocumentSource) validatorComponent); 188 fSchemaValidator = validatorComponent; 189 } 190 else { 191 fSchemaValidationManager = null; 192 fUnparsedEntityHandler = null; 193 fSchemaValidatorComponentManager = null; 194 fSchemaValidator = null; 195 setFeatures(features); 196 } 197 198 // Set attributes 199 setDocumentBuilderFactoryAttributes(dbfAttrs); 200 201 // Initial EntityResolver 202 fInitEntityResolver = domParser.getEntityResolver(); 203 } 204 205 private void setFeatures(Hashtable features) 206 throws SAXNotSupportedException, SAXNotRecognizedException { 207 if (features != null) { 208 Iterator entries = features.entrySet().iterator(); 209 while (entries.hasNext()) { 210 Map.Entry entry = (Map.Entry) entries.next(); 211 String feature = (String) entry.getKey(); 212 boolean value = ((Boolean) entry.getValue()).booleanValue(); 213 domParser.setFeature(feature, value); 214 } 215 } 216 } 217 218 /** 219 * Set any DocumentBuilderFactory attributes of our underlying DOMParser 220 * 221 * Note: code does not handle possible conflicts between DOMParser 222 * attribute names and JAXP specific attribute names, 223 * eg. DocumentBuilderFactory.setValidating() 224 */ 225 private void setDocumentBuilderFactoryAttributes(Hashtable dbfAttrs) 226 throws SAXNotSupportedException, SAXNotRecognizedException 227 { 228 if (dbfAttrs == null) { 229 // Nothing to do 230 return; 231 } 232 233 Iterator entries = dbfAttrs.entrySet().iterator(); 234 while (entries.hasNext()) { 235 Map.Entry entry = (Map.Entry) entries.next(); 236 String name = (String) entry.getKey(); 237 Object val = entry.getValue(); 238 if (val instanceof Boolean) { 239 // Assume feature 240 domParser.setFeature(name, ((Boolean)val).booleanValue()); 241 } else { 242 // Assume property 243 if (JAXP_SCHEMA_LANGUAGE.equals(name)) { 244 // JAXP 1.2 support 245 //None of the properties will take effect till the setValidating(true) has been called 246 if ( W3C_XML_SCHEMA.equals(val) ) { 247 if( isValidating() ) { 248 domParser.setFeature(XMLSCHEMA_VALIDATION_FEATURE, true); 249 // this should allow us not to emit DTD errors, as expected by the 250 // spec when schema validation is enabled 251 domParser.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA); 252 } 253 } 254 } else if(JAXP_SCHEMA_SOURCE.equals(name)){ 255 if( isValidating() ) { 256 String value=(String)dbfAttrs.get(JAXP_SCHEMA_LANGUAGE); 257 if(value !=null && W3C_XML_SCHEMA.equals(value)){ 258 domParser.setProperty(name, val); 259 }else{ 260 throw new IllegalArgumentException( 261 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, 262 "jaxp-order-not-supported", 263 new Object[] {JAXP_SCHEMA_LANGUAGE, JAXP_SCHEMA_SOURCE})); 264 } 265 } 266 } else { 267 // Let Xerces code handle the property 268 domParser.setProperty(name, val); 269 } 270 } 271 } 272 } 273 274 /** 275 * Non-preferred: use the getDOMImplementation() method instead of this 276 * one to get a DOM Level 2 DOMImplementation object and then use DOM 277 * Level 2 methods to create a DOM Document object. 278 */ 279 public Document newDocument() { 280 return new com.sun.org.apache.xerces.internal.dom.DocumentImpl(); 281 } 282 283 public DOMImplementation getDOMImplementation() { 284 return DOMImplementationImpl.getDOMImplementation(); 285 } 286 287 public Document parse(InputSource is) throws SAXException, IOException { 288 if (is == null) { 289 throw new IllegalArgumentException( 290 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, 291 "jaxp-null-input-source", null)); 292 } 293 if (fSchemaValidator != null) { 294 if (fSchemaValidationManager != null) { 295 fSchemaValidationManager.reset(); 296 fUnparsedEntityHandler.reset(); 297 } 298 resetSchemaValidator(); 299 } 300 domParser.parse(is); 301 Document doc = domParser.getDocument(); 302 domParser.dropDocumentReferences(); 303 return doc; 304 } 305 306 public boolean isNamespaceAware() { 307 try { 308 return domParser.getFeature(NAMESPACES_FEATURE); 309 } 310 catch (SAXException x) { 311 throw new IllegalStateException(x.getMessage()); 312 } 313 } 314 315 public boolean isValidating() { 316 try { 317 return domParser.getFeature(VALIDATION_FEATURE); 318 } 319 catch (SAXException x) { 320 throw new IllegalStateException(x.getMessage()); 321 } 322 } 323 324 /** 325 * Gets the XInclude processing mode for this parser 326 * @return the state of XInclude processing mode 327 */ 328 public boolean isXIncludeAware() { 329 try { 330 return domParser.getFeature(XINCLUDE_FEATURE); 331 } 332 catch (SAXException exc) { 333 return false; 334 } 335 } 336 337 public void setEntityResolver(EntityResolver er) { 338 domParser.setEntityResolver(er); 339 } 340 341 public void setErrorHandler(ErrorHandler eh) { 342 domParser.setErrorHandler(eh); 343 } 344 345 public Schema getSchema() { 346 return grammar; 347 } 348 349 public void reset() { 350 /** Restore the initial error handler. **/ 351 if (domParser.getErrorHandler() != fInitErrorHandler) { 352 domParser.setErrorHandler(fInitErrorHandler); 353 } 354 /** Restore the initial entity resolver. **/ 355 if (domParser.getEntityResolver() != fInitEntityResolver) { 356 domParser.setEntityResolver(fInitEntityResolver); 357 } 358 } 359 360 // package private 361 DOMParser getDOMParser() { 362 return domParser; 363 } 364 365 private void resetSchemaValidator() throws SAXException { 366 try { 367 fSchemaValidator.reset(fSchemaValidatorComponentManager); 368 } 369 // This should never be thrown from the schema validator. 370 catch (XMLConfigurationException e) { 371 throw new SAXException(e); 372 } 373 } 374 }