1 /*
2 * Copyright (c) 2011, 2017, 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.impl.xs;
22
23 import com.sun.org.apache.xerces.internal.dom.DOMErrorImpl;
24 import com.sun.org.apache.xerces.internal.dom.DOMMessageFormatter;
25 import com.sun.org.apache.xerces.internal.dom.DOMStringListImpl;
26 import com.sun.org.apache.xerces.internal.impl.Constants;
27 import com.sun.org.apache.xerces.internal.impl.XMLEntityManager;
28 import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
29 import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException;
30 import com.sun.org.apache.xerces.internal.impl.dv.SchemaDVFactory;
31 import com.sun.org.apache.xerces.internal.impl.dv.xs.SchemaDVFactoryImpl;
32 import com.sun.org.apache.xerces.internal.impl.xs.models.CMBuilder;
33 import com.sun.org.apache.xerces.internal.impl.xs.models.CMNodeFactory;
34 import com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler;
35 import com.sun.org.apache.xerces.internal.util.DOMEntityResolverWrapper;
36 import com.sun.org.apache.xerces.internal.util.DOMErrorHandlerWrapper;
37 import com.sun.org.apache.xerces.internal.util.DefaultErrorHandler;
38 import com.sun.org.apache.xerces.internal.util.MessageFormatter;
39 import com.sun.org.apache.xerces.internal.util.ParserConfigurationSettings;
40 import com.sun.org.apache.xerces.internal.util.Status;
41 import com.sun.org.apache.xerces.internal.util.SymbolTable;
42 import com.sun.org.apache.xerces.internal.util.URI.MalformedURIException;
43 import com.sun.org.apache.xerces.internal.util.XMLSymbols;
44 import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
45 import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager;
46 import com.sun.org.apache.xerces.internal.xni.QName;
47 import com.sun.org.apache.xerces.internal.xni.XNIException;
48 import com.sun.org.apache.xerces.internal.xni.grammars.Grammar;
49 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription;
50 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarLoader;
51 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
52 import com.sun.org.apache.xerces.internal.xni.grammars.XSGrammar;
53 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
54 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
55 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
56 import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver;
57 import com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler;
58 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
59 import com.sun.org.apache.xerces.internal.xs.LSInputList;
60 import com.sun.org.apache.xerces.internal.xs.StringList;
61 import com.sun.org.apache.xerces.internal.xs.XSLoader;
62 import com.sun.org.apache.xerces.internal.xs.XSModel;
63 import java.io.BufferedInputStream;
64 import java.io.File;
65 import java.io.FileInputStream;
66 import java.io.FileNotFoundException;
67 import java.io.IOException;
68 import java.io.InputStream;
69 import java.io.Reader;
70 import java.io.StringReader;
71 import java.util.ArrayList;
72 import java.util.HashMap;
73 import java.util.Locale;
74 import java.util.Map;
75 import java.util.StringTokenizer;
76 import java.util.WeakHashMap;
77 import javax.xml.XMLConstants;
78 import jdk.xml.internal.JdkXmlUtils;
79 import jdk.xml.internal.SecuritySupport;
80 import org.w3c.dom.DOMConfiguration;
81 import org.w3c.dom.DOMError;
82 import org.w3c.dom.DOMErrorHandler;
83 import org.w3c.dom.DOMException;
84 import org.w3c.dom.DOMStringList;
85 import org.w3c.dom.ls.LSInput;
86 import org.w3c.dom.ls.LSResourceResolver;
87 import org.xml.sax.InputSource;
88
89 /**
90 * This class implements xni.grammars.XMLGrammarLoader.
91 * It also serves as implementation of xs.XSLoader interface and DOMConfiguration interface.
92 *
93 * This class is designed to interact either with a proxy for a user application
94 * which wants to preparse schemas, or with our own Schema validator.
95 * It is hoped that none of these "external" classes will therefore need to communicate directly
96 * with XSDHandler in future.
97 * <p>This class only knows how to make XSDHandler do its thing.
98 * The caller must ensure that all its properties (schemaLocation, JAXPSchemaSource
99 * etc.) have been properly set.
100 *
101 * @xerces.internal
102 *
103 * @author Neil Graham, IBM
104 * @LastModified: Sep 2017
105 */
106
107 public class XMLSchemaLoader implements XMLGrammarLoader, XMLComponent, XSElementDeclHelper,
108 // XML Component API
109 XSLoader, DOMConfiguration {
110
111 // Feature identifiers:
112
113 /** Feature identifier: schema full checking*/
114 protected static final String SCHEMA_FULL_CHECKING =
115 Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_FULL_CHECKING;
116
117 /** Feature identifier: continue after fatal error. */
118 protected static final String CONTINUE_AFTER_FATAL_ERROR =
119 Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
120
121 /** Feature identifier: allow java encodings to be recognized when parsing schema docs. */
122 protected static final String ALLOW_JAVA_ENCODINGS =
123 Constants.XERCES_FEATURE_PREFIX + Constants.ALLOW_JAVA_ENCODINGS_FEATURE;
124
125 /** Feature identifier: standard uri conformant feature. */
126 protected static final String STANDARD_URI_CONFORMANT_FEATURE =
127 Constants.XERCES_FEATURE_PREFIX + Constants.STANDARD_URI_CONFORMANT_FEATURE;
128
129 /** Feature identifier: validate annotations. */
130 protected static final String VALIDATE_ANNOTATIONS =
131 Constants.XERCES_FEATURE_PREFIX + Constants.VALIDATE_ANNOTATIONS_FEATURE;
132
133 /** Feature: disallow doctype*/
134 protected static final String DISALLOW_DOCTYPE =
135 Constants.XERCES_FEATURE_PREFIX + Constants.DISALLOW_DOCTYPE_DECL_FEATURE;
136
137 /** Feature: generate synthetic annotations */
138 protected static final String GENERATE_SYNTHETIC_ANNOTATIONS =
139 Constants.XERCES_FEATURE_PREFIX + Constants.GENERATE_SYNTHETIC_ANNOTATIONS_FEATURE;
140
141 /** Feature identifier: honour all schemaLocations */
142 protected static final String HONOUR_ALL_SCHEMALOCATIONS =
143 Constants.XERCES_FEATURE_PREFIX + Constants.HONOUR_ALL_SCHEMALOCATIONS_FEATURE;
144
145 protected static final String AUGMENT_PSVI =
146 Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_AUGMENT_PSVI;
147
148 protected static final String PARSER_SETTINGS =
149 Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS;
150
151 /** Feature identifier: namespace growth */
152 protected static final String NAMESPACE_GROWTH =
153 Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACE_GROWTH_FEATURE;
154
155 /** Feature identifier: tolerate duplicates */
156 protected static final String TOLERATE_DUPLICATES =
157 Constants.XERCES_FEATURE_PREFIX + Constants.TOLERATE_DUPLICATES_FEATURE;
158
159 /** Property identifier: Schema DV Factory */
160 protected static final String SCHEMA_DV_FACTORY =
161 Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_DV_FACTORY_PROPERTY;
162
163 protected static final String USE_SERVICE_MECHANISM = Constants.ORACLE_FEATURE_SERVICE_MECHANISM;
164
165 // recognized features:
166 private static final String[] RECOGNIZED_FEATURES = {
167 SCHEMA_FULL_CHECKING,
168 AUGMENT_PSVI,
169 CONTINUE_AFTER_FATAL_ERROR,
170 ALLOW_JAVA_ENCODINGS,
171 STANDARD_URI_CONFORMANT_FEATURE,
172 DISALLOW_DOCTYPE,
173 GENERATE_SYNTHETIC_ANNOTATIONS,
174 VALIDATE_ANNOTATIONS,
175 HONOUR_ALL_SCHEMALOCATIONS,
176 NAMESPACE_GROWTH,
177 TOLERATE_DUPLICATES,
178 USE_SERVICE_MECHANISM,
179 XMLConstants.USE_CATALOG
180 };
181
182 // property identifiers
183
184 /** Property identifier: symbol table. */
185 public static final String SYMBOL_TABLE =
186 Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
187
188 /** Property identifier: error reporter. */
189 public static final String ERROR_REPORTER =
190 Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
191
192 /** Property identifier: error handler. */
193 public static final String ERROR_HANDLER =
194 Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
195
196 /** Property identifier: entity resolver. */
197 public static final String ENTITY_RESOLVER =
198 Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
199
200 /** Property identifier: grammar pool. */
201 public static final String XMLGRAMMAR_POOL =
202 Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
203
204 /** Property identifier: schema location. */
205 protected static final String SCHEMA_LOCATION =
206 Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_LOCATION;
207
208 /** Property identifier: no namespace schema location. */
209 protected static final String SCHEMA_NONS_LOCATION =
210 Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_NONS_LOCATION;
211
212 /** Property identifier: JAXP schema source. */
213 protected static final String JAXP_SCHEMA_SOURCE =
214 Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE;
215
216 protected static final String SECURITY_MANAGER =
217 Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY;
218
219 /** Property identifier: locale. */
220 protected static final String LOCALE =
221 Constants.XERCES_PROPERTY_PREFIX + Constants.LOCALE_PROPERTY;
222
223 protected static final String ENTITY_MANAGER =
224 Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
225
226 /** Property identifier: Security property manager. */
227 private static final String XML_SECURITY_PROPERTY_MANAGER =
228 Constants.XML_SECURITY_PROPERTY_MANAGER;
229
230 /** Property identifier: access to external dtd */
231 public static final String ACCESS_EXTERNAL_DTD = XMLConstants.ACCESS_EXTERNAL_DTD;
232
233 /** Property identifier: access to external schema */
234 public static final String ACCESS_EXTERNAL_SCHEMA = XMLConstants.ACCESS_EXTERNAL_SCHEMA;
235
236 // recognized properties
237 private static final String [] RECOGNIZED_PROPERTIES = {
238 ENTITY_MANAGER,
239 SYMBOL_TABLE,
240 ERROR_REPORTER,
241 ERROR_HANDLER,
242 ENTITY_RESOLVER,
243 XMLGRAMMAR_POOL,
244 SCHEMA_LOCATION,
245 SCHEMA_NONS_LOCATION,
246 JAXP_SCHEMA_SOURCE,
247 SECURITY_MANAGER,
248 LOCALE,
249 SCHEMA_DV_FACTORY,
250 XML_SECURITY_PROPERTY_MANAGER,
251 JdkXmlUtils.CATALOG_DEFER,
252 JdkXmlUtils.CATALOG_FILES,
253 JdkXmlUtils.CATALOG_PREFER,
254 JdkXmlUtils.CATALOG_RESOLVE,
255 JdkXmlUtils.CDATA_CHUNK_SIZE
256 };
257
258 // Data
259
260 // features and properties
261 private final ParserConfigurationSettings fLoaderConfig = new ParserConfigurationSettings();
262 private XMLErrorReporter fErrorReporter = new XMLErrorReporter ();
263 private XMLEntityManager fEntityManager = null;
264 private XMLEntityResolver fUserEntityResolver = null;
265 private XMLGrammarPool fGrammarPool = null;
266 private String fExternalSchemas = null;
267 private String fExternalNoNSSchema = null;
268 // JAXP property: schema source
269 private Object fJAXPSource = null;
270 // is Schema Full Checking enabled
271 private boolean fIsCheckedFully = false;
272 // boolean that tells whether we've tested the JAXP property.
273 private boolean fJAXPProcessed = false;
274 // if features/properties has not been changed, the value of this attribute is "false"
275 private boolean fSettingsChanged = true;
276
277 // xml schema parsing
278 private XSDHandler fSchemaHandler;
279 private XSGrammarBucket fGrammarBucket;
280 private XSDeclarationPool fDeclPool = null;
281 private SubstitutionGroupHandler fSubGroupHandler;
282 private final CMNodeFactory fNodeFactory = new CMNodeFactory(); //component mgr will be set later
283 private CMBuilder fCMBuilder;
284 private XSDDescription fXSDDescription = new XSDDescription();
285 private String faccessExternalSchema = Constants.EXTERNAL_ACCESS_DEFAULT;
286
287 private WeakHashMap<Object, SchemaGrammar> fJAXPCache;
288 private Locale fLocale = Locale.getDefault();
289
290 // XSLoader attributes
291 private DOMStringList fRecognizedParameters = null;
292
293 /** DOM L3 error handler */
294 private DOMErrorHandlerWrapper fErrorHandler = null;
295
296 /** DOM L3 resource resolver */
297 private DOMEntityResolverWrapper fResourceResolver = null;
298
299 // default constructor. Create objects we absolutely need:
300 public XMLSchemaLoader() {
301 this( new SymbolTable(), null, new XMLEntityManager(), null, null, null);
302 }
303
304 public XMLSchemaLoader(SymbolTable symbolTable) {
305 this( symbolTable, null, new XMLEntityManager(), null, null, null);
306 }
307
308 /**
309 * This constractor is used by the XMLSchemaValidator. Additional properties, i.e. XMLEntityManager,
310 * will be passed during reset(XMLComponentManager).
311 * @param errorReporter
312 * @param grammarBucket
313 * @param sHandler
314 * @param builder
315 */
316 XMLSchemaLoader(XMLErrorReporter errorReporter,
317 XSGrammarBucket grammarBucket,
318 SubstitutionGroupHandler sHandler, CMBuilder builder) {
319 this(null, errorReporter, null, grammarBucket, sHandler, builder);
320 }
321
322 XMLSchemaLoader(SymbolTable symbolTable,
323 XMLErrorReporter errorReporter,
324 XMLEntityManager entityResolver,
325 XSGrammarBucket grammarBucket,
326 SubstitutionGroupHandler sHandler,
327 CMBuilder builder) {
328
329 // store properties and features in configuration
330 fLoaderConfig.addRecognizedFeatures(RECOGNIZED_FEATURES);
331 fLoaderConfig.addRecognizedProperties(RECOGNIZED_PROPERTIES);
332 if (symbolTable != null){
333 fLoaderConfig.setProperty(SYMBOL_TABLE, symbolTable);
334 }
335
336 if(errorReporter == null) {
337 errorReporter = new XMLErrorReporter ();
338 errorReporter.setLocale(fLocale);
339 errorReporter.setProperty(ERROR_HANDLER, new DefaultErrorHandler());
340
341 }
342 fErrorReporter = errorReporter;
343 // make sure error reporter knows about schemas...
344 if(fErrorReporter.getMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN) == null) {
345 fErrorReporter.putMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN, new XSMessageFormatter());
346 }
347 fLoaderConfig.setProperty(ERROR_REPORTER, fErrorReporter);
348 fEntityManager = entityResolver;
349 // entity manager is null if XMLSchemaValidator creates the loader
350 if (fEntityManager != null){
351 fLoaderConfig.setProperty(ENTITY_MANAGER, fEntityManager);
352 }
353
354 // by default augment PSVI (i.e. don't use declaration pool)
355 fLoaderConfig.setFeature(AUGMENT_PSVI, true);
356
357 if(grammarBucket == null ) {
358 grammarBucket = new XSGrammarBucket();
359 }
360 fGrammarBucket = grammarBucket;
361 if (sHandler == null) {
362 sHandler = new SubstitutionGroupHandler(this);
363 }
364 fSubGroupHandler = sHandler;
365
366 if(builder == null) {
367 builder = new CMBuilder(fNodeFactory);
368 }
369 fCMBuilder = builder;
370 fSchemaHandler = new XSDHandler(fGrammarBucket);
371 fJAXPCache = new WeakHashMap<>();
372
373 fSettingsChanged = true;
374 }
375
376 /**
377 * Returns a list of feature identifiers that are recognized by
378 * this XMLGrammarLoader. This method may return null if no features
379 * are recognized.
380 */
381 public String[] getRecognizedFeatures() {
382 return RECOGNIZED_FEATURES.clone();
383 } // getRecognizedFeatures(): String[]
384
385 /**
386 * Returns the state of a feature.
387 *
388 * @param featureId The feature identifier.
389 *
390 * @throws XMLConfigurationException Thrown on configuration error.
391 */
392 public boolean getFeature(String featureId)
393 throws XMLConfigurationException {
394 return fLoaderConfig.getFeature(featureId);
395 } // getFeature (String): boolean
396
397 /**
398 * Sets the state of a feature.
399 *
400 * @param featureId The feature identifier.
401 * @param state The state of the feature.
402 *
403 * @throws XMLConfigurationException Thrown when a feature is not
404 * recognized or cannot be set.
405 */
406 public void setFeature(String featureId,
407 boolean state) throws XMLConfigurationException {
408 fSettingsChanged = true;
409 if(featureId.equals(CONTINUE_AFTER_FATAL_ERROR)) {
410 fErrorReporter.setFeature(CONTINUE_AFTER_FATAL_ERROR, state);
411 }
412 else if(featureId.equals(GENERATE_SYNTHETIC_ANNOTATIONS)) {
413 fSchemaHandler.setGenerateSyntheticAnnotations(state);
414 }
415 fLoaderConfig.setFeature(featureId, state);
416 } // setFeature(String, boolean)
417
418 /**
419 * Returns a list of property identifiers that are recognized by
420 * this XMLGrammarLoader. This method may return null if no properties
421 * are recognized.
422 */
423 public String[] getRecognizedProperties() {
424 return RECOGNIZED_PROPERTIES.clone();
425 } // getRecognizedProperties(): String[]
426
427 /**
428 * Returns the state of a property.
429 *
430 * @param propertyId The property identifier.
431 *
432 * @throws XMLConfigurationException Thrown on configuration error.
433 */
434 public Object getProperty(String propertyId)
435 throws XMLConfigurationException {
436 return fLoaderConfig.getProperty(propertyId);
437 } // getProperty(String): Object
438
439 /**
440 * Sets the state of a property.
441 *
442 * @param propertyId The property identifier.
443 * @param state The state of the property.
444 *
445 * @throws XMLConfigurationException Thrown when a property is not
446 * recognized or cannot be set.
447 */
448 public void setProperty(String propertyId,
449 Object state) throws XMLConfigurationException {
450 fSettingsChanged = true;
451 fLoaderConfig.setProperty(propertyId, state);
452 if (propertyId.equals(JAXP_SCHEMA_SOURCE)) {
453 fJAXPSource = state;
454 fJAXPProcessed = false;
455 }
456 else if (propertyId.equals(XMLGRAMMAR_POOL)) {
457 fGrammarPool = (XMLGrammarPool)state;
458 }
459 else if (propertyId.equals(SCHEMA_LOCATION)) {
460 fExternalSchemas = (String)state;
461 }
462 else if (propertyId.equals(SCHEMA_NONS_LOCATION)) {
463 fExternalNoNSSchema = (String) state;
464 }
465 else if (propertyId.equals(LOCALE)) {
466 setLocale((Locale) state);
467 }
468 else if (propertyId.equals(ENTITY_RESOLVER)) {
469 fEntityManager.setProperty(ENTITY_RESOLVER, state);
470 }
471 else if (propertyId.equals(ERROR_REPORTER)) {
472 fErrorReporter = (XMLErrorReporter)state;
473 if (fErrorReporter.getMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN) == null) {
474 fErrorReporter.putMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN, new XSMessageFormatter());
475 }
476 }
477 else if (propertyId.equals(XML_SECURITY_PROPERTY_MANAGER)) {
478 XMLSecurityPropertyManager spm = (XMLSecurityPropertyManager)state;
479 faccessExternalSchema = spm.getValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA);
480 }
481 } // setProperty(String, Object)
482
483 /**
484 * Set the locale to use for messages.
485 *
486 * @param locale The locale object to use for localization of messages.
487 *
488 * @exception XNIException Thrown if the parser does not support the
489 * specified locale.
490 */
491 public void setLocale(Locale locale) {
492 fLocale = locale;
493 fErrorReporter.setLocale(locale);
494 } // setLocale(Locale)
495
496 /** Return the Locale the XMLGrammarLoader is using. */
497 public Locale getLocale() {
498 return fLocale;
499 } // getLocale(): Locale
500
501 /**
502 * Sets the error handler.
503 *
504 * @param errorHandler The error handler.
505 */
506 public void setErrorHandler(XMLErrorHandler errorHandler) {
507 fErrorReporter.setProperty(ERROR_HANDLER, errorHandler);
508 } // setErrorHandler(XMLErrorHandler)
509
510 /** Returns the registered error handler. */
511 public XMLErrorHandler getErrorHandler() {
512 return fErrorReporter.getErrorHandler();
513 } // getErrorHandler(): XMLErrorHandler
514
515 /**
516 * Sets the entity resolver.
517 *
518 * @param entityResolver The new entity resolver.
519 */
520 public void setEntityResolver(XMLEntityResolver entityResolver) {
521 fUserEntityResolver = entityResolver;
522 fLoaderConfig.setProperty(ENTITY_RESOLVER, entityResolver);
523 fEntityManager.setProperty(ENTITY_RESOLVER, entityResolver);
524 } // setEntityResolver(XMLEntityResolver)
525
526 /** Returns the registered entity resolver. */
527 public XMLEntityResolver getEntityResolver() {
528 return fUserEntityResolver;
529 } // getEntityResolver(): XMLEntityResolver
530
531 /**
532 * Returns a Grammar object by parsing the contents of the
533 * entities pointed to by sources.
534 *
535 * @param source the locations of the entity which forms
536 * the staring point of the grammars to be constructed
537 * @throws IOException when a problem is encounted reading the entity
538 * @throws XNIException when a condition arises (such as a FatalError) that requires parsing
539 * of the entity be terminated
540 */
541 public void loadGrammar(XMLInputSource source[])
542 throws IOException, XNIException {
543 int numSource = source.length;
544 for (int i = 0; i < numSource; ++i) {
545 loadGrammar(source[i]);
546 }
547 }
548
549 /**
550 * Returns a Grammar object by parsing the contents of the
551 * entity pointed to by source.
552 *
553 * @param source the location of the entity which forms
554 * the starting point of the grammar to be constructed.
555 * @throws IOException When a problem is encountered reading the entity
556 * XNIException When a condition arises (such as a FatalError) that requires parsing
557 * of the entity be terminated.
558 */
559 public Grammar loadGrammar(XMLInputSource source)
560 throws IOException, XNIException {
561
562 // REVISIT: this method should have a namespace parameter specified by
563 // user. In this case we can easily detect if a schema asked to be loaded
564 // is already in the local cache.
565
566 reset(fLoaderConfig);
567 fSettingsChanged = false;
568 XSDDescription desc = new XSDDescription();
569 desc.fContextType = XSDDescription.CONTEXT_PREPARSE;
570 desc.setBaseSystemId(source.getBaseSystemId());
571 desc.setLiteralSystemId( source.getSystemId());
572 // none of the other fields make sense for preparsing
573 Map<String, LocationArray> locationPairs = new HashMap<>();
574 // Process external schema location properties.
575 // We don't call tokenizeSchemaLocationStr here, because we also want
576 // to check whether the values are valid URI.
577 processExternalHints(fExternalSchemas, fExternalNoNSSchema,
578 locationPairs, fErrorReporter);
579 SchemaGrammar grammar = loadSchema(desc, source, locationPairs);
580
581 if(grammar != null && fGrammarPool != null) {
582 fGrammarPool.cacheGrammars(XMLGrammarDescription.XML_SCHEMA, fGrammarBucket.getGrammars());
583 // NOTE: we only need to verify full checking in case the schema was not provided via JAXP
584 // since full checking already verified for all JAXP schemas
585 if(fIsCheckedFully && fJAXPCache.get(grammar) != grammar) {
586 XSConstraints.fullSchemaChecking(fGrammarBucket, fSubGroupHandler, fCMBuilder, fErrorReporter);
587 }
588 }
589 return grammar;
590 } // loadGrammar(XMLInputSource): Grammar
591
592 /**
593 * This method is called either from XMLGrammarLoader.loadGrammar or from XMLSchemaValidator.
594 * Note: in either case, the EntityManager (or EntityResolvers) are not going to be invoked
595 * to resolve the location of the schema in XSDDescription
596 * @param desc
597 * @param source
598 * @param locationPairs
599 * @return An XML Schema grammar
600 * @throws IOException
601 * @throws XNIException
602 */
603 SchemaGrammar loadSchema(XSDDescription desc, XMLInputSource source,
604 Map<String, LocationArray> locationPairs) throws IOException, XNIException {
605
606 // this should only be done once per invocation of this object;
607 // unless application alters JAXPSource in the mean time.
608 if(!fJAXPProcessed) {
609 processJAXPSchemaSource(locationPairs);
610 }
611
612 if (desc.isExternal() && !source.isCreatedByResolver()) {
613 String accessError = SecuritySupport.checkAccess(desc.getExpandedSystemId(), faccessExternalSchema, Constants.ACCESS_EXTERNAL_ALL);
614 if (accessError != null) {
615 throw new XNIException(fErrorReporter.reportError(XSMessageFormatter.SCHEMA_DOMAIN,
616 "schema_reference.access",
617 new Object[] { SecuritySupport.sanitizePath(desc.getExpandedSystemId()), accessError }, XMLErrorReporter.SEVERITY_ERROR));
618 }
619 }
620 SchemaGrammar grammar = fSchemaHandler.parseSchema(source, desc, locationPairs);
621
622 return grammar;
623 } // loadSchema(XSDDescription, XMLInputSource): SchemaGrammar
624
625 /**
626 * This method tries to resolve location of the given schema.
627 * The loader stores the namespace/location pairs in a map (use "" as the
628 * namespace of absent namespace). When resolving an entity, loader first tries
629 * to find in the map whether there is a value for that namespace,
630 * if so, pass that location value to the user-defined entity resolver.
631 *
632 * @param desc
633 * @param locationPairs
634 * @param entityResolver
635 * @return the XMLInputSource
636 * @throws IOException
637 */
638 public static XMLInputSource resolveDocument(XSDDescription desc,
639 Map<String, LocationArray> locationPairs,
640 XMLEntityResolver entityResolver) throws IOException {
641 String loc = null;
642 // we consider the schema location properties for import
643 if (desc.getContextType() == XSDDescription.CONTEXT_IMPORT ||
644 desc.fromInstance()) {
645 // use empty string as the key for absent namespace
646 String namespace = desc.getTargetNamespace();
647 String ns = namespace == null ? XMLSymbols.EMPTY_STRING : namespace;
648 // get the location hint for that namespace
649 LocationArray tempLA = locationPairs.get(ns);
650 if(tempLA != null)
651 loc = tempLA.getFirstLocation();
652 }
653
654 // if it's not import, or if the target namespace is not set
655 // in the schema location properties, use location hint
656 if (loc == null) {
657 String[] hints = desc.getLocationHints();
658 if (hints != null && hints.length > 0)
659 loc = hints[0];
660 }
661
662 String expandedLoc = XMLEntityManager.expandSystemId(loc, desc.getBaseSystemId(), false);
663 desc.setLiteralSystemId(loc);
664 desc.setExpandedSystemId(expandedLoc);
665 return entityResolver.resolveEntity(desc);
666 }
667
668 // add external schema locations to the location pairs
669 public static void processExternalHints(String sl, String nsl,
670 Map<String, LocationArray> locations,
671 XMLErrorReporter er) {
672 if (sl != null) {
673 try {
674 // get the attribute decl for xsi:schemaLocation
675 // because external schema location property has the same syntax
676 // as xsi:schemaLocation
677 XSAttributeDecl attrDecl = SchemaGrammar.SG_XSI.getGlobalAttributeDecl(SchemaSymbols.XSI_SCHEMALOCATION);
678 // validation the string value to get the list of URI's
679 attrDecl.fType.validate(sl, null, null);
680 if (!tokenizeSchemaLocationStr(sl, locations, null)) {
681 // report warning (odd number of items)
682 er.reportError(XSMessageFormatter.SCHEMA_DOMAIN,
683 "SchemaLocation",
684 new Object[]{sl},
685 XMLErrorReporter.SEVERITY_WARNING);
686 }
687 }
688 catch (InvalidDatatypeValueException ex) {
689 // report warning (not list of URI's)
690 er.reportError(XSMessageFormatter.SCHEMA_DOMAIN,
691 ex.getKey(), ex.getArgs(),
692 XMLErrorReporter.SEVERITY_WARNING);
693 }
694 }
695
696 if (nsl != null) {
697 try {
698 // similarly for no ns schema location property
699 XSAttributeDecl attrDecl = SchemaGrammar.SG_XSI.getGlobalAttributeDecl(
700 SchemaSymbols.XSI_NONAMESPACESCHEMALOCATION);
701 attrDecl.fType.validate(nsl, null, null);
702 LocationArray la = locations.get(XMLSymbols.EMPTY_STRING);
703 if(la == null) {
704 la = new LocationArray();
705 locations.put(XMLSymbols.EMPTY_STRING, la);
706 }
707 la.addLocation(nsl);
708 }
709 catch (InvalidDatatypeValueException ex) {
710 // report warning (not a URI)
711 er.reportError(XSMessageFormatter.SCHEMA_DOMAIN,
712 ex.getKey(), ex.getArgs(),
713 XMLErrorReporter.SEVERITY_WARNING);
714 }
715 }
716 }
717 // this method takes a SchemaLocation string.
718 // If an error is encountered, false is returned;
719 // otherwise, true is returned. In either case, locations
720 // is augmented to include as many tokens as possible.
721 // @param schemaStr The schemaLocation string to tokenize
722 // @param locations HashMap mapping namespaces to LocationArray objects holding lists of locaitons
723 // @return true if no problems; false if string could not be tokenized
724 public static boolean tokenizeSchemaLocationStr(String schemaStr,
725 Map<String, XMLSchemaLoader.LocationArray> locations, String base) {
726 if (schemaStr!= null) {
727 StringTokenizer t = new StringTokenizer(schemaStr, " \n\t\r");
728 String namespace, location;
729 while (t.hasMoreTokens()) {
730 namespace = t.nextToken ();
731 if (!t.hasMoreTokens()) {
732 return false; // error!
733 }
734 location = t.nextToken();
735 LocationArray la = locations.get(namespace);
736 if(la == null) {
737 la = new LocationArray();
738 locations.put(namespace, la);
739 }
740 if (base != null) {
741 try {
742 location = XMLEntityManager.expandSystemId(location, base, false);
743 } catch (MalformedURIException e) {
744 }
745 }
746 la.addLocation(location);
747 }
748 }
749 return true;
750 } // tokenizeSchemaLocation(String, HashMap): boolean
751
752 /**
753 * Translate the various JAXP SchemaSource property types to XNI
754 * XMLInputSource. Valid types are: String, org.xml.sax.InputSource,
755 * InputStream, File, or Object[] of any of previous types.
756 * REVISIT: the JAXP 1.2 spec is less than clear as to whether this property
757 * should be available to imported schemas. I have assumed
758 * that it should. - NG
759 * Note: all JAXP schema files will be checked for full-schema validity if the feature was set up
760 *
761 */
762 private void processJAXPSchemaSource(
763 Map<String, LocationArray> locationPairs) throws IOException {
764 fJAXPProcessed = true;
765 if (fJAXPSource == null) {
766 return;
767 }
768
769 Class<?> componentType = fJAXPSource.getClass().getComponentType();
770 XMLInputSource xis = null;
771 String sid = null;
772 if (componentType == null) {
773 // Not an array
774 if (fJAXPSource instanceof InputStream ||
775 fJAXPSource instanceof InputSource) {
776 SchemaGrammar g = fJAXPCache.get(fJAXPSource);
777 if (g != null) {
778 fGrammarBucket.putGrammar(g);
779 return;
780 }
781 }
782 fXSDDescription.reset();
783 xis = xsdToXMLInputSource(fJAXPSource);
784 sid = xis.getSystemId();
785 fXSDDescription.fContextType = XSDDescription.CONTEXT_PREPARSE;
786 if (sid != null) {
787 fXSDDescription.setBaseSystemId(xis.getBaseSystemId());
788 fXSDDescription.setLiteralSystemId(sid);
789 fXSDDescription.setExpandedSystemId(sid);
790 fXSDDescription.fLocationHints = new String[]{sid};
791 }
792 SchemaGrammar g = loadSchema(fXSDDescription, xis, locationPairs);
793 // it is possible that we won't be able to resolve JAXP schema-source location
794 if (g != null) {
795 if (fJAXPSource instanceof InputStream ||
796 fJAXPSource instanceof InputSource) {
797 fJAXPCache.put(fJAXPSource, g);
798 if (fIsCheckedFully) {
799 XSConstraints.fullSchemaChecking(fGrammarBucket, fSubGroupHandler, fCMBuilder, fErrorReporter);
800 }
801 }
802 fGrammarBucket.putGrammar(g);
803 }
804 return;
805 }
806 else if ( (componentType != Object.class) &&
807 (componentType != String.class) &&
808 !File.class.isAssignableFrom(componentType) &&
809 !InputStream.class.isAssignableFrom(componentType) &&
810 !InputSource.class.isAssignableFrom(componentType) &&
811 !componentType.isInterface()
812 ) {
813 // Not an Object[], String[], File[], InputStream[], InputSource[]
814 MessageFormatter mf = fErrorReporter.getMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN);
815 throw new XMLConfigurationException(
816 Status.NOT_SUPPORTED,
817 mf.formatMessage(fErrorReporter.getLocale(), "jaxp12-schema-source-type.2",
818 new Object [] {componentType.getName()}));
819 }
820
821 // JAXP spec. allow []s of type String, File, InputStream,
822 // InputSource also, apart from [] of type Object.
823 Object[] objArr = (Object[]) fJAXPSource;
824 // make local array for storing target namespaces of schemasources specified in object arrays.
825 ArrayList<String> jaxpSchemaSourceNamespaces = new ArrayList<>();
826 for (int i = 0; i < objArr.length; i++) {
827 if (objArr[i] instanceof InputStream ||
828 objArr[i] instanceof InputSource) {
829 SchemaGrammar g = fJAXPCache.get(objArr[i]);
830 if (g != null) {
831 fGrammarBucket.putGrammar(g);
832 continue;
833 }
834 }
835 fXSDDescription.reset();
836 xis = xsdToXMLInputSource(objArr[i]);
837 sid = xis.getSystemId();
838 fXSDDescription.fContextType = XSDDescription.CONTEXT_PREPARSE;
839 if (sid != null) {
840 fXSDDescription.setBaseSystemId(xis.getBaseSystemId());
841 fXSDDescription.setLiteralSystemId(sid);
842 fXSDDescription.setExpandedSystemId(sid);
843 fXSDDescription.fLocationHints = new String[]{sid};
844 }
845 String targetNamespace = null ;
846 // load schema
847 SchemaGrammar grammar = fSchemaHandler.parseSchema(xis,fXSDDescription, locationPairs);
848
849 if (fIsCheckedFully) {
850 XSConstraints.fullSchemaChecking(fGrammarBucket, fSubGroupHandler, fCMBuilder, fErrorReporter);
851 }
852 if (grammar != null) {
853 targetNamespace = grammar.getTargetNamespace();
854 if (jaxpSchemaSourceNamespaces.contains(targetNamespace)) {
855 // when an array of objects is passed it is illegal to have two schemas that share same namespace.
856 MessageFormatter mf = fErrorReporter.getMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN);
857 throw new java.lang.IllegalArgumentException(mf.formatMessage(fErrorReporter.getLocale(),
858 "jaxp12-schema-source-ns", null));
859 }
860 else {
861 jaxpSchemaSourceNamespaces.add(targetNamespace) ;
862 }
863 if(objArr[i] instanceof InputStream ||
864 objArr[i] instanceof InputSource) {
865 fJAXPCache.put(objArr[i], grammar);
866 }
867 fGrammarBucket.putGrammar(grammar);
868 }
869 else {
870 //REVISIT: What should be the acutal behavior if grammar can't be loaded as specified in schema source?
871 }
872 }
873 }//processJAXPSchemaSource
874
875 private XMLInputSource xsdToXMLInputSource(Object val) {
876 if (val instanceof String) {
877 // String value is treated as a URI that is passed through the
878 // EntityResolver
879 String loc = (String) val;
880 fXSDDescription.reset();
881 fXSDDescription.setValues(null, loc, null, null);
882 XMLInputSource xis = null;
883 try {
884 xis = fEntityManager.resolveEntity(fXSDDescription);
885 }
886 catch (IOException ex) {
887 fErrorReporter.reportError(XSMessageFormatter.SCHEMA_DOMAIN,
888 "schema_reference.4",
889 new Object[] { loc }, XMLErrorReporter.SEVERITY_ERROR);
890 }
891 if (xis == null) {
892 // REVISIT: can this happen?
893 // Treat value as a URI and pass in as systemId
894 return new XMLInputSource(null, loc, null, false);
895 }
896 return xis;
897 }
898 else if (val instanceof InputSource) {
899 return saxToXMLInputSource((InputSource) val);
900 }
901 else if (val instanceof InputStream) {
902 return new XMLInputSource(null, null, null,
903 (InputStream) val, null);
904 }
905 else if (val instanceof File) {
906 File file = (File) val;
907 InputStream is = null;
908 try {
909 is = new BufferedInputStream(new FileInputStream(file));
910 } catch (FileNotFoundException ex) {
911 fErrorReporter.reportError(XSMessageFormatter.SCHEMA_DOMAIN,
912 "schema_reference.4", new Object[] { file.toString() },
913 XMLErrorReporter.SEVERITY_ERROR);
914 }
915 return new XMLInputSource(null, file.toURI().toString(), null, is, null);
916 }
917 MessageFormatter mf = fErrorReporter.getMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN);
918 throw new XMLConfigurationException(
919 Status.NOT_SUPPORTED,
920 mf.formatMessage(fErrorReporter.getLocale(), "jaxp12-schema-source-type.1",
921 new Object [] {val != null ? val.getClass().getName() : "null"}));
922 }
923
924
925 //Convert a SAX InputSource to an equivalent XNI XMLInputSource
926
927 private static XMLInputSource saxToXMLInputSource(InputSource sis) {
928 String publicId = sis.getPublicId();
929 String systemId = sis.getSystemId();
930
931 Reader charStream = sis.getCharacterStream();
932 if (charStream != null) {
933 return new XMLInputSource(publicId, systemId, null, charStream,
934 null);
935 }
936
937 InputStream byteStream = sis.getByteStream();
938 if (byteStream != null) {
939 return new XMLInputSource(publicId, systemId, null, byteStream,
940 sis.getEncoding());
941 }
942
943 return new XMLInputSource(publicId, systemId, null, false);
944 }
945
946 public static class LocationArray{
947
948 int length ;
949 String [] locations = new String[2];
950
951 public void resize(int oldLength , int newLength){
952 String [] temp = new String[newLength] ;
953 System.arraycopy(locations, 0, temp, 0, Math.min(oldLength, newLength));
954 locations = temp ;
955 length = Math.min(oldLength, newLength);
956 }
957
958 public void addLocation(String location){
959 if(length >= locations.length ){
960 resize(length, Math.max(1, length*2));
961 }
962 locations[length++] = location;
963 }//setLocation()
964
965 public String [] getLocationArray(){
966 if(length < locations.length ){
967 resize(locations.length, length);
968 }
969 return locations;
970 }//getLocationArray()
971
972 public String getFirstLocation(){
973 return length > 0 ? locations[0] : null;
974 }
975
976 public int getLength(){
977 return length ;
978 }
979
980 } //locationArray
981
982 /* (non-Javadoc)
983 * @see com.sun.org.apache.xerces.internal.xni.parser.XMLComponent#getFeatureDefault(java.lang.String)
984 */
985 public Boolean getFeatureDefault(String featureId) {
986 if (featureId.equals(AUGMENT_PSVI)){
987 return Boolean.TRUE;
988 }
989 return null;
990 }
991
992 /* (non-Javadoc)
993 * @see com.sun.org.apache.xerces.internal.xni.parser.XMLComponent#getPropertyDefault(java.lang.String)
994 */
995 public Object getPropertyDefault(String propertyId) {
996 // TODO Auto-generated method stub
997 return null;
998 }
999
1000 /* (non-Javadoc)
1001 * @see com.sun.org.apache.xerces.internal.xni.parser.XMLComponent#reset(com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager)
1002 */
1003 public void reset(XMLComponentManager componentManager) throws XMLConfigurationException {
1004
1005 XMLSecurityPropertyManager spm = (XMLSecurityPropertyManager)componentManager.getProperty(XML_SECURITY_PROPERTY_MANAGER);
1006 if (spm == null) {
1007 spm = new XMLSecurityPropertyManager();
1008 setProperty(XML_SECURITY_PROPERTY_MANAGER, spm);
1009 }
1010
1011 XMLSecurityManager sm = (XMLSecurityManager)componentManager.getProperty(SECURITY_MANAGER);
1012 if (sm == null)
1013 setProperty(SECURITY_MANAGER,new XMLSecurityManager(true));
1014
1015 faccessExternalSchema = spm.getValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA);
1016
1017 fGrammarBucket.reset();
1018
1019 fSubGroupHandler.reset();
1020
1021 boolean parser_settings = true;
1022 // If the component manager is the loader config don't bother querying it since it doesn't
1023 // recognize the PARSER_SETTINGS feature. Prevents an XMLConfigurationException from being
1024 // thrown.
1025 if (componentManager != fLoaderConfig) {
1026 parser_settings = componentManager.getFeature(PARSER_SETTINGS, true);
1027 }
1028
1029 if (!parser_settings || !fSettingsChanged){
1030 // need to reprocess JAXP schema sources
1031 fJAXPProcessed = false;
1032 // reinitialize grammar bucket
1033 initGrammarBucket();
1034 if (fDeclPool != null) {
1035 fDeclPool.reset();
1036 }
1037 return;
1038 }
1039
1040 //pass the component manager to the factory..
1041 fNodeFactory.reset(componentManager);
1042
1043 // get registered entity manager to be able to resolve JAXP schema-source property:
1044 // Note: in case XMLSchemaValidator has created the loader,
1045 // the entity manager property is null
1046 fEntityManager = (XMLEntityManager)componentManager.getProperty(ENTITY_MANAGER);
1047
1048 // get the error reporter
1049 fErrorReporter = (XMLErrorReporter)componentManager.getProperty(ERROR_REPORTER);
1050
1051 // Determine schema dv factory to use
1052 SchemaDVFactory dvFactory = null;
1053 dvFactory = fSchemaHandler.getDVFactory();
1054 if (dvFactory == null) {
1055 dvFactory = SchemaDVFactory.getInstance();
1056 fSchemaHandler.setDVFactory(dvFactory);
1057 }
1058
1059 // get schema location properties
1060 try {
1061 fExternalSchemas = (String) componentManager.getProperty(SCHEMA_LOCATION);
1062 fExternalNoNSSchema = (String) componentManager.getProperty(SCHEMA_NONS_LOCATION);
1063 } catch (XMLConfigurationException e) {
1064 fExternalSchemas = null;
1065 fExternalNoNSSchema = null;
1066 }
1067
1068 // get JAXP sources if available
1069 fJAXPSource = componentManager.getProperty(JAXP_SCHEMA_SOURCE, null);
1070 fJAXPProcessed = false;
1071
1072 // clear grammars, and put the one for schema namespace there
1073 fGrammarPool = (XMLGrammarPool) componentManager.getProperty(XMLGRAMMAR_POOL, null);
1074 initGrammarBucket();
1075
1076 boolean psvi = componentManager.getFeature(AUGMENT_PSVI, false);
1077
1078 // Only use the decl pool when there is no chance that the schema
1079 // components will be exposed or cached.
1080 // TODO: when someone calls loadGrammar(XMLInputSource), the schema is
1081 // always exposed even without the use of a grammar pool.
1082 // Disabling the "decl pool" feature for now until we understand when
1083 // it can be safely used.
1084 if (!psvi && fGrammarPool == null && false) {
1085 if (fDeclPool != null) {
1086 fDeclPool.reset();
1087 }
1088 else {
1089 fDeclPool = new XSDeclarationPool();
1090 }
1091 fCMBuilder.setDeclPool(fDeclPool);
1092 fSchemaHandler.setDeclPool(fDeclPool);
1093 if (dvFactory instanceof SchemaDVFactoryImpl) {
1094 fDeclPool.setDVFactory((SchemaDVFactoryImpl)dvFactory);
1095 ((SchemaDVFactoryImpl)dvFactory).setDeclPool(fDeclPool);
1096 }
1097 } else {
1098 fCMBuilder.setDeclPool(null);
1099 fSchemaHandler.setDeclPool(null);
1100 if (dvFactory instanceof SchemaDVFactoryImpl) {
1101 ((SchemaDVFactoryImpl)dvFactory).setDeclPool(null);
1102 }
1103 }
1104
1105 // get continue-after-fatal-error feature
1106 try {
1107 boolean fatalError = componentManager.getFeature(CONTINUE_AFTER_FATAL_ERROR, false);
1108 if (!fatalError) {
1109 fErrorReporter.setFeature(CONTINUE_AFTER_FATAL_ERROR, fatalError);
1110 }
1111 } catch (XMLConfigurationException e) {
1112 }
1113 // set full validation to false
1114 fIsCheckedFully = componentManager.getFeature(SCHEMA_FULL_CHECKING, false);
1115
1116 // get generate-synthetic-annotations feature
1117 fSchemaHandler.setGenerateSyntheticAnnotations(componentManager.getFeature(GENERATE_SYNTHETIC_ANNOTATIONS, false));
1118 fSchemaHandler.reset(componentManager);
1119 }
1120
1121 private void initGrammarBucket(){
1122 if(fGrammarPool != null) {
1123 Grammar [] initialGrammars = fGrammarPool.retrieveInitialGrammarSet(XMLGrammarDescription.XML_SCHEMA);
1124 final int length = (initialGrammars != null) ? initialGrammars.length : 0;
1125 for (int i = 0; i < length; ++i) {
1126 // put this grammar into the bucket, along with grammars
1127 // imported by it (directly or indirectly)
1128 if (!fGrammarBucket.putGrammar((SchemaGrammar)(initialGrammars[i]), true)) {
1129 // REVISIT: a conflict between new grammar(s) and grammars
1130 // in the bucket. What to do? A warning? An exception?
1131 fErrorReporter.reportError(XSMessageFormatter.SCHEMA_DOMAIN,
1132 "GrammarConflict", null,
1133 XMLErrorReporter.SEVERITY_WARNING);
1134 }
1135 }
1136 }
1137 }
1138
1139
1140 /* (non-Javadoc)
1141 * @see com.sun.org.apache.xerces.internal.xs.XSLoader#getConfig()
1142 */
1143 public DOMConfiguration getConfig() {
1144 return this;
1145 }
1146
1147 /* (non-Javadoc)
1148 * @see com.sun.org.apache.xerces.internal.xs.XSLoader#load(org.w3c.dom.ls.LSInput)
1149 */
1150 public XSModel load(LSInput is) {
1151 try {
1152 Grammar g = loadGrammar(dom2xmlInputSource(is));
1153 return ((XSGrammar) g).toXSModel();
1154 } catch (Exception e) {
1155 reportDOMFatalError(e);
1156 return null;
1157 }
1158 }
1159
1160 /* (non-Javadoc)
1161 * @see com.sun.org.apache.xerces.internal.xs.XSLoader#loadInputList(com.sun.org.apache.xerces.internal.xs.LSInputList)
1162 */
1163 public XSModel loadInputList(LSInputList is) {
1164 int length = is.getLength();
1165 SchemaGrammar[] gs = new SchemaGrammar[length];
1166 for (int i = 0; i < length; i++) {
1167 try {
1168 gs[i] = (SchemaGrammar) loadGrammar(dom2xmlInputSource(is.item(i)));
1169 } catch (Exception e) {
1170 reportDOMFatalError(e);
1171 return null;
1172 }
1173 }
1174 return new XSModelImpl(gs);
1175 }
1176
1177 /* (non-Javadoc)
1178 * @see com.sun.org.apache.xerces.internal.xs.XSLoader#loadURI(java.lang.String)
1179 */
1180 public XSModel loadURI(String uri) {
1181 try {
1182 Grammar g = loadGrammar(new XMLInputSource(null, uri, null, false));
1183 return ((XSGrammar)g).toXSModel();
1184 }
1185 catch (Exception e){
1186 reportDOMFatalError(e);
1187 return null;
1188 }
1189 }
1190
1191 /* (non-Javadoc)
1192 * @see com.sun.org.apache.xerces.internal.xs.XSLoader#loadURIList(com.sun.org.apache.xerces.internal.xs.StringList)
1193 */
1194 public XSModel loadURIList(StringList uriList) {
1195 int length = uriList.getLength();
1196 SchemaGrammar[] gs = new SchemaGrammar[length];
1197 for (int i = 0; i < length; i++) {
1198 try {
1199 gs[i] =
1200 (SchemaGrammar) loadGrammar(new XMLInputSource(null, uriList.item(i), null, false));
1201 } catch (Exception e) {
1202 reportDOMFatalError(e);
1203 return null;
1204 }
1205 }
1206 return new XSModelImpl(gs);
1207 }
1208
1209 void reportDOMFatalError(Exception e) {
1210 if (fErrorHandler != null) {
1211 DOMErrorImpl error = new DOMErrorImpl();
1212 error.fException = e;
1213 error.fMessage = e.getMessage();
1214 error.fSeverity = DOMError.SEVERITY_FATAL_ERROR;
1215 fErrorHandler.getErrorHandler().handleError(error);
1216 }
1217 }
1218
1219 /* (non-Javadoc)
1220 * @see DOMConfiguration#canSetParameter(String, Object)
1221 */
1222 public boolean canSetParameter(String name, Object value) {
1223 if(value instanceof Boolean){
1224 if (name.equals(Constants.DOM_VALIDATE) ||
1225 name.equals(SCHEMA_FULL_CHECKING) ||
1226 name.equals(VALIDATE_ANNOTATIONS) ||
1227 name.equals(CONTINUE_AFTER_FATAL_ERROR) ||
1228 name.equals(ALLOW_JAVA_ENCODINGS) ||
1229 name.equals(STANDARD_URI_CONFORMANT_FEATURE) ||
1230 name.equals(GENERATE_SYNTHETIC_ANNOTATIONS) ||
1231 name.equals(HONOUR_ALL_SCHEMALOCATIONS) ||
1232 name.equals(NAMESPACE_GROWTH) ||
1233 name.equals(TOLERATE_DUPLICATES) ||
1234 name.equals(USE_SERVICE_MECHANISM)) {
1235 return true;
1236
1237 }
1238 return false;
1239 }
1240 if (name.equals(Constants.DOM_ERROR_HANDLER) ||
1241 name.equals(Constants.DOM_RESOURCE_RESOLVER) ||
1242 name.equals(SYMBOL_TABLE) ||
1243 name.equals(ERROR_REPORTER) ||
1244 name.equals(ERROR_HANDLER) ||
1245 name.equals(ENTITY_RESOLVER) ||
1246 name.equals(XMLGRAMMAR_POOL) ||
1247 name.equals(SCHEMA_LOCATION) ||
1248 name.equals(SCHEMA_NONS_LOCATION) ||
1249 name.equals(JAXP_SCHEMA_SOURCE) ||
1250 name.equals(SCHEMA_DV_FACTORY)) {
1251 return true;
1252 }
1253 return false;
1254 }
1255
1256 /* (non-Javadoc)
1257 * @see DOMConfiguration#getParameter(String)
1258 */
1259 public Object getParameter(String name) throws DOMException {
1260
1261 if (name.equals(Constants.DOM_ERROR_HANDLER)){
1262 return (fErrorHandler != null) ? fErrorHandler.getErrorHandler() : null;
1263 }
1264 else if (name.equals(Constants.DOM_RESOURCE_RESOLVER)) {
1265 return (fResourceResolver != null) ? fResourceResolver.getEntityResolver() : null;
1266 }
1267
1268 try {
1269 boolean feature = getFeature(name);
1270 return (feature) ? Boolean.TRUE : Boolean.FALSE;
1271 } catch (Exception e) {
1272 Object property;
1273 try {
1274 property = getProperty(name);
1275 return property;
1276 } catch (Exception ex) {
1277 String msg =
1278 DOMMessageFormatter.formatMessage(
1279 DOMMessageFormatter.DOM_DOMAIN,
1280 "FEATURE_NOT_SUPPORTED",
1281 new Object[] { name });
1282 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
1283 }
1284 }
1285 }
1286
1287 /* (non-Javadoc)
1288 * @see DOMConfiguration#getParameterNames()
1289 */
1290 public DOMStringList getParameterNames() {
1291 if (fRecognizedParameters == null){
1292 ArrayList<String> v = new ArrayList<>();
1293 v.add(Constants.DOM_VALIDATE);
1294 v.add(Constants.DOM_ERROR_HANDLER);
1295 v.add(Constants.DOM_RESOURCE_RESOLVER);
1296 v.add(SYMBOL_TABLE);
1297 v.add(ERROR_REPORTER);
1298 v.add(ERROR_HANDLER);
1299 v.add(ENTITY_RESOLVER);
1300 v.add(XMLGRAMMAR_POOL);
1301 v.add(SCHEMA_LOCATION);
1302 v.add(SCHEMA_NONS_LOCATION);
1303 v.add(JAXP_SCHEMA_SOURCE);
1304 v.add(SCHEMA_FULL_CHECKING);
1305 v.add(CONTINUE_AFTER_FATAL_ERROR);
1306 v.add(ALLOW_JAVA_ENCODINGS);
1307 v.add(STANDARD_URI_CONFORMANT_FEATURE);
1308 v.add(VALIDATE_ANNOTATIONS);
1309 v.add(GENERATE_SYNTHETIC_ANNOTATIONS);
1310 v.add(HONOUR_ALL_SCHEMALOCATIONS);
1311 v.add(NAMESPACE_GROWTH);
1312 v.add(TOLERATE_DUPLICATES);
1313 v.add(USE_SERVICE_MECHANISM);
1314 fRecognizedParameters = new DOMStringListImpl(v);
1315 }
1316 return fRecognizedParameters;
1317 }
1318
1319 /* (non-Javadoc)
1320 * @see DOMConfiguration#setParameter(String, Object)
1321 */
1322 public void setParameter(String name, Object value) throws DOMException {
1323 if (value instanceof Boolean) {
1324 boolean state = ((Boolean) value).booleanValue();
1325 if (name.equals("validate") && state) {
1326 return;
1327 }
1328 try {
1329 setFeature(name, state);
1330 } catch (Exception e) {
1331 String msg =
1332 DOMMessageFormatter.formatMessage(
1333 DOMMessageFormatter.DOM_DOMAIN,
1334 "FEATURE_NOT_SUPPORTED",
1335 new Object[] { name });
1336 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
1337 }
1338 return;
1339 }
1340 if (name.equals(Constants.DOM_ERROR_HANDLER)) {
1341 if (value instanceof DOMErrorHandler) {
1342 try {
1343 fErrorHandler = new DOMErrorHandlerWrapper((DOMErrorHandler) value);
1344 setErrorHandler(fErrorHandler);
1345 } catch (XMLConfigurationException e) {
1346 }
1347 } else {
1348 // REVISIT: type mismatch
1349 String msg =
1350 DOMMessageFormatter.formatMessage(
1351 DOMMessageFormatter.DOM_DOMAIN,
1352 "FEATURE_NOT_SUPPORTED",
1353 new Object[] { name });
1354 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
1355 }
1356 return;
1357
1358 }
1359 if (name.equals(Constants.DOM_RESOURCE_RESOLVER)) {
1360 if (value instanceof LSResourceResolver) {
1361 try {
1362 fResourceResolver = new DOMEntityResolverWrapper((LSResourceResolver) value);
1363 setEntityResolver(fResourceResolver);
1364 }
1365 catch (XMLConfigurationException e) {}
1366 } else {
1367 // REVISIT: type mismatch
1368 String msg =
1369 DOMMessageFormatter.formatMessage(
1370 DOMMessageFormatter.DOM_DOMAIN,
1371 "FEATURE_NOT_SUPPORTED",
1372 new Object[] { name });
1373 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
1374 }
1375 return;
1376 }
1377
1378 try {
1379 setProperty(name, value);
1380 } catch (Exception ex) {
1381
1382 String msg =
1383 DOMMessageFormatter.formatMessage(
1384 DOMMessageFormatter.DOM_DOMAIN,
1385 "FEATURE_NOT_SUPPORTED",
1386 new Object[] { name });
1387 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
1388
1389 }
1390
1391 }
1392
1393 XMLInputSource dom2xmlInputSource(LSInput is) {
1394 // need to wrap the LSInput with an XMLInputSource
1395 XMLInputSource xis = null;
1396
1397 /**
1398 * An LSParser looks at inputs specified in LSInput in
1399 * the following order: characterStream, byteStream,
1400 * stringData, systemId, publicId. For consistency
1401 * have the same behaviour for XSLoader.
1402 */
1403
1404 // check whether there is a Reader
1405 // according to DOM, we need to treat such reader as "UTF-16".
1406 if (is.getCharacterStream() != null) {
1407 xis = new XMLInputSource(is.getPublicId(), is.getSystemId(),
1408 is.getBaseURI(), is.getCharacterStream(),
1409 "UTF-16");
1410 }
1411 // check whether there is an InputStream
1412 else if (is.getByteStream() != null) {
1413 xis = new XMLInputSource(is.getPublicId(), is.getSystemId(),
1414 is.getBaseURI(), is.getByteStream(),
1415 is.getEncoding());
1416 }
1417 // if there is a string data, use a StringReader
1418 // according to DOM, we need to treat such data as "UTF-16".
1419 else if (is.getStringData() != null && is.getStringData().length() != 0) {
1420 xis = new XMLInputSource(is.getPublicId(), is.getSystemId(),
1421 is.getBaseURI(), new StringReader(is.getStringData()),
1422 "UTF-16");
1423 }
1424 // otherwise, just use the public/system/base Ids
1425 else {
1426 xis = new XMLInputSource(is.getPublicId(), is.getSystemId(),
1427 is.getBaseURI(), false);
1428 }
1429
1430 return xis;
1431 }
1432
1433 // Implements XSElementDeclHelper interface
1434 public XSElementDecl getGlobalElementDecl(QName element) {
1435 SchemaGrammar sGrammar = fGrammarBucket.getGrammar(element.uri);
1436 if (sGrammar != null) {
1437 return sGrammar.getGlobalElementDecl(element.localpart);
1438 }
1439 return null;
1440 }
1441
1442 } // XMLGrammarLoader
--- EOF ---