1 /*
2 * Copyright (c) 2013, 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.jaxp.validation;
22
23 import com.sun.org.apache.xerces.internal.impl.Constants;
24 import com.sun.org.apache.xerces.internal.impl.XMLEntityManager;
25 import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
26 import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType;
27 import com.sun.org.apache.xerces.internal.impl.validation.EntityState;
28 import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager;
29 import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator;
30 import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl;
31 import com.sun.org.apache.xerces.internal.util.AttributesProxy;
32 import com.sun.org.apache.xerces.internal.util.SAXLocatorWrapper;
33 import com.sun.org.apache.xerces.internal.util.SAXMessageFormatter;
34 import com.sun.org.apache.xerces.internal.util.Status;
35 import com.sun.org.apache.xerces.internal.util.SymbolTable;
36 import com.sun.org.apache.xerces.internal.util.URI;
37 import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl;
38 import com.sun.org.apache.xerces.internal.util.XMLSymbols;
39 import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
40 import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager;
41 import com.sun.org.apache.xerces.internal.xni.Augmentations;
42 import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
43 import com.sun.org.apache.xerces.internal.xni.QName;
44 import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
45 import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
46 import com.sun.org.apache.xerces.internal.xni.XMLLocator;
47 import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
48 import com.sun.org.apache.xerces.internal.xni.XMLString;
49 import com.sun.org.apache.xerces.internal.xni.XNIException;
50 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
51 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
52 import com.sun.org.apache.xerces.internal.xni.parser.XMLParseException;
53 import com.sun.org.apache.xerces.internal.xs.AttributePSVI;
54 import com.sun.org.apache.xerces.internal.xs.ElementPSVI;
55 import com.sun.org.apache.xerces.internal.xs.ItemPSVI;
56 import com.sun.org.apache.xerces.internal.xs.PSVIProvider;
57 import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
58 import java.io.IOException;
59 import java.io.InputStream;
60 import java.io.Reader;
61 import java.io.StringReader;
62 import java.util.HashMap;
63 import java.util.Map;
64 import javax.xml.XMLConstants;
65 import javax.xml.parsers.FactoryConfigurationError;
66 import javax.xml.parsers.SAXParserFactory;
67 import javax.xml.transform.Result;
68 import javax.xml.transform.Source;
69 import javax.xml.transform.sax.SAXResult;
70 import javax.xml.transform.sax.SAXSource;
71 import javax.xml.validation.TypeInfoProvider;
72 import javax.xml.validation.ValidatorHandler;
73 import jdk.xml.internal.JdkXmlUtils;
74 import org.w3c.dom.TypeInfo;
75 import org.w3c.dom.ls.LSInput;
76 import org.w3c.dom.ls.LSResourceResolver;
77 import org.xml.sax.Attributes;
78 import org.xml.sax.ContentHandler;
79 import org.xml.sax.DTDHandler;
80 import org.xml.sax.ErrorHandler;
81 import org.xml.sax.InputSource;
82 import org.xml.sax.Locator;
83 import org.xml.sax.SAXException;
84 import org.xml.sax.SAXNotRecognizedException;
85 import org.xml.sax.SAXNotSupportedException;
86 import org.xml.sax.XMLReader;
87 import org.xml.sax.ext.Attributes2;
88 import org.xml.sax.ext.EntityResolver2;
89
90 /**
91 * <p>Implementation of ValidatorHandler for W3C XML Schemas and
92 * also a validator helper for <code>SAXSource</code>s.</p>
93 *
94 * @author Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
95 * @author Michael Glavassevich, IBM
96 *
97 * @LastModified: Oct 2017
98 */
99 final class ValidatorHandlerImpl extends ValidatorHandler implements
100 DTDHandler, EntityState, PSVIProvider, ValidatorHelper, XMLDocumentHandler {
101
102 // feature identifiers
103
104 /** Feature identifier: namespace prefixes. */
105 private static final String NAMESPACE_PREFIXES =
106 Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACE_PREFIXES_FEATURE;
107
108 /** Feature identifier: string interning. */
109 protected static final String STRING_INTERNING =
110 Constants.SAX_FEATURE_PREFIX + Constants.STRING_INTERNING_FEATURE;
111
112 // property identifiers
113
114 /** Property identifier: error reporter. */
115 private static final String ERROR_REPORTER =
116 Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
117
118 /** Property identifier: namespace context. */
119 private static final String NAMESPACE_CONTEXT =
120 Constants.XERCES_PROPERTY_PREFIX + Constants.NAMESPACE_CONTEXT_PROPERTY;
121
122 /** Property identifier: XML Schema validator. */
123 private static final String SCHEMA_VALIDATOR =
124 Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_VALIDATOR_PROPERTY;
125
126 /** Property identifier: security manager. */
127 private static final String SECURITY_MANAGER =
128 Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY;
129
130 /** Property identifier: symbol table. */
131 private static final String SYMBOL_TABLE =
132 Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
133
134 /** Property identifier: validation manager. */
135 private static final String VALIDATION_MANAGER =
136 Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
137
138 /** Property identifier: Security property manager. */
139 private static final String XML_SECURITY_PROPERTY_MANAGER =
140 Constants.XML_SECURITY_PROPERTY_MANAGER;
141
142 //
143 // Data
144 //
145
146 /** Error reporter. */
147 private XMLErrorReporter fErrorReporter;
148
149 /** The namespace context of this document: stores namespaces in scope */
150 private NamespaceContext fNamespaceContext;
151
152 /** Schema validator. **/
153 private XMLSchemaValidator fSchemaValidator;
154
155 /** Symbol table **/
156 private SymbolTable fSymbolTable;
157
158 /** Validation manager. */
159 private ValidationManager fValidationManager;
160
161 /** Component manager. **/
162 private XMLSchemaValidatorComponentManager fComponentManager;
163
164 /** XML Locator wrapper for SAX. **/
165 private final SAXLocatorWrapper fSAXLocatorWrapper = new SAXLocatorWrapper();
166
167 /** Flag used to track whether the namespace context needs to be pushed. */
168 private boolean fNeedPushNSContext = true;
169
170 /** Map for tracking unparsed entities. */
171 private Map<String, String> fUnparsedEntities = null;
172
173 /** Flag used to track whether XML names and Namespace URIs have been internalized. */
174 private boolean fStringsInternalized = false;
175
176 /** Fields for start element, end element and characters. */
177 private final QName fElementQName = new QName();
178 private final QName fAttributeQName = new QName();
179 private final XMLAttributesImpl fAttributes = new XMLAttributesImpl();
180 private final AttributesProxy fAttrAdapter = new AttributesProxy(fAttributes);
181 private final XMLString fTempString = new XMLString();
182
183 //
184 // User Objects
185 //
186
187 private ContentHandler fContentHandler = null;
188
189 /*
190 * Constructors
191 */
192
193 public ValidatorHandlerImpl(XSGrammarPoolContainer grammarContainer) {
194 this(new XMLSchemaValidatorComponentManager(grammarContainer));
195 fComponentManager.addRecognizedFeatures(new String [] {NAMESPACE_PREFIXES});
196 fComponentManager.setFeature(NAMESPACE_PREFIXES, false);
197 setErrorHandler(null);
198 setResourceResolver(null);
199 }
200
201 public ValidatorHandlerImpl(XMLSchemaValidatorComponentManager componentManager) {
202 fComponentManager = componentManager;
203 fErrorReporter = (XMLErrorReporter) fComponentManager.getProperty(ERROR_REPORTER);
204 fNamespaceContext = (NamespaceContext) fComponentManager.getProperty(NAMESPACE_CONTEXT);
205 fSchemaValidator = (XMLSchemaValidator) fComponentManager.getProperty(SCHEMA_VALIDATOR);
206 fSymbolTable = (SymbolTable) fComponentManager.getProperty(SYMBOL_TABLE);
207 fValidationManager = (ValidationManager) fComponentManager.getProperty(VALIDATION_MANAGER);
208 }
209
210 /*
211 * ValidatorHandler methods
212 */
213
214 public void setContentHandler(ContentHandler receiver) {
215 fContentHandler = receiver;
216 }
217
218 public ContentHandler getContentHandler() {
219 return fContentHandler;
220 }
221
222 public void setErrorHandler(ErrorHandler errorHandler) {
223 fComponentManager.setErrorHandler(errorHandler);
224 }
225
226 public ErrorHandler getErrorHandler() {
227 return fComponentManager.getErrorHandler();
228 }
229
230 public void setResourceResolver(LSResourceResolver resourceResolver) {
231 fComponentManager.setResourceResolver(resourceResolver);
232 }
233
234 public LSResourceResolver getResourceResolver() {
235 return fComponentManager.getResourceResolver();
236 }
237
238 public TypeInfoProvider getTypeInfoProvider() {
239 return fTypeInfoProvider;
240 }
241
242 public boolean getFeature(String name)
243 throws SAXNotRecognizedException, SAXNotSupportedException {
244 if (name == null) {
245 throw new NullPointerException();
246 }
247 try {
248 return fComponentManager.getFeature(name);
249 }
250 catch (XMLConfigurationException e) {
251 final String identifier = e.getIdentifier();
252 final String key = e.getType() == Status.NOT_RECOGNIZED ?
253 "feature-not-recognized" : "feature-not-supported";
254 throw new SAXNotRecognizedException(
255 SAXMessageFormatter.formatMessage(fComponentManager.getLocale(),
256 key, new Object [] {identifier}));
257 }
258 }
259
260 public void setFeature(String name, boolean value)
261 throws SAXNotRecognizedException, SAXNotSupportedException {
262 if (name == null) {
263 throw new NullPointerException();
264 }
265 try {
266 fComponentManager.setFeature(name, value);
267 }
268 catch (XMLConfigurationException e) {
269 final String identifier = e.getIdentifier();
270 final String key;
271 if (e.getType() == Status.NOT_ALLOWED) {
272 //for now, the identifier can only be (XMLConstants.FEATURE_SECURE_PROCESSING)
273 throw new SAXNotSupportedException(
274 SAXMessageFormatter.formatMessage(fComponentManager.getLocale(),
275 "jaxp-secureprocessing-feature", null));
276 } else if (e.getType() == Status.NOT_RECOGNIZED) {
277 key = "feature-not-recognized";
278 } else {
279 key = "feature-not-supported";
280 }
281 throw new SAXNotRecognizedException(
282 SAXMessageFormatter.formatMessage(fComponentManager.getLocale(),
283 key, new Object [] {identifier}));
284 }
285 }
286
287 public Object getProperty(String name)
288 throws SAXNotRecognizedException, SAXNotSupportedException {
289 if (name == null) {
290 throw new NullPointerException();
291 }
292 try {
293 return fComponentManager.getProperty(name);
294 }
295 catch (XMLConfigurationException e) {
296 final String identifier = e.getIdentifier();
297 final String key = e.getType() == Status.NOT_RECOGNIZED ?
298 "property-not-recognized" : "property-not-supported";
299 throw new SAXNotRecognizedException(
300 SAXMessageFormatter.formatMessage(fComponentManager.getLocale(),
301 key, new Object [] {identifier}));
302 }
303 }
304
305 public void setProperty(String name, Object object)
306 throws SAXNotRecognizedException, SAXNotSupportedException {
307 if (name == null) {
308 throw new NullPointerException();
309 }
310 try {
311 fComponentManager.setProperty(name, object);
312 }
313 catch (XMLConfigurationException e) {
314 final String identifier = e.getIdentifier();
315 final String key = e.getType() == Status.NOT_RECOGNIZED ?
316 "property-not-recognized" : "property-not-supported";
317 throw new SAXNotRecognizedException(
318 SAXMessageFormatter.formatMessage(fComponentManager.getLocale(),
319 key, new Object [] {identifier}));
320 }
321 }
322
323 /*
324 * EntityState methods
325 */
326
327 public boolean isEntityDeclared(String name) {
328 return false;
329 }
330
331 public boolean isEntityUnparsed(String name) {
332 if (fUnparsedEntities != null) {
333 return fUnparsedEntities.containsKey(name);
334 }
335 return false;
336 }
337
338 /*
339 * XMLDocumentHandler methods
340 */
341
342 public void startDocument(XMLLocator locator, String encoding,
343 NamespaceContext namespaceContext, Augmentations augs)
344 throws XNIException {
345 if (fContentHandler != null) {
346 try {
347 fContentHandler.startDocument();
348 }
349 catch (SAXException e) {
350 throw new XNIException(e);
351 }
352 }
353 }
354
355 public void xmlDecl(String version, String encoding, String standalone,
356 Augmentations augs) throws XNIException {}
357
358 public void doctypeDecl(String rootElement, String publicId,
359 String systemId, Augmentations augs) throws XNIException {}
360
361 public void comment(XMLString text, Augmentations augs) throws XNIException {}
362
363 public void processingInstruction(String target, XMLString data,
364 Augmentations augs) throws XNIException {
365 if (fContentHandler != null) {
366 try {
367 fContentHandler.processingInstruction(target, data.toString());
368 }
369 catch (SAXException e) {
370 throw new XNIException(e);
371 }
372 }
373 }
374
375 public void startElement(QName element, XMLAttributes attributes,
376 Augmentations augs) throws XNIException {
377 if (fContentHandler != null) {
378 try {
379 fTypeInfoProvider.beginStartElement(augs, attributes);
380 fContentHandler.startElement((element.uri != null) ? element.uri : XMLSymbols.EMPTY_STRING,
381 element.localpart, element.rawname, fAttrAdapter);
382 }
383 catch (SAXException e) {
384 throw new XNIException(e);
385 }
386 finally {
387 fTypeInfoProvider.finishStartElement();
388 }
389 }
390 }
391
392 public void emptyElement(QName element, XMLAttributes attributes,
393 Augmentations augs) throws XNIException {
394 /** Split empty element event. **/
395 startElement(element, attributes, augs);
396 endElement(element, augs);
397 }
398
399 public void startGeneralEntity(String name,
400 XMLResourceIdentifier identifier, String encoding,
401 Augmentations augs) throws XNIException {}
402
403 public void textDecl(String version, String encoding, Augmentations augs)
404 throws XNIException {}
405
406 public void endGeneralEntity(String name, Augmentations augs)
407 throws XNIException {}
408
409 public void characters(XMLString text, Augmentations augs)
410 throws XNIException {
411 if (fContentHandler != null) {
412 // if the type is union it is possible that we receive
413 // a character call with empty data
414 if (text.length == 0) {
415 return;
416 }
417 try {
418 fContentHandler.characters(text.ch, text.offset, text.length);
419 }
420 catch (SAXException e) {
421 throw new XNIException(e);
422 }
423 }
424 }
425
426 public void ignorableWhitespace(XMLString text, Augmentations augs)
427 throws XNIException {
428 if (fContentHandler != null) {
429 try {
430 fContentHandler.ignorableWhitespace(text.ch, text.offset, text.length);
431 }
432 catch (SAXException e) {
433 throw new XNIException(e);
434 }
435 }
436 }
437
438 public void endElement(QName element, Augmentations augs)
439 throws XNIException {
440 if (fContentHandler != null) {
441 try {
442 fTypeInfoProvider.beginEndElement(augs);
443 fContentHandler.endElement((element.uri != null) ? element.uri : XMLSymbols.EMPTY_STRING,
444 element.localpart, element.rawname);
445 }
446 catch (SAXException e) {
447 throw new XNIException(e);
448 }
449 finally {
450 fTypeInfoProvider.finishEndElement();
451 }
452 }
453 }
454
455 public void startCDATA(Augmentations augs) throws XNIException {}
456
457 public void endCDATA(Augmentations augs) throws XNIException {}
458
459 public void endDocument(Augmentations augs) throws XNIException {
460 if (fContentHandler != null) {
461 try {
462 fContentHandler.endDocument();
463 }
464 catch (SAXException e) {
465 throw new XNIException(e);
466 }
467 }
468 }
469
470 // NO-OP
471 public void setDocumentSource(XMLDocumentSource source) {}
472
473 public XMLDocumentSource getDocumentSource() {
474 return fSchemaValidator;
475 }
476
477 /*
478 * ContentHandler methods
479 */
480
481 public void setDocumentLocator(Locator locator) {
482 fSAXLocatorWrapper.setLocator(locator);
483 if (fContentHandler != null) {
484 fContentHandler.setDocumentLocator(locator);
485 }
486 }
487
488 public void startDocument() throws SAXException {
489 fComponentManager.reset();
490 fSchemaValidator.setDocumentHandler(this);
491 fValidationManager.setEntityState(this);
492 fTypeInfoProvider.finishStartElement(); // cleans up TypeInfoProvider
493 fNeedPushNSContext = true;
494 if (fUnparsedEntities != null && !fUnparsedEntities.isEmpty()) {
495 // should only clear this if the last document contained unparsed entities
496 fUnparsedEntities.clear();
497 }
498 fErrorReporter.setDocumentLocator(fSAXLocatorWrapper);
499 try {
500 fSchemaValidator.startDocument(fSAXLocatorWrapper, fSAXLocatorWrapper.getEncoding(), fNamespaceContext, null);
501 }
502 catch (XMLParseException e) {
503 throw Util.toSAXParseException(e);
504 }
505 catch (XNIException e) {
506 throw Util.toSAXException(e);
507 }
508 }
509
510 public void endDocument() throws SAXException {
511 fSAXLocatorWrapper.setLocator(null);
512 try {
513 fSchemaValidator.endDocument(null);
514 }
515 catch (XMLParseException e) {
516 throw Util.toSAXParseException(e);
517 }
518 catch (XNIException e) {
519 throw Util.toSAXException(e);
520 }
521 }
522
523 public void startPrefixMapping(String prefix, String uri)
524 throws SAXException {
525 String prefixSymbol;
526 String uriSymbol;
527 if (!fStringsInternalized) {
528 prefixSymbol = (prefix != null) ? fSymbolTable.addSymbol(prefix) : XMLSymbols.EMPTY_STRING;
529 uriSymbol = (uri != null && uri.length() > 0) ? fSymbolTable.addSymbol(uri) : null;
530 }
531 else {
532 prefixSymbol = (prefix != null) ? prefix : XMLSymbols.EMPTY_STRING;
533 uriSymbol = (uri != null && uri.length() > 0) ? uri : null;
534 }
535 if (fNeedPushNSContext) {
536 fNeedPushNSContext = false;
537 fNamespaceContext.pushContext();
538 }
539 fNamespaceContext.declarePrefix(prefixSymbol, uriSymbol);
540 if (fContentHandler != null) {
541 fContentHandler.startPrefixMapping(prefix, uri);
542 }
543 }
544
545 public void endPrefixMapping(String prefix) throws SAXException {
546 if (fContentHandler != null) {
547 fContentHandler.endPrefixMapping(prefix);
548 }
549 }
550
551 public void startElement(String uri, String localName, String qName,
552 Attributes atts) throws SAXException {
553 if (fNeedPushNSContext) {
554 fNamespaceContext.pushContext();
555 }
556 fNeedPushNSContext = true;
557
558 // Fill element QName
559 fillQName(fElementQName, uri, localName, qName);
560
561 // Fill XMLAttributes
562 if (atts instanceof Attributes2) {
563 fillXMLAttributes2((Attributes2) atts);
564 }
565 else {
566 fillXMLAttributes(atts);
567 }
568
569 try {
570 fSchemaValidator.startElement(fElementQName, fAttributes, null);
571 }
572 catch (XMLParseException e) {
573 throw Util.toSAXParseException(e);
574 }
575 catch (XNIException e) {
576 throw Util.toSAXException(e);
577 }
578 }
579
580 public void endElement(String uri, String localName, String qName)
581 throws SAXException {
582 fillQName(fElementQName, uri, localName, qName);
583 try {
584 fSchemaValidator.endElement(fElementQName, null);
585 }
586 catch (XMLParseException e) {
587 throw Util.toSAXParseException(e);
588 }
589 catch (XNIException e) {
590 throw Util.toSAXException(e);
591 }
592 finally {
593 fNamespaceContext.popContext();
594 }
595 }
596
597 public void characters(char[] ch, int start, int length)
598 throws SAXException {
599 try {
600 fTempString.setValues(ch, start, length);
601 fSchemaValidator.characters(fTempString, null);
602 }
603 catch (XMLParseException e) {
604 throw Util.toSAXParseException(e);
605 }
606 catch (XNIException e) {
607 throw Util.toSAXException(e);
608 }
609 }
610
611 public void ignorableWhitespace(char[] ch, int start, int length)
612 throws SAXException {
613 try {
614 fTempString.setValues(ch, start, length);
615 fSchemaValidator.ignorableWhitespace(fTempString, null);
616 }
617 catch (XMLParseException e) {
618 throw Util.toSAXParseException(e);
619 }
620 catch (XNIException e) {
621 throw Util.toSAXException(e);
622 }
623 }
624
625 public void processingInstruction(String target, String data)
626 throws SAXException {
627 /**
628 * Processing instructions do not participate in schema validation,
629 * so just forward the event to the application's content
630 * handler.
631 */
632 if (fContentHandler != null) {
633 fContentHandler.processingInstruction(target, data);
634 }
635 }
636
637 public void skippedEntity(String name) throws SAXException {
638 // there seems to be no corresponding method on XMLDocumentFilter.
639 // just pass it down to the output, if any.
640 if (fContentHandler != null) {
641 fContentHandler.skippedEntity(name);
642 }
643 }
644
645 /*
646 * DTDHandler methods
647 */
648
649 public void notationDecl(String name, String publicId,
650 String systemId) throws SAXException {}
651
652 public void unparsedEntityDecl(String name, String publicId,
653 String systemId, String notationName) throws SAXException {
654 if (fUnparsedEntities == null) {
655 fUnparsedEntities = new HashMap<>();
656 }
657 fUnparsedEntities.put(name, name);
658 }
659
660 /*
661 * ValidatorHelper methods
662 */
663
664 public void validate(Source source, Result result)
665 throws SAXException, IOException {
666 if (result instanceof SAXResult || result == null) {
667 final SAXSource saxSource = (SAXSource) source;
668 final SAXResult saxResult = (SAXResult) result;
669
670 if (result != null) {
671 setContentHandler(saxResult.getHandler());
672 }
673
674 try {
675 XMLReader reader = saxSource.getXMLReader();
676 if( reader==null ) {
677 // create one now
678 SAXParserFactory spf = fComponentManager.getFeature(Constants.ORACLE_FEATURE_SERVICE_MECHANISM) ?
679 SAXParserFactory.newInstance() : new SAXParserFactoryImpl();
680 spf.setNamespaceAware(true);
681 try {
682 spf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING,
683 fComponentManager.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING));
684 reader = spf.newSAXParser().getXMLReader();
685 // If this is a Xerces SAX parser, set the security manager if there is one
686 if (reader instanceof com.sun.org.apache.xerces.internal.parsers.SAXParser) {
687 XMLSecurityManager securityManager = (XMLSecurityManager) fComponentManager.getProperty(SECURITY_MANAGER);
688 if (securityManager != null) {
689 try {
690 reader.setProperty(SECURITY_MANAGER, securityManager);
691 }
692 // Ignore the exception if the security manager cannot be set.
693 catch (SAXException exc) {}
694 }
695 try {
696 XMLSecurityPropertyManager spm = (XMLSecurityPropertyManager)
697 fComponentManager.getProperty(XML_SECURITY_PROPERTY_MANAGER);
698 reader.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD,
699 spm.getValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD));
700 } catch (SAXException exc) {
701 XMLSecurityManager.printWarning(reader.getClass().getName(),
702 XMLConstants.ACCESS_EXTERNAL_DTD, exc);
703 }
704 }
705
706 // Passing on the CatalogFeatures settings from a configuration object to the reader
707 JdkXmlUtils.catalogFeaturesConfig2Reader(fComponentManager, reader);
708 } catch( Exception e ) {
709 // this is impossible, but better safe than sorry
710 throw new FactoryConfigurationError(e);
711 }
712 }
713
714 // If XML names and Namespace URIs are already internalized we
715 // can avoid running them through the SymbolTable.
716 try {
717 fStringsInternalized = reader.getFeature(STRING_INTERNING);
718 }
719 catch (SAXException exc) {
720 // The feature isn't recognized or getting it is not supported.
721 // In either case, assume that strings are not internalized.
722 fStringsInternalized = false;
723 }
724
725 ErrorHandler errorHandler = fComponentManager.getErrorHandler();
726 reader.setErrorHandler(errorHandler != null ? errorHandler : DraconianErrorHandler.getInstance());
727 reader.setEntityResolver(fResolutionForwarder);
728 fResolutionForwarder.setEntityResolver(fComponentManager.getResourceResolver());
729 reader.setContentHandler(this);
730 reader.setDTDHandler(this);
731
732 InputSource is = saxSource.getInputSource();
733 reader.parse(is);
734 }
735 finally {
736 // release the reference to user's handler ASAP
737 setContentHandler(null);
738 }
739 return;
740 }
741 throw new IllegalArgumentException(JAXPValidationMessageFormatter.formatMessage(fComponentManager.getLocale(),
742 "SourceResultMismatch",
743 new Object [] {source.getClass().getName(), result.getClass().getName()}));
744 }
745
746 /*
747 * PSVIProvider methods
748 */
749
750 public ElementPSVI getElementPSVI() {
751 return fTypeInfoProvider.getElementPSVI();
752 }
753
754 public AttributePSVI getAttributePSVI(int index) {
755 return fTypeInfoProvider.getAttributePSVI(index);
756 }
757
758 public AttributePSVI getAttributePSVIByName(String uri, String localname) {
759 return fTypeInfoProvider.getAttributePSVIByName(uri, localname);
760 }
761
762 //
763 //
764 // helper methods
765 //
766 //
767
768 /** Fills in a QName object. */
769 private void fillQName(QName toFill, String uri, String localpart, String raw) {
770 if (!fStringsInternalized) {
771 uri = (uri != null && uri.length() > 0) ? fSymbolTable.addSymbol(uri) : null;
772 localpart = (localpart != null) ? fSymbolTable.addSymbol(localpart) : XMLSymbols.EMPTY_STRING;
773 raw = (raw != null) ? fSymbolTable.addSymbol(raw) : XMLSymbols.EMPTY_STRING;
774 }
775 else {
776 if (uri != null && uri.length() == 0) {
777 uri = null;
778 }
779 if (localpart == null) {
780 localpart = XMLSymbols.EMPTY_STRING;
781 }
782 if (raw == null) {
783 raw = XMLSymbols.EMPTY_STRING;
784 }
785 }
786 String prefix = XMLSymbols.EMPTY_STRING;
787 int prefixIdx = raw.indexOf(':');
788 if (prefixIdx != -1) {
789 prefix = fSymbolTable.addSymbol(raw.substring(0, prefixIdx));
790 }
791 toFill.setValues(prefix, localpart, raw, uri);
792 }
793
794 /** Fills in the XMLAttributes object. */
795 private void fillXMLAttributes(Attributes att) {
796 fAttributes.removeAllAttributes();
797 final int len = att.getLength();
798 for (int i = 0; i < len; ++i) {
799 fillXMLAttribute(att, i);
800 fAttributes.setSpecified(i, true);
801 }
802 }
803
804 /** Fills in the XMLAttributes object. */
805 private void fillXMLAttributes2(Attributes2 att) {
806 fAttributes.removeAllAttributes();
807 final int len = att.getLength();
808 for (int i = 0; i < len; ++i) {
809 fillXMLAttribute(att, i);
810 fAttributes.setSpecified(i, att.isSpecified(i));
811 if (att.isDeclared(i)) {
812 fAttributes.getAugmentations(i).putItem(Constants.ATTRIBUTE_DECLARED, Boolean.TRUE);
813 }
814 }
815 }
816
817 /** Adds an attribute to the XMLAttributes object. */
818 private void fillXMLAttribute(Attributes att, int index) {
819 fillQName(fAttributeQName, att.getURI(index), att.getLocalName(index), att.getQName(index));
820 String type = att.getType(index);
821 fAttributes.addAttributeNS(fAttributeQName, (type != null) ? type : XMLSymbols.fCDATASymbol, att.getValue(index));
822 }
823
824 /**
825 * {@link TypeInfoProvider} implementation.
826 *
827 * REVISIT: I'm not sure if this code should belong here.
828 */
829 private final XMLSchemaTypeInfoProvider fTypeInfoProvider = new XMLSchemaTypeInfoProvider();
830 private class XMLSchemaTypeInfoProvider extends TypeInfoProvider {
831
832 /** Element augmentations: contains ElementPSVI. **/
833 private Augmentations fElementAugs;
834
835 /** Attributes: augmentations for each attribute contain AttributePSVI. **/
836 private XMLAttributes fAttributes;
837
838 /** In start element. **/
839 private boolean fInStartElement = false;
840
841 /** In end element. **/
842 private boolean fInEndElement = false;
843
844 /** Initializes the TypeInfoProvider with type information for the current element. **/
845 void beginStartElement(Augmentations elementAugs, XMLAttributes attributes) {
846 fInStartElement = true;
847 fElementAugs = elementAugs;
848 fAttributes = attributes;
849 }
850
851 /** Cleanup at the end of start element. **/
852 void finishStartElement() {
853 fInStartElement = false;
854 fElementAugs = null;
855 fAttributes = null;
856 }
857
858 /** Initializes the TypeInfoProvider with type information for the current element. **/
859 void beginEndElement(Augmentations elementAugs) {
860 fInEndElement = true;
861 fElementAugs = elementAugs;
862 }
863
864 /** Cleanup at the end of end element. **/
865 void finishEndElement() {
866 fInEndElement = false;
867 fElementAugs = null;
868 }
869
870 /**
871 * Throws a {@link IllegalStateException} if we are not in
872 * the startElement callback. the JAXP API requires this
873 * for most of the public methods.
874 */
875 private void checkState(boolean forElementInfo) {
876 if (! (fInStartElement || (fInEndElement && forElementInfo))) {
877 throw new IllegalStateException(JAXPValidationMessageFormatter.formatMessage(fComponentManager.getLocale(),
878 "TypeInfoProviderIllegalState", null));
879 }
880 }
881
882 public TypeInfo getAttributeTypeInfo(int index) {
883 checkState(false);
884 return getAttributeType(index);
885 }
886
887 private TypeInfo getAttributeType( int index ) {
888 checkState(false);
889 if( index<0 || fAttributes.getLength()<=index )
890 throw new IndexOutOfBoundsException(Integer.toString(index));
891 Augmentations augs = fAttributes.getAugmentations(index);
892 if (augs == null) return null;
893 AttributePSVI psvi = (AttributePSVI)augs.getItem(Constants.ATTRIBUTE_PSVI);
894 return getTypeInfoFromPSVI(psvi);
895 }
896
897 public TypeInfo getAttributeTypeInfo(String attributeUri, String attributeLocalName) {
898 checkState(false);
899 return getAttributeTypeInfo(fAttributes.getIndex(attributeUri,attributeLocalName));
900 }
901
902 public TypeInfo getAttributeTypeInfo(String attributeQName) {
903 checkState(false);
904 return getAttributeTypeInfo(fAttributes.getIndex(attributeQName));
905 }
906
907 public TypeInfo getElementTypeInfo() {
908 checkState(true);
909 if (fElementAugs == null) return null;
910 ElementPSVI psvi = (ElementPSVI)fElementAugs.getItem(Constants.ELEMENT_PSVI);
911 return getTypeInfoFromPSVI(psvi);
912 }
913
914 private TypeInfo getTypeInfoFromPSVI( ItemPSVI psvi ) {
915 if(psvi==null) return null;
916
917 // TODO: make sure if this is correct.
918 // TODO: since the number of types in a schema is quite limited,
919 // TypeInfoImpl should be pooled. Even better, it should be a part
920 // of the element decl.
921 if( psvi.getValidity()== ElementPSVI.VALIDITY_VALID ) {
922 XSTypeDefinition t = psvi.getMemberTypeDefinition();
923 if (t != null) {
924 return (t instanceof TypeInfo) ? (TypeInfo) t : null;
925 }
926 }
927
928 XSTypeDefinition t = psvi.getTypeDefinition();
929 // TODO: can t be null?
930 if (t != null) {
931 return (t instanceof TypeInfo) ? (TypeInfo) t : null;
932 }
933 return null;
934 }
935
936 public boolean isIdAttribute(int index) {
937 checkState(false);
938 XSSimpleType type = (XSSimpleType)getAttributeType(index);
939 if(type==null) return false;
940 return type.isIDType();
941 }
942
943 public boolean isSpecified(int index) {
944 checkState(false);
945 return fAttributes.isSpecified(index);
946 }
947
948 /*
949 * Other methods
950 */
951
952 // PSVIProvider support
953 ElementPSVI getElementPSVI() {
954 return (fElementAugs != null) ? (ElementPSVI) fElementAugs.getItem(Constants.ELEMENT_PSVI) : null;
955 }
956
957 AttributePSVI getAttributePSVI(int index) {
958 if (fAttributes != null) {
959 Augmentations augs = fAttributes.getAugmentations(index);
960 if (augs != null) {
961 return (AttributePSVI) augs.getItem(Constants.ATTRIBUTE_PSVI);
962 }
963 }
964 return null;
965 }
966
967 AttributePSVI getAttributePSVIByName(String uri, String localname) {
968 if (fAttributes != null) {
969 Augmentations augs = fAttributes.getAugmentations(uri, localname);
970 if (augs != null) {
971 return (AttributePSVI) augs.getItem(Constants.ATTRIBUTE_PSVI);
972 }
973 }
974 return null;
975 }
976 }
977
978 /** SAX adapter for an LSResourceResolver. */
979 private final ResolutionForwarder fResolutionForwarder = new ResolutionForwarder(null);
980 static final class ResolutionForwarder
981 implements EntityResolver2 {
982
983 //
984 // Data
985 //
986
987 /** XML 1.0 type constant according to DOM L3 LS REC spec "http://www.w3.org/TR/2004/REC-DOM-Level-3-LS-20040407/" */
988 private static final String XML_TYPE = "http://www.w3.org/TR/REC-xml";
989
990 /** The DOM entity resolver. */
991 protected LSResourceResolver fEntityResolver;
992
993 //
994 // Constructors
995 //
996
997 /** Default constructor. */
998 public ResolutionForwarder() {}
999
1000 /** Wraps the specified DOM entity resolver. */
1001 public ResolutionForwarder(LSResourceResolver entityResolver) {
1002 setEntityResolver(entityResolver);
1003 }
1004
1005 //
1006 // Public methods
1007 //
1008
1009 /** Sets the DOM entity resolver. */
1010 public void setEntityResolver(LSResourceResolver entityResolver) {
1011 fEntityResolver = entityResolver;
1012 } // setEntityResolver(LSResourceResolver)
1013
1014 /** Returns the DOM entity resolver. */
1015 public LSResourceResolver getEntityResolver() {
1016 return fEntityResolver;
1017 } // getEntityResolver():LSResourceResolver
1018
1019 /**
1020 * Always returns <code>null</code>. An LSResourceResolver has no corresponding method.
1021 */
1022 public InputSource getExternalSubset(String name, String baseURI)
1023 throws SAXException, IOException {
1024 return null;
1025 }
1026
1027 /**
1028 * Resolves the given resource and adapts the <code>LSInput</code>
1029 * returned into an <code>InputSource</code>.
1030 */
1031 public InputSource resolveEntity(String name, String publicId,
1032 String baseURI, String systemId) throws SAXException, IOException {
1033 if (fEntityResolver != null) {
1034 LSInput lsInput = fEntityResolver.resolveResource(XML_TYPE, null, publicId, systemId, baseURI);
1035 if (lsInput != null) {
1036 final String pubId = lsInput.getPublicId();
1037 final String sysId = lsInput.getSystemId();
1038 final String baseSystemId = lsInput.getBaseURI();
1039 final Reader charStream = lsInput.getCharacterStream();
1040 final InputStream byteStream = lsInput.getByteStream();
1041 final String data = lsInput.getStringData();
1042 final String encoding = lsInput.getEncoding();
1043
1044 /**
1045 * An LSParser looks at inputs specified in LSInput in
1046 * the following order: characterStream, byteStream,
1047 * stringData, systemId, publicId. For consistency
1048 * with the DOM Level 3 Load and Save Recommendation
1049 * use the same lookup order here.
1050 */
1051 InputSource inputSource = new InputSource();
1052 inputSource.setPublicId(pubId);
1053 inputSource.setSystemId((baseSystemId != null) ? resolveSystemId(sysId, baseSystemId) : sysId);
1054
1055 if (charStream != null) {
1056 inputSource.setCharacterStream(charStream);
1057 }
1058 else if (byteStream != null) {
1059 inputSource.setByteStream(byteStream);
1060 }
1061 else if (data != null && data.length() != 0) {
1062 inputSource.setCharacterStream(new StringReader(data));
1063 }
1064 inputSource.setEncoding(encoding);
1065 return inputSource;
1066 }
1067 }
1068 return null;
1069 }
1070
1071 /** Delegates to EntityResolver2.resolveEntity(String, String, String, String). */
1072 public InputSource resolveEntity(String publicId, String systemId)
1073 throws SAXException, IOException {
1074 return resolveEntity(null, publicId, null, systemId);
1075 }
1076
1077 /** Resolves a system identifier against a base URI. */
1078 private String resolveSystemId(String systemId, String baseURI) {
1079 try {
1080 return XMLEntityManager.expandSystemId(systemId, baseURI, false);
1081 }
1082 // In the event that resolution failed against the
1083 // base URI, just return the system id as is. There's not
1084 // much else we can do.
1085 catch (URI.MalformedURIException ex) {
1086 return systemId;
1087 }
1088 }
1089 }
1090 }
--- EOF ---