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 170 /** 171 * <p>Is specified schema supported by this <code>SchemaFactory</code>?</p> 172 * 173 * @param schemaLanguage Specifies the schema language which the returned <code>SchemaFactory</code> will understand. 174 * <code>schemaLanguage</code> must specify a <a href="#schemaLanguage">valid</a> schema language. 175 * 176 * @return <code>true</code> if <code>SchemaFactory</code> supports <code>schemaLanguage</code>, else <code>false</code>. 177 * 178 * @throws NullPointerException If <code>schemaLanguage</code> is <code>null</code>. 179 * @throws IllegalArgumentException If <code>schemaLanguage.length() == 0</code> 180 * or <code>schemaLanguage</code> does not specify a <a href="#schemaLanguage">valid</a> schema language. 181 */ 182 public boolean isSchemaLanguageSupported(String schemaLanguage) { 183 if (schemaLanguage == null) { 184 throw new NullPointerException(JAXPValidationMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 185 "SchemaLanguageNull", null)); 186 } 187 if (schemaLanguage.length() == 0) { 188 throw new IllegalArgumentException(JAXPValidationMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 189 "SchemaLanguageLengthZero", null)); 190 } 191 // only W3C XML Schema 1.0 is supported 192 return schemaLanguage.equals(XMLConstants.W3C_XML_SCHEMA_NS_URI) || 193 schemaLanguage.equals(Constants.W3C_XML_SCHEMA10_NS_URI); 194 } 195 196 public LSResourceResolver getResourceResolver() { 197 return fLSResourceResolver; 198 } 199 200 public void setResourceResolver(LSResourceResolver resourceResolver) { 201 fLSResourceResolver = resourceResolver; 202 fDOMEntityResolverWrapper.setEntityResolver(resourceResolver); 203 fXMLSchemaLoader.setEntityResolver(fDOMEntityResolverWrapper); 204 } 205 206 public ErrorHandler getErrorHandler() { 207 return fErrorHandler; 208 } 209 210 public void setErrorHandler(ErrorHandler errorHandler) { 211 fErrorHandler = errorHandler; 212 fErrorHandlerWrapper.setErrorHandler(errorHandler != null ? errorHandler : DraconianErrorHandler.getInstance()); 213 fXMLSchemaLoader.setErrorHandler(fErrorHandlerWrapper); 214 } 215 216 public Schema newSchema( Source[] schemas ) throws SAXException { 217 218 // this will let the loader store parsed Grammars into the pool. 219 XMLGrammarPoolImplExtension pool = new XMLGrammarPoolImplExtension(); 220 fXMLGrammarPoolWrapper.setGrammarPool(pool); 221 222 XMLInputSource[] xmlInputSources = new XMLInputSource[schemas.length]; 223 InputStream inputStream; 224 Reader reader; 225 for (int i = 0; i < schemas.length; ++i) { 226 Source source = schemas[i]; 227 if (source instanceof StreamSource) { 228 StreamSource streamSource = (StreamSource) source; 229 String publicId = streamSource.getPublicId(); 230 String systemId = streamSource.getSystemId(); 231 inputStream = streamSource.getInputStream(); 232 reader = streamSource.getReader(); 233 XMLInputSource xmlInputSource = new XMLInputSource(publicId, systemId, null, false); 234 xmlInputSource.setByteStream(inputStream); 235 xmlInputSource.setCharacterStream(reader); 236 xmlInputSources[i] = xmlInputSource; 237 } 238 else if (source instanceof SAXSource) { 239 SAXSource saxSource = (SAXSource) source; 240 InputSource inputSource = saxSource.getInputSource(); 241 if (inputSource == null) { 242 throw new SAXException(JAXPValidationMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 243 "SAXSourceNullInputSource", null)); 244 } 245 xmlInputSources[i] = new SAXInputSource(saxSource.getXMLReader(), inputSource); 246 } 247 else if (source instanceof DOMSource) { 248 DOMSource domSource = (DOMSource) source; 249 Node node = domSource.getNode(); 250 String systemID = domSource.getSystemId(); 251 xmlInputSources[i] = new DOMInputSource(node, systemID); 252 } 253 else if (source instanceof StAXSource) { 254 StAXSource staxSource = (StAXSource) source; 255 XMLEventReader eventReader = staxSource.getXMLEventReader(); 256 if (eventReader != null) { 257 xmlInputSources[i] = new StAXInputSource(eventReader); 258 } 259 else { 260 xmlInputSources[i] = new StAXInputSource(staxSource.getXMLStreamReader()); 261 } 262 } 263 else if (source == null) { 264 throw new NullPointerException(JAXPValidationMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 265 "SchemaSourceArrayMemberNull", null)); 266 } 267 else { 268 throw new IllegalArgumentException(JAXPValidationMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 269 "SchemaFactorySourceUnrecognized", 270 new Object [] {source.getClass().getName()})); 271 } 272 } 273 274 try { 275 fXMLSchemaLoader.loadGrammar(xmlInputSources); 276 } 277 catch (XNIException e) { 278 // this should have been reported to users already. 279 throw Util.toSAXException(e); 280 } 281 catch (IOException e) { 282 // this hasn't been reported, so do so now. 283 SAXParseException se = new SAXParseException(e.getMessage(),null,e); 284 if (fErrorHandler != null) { 285 fErrorHandler.error(se); 286 } 287 throw se; // and we must throw it. 288 } 289 290 // Clear reference to grammar pool. 291 fXMLGrammarPoolWrapper.setGrammarPool(null); 292 293 // Select Schema implementation based on grammar count. 294 final int grammarCount = pool.getGrammarCount(); 295 AbstractXMLSchema schema = null; 296 if (fUseGrammarPoolOnly) { 297 if (grammarCount > 1) { 298 schema = new XMLSchema(new ReadOnlyGrammarPool(pool)); 299 } 300 else if (grammarCount == 1) { 301 Grammar[] grammars = pool.retrieveInitialGrammarSet(XMLGrammarDescription.XML_SCHEMA); 302 schema = new SimpleXMLSchema(grammars[0]); 303 } 304 else { 305 schema = new EmptyXMLSchema(); 306 } 307 } 308 else { 309 schema = new XMLSchema(new ReadOnlyGrammarPool(pool), false); 310 } 311 propagateFeatures(schema); 312 propagateProperties(schema); 313 return schema; 314 } 315 316 public Schema newSchema() throws SAXException { 317 /* 318 * It would make sense to return an EmptyXMLSchema object here, if 319 * fUseGrammarPoolOnly is set to true. However, because the default 320 * value of this feature is true, doing so would change the default 321 * behaviour of this method. Thus, we return a WeakReferenceXMLSchema 322 * regardless of the value of fUseGrammarPoolOnly. -PM 323 */ 324 325 // Use a Schema that uses the system id as the equality source. 326 AbstractXMLSchema schema = new WeakReferenceXMLSchema(); 327 propagateFeatures(schema); 328 propagateProperties(schema); 329 return schema; 330 } 331 332 public Schema newSchema(XMLGrammarPool pool) throws SAXException { 333 // If the "use-grammar-pool-only" feature is set to true 334 // prevent the application's grammar pool from being mutated 335 // by wrapping it in a ReadOnlyGrammarPool. 336 final AbstractXMLSchema schema = (fUseGrammarPoolOnly) ? 337 new XMLSchema(new ReadOnlyGrammarPool(pool)) : 338 new XMLSchema(pool, false); 339 propagateFeatures(schema); 340 return schema; 341 } 342 343 public boolean getFeature(String name) 344 throws SAXNotRecognizedException, SAXNotSupportedException { 345 if (name == null) { 346 throw new NullPointerException(JAXPValidationMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 347 "FeatureNameNull", null)); 348 } 349 if (name.startsWith(JAXP_SOURCE_FEATURE_PREFIX)) { 350 // Indicates to the caller that this SchemaFactory supports a specific JAXP Source. 351 if (name.equals(StreamSource.FEATURE) || 352 name.equals(SAXSource.FEATURE) || 353 name.equals(DOMSource.FEATURE) || 354 name.equals(StAXSource.FEATURE)) { 355 return true; 356 } 357 } 358 if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) { 359 return (fSecurityManager != null && fSecurityManager.isSecureProcessing()); 360 } 361 else if (name.equals(USE_GRAMMAR_POOL_ONLY)) { 362 return fUseGrammarPoolOnly; 363 } 364 try { 365 return fXMLSchemaLoader.getFeature(name); 366 } 367 catch (XMLConfigurationException e) { 368 String identifier = e.getIdentifier(); 369 if (e.getType() == Status.NOT_RECOGNIZED) { 370 throw new SAXNotRecognizedException( 371 SAXMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 372 "feature-not-recognized", new Object [] {identifier})); 373 } 374 else { 375 throw new SAXNotSupportedException( 376 SAXMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 377 "feature-not-supported", new Object [] {identifier})); 378 } 379 } 380 } 381 382 public Object getProperty(String name) 383 throws SAXNotRecognizedException, SAXNotSupportedException { 384 if (name == null) { 385 throw new NullPointerException(JAXPValidationMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 386 "ProperyNameNull", null)); 387 } 388 if (name.equals(SECURITY_MANAGER)) { 389 return fSecurityManager; 390 } 391 else if (name.equals(XMLGRAMMAR_POOL)) { 392 throw new SAXNotSupportedException( 393 SAXMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 394 "property-not-supported", new Object [] {name})); 395 } 396 try { 397 return fXMLSchemaLoader.getProperty(name); 398 } 399 catch (XMLConfigurationException e) { 400 String identifier = e.getIdentifier(); 401 if (e.getType() == Status.NOT_RECOGNIZED) { 402 throw new SAXNotRecognizedException( 403 SAXMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 404 "property-not-recognized", new Object [] {identifier})); 405 } 406 else { 407 throw new SAXNotSupportedException( 408 SAXMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 409 "property-not-supported", new Object [] {identifier})); 410 } 411 } 412 } 413 414 public void setFeature(String name, boolean value) 415 throws SAXNotRecognizedException, SAXNotSupportedException { 416 if (name == null) { 417 throw new NullPointerException(JAXPValidationMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 418 "FeatureNameNull", null)); 419 } 420 if (name.startsWith(JAXP_SOURCE_FEATURE_PREFIX)) { 421 if (name.equals(StreamSource.FEATURE) || 422 name.equals(SAXSource.FEATURE) || 423 name.equals(DOMSource.FEATURE) || 424 name.equals(StAXSource.FEATURE)) { 425 throw new SAXNotSupportedException( 426 SAXMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 427 "feature-read-only", new Object [] {name})); 428 } 429 } 430 if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) { 431 if (System.getSecurityManager() != null && (!value)) { 432 throw new SAXNotSupportedException( 433 SAXMessageFormatter.formatMessage(null, 434 "jaxp-secureprocessing-feature", null)); 435 } 436 437 fSecurityManager.setSecureProcessing(value); 438 if (value) { 439 fSecurityPropertyMgr.setValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD, 440 XMLSecurityPropertyManager.State.FSP, Constants.EXTERNAL_ACCESS_DEFAULT_FSP); 441 fSecurityPropertyMgr.setValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA, 442 XMLSecurityPropertyManager.State.FSP, Constants.EXTERNAL_ACCESS_DEFAULT_FSP); 443 } 444 445 fXMLSchemaLoader.setProperty(SECURITY_MANAGER, fSecurityManager); 446 return; 447 } 448 else if (name.equals(USE_GRAMMAR_POOL_ONLY)) { 449 fUseGrammarPoolOnly = value; 450 return; 451 } 452 else if (name.equals(Constants.ORACLE_FEATURE_SERVICE_MECHANISM)) { 453 //in secure mode, let _useServicesMechanism be determined by the constructor 454 if (System.getSecurityManager() != null) 455 return; 456 } 457 try { 458 fXMLSchemaLoader.setFeature(name, value); 459 } 460 catch (XMLConfigurationException e) { 461 String identifier = e.getIdentifier(); 462 if (e.getType() == Status.NOT_RECOGNIZED) { 463 throw new SAXNotRecognizedException( 464 SAXMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 465 "feature-not-recognized", new Object [] {identifier})); 466 } 467 else { 468 throw new SAXNotSupportedException( 469 SAXMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 470 "feature-not-supported", new Object [] {identifier})); 471 } 472 } 473 } 474 475 public void setProperty(String name, Object object) 476 throws SAXNotRecognizedException, SAXNotSupportedException { 477 if (name == null) { 478 throw new NullPointerException(JAXPValidationMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 479 "ProperyNameNull", null)); 480 } 481 if (name.equals(SECURITY_MANAGER)) { 482 fSecurityManager = XMLSecurityManager.convert(object, fSecurityManager); 483 fXMLSchemaLoader.setProperty(SECURITY_MANAGER, fSecurityManager); 484 return; 485 } else if (name.equals(Constants.XML_SECURITY_PROPERTY_MANAGER)) { 486 if (object == null) { 487 fSecurityPropertyMgr = new XMLSecurityPropertyManager(); 488 } else { 489 fSecurityPropertyMgr = (XMLSecurityPropertyManager)object; 490 } 491 fXMLSchemaLoader.setProperty(Constants.XML_SECURITY_PROPERTY_MANAGER, fSecurityPropertyMgr); 492 return; 493 } 494 else if (name.equals(XMLGRAMMAR_POOL)) { 495 throw new SAXNotSupportedException( 496 SAXMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 497 "property-not-supported", new Object [] {name})); 498 } 499 try { 500 //check if the property is managed by security manager 501 if (fSecurityManager == null || 502 !fSecurityManager.setLimit(name, XMLSecurityManager.State.APIPROPERTY, object)) { 503 //check if the property is managed by security property manager 504 if (fSecurityPropertyMgr == null || 505 !fSecurityPropertyMgr.setValue(name, XMLSecurityPropertyManager.State.APIPROPERTY, object)) { 506 //fall back to the existing property manager 507 fXMLSchemaLoader.setProperty(name, object); 508 } 509 } 510 } 511 catch (XMLConfigurationException e) { 512 String identifier = e.getIdentifier(); 513 if (e.getType() == Status.NOT_RECOGNIZED) { 514 throw new SAXNotRecognizedException( 515 SAXMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 516 "property-not-recognized", new Object [] {identifier})); 517 } 518 else { 519 throw new SAXNotSupportedException( 520 SAXMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), 521 "property-not-supported", new Object [] {identifier})); 522 } 523 } 524 } 525 526 private void propagateFeatures(AbstractXMLSchema schema) { 527 schema.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, 528 (fSecurityManager != null && fSecurityManager.isSecureProcessing())); 529 schema.setFeature(Constants.ORACLE_FEATURE_SERVICE_MECHANISM, fUseServicesMechanism); 530 String[] features = fXMLSchemaLoader.getRecognizedFeatures(); 531 for (int i = 0; i < features.length; ++i) { 532 boolean state = fXMLSchemaLoader.getFeature(features[i]); 533 schema.setFeature(features[i], state); 534 } 535 } 536 537 private void propagateProperties(AbstractXMLSchema schema) { 538 String[] properties = fXMLSchemaLoader.getRecognizedProperties(); 539 for (int i = 0; i < properties.length; ++i) { 540 Object state = fXMLSchemaLoader.getProperty(properties[i]); 541 schema.setProperty(properties[i], state); 542 } 543 } 544 545 546 /** 547 * Extension of XMLGrammarPoolImpl which exposes the number of 548 * grammars stored in the grammar pool. 549 */ 550 static class XMLGrammarPoolImplExtension extends XMLGrammarPoolImpl { 551 552 /** Constructs a grammar pool with a default number of buckets. */ 553 public XMLGrammarPoolImplExtension() { 554 super(); 555 } 556 557 /** Constructs a grammar pool with a specified number of buckets. */ 558 public XMLGrammarPoolImplExtension(int initialCapacity) { 559 super(initialCapacity); 560 } 561 562 /** Returns the number of grammars contained in this pool. */ 563 int getGrammarCount() { 564 return fGrammarCount; 565 } 566 567 } // XMLSchemaFactory.XMLGrammarPoolImplExtension 568 569 /** 570 * A grammar pool which wraps another. 571 */ 572 static class XMLGrammarPoolWrapper implements XMLGrammarPool { 573 574 private XMLGrammarPool fGrammarPool; 575 576 /* 577 * XMLGrammarPool methods 578 */ 579 580 public Grammar[] retrieveInitialGrammarSet(String grammarType) { 581 return fGrammarPool.retrieveInitialGrammarSet(grammarType); 582 } 583 584 public void cacheGrammars(String grammarType, Grammar[] grammars) { 585 fGrammarPool.cacheGrammars(grammarType, grammars); 586 } 587 588 public Grammar retrieveGrammar(XMLGrammarDescription desc) { 589 return fGrammarPool.retrieveGrammar(desc); 590 } 591 592 public void lockPool() { 593 fGrammarPool.lockPool(); 594 } 595 596 public void unlockPool() { 597 fGrammarPool.unlockPool(); 598 } 599 600 public void clear() { 601 fGrammarPool.clear(); 602 } 603 604 /* 605 * Other methods 606 */ 607 608 void setGrammarPool(XMLGrammarPool grammarPool) { 609 fGrammarPool = grammarPool; 610 } 611 612 XMLGrammarPool getGrammarPool() { 613 return fGrammarPool; 614 } 615 616 } // XMLSchemaFactory.XMLGrammarPoolWrapper 617 618 } // XMLSchemaFactory