1 /* 2 * Copyright (c) 2007, 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 21 package com.sun.org.apache.xerces.internal.jaxp.validation; 22 23 import com.sun.org.apache.xerces.internal.impl.Constants; 24 import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader; 25 import com.sun.org.apache.xerces.internal.util.DOMEntityResolverWrapper; 26 import com.sun.org.apache.xerces.internal.util.DOMInputSource; 27 import com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper; 28 import com.sun.org.apache.xerces.internal.util.SAXInputSource; 29 import com.sun.org.apache.xerces.internal.util.SAXMessageFormatter; 30 import com.sun.org.apache.xerces.internal.util.StAXInputSource; 31 import com.sun.org.apache.xerces.internal.util.Status; 32 import com.sun.org.apache.xerces.internal.util.XMLGrammarPoolImpl; 33 import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; 34 import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager; 35 import com.sun.org.apache.xerces.internal.xni.XNIException; 36 import com.sun.org.apache.xerces.internal.xni.grammars.Grammar; 37 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription; 38 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool; 39 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; 40 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; 41 import java.io.IOException; 42 import java.io.InputStream; 43 import java.io.Reader; 44 import javax.xml.XMLConstants; 45 import javax.xml.catalog.CatalogFeatures.Feature; 46 import javax.xml.stream.XMLEventReader; 47 import javax.xml.transform.Source; 48 import javax.xml.transform.dom.DOMSource; 49 import javax.xml.transform.sax.SAXSource; 50 import javax.xml.transform.stax.StAXSource; 51 import javax.xml.transform.stream.StreamSource; 52 import javax.xml.validation.Schema; 53 import javax.xml.validation.SchemaFactory; 54 import jdk.xml.internal.JdkXmlUtils; 55 import org.w3c.dom.Node; 56 import org.w3c.dom.ls.LSResourceResolver; 57 import org.xml.sax.ErrorHandler; 58 import org.xml.sax.InputSource; 59 import org.xml.sax.SAXException; 60 import org.xml.sax.SAXNotRecognizedException; 61 import org.xml.sax.SAXNotSupportedException; 62 import org.xml.sax.SAXParseException; 63 64 /** 65 * {@link SchemaFactory} for XML Schema. 66 * 67 * @author Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) 68 */ 69 public final class XMLSchemaFactory extends SchemaFactory { 70 71 // feature identifiers 72 73 /** JAXP Source feature prefix. */ 74 private static final String JAXP_SOURCE_FEATURE_PREFIX = "http://javax.xml.transform"; 75 76 /** Feature identifier: schema full checking. */ 77 private static final String SCHEMA_FULL_CHECKING = 78 Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_FULL_CHECKING; 79 80 /** Feature identifier: use grammar pool only. */ 81 private static final String USE_GRAMMAR_POOL_ONLY = 82 Constants.XERCES_FEATURE_PREFIX + Constants.USE_GRAMMAR_POOL_ONLY_FEATURE; 83 84 // property identifiers 85 86 /** Property identifier: grammar pool. */ 87 private static final String XMLGRAMMAR_POOL = 88 Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY; 89 90 /** Property identifier: XMLSecurityManager. */ 91 private static final String SECURITY_MANAGER = 92 Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY; 93 94 /** Property identifier: Security property manager. */ 95 private static final String XML_SECURITY_PROPERTY_MANAGER = 96 Constants.XML_SECURITY_PROPERTY_MANAGER; 97 98 99 // 100 // Data 101 // 102 103 /** The XMLSchemaLoader */ 104 private final XMLSchemaLoader fXMLSchemaLoader = new XMLSchemaLoader(); 105 106 /** User-specified ErrorHandler; can be null. */ 107 private ErrorHandler fErrorHandler; 108 109 /** The LSResrouceResolver */ 110 private LSResourceResolver fLSResourceResolver; 111 112 /** The DOMEntityResolverWrapper */ 113 private final DOMEntityResolverWrapper fDOMEntityResolverWrapper; 114 115 /** The ErrorHandlerWrapper */ 116 private final ErrorHandlerWrapper fErrorHandlerWrapper; 117 118 /** The SecurityManager. */ 119 private XMLSecurityManager fSecurityManager; 120 121 /** The Security property manager. */ 122 private XMLSecurityPropertyManager fSecurityPropertyMgr; 123 124 /** The container for the real grammar pool. */ 125 private final XMLGrammarPoolWrapper fXMLGrammarPoolWrapper; 126 127 /** Whether or not to allow new schemas to be added to the grammar pool */ 128 private boolean fUseGrammarPoolOnly; 129 130 /** 131 * Indicates whether implementation parts should use 132 * service loader (or similar). 133 * Note the default value (false) is the safe option.. 134 */ 135 private final boolean fUseServicesMechanism; 136 137 138 public XMLSchemaFactory() { 139 this(true); 140 } 141 public static XMLSchemaFactory newXMLSchemaFactoryNoServiceLoader() { 142 return new XMLSchemaFactory(false); 143 } 144 private XMLSchemaFactory(boolean useServicesMechanism) { 145 fUseServicesMechanism = useServicesMechanism; 146 fErrorHandlerWrapper = new ErrorHandlerWrapper(DraconianErrorHandler.getInstance()); 147 fDOMEntityResolverWrapper = new DOMEntityResolverWrapper(); 148 fXMLGrammarPoolWrapper = new XMLGrammarPoolWrapper(); 149 fXMLSchemaLoader.setFeature(SCHEMA_FULL_CHECKING, true); 150 fXMLSchemaLoader.setProperty(XMLGRAMMAR_POOL, fXMLGrammarPoolWrapper); 151 fXMLSchemaLoader.setEntityResolver(fDOMEntityResolverWrapper); 152 fXMLSchemaLoader.setErrorHandler(fErrorHandlerWrapper); 153 fUseGrammarPoolOnly = true; 154 155 // Enable secure processing feature by default 156 fSecurityManager = new XMLSecurityManager(true); 157 fXMLSchemaLoader.setProperty(SECURITY_MANAGER, fSecurityManager); 158 159 fSecurityPropertyMgr = new XMLSecurityPropertyManager(); 160 fXMLSchemaLoader.setProperty(XML_SECURITY_PROPERTY_MANAGER, 161 fSecurityPropertyMgr); 162 163 // use catalog 164 fXMLSchemaLoader.setFeature(XMLConstants.USE_CATALOG, JdkXmlUtils.USE_CATALOG_DEFAULT); 165 for (Feature f : Feature.values()) { 166 fXMLSchemaLoader.setProperty(f.getPropertyName(), null); 167 } 168 169 fXMLSchemaLoader.setProperty(JdkXmlUtils.CDATA_CHUNK_SIZE, JdkXmlUtils.CDATA_CHUNK_SIZE_DEFAULT); 170 } 171 172 /** 173 * <p>Is specified schema supported by this <code>SchemaFactory</code>?</p> 174 * 175 * @param schemaLanguage Specifies the schema language which the returned <code>SchemaFactory</code> will understand. 176 * <code>schemaLanguage</code> must specify a <a href="#schemaLanguage">valid</a> schema language. 177 * 178 * @return <code>true</code> if <code>SchemaFactory</code> supports <code>schemaLanguage</code>, else <code>false</code>. 179 * 180 * @throws NullPointerException If <code>schemaLanguage</code> is <code>null</code>. 181 * @throws IllegalArgumentException If <code>schemaLanguage.length() == 0</code> 182 * or <code>schemaLanguage</code> does not specify a <a href="#schemaLanguage">valid</a> schema language. 183 */ 184 public boolean isSchemaLanguageSupported(String schemaLanguage) { 185 if (schemaLanguage == null) { 186 throw new NullPointerException(JAXPValidationMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 187 "SchemaLanguageNull", null)); 188 } 189 if (schemaLanguage.length() == 0) { 190 throw new IllegalArgumentException(JAXPValidationMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 191 "SchemaLanguageLengthZero", null)); 192 } 193 // only W3C XML Schema 1.0 is supported 194 return schemaLanguage.equals(XMLConstants.W3C_XML_SCHEMA_NS_URI) || 195 schemaLanguage.equals(Constants.W3C_XML_SCHEMA10_NS_URI); 196 } 197 198 public LSResourceResolver getResourceResolver() { 199 return fLSResourceResolver; 200 } 201 202 public void setResourceResolver(LSResourceResolver resourceResolver) { 203 fLSResourceResolver = resourceResolver; 204 fDOMEntityResolverWrapper.setEntityResolver(resourceResolver); 205 fXMLSchemaLoader.setEntityResolver(fDOMEntityResolverWrapper); 206 } 207 208 public ErrorHandler getErrorHandler() { 209 return fErrorHandler; 210 } 211 212 public void setErrorHandler(ErrorHandler errorHandler) { 213 fErrorHandler = errorHandler; 214 fErrorHandlerWrapper.setErrorHandler(errorHandler != null ? errorHandler : DraconianErrorHandler.getInstance()); 215 fXMLSchemaLoader.setErrorHandler(fErrorHandlerWrapper); 216 } 217 218 public Schema newSchema( Source[] schemas ) throws SAXException { 219 220 // this will let the loader store parsed Grammars into the pool. 221 XMLGrammarPoolImplExtension pool = new XMLGrammarPoolImplExtension(); 222 fXMLGrammarPoolWrapper.setGrammarPool(pool); 223 224 XMLInputSource[] xmlInputSources = new XMLInputSource[schemas.length]; 225 InputStream inputStream; 226 Reader reader; 227 for (int i = 0; i < schemas.length; ++i) { 228 Source source = schemas[i]; 229 if (source instanceof StreamSource) { 230 StreamSource streamSource = (StreamSource) source; 231 String publicId = streamSource.getPublicId(); 232 String systemId = streamSource.getSystemId(); 233 inputStream = streamSource.getInputStream(); 234 reader = streamSource.getReader(); 235 XMLInputSource xmlInputSource = new XMLInputSource(publicId, systemId, null, false); 236 xmlInputSource.setByteStream(inputStream); 237 xmlInputSource.setCharacterStream(reader); 238 xmlInputSources[i] = xmlInputSource; 239 } 240 else if (source instanceof SAXSource) { 241 SAXSource saxSource = (SAXSource) source; 242 InputSource inputSource = saxSource.getInputSource(); 243 if (inputSource == null) { 244 throw new SAXException(JAXPValidationMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 245 "SAXSourceNullInputSource", null)); 246 } 247 xmlInputSources[i] = new SAXInputSource(saxSource.getXMLReader(), inputSource); 248 } 249 else if (source instanceof DOMSource) { 250 DOMSource domSource = (DOMSource) source; 251 Node node = domSource.getNode(); 252 String systemID = domSource.getSystemId(); 253 xmlInputSources[i] = new DOMInputSource(node, systemID); 254 } 255 else if (source instanceof StAXSource) { 256 StAXSource staxSource = (StAXSource) source; 257 XMLEventReader eventReader = staxSource.getXMLEventReader(); 258 if (eventReader != null) { 259 xmlInputSources[i] = new StAXInputSource(eventReader); 260 } 261 else { 262 xmlInputSources[i] = new StAXInputSource(staxSource.getXMLStreamReader()); 263 } 264 } 265 else if (source == null) { 266 throw new NullPointerException(JAXPValidationMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 267 "SchemaSourceArrayMemberNull", null)); 268 } 269 else { 270 throw new IllegalArgumentException(JAXPValidationMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 271 "SchemaFactorySourceUnrecognized", 272 new Object [] {source.getClass().getName()})); 273 } 274 } 275 276 try { 277 fXMLSchemaLoader.loadGrammar(xmlInputSources); 278 } 279 catch (XNIException e) { 280 // this should have been reported to users already. 281 throw Util.toSAXException(e); 282 } 283 catch (IOException e) { 284 // this hasn't been reported, so do so now. 285 SAXParseException se = new SAXParseException(e.getMessage(),null,e); 286 if (fErrorHandler != null) { 287 fErrorHandler.error(se); 288 } 289 throw se; // and we must throw it. 290 } 291 292 // Clear reference to grammar pool. 293 fXMLGrammarPoolWrapper.setGrammarPool(null); 294 295 // Select Schema implementation based on grammar count. 296 final int grammarCount = pool.getGrammarCount(); 297 AbstractXMLSchema schema = null; 298 if (fUseGrammarPoolOnly) { 299 if (grammarCount > 1) { 300 schema = new XMLSchema(new ReadOnlyGrammarPool(pool)); 301 } 302 else if (grammarCount == 1) { 303 Grammar[] grammars = pool.retrieveInitialGrammarSet(XMLGrammarDescription.XML_SCHEMA); 304 schema = new SimpleXMLSchema(grammars[0]); 305 } 306 else { 307 schema = new EmptyXMLSchema(); 308 } 309 } 310 else { 311 schema = new XMLSchema(new ReadOnlyGrammarPool(pool), false); 312 } 313 propagateFeatures(schema); 314 propagateProperties(schema); 315 return schema; 316 } 317 318 public Schema newSchema() throws SAXException { 319 /* 320 * It would make sense to return an EmptyXMLSchema object here, if 321 * fUseGrammarPoolOnly is set to true. However, because the default 322 * value of this feature is true, doing so would change the default 323 * behaviour of this method. Thus, we return a WeakReferenceXMLSchema 324 * regardless of the value of fUseGrammarPoolOnly. -PM 325 */ 326 327 // Use a Schema that uses the system id as the equality source. 328 AbstractXMLSchema schema = new WeakReferenceXMLSchema(); 329 propagateFeatures(schema); 330 propagateProperties(schema); 331 return schema; 332 } 333 334 public Schema newSchema(XMLGrammarPool pool) throws SAXException { 335 // If the "use-grammar-pool-only" feature is set to true 336 // prevent the application's grammar pool from being mutated 337 // by wrapping it in a ReadOnlyGrammarPool. 338 final AbstractXMLSchema schema = (fUseGrammarPoolOnly) ? 339 new XMLSchema(new ReadOnlyGrammarPool(pool)) : 340 new XMLSchema(pool, false); 341 propagateFeatures(schema); 342 return schema; 343 } 344 345 public boolean getFeature(String name) 346 throws SAXNotRecognizedException, SAXNotSupportedException { 347 if (name == null) { 348 throw new NullPointerException(JAXPValidationMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 349 "FeatureNameNull", null)); 350 } 351 if (name.startsWith(JAXP_SOURCE_FEATURE_PREFIX)) { 352 // Indicates to the caller that this SchemaFactory supports a specific JAXP Source. 353 if (name.equals(StreamSource.FEATURE) || 354 name.equals(SAXSource.FEATURE) || 355 name.equals(DOMSource.FEATURE) || 356 name.equals(StAXSource.FEATURE)) { 357 return true; 358 } 359 } 360 if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) { 361 return (fSecurityManager != null && fSecurityManager.isSecureProcessing()); 362 } 363 else if (name.equals(USE_GRAMMAR_POOL_ONLY)) { 364 return fUseGrammarPoolOnly; 365 } 366 try { 367 return fXMLSchemaLoader.getFeature(name); 368 } 369 catch (XMLConfigurationException e) { 370 String identifier = e.getIdentifier(); 371 if (e.getType() == Status.NOT_RECOGNIZED) { 372 throw new SAXNotRecognizedException( 373 SAXMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 374 "feature-not-recognized", new Object [] {identifier})); 375 } 376 else { 377 throw new SAXNotSupportedException( 378 SAXMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 379 "feature-not-supported", new Object [] {identifier})); 380 } 381 } 382 } 383 384 public Object getProperty(String name) 385 throws SAXNotRecognizedException, SAXNotSupportedException { 386 if (name == null) { 387 throw new NullPointerException(JAXPValidationMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 388 "ProperyNameNull", null)); 389 } 390 if (name.equals(SECURITY_MANAGER)) { 391 return fSecurityManager; 392 } 393 else if (name.equals(XMLGRAMMAR_POOL)) { 394 throw new SAXNotSupportedException( 395 SAXMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 396 "property-not-supported", new Object [] {name})); 397 } 398 try { 399 return fXMLSchemaLoader.getProperty(name); 400 } 401 catch (XMLConfigurationException e) { 402 String identifier = e.getIdentifier(); 403 if (e.getType() == Status.NOT_RECOGNIZED) { 404 throw new SAXNotRecognizedException( 405 SAXMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 406 "property-not-recognized", new Object [] {identifier})); 407 } 408 else { 409 throw new SAXNotSupportedException( 410 SAXMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 411 "property-not-supported", new Object [] {identifier})); 412 } 413 } 414 } 415 416 public void setFeature(String name, boolean value) 417 throws SAXNotRecognizedException, SAXNotSupportedException { 418 if (name == null) { 419 throw new NullPointerException(JAXPValidationMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 420 "FeatureNameNull", null)); 421 } 422 if (name.startsWith(JAXP_SOURCE_FEATURE_PREFIX)) { 423 if (name.equals(StreamSource.FEATURE) || 424 name.equals(SAXSource.FEATURE) || 425 name.equals(DOMSource.FEATURE) || 426 name.equals(StAXSource.FEATURE)) { 427 throw new SAXNotSupportedException( 428 SAXMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 429 "feature-read-only", new Object [] {name})); 430 } 431 } 432 if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) { 433 if (System.getSecurityManager() != null && (!value)) { 434 throw new SAXNotSupportedException( 435 SAXMessageFormatter.formatMessage(null, 436 "jaxp-secureprocessing-feature", null)); 437 } 438 439 fSecurityManager.setSecureProcessing(value); 440 if (value) { 441 fSecurityPropertyMgr.setValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD, 442 XMLSecurityPropertyManager.State.FSP, Constants.EXTERNAL_ACCESS_DEFAULT_FSP); 443 fSecurityPropertyMgr.setValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA, 444 XMLSecurityPropertyManager.State.FSP, Constants.EXTERNAL_ACCESS_DEFAULT_FSP); 445 } 446 447 fXMLSchemaLoader.setProperty(SECURITY_MANAGER, fSecurityManager); 448 return; 449 } 450 else if (name.equals(USE_GRAMMAR_POOL_ONLY)) { 451 fUseGrammarPoolOnly = value; 452 return; 453 } 454 else if (name.equals(Constants.ORACLE_FEATURE_SERVICE_MECHANISM)) { 455 //in secure mode, let _useServicesMechanism be determined by the constructor 456 if (System.getSecurityManager() != null) 457 return; 458 } 459 try { 460 fXMLSchemaLoader.setFeature(name, value); 461 } 462 catch (XMLConfigurationException e) { 463 String identifier = e.getIdentifier(); 464 if (e.getType() == Status.NOT_RECOGNIZED) { 465 throw new SAXNotRecognizedException( 466 SAXMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 467 "feature-not-recognized", new Object [] {identifier})); 468 } 469 else { 470 throw new SAXNotSupportedException( 471 SAXMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 472 "feature-not-supported", new Object [] {identifier})); 473 } 474 } 475 } 476 477 public void setProperty(String name, Object object) 478 throws SAXNotRecognizedException, SAXNotSupportedException { 479 if (name == null) { 480 throw new NullPointerException(JAXPValidationMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 481 "ProperyNameNull", null)); 482 } 483 if (name.equals(SECURITY_MANAGER)) { 484 fSecurityManager = XMLSecurityManager.convert(object, fSecurityManager); 485 fXMLSchemaLoader.setProperty(SECURITY_MANAGER, fSecurityManager); 486 return; 487 } else if (name.equals(Constants.XML_SECURITY_PROPERTY_MANAGER)) { 488 if (object == null) { 489 fSecurityPropertyMgr = new XMLSecurityPropertyManager(); 490 } else { 491 fSecurityPropertyMgr = (XMLSecurityPropertyManager)object; 492 } 493 fXMLSchemaLoader.setProperty(Constants.XML_SECURITY_PROPERTY_MANAGER, fSecurityPropertyMgr); 494 return; 495 } 496 else if (name.equals(XMLGRAMMAR_POOL)) { 497 throw new SAXNotSupportedException( 498 SAXMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 499 "property-not-supported", new Object [] {name})); 500 } 501 try { 502 //check if the property is managed by security manager 503 if (fSecurityManager == null || 504 !fSecurityManager.setLimit(name, XMLSecurityManager.State.APIPROPERTY, object)) { 505 //check if the property is managed by security property manager 506 if (fSecurityPropertyMgr == null || 507 !fSecurityPropertyMgr.setValue(name, XMLSecurityPropertyManager.State.APIPROPERTY, object)) { 508 //fall back to the existing property manager 509 fXMLSchemaLoader.setProperty(name, object); 510 } 511 } 512 } 513 catch (XMLConfigurationException e) { 514 String identifier = e.getIdentifier(); 515 if (e.getType() == Status.NOT_RECOGNIZED) { 516 throw new SAXNotRecognizedException( 517 SAXMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 518 "property-not-recognized", new Object [] {identifier})); 519 } 520 else { 521 throw new SAXNotSupportedException( 522 SAXMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 523 "property-not-supported", new Object [] {identifier})); 524 } 525 } 526 } 527 528 private void propagateFeatures(AbstractXMLSchema schema) { 529 schema.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, 530 (fSecurityManager != null && fSecurityManager.isSecureProcessing())); 531 schema.setFeature(Constants.ORACLE_FEATURE_SERVICE_MECHANISM, fUseServicesMechanism); 532 String[] features = fXMLSchemaLoader.getRecognizedFeatures(); 533 for (int i = 0; i < features.length; ++i) { 534 boolean state = fXMLSchemaLoader.getFeature(features[i]); 535 schema.setFeature(features[i], state); 536 } 537 } 538 539 private void propagateProperties(AbstractXMLSchema schema) { 540 String[] properties = fXMLSchemaLoader.getRecognizedProperties(); 541 for (int i = 0; i < properties.length; ++i) { 542 Object state = fXMLSchemaLoader.getProperty(properties[i]); 543 schema.setProperty(properties[i], state); 544 } 545 } 546 547 548 /** 549 * Extension of XMLGrammarPoolImpl which exposes the number of 550 * grammars stored in the grammar pool. 551 */ 552 static class XMLGrammarPoolImplExtension extends XMLGrammarPoolImpl { 553 554 /** Constructs a grammar pool with a default number of buckets. */ 555 public XMLGrammarPoolImplExtension() { 556 super(); 557 } 558 559 /** Constructs a grammar pool with a specified number of buckets. */ 560 public XMLGrammarPoolImplExtension(int initialCapacity) { 561 super(initialCapacity); 562 } 563 564 /** Returns the number of grammars contained in this pool. */ 565 int getGrammarCount() { 566 return fGrammarCount; 567 } 568 569 } // XMLSchemaFactory.XMLGrammarPoolImplExtension 570 571 /** 572 * A grammar pool which wraps another. 573 */ 574 static class XMLGrammarPoolWrapper implements XMLGrammarPool { 575 576 private XMLGrammarPool fGrammarPool; 577 578 /* 579 * XMLGrammarPool methods 580 */ 581 582 public Grammar[] retrieveInitialGrammarSet(String grammarType) { 583 return fGrammarPool.retrieveInitialGrammarSet(grammarType); 584 } 585 586 public void cacheGrammars(String grammarType, Grammar[] grammars) { 587 fGrammarPool.cacheGrammars(grammarType, grammars); 588 } 589 590 public Grammar retrieveGrammar(XMLGrammarDescription desc) { 591 return fGrammarPool.retrieveGrammar(desc); 592 } 593 594 public void lockPool() { 595 fGrammarPool.lockPool(); 596 } 597 598 public void unlockPool() { 599 fGrammarPool.unlockPool(); 600 } 601 602 public void clear() { 603 fGrammarPool.clear(); 604 } 605 606 /* 607 * Other methods 608 */ 609 610 void setGrammarPool(XMLGrammarPool grammarPool) { 611 fGrammarPool = grammarPool; 612 } 613 614 XMLGrammarPool getGrammarPool() { 615 return fGrammarPool; 616 } 617 618 } // XMLSchemaFactory.XMLGrammarPoolWrapper 619 620 } // XMLSchemaFactory