2
* Copyright 2005,2006 The Apache Software Foundation.
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
17
package org.apache.xerces.jaxp.validation;
19
import java.io.IOException;
20
import java.io.InputStream;
21
import java.io.Reader;
22
import java.io.StringReader;
23
import java.util.HashMap;
24
import java.util.Locale;
26
import javax.xml.parsers.FactoryConfigurationError;
27
import javax.xml.parsers.SAXParserFactory;
28
import javax.xml.transform.Result;
29
import javax.xml.transform.Source;
30
import javax.xml.transform.sax.SAXResult;
31
import javax.xml.transform.sax.SAXSource;
32
import javax.xml.validation.TypeInfoProvider;
33
import javax.xml.validation.ValidatorHandler;
35
import org.apache.xerces.impl.Constants;
36
import org.apache.xerces.impl.XMLEntityManager;
37
import org.apache.xerces.impl.XMLErrorReporter;
38
import org.apache.xerces.impl.dv.XSSimpleType;
39
import org.apache.xerces.impl.validation.EntityState;
40
import org.apache.xerces.impl.validation.ValidationManager;
41
import org.apache.xerces.impl.xs.XMLSchemaValidator;
42
import org.apache.xerces.util.AttributesProxy;
43
import org.apache.xerces.util.SAXLocatorWrapper;
44
import org.apache.xerces.util.SAXMessageFormatter;
45
import org.apache.xerces.util.SymbolTable;
46
import org.apache.xerces.util.URI;
47
import org.apache.xerces.util.XMLAttributesImpl;
48
import org.apache.xerces.util.XMLSymbols;
49
import org.apache.xerces.xni.Augmentations;
50
import org.apache.xerces.xni.NamespaceContext;
51
import org.apache.xerces.xni.QName;
52
import org.apache.xerces.xni.XMLAttributes;
53
import org.apache.xerces.xni.XMLDocumentHandler;
54
import org.apache.xerces.xni.XMLLocator;
55
import org.apache.xerces.xni.XMLResourceIdentifier;
56
import org.apache.xerces.xni.XMLString;
57
import org.apache.xerces.xni.XNIException;
58
import org.apache.xerces.xni.parser.XMLConfigurationException;
59
import org.apache.xerces.xni.parser.XMLDocumentSource;
60
import org.apache.xerces.xni.parser.XMLParseException;
61
import org.apache.xerces.xs.AttributePSVI;
62
import org.apache.xerces.xs.ElementPSVI;
63
import org.apache.xerces.xs.ItemPSVI;
64
import org.apache.xerces.xs.PSVIProvider;
65
import org.apache.xerces.xs.XSTypeDefinition;
66
import org.w3c.dom.TypeInfo;
67
import org.w3c.dom.ls.LSInput;
68
import org.w3c.dom.ls.LSResourceResolver;
69
import org.xml.sax.Attributes;
70
import org.xml.sax.ContentHandler;
71
import org.xml.sax.DTDHandler;
72
import org.xml.sax.ErrorHandler;
73
import org.xml.sax.InputSource;
74
import org.xml.sax.Locator;
75
import org.xml.sax.SAXException;
76
import org.xml.sax.SAXNotRecognizedException;
77
import org.xml.sax.SAXNotSupportedException;
78
import org.xml.sax.XMLReader;
79
import org.xml.sax.ext.Attributes2;
80
import org.xml.sax.ext.EntityResolver2;
81
import org.xml.sax.ext.LexicalHandler;
84
* <p>Implementation of ValidatorHandler for W3C XML Schemas and
85
* also a validator helper for <code>SAXSource</code>s.</p>
87
* @author Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
88
* @author Michael Glavassevich, IBM
90
* @version $Id: ValidatorHandlerImpl.java 374971 2006-02-05 04:52:41Z mrglavas $
92
final class ValidatorHandlerImpl extends ValidatorHandler implements
93
DTDHandler, EntityState, PSVIProvider, ValidatorHelper, XMLDocumentHandler {
95
// feature identifiers
97
/** Feature identifier: namespace prefixes. */
98
private static final String NAMESPACE_PREFIXES =
99
Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACE_PREFIXES_FEATURE;
101
/** Feature identifier: string interning. */
102
protected static final String STRING_INTERNING =
103
Constants.SAX_FEATURE_PREFIX + Constants.STRING_INTERNING_FEATURE;
105
// property identifiers
107
/** Property identifier: error reporter. */
108
private static final String ERROR_REPORTER =
109
Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
111
/** Property identifier: lexical handler. */
112
private static final String LEXICAL_HANDLER =
113
Constants.SAX_PROPERTY_PREFIX + Constants.LEXICAL_HANDLER_PROPERTY;
115
/** Property identifier: namespace context. */
116
private static final String NAMESPACE_CONTEXT =
117
Constants.XERCES_PROPERTY_PREFIX + Constants.NAMESPACE_CONTEXT_PROPERTY;
119
/** Property identifier: XML Schema validator. */
120
private static final String SCHEMA_VALIDATOR =
121
Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_VALIDATOR_PROPERTY;
123
/** Property identifier: security manager. */
124
private static final String SECURITY_MANAGER =
125
Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY;
127
/** Property identifier: symbol table. */
128
private static final String SYMBOL_TABLE =
129
Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
131
/** Property identifier: validation manager. */
132
private static final String VALIDATION_MANAGER =
133
Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
139
/** Error reporter. */
140
private XMLErrorReporter fErrorReporter;
142
/** The namespace context of this document: stores namespaces in scope */
143
private NamespaceContext fNamespaceContext;
145
/** Schema validator. **/
146
private XMLSchemaValidator fSchemaValidator;
149
private SymbolTable fSymbolTable;
151
/** Validation manager. */
152
private ValidationManager fValidationManager;
154
/** Component manager. **/
155
private XMLSchemaValidatorComponentManager fComponentManager;
157
/** XML Locator wrapper for SAX. **/
158
private final SAXLocatorWrapper fSAXLocatorWrapper = new SAXLocatorWrapper();
160
/** Flag used to track whether the namespace context needs to be pushed. */
161
private boolean fNeedPushNSContext = true;
163
/** Map for tracking unparsed entities. */
164
private HashMap fUnparsedEntities = null;
166
/** Flag used to track whether XML names and Namespace URIs have been internalized. */
167
private boolean fStringsInternalized = false;
169
/** Fields for start element, end element and characters. */
170
private final QName fElementQName = new QName();
171
private final QName fAttributeQName = new QName();
172
private final XMLAttributesImpl fAttributes = new XMLAttributesImpl();
173
private final AttributesProxy fAttrAdapter = new AttributesProxy(fAttributes);
174
private final XMLString fTempString = new XMLString();
180
private ContentHandler fContentHandler = null;
186
public ValidatorHandlerImpl(XSGrammarPoolContainer grammarContainer) {
187
this(new XMLSchemaValidatorComponentManager(grammarContainer));
188
fComponentManager.addRecognizedFeatures(new String [] {NAMESPACE_PREFIXES});
189
fComponentManager.setFeature(NAMESPACE_PREFIXES, false);
190
setErrorHandler(null);
191
setResourceResolver(null);
194
public ValidatorHandlerImpl(XMLSchemaValidatorComponentManager componentManager) {
195
fComponentManager = componentManager;
196
fErrorReporter = (XMLErrorReporter) fComponentManager.getProperty(ERROR_REPORTER);
197
fNamespaceContext = (NamespaceContext) fComponentManager.getProperty(NAMESPACE_CONTEXT);
198
fSchemaValidator = (XMLSchemaValidator) fComponentManager.getProperty(SCHEMA_VALIDATOR);
199
fSymbolTable = (SymbolTable) fComponentManager.getProperty(SYMBOL_TABLE);
200
fValidationManager = (ValidationManager) fComponentManager.getProperty(VALIDATION_MANAGER);
204
* ValidatorHandler methods
207
public void setContentHandler(ContentHandler receiver) {
208
fContentHandler = receiver;
211
public ContentHandler getContentHandler() {
212
return fContentHandler;
215
public void setErrorHandler(ErrorHandler errorHandler) {
216
fComponentManager.setErrorHandler(errorHandler);
219
public ErrorHandler getErrorHandler() {
220
return fComponentManager.getErrorHandler();
223
public void setResourceResolver(LSResourceResolver resourceResolver) {
224
fComponentManager.setResourceResolver(resourceResolver);
227
public LSResourceResolver getResourceResolver() {
228
return fComponentManager.getResourceResolver();
231
public TypeInfoProvider getTypeInfoProvider() {
232
return fTypeInfoProvider;
235
public boolean getFeature(String name)
236
throws SAXNotRecognizedException, SAXNotSupportedException {
238
throw new NullPointerException();
241
return fComponentManager.getFeature(name);
243
catch (XMLConfigurationException e) {
244
final String identifier = e.getIdentifier();
245
final String key = e.getType() == XMLConfigurationException.NOT_RECOGNIZED ?
246
"feature-not-recognized" : "feature-not-supported";
247
throw new SAXNotRecognizedException(
248
SAXMessageFormatter.formatMessage(Locale.getDefault(),
249
key, new Object [] {identifier}));
253
public void setFeature(String name, boolean value)
254
throws SAXNotRecognizedException, SAXNotSupportedException {
256
throw new NullPointerException();
259
fComponentManager.setFeature(name, value);
261
catch (XMLConfigurationException e) {
262
final String identifier = e.getIdentifier();
263
final String key = e.getType() == XMLConfigurationException.NOT_RECOGNIZED ?
264
"feature-not-recognized" : "feature-not-supported";
265
throw new SAXNotRecognizedException(
266
SAXMessageFormatter.formatMessage(Locale.getDefault(),
267
key, new Object [] {identifier}));
271
public Object getProperty(String name)
272
throws SAXNotRecognizedException, SAXNotSupportedException {
274
throw new NullPointerException();
277
return fComponentManager.getProperty(name);
279
catch (XMLConfigurationException e) {
280
final String identifier = e.getIdentifier();
281
final String key = e.getType() == XMLConfigurationException.NOT_RECOGNIZED ?
282
"property-not-recognized" : "property-not-supported";
283
throw new SAXNotRecognizedException(
284
SAXMessageFormatter.formatMessage(Locale.getDefault(),
285
key, new Object [] {identifier}));
289
public void setProperty(String name, Object object)
290
throws SAXNotRecognizedException, SAXNotSupportedException {
292
throw new NullPointerException();
295
fComponentManager.setProperty(name, object);
297
catch (XMLConfigurationException e) {
298
final String identifier = e.getIdentifier();
299
final String key = e.getType() == XMLConfigurationException.NOT_RECOGNIZED ?
300
"property-not-recognized" : "property-not-supported";
301
throw new SAXNotRecognizedException(
302
SAXMessageFormatter.formatMessage(Locale.getDefault(),
303
key, new Object [] {identifier}));
308
* EntityState methods
311
public boolean isEntityDeclared(String name) {
315
public boolean isEntityUnparsed(String name) {
316
if (fUnparsedEntities != null) {
317
return fUnparsedEntities.containsKey(name);
323
* XMLDocumentHandler methods
326
public void startDocument(XMLLocator locator, String encoding,
327
NamespaceContext namespaceContext, Augmentations augs)
328
throws XNIException {
329
if (fContentHandler != null) {
331
fContentHandler.startDocument();
333
catch (SAXException e) {
334
throw new XNIException(e);
339
public void xmlDecl(String version, String encoding, String standalone,
340
Augmentations augs) throws XNIException {}
342
public void doctypeDecl(String rootElement, String publicId,
343
String systemId, Augmentations augs) throws XNIException {}
345
public void comment(XMLString text, Augmentations augs) throws XNIException {}
347
public void processingInstruction(String target, XMLString data,
348
Augmentations augs) throws XNIException {
349
if (fContentHandler != null) {
351
fContentHandler.processingInstruction(target, data.toString());
353
catch (SAXException e) {
354
throw new XNIException(e);
359
public void startElement(QName element, XMLAttributes attributes,
360
Augmentations augs) throws XNIException {
361
if (fContentHandler != null) {
363
fTypeInfoProvider.beginStartElement(augs, attributes);
364
fContentHandler.startElement((element.uri != null) ? element.uri : XMLSymbols.EMPTY_STRING,
365
element.localpart, element.rawname, fAttrAdapter);
367
catch (SAXException e) {
368
throw new XNIException(e);
371
fTypeInfoProvider.finishStartElement();
376
public void emptyElement(QName element, XMLAttributes attributes,
377
Augmentations augs) throws XNIException {
378
/** Split empty element event. **/
379
startElement(element, attributes, augs);
380
endElement(element, augs);
383
public void startGeneralEntity(String name,
384
XMLResourceIdentifier identifier, String encoding,
385
Augmentations augs) throws XNIException {}
387
public void textDecl(String version, String encoding, Augmentations augs)
388
throws XNIException {}
390
public void endGeneralEntity(String name, Augmentations augs)
391
throws XNIException {}
393
public void characters(XMLString text, Augmentations augs)
394
throws XNIException {
395
if (fContentHandler != null) {
396
// if the type is union it is possible that we receive
397
// a character call with empty data
398
if (text.length == 0) {
402
fContentHandler.characters(text.ch, text.offset, text.length);
404
catch (SAXException e) {
405
throw new XNIException(e);
410
public void ignorableWhitespace(XMLString text, Augmentations augs)
411
throws XNIException {
412
if (fContentHandler != null) {
414
fContentHandler.ignorableWhitespace(text.ch, text.offset, text.length);
416
catch (SAXException e) {
417
throw new XNIException(e);
422
public void endElement(QName element, Augmentations augs)
423
throws XNIException {
424
if (fContentHandler != null) {
426
fTypeInfoProvider.beginEndElement(augs);
427
fContentHandler.endElement((element.uri != null) ? element.uri : XMLSymbols.EMPTY_STRING,
428
element.localpart, element.rawname);
430
catch (SAXException e) {
431
throw new XNIException(e);
434
fTypeInfoProvider.finishEndElement();
439
public void startCDATA(Augmentations augs) throws XNIException {}
441
public void endCDATA(Augmentations augs) throws XNIException {}
443
public void endDocument(Augmentations augs) throws XNIException {
444
if (fContentHandler != null) {
446
fContentHandler.endDocument();
448
catch (SAXException e) {
449
throw new XNIException(e);
455
public void setDocumentSource(XMLDocumentSource source) {}
457
public XMLDocumentSource getDocumentSource() {
458
return fSchemaValidator;
462
* ContentHandler methods
465
public void setDocumentLocator(Locator locator) {
466
fSAXLocatorWrapper.setLocator(locator);
467
if (fContentHandler != null) {
468
fContentHandler.setDocumentLocator(locator);
472
public void startDocument() throws SAXException {
473
fComponentManager.reset();
474
fSchemaValidator.setDocumentHandler(this);
475
fValidationManager.setEntityState(this);
476
fTypeInfoProvider.finishStartElement(); // cleans up TypeInfoProvider
477
fNeedPushNSContext = true;
478
if (fUnparsedEntities != null && !fUnparsedEntities.isEmpty()) {
479
// should only clear this if the last document contained unparsed entities
480
fUnparsedEntities.clear();
482
fErrorReporter.setDocumentLocator(fSAXLocatorWrapper);
484
fSchemaValidator.startDocument(fSAXLocatorWrapper, fSAXLocatorWrapper.getEncoding(), fNamespaceContext, null);
486
catch (XMLParseException e) {
487
throw Util.toSAXParseException(e);
489
catch (XNIException e) {
490
throw Util.toSAXException(e);
494
public void endDocument() throws SAXException {
495
fSAXLocatorWrapper.setLocator(null);
497
fSchemaValidator.endDocument(null);
499
catch (XMLParseException e) {
500
throw Util.toSAXParseException(e);
502
catch (XNIException e) {
503
throw Util.toSAXException(e);
507
public void startPrefixMapping(String prefix, String uri)
508
throws SAXException {
511
if (!fStringsInternalized) {
512
prefixSymbol = (prefix != null) ? fSymbolTable.addSymbol(prefix) : XMLSymbols.EMPTY_STRING;
513
uriSymbol = (uri != null && uri.length() > 0) ? fSymbolTable.addSymbol(uri) : null;
516
prefixSymbol = (prefix != null) ? prefix : XMLSymbols.EMPTY_STRING;
517
uriSymbol = (uri != null && uri.length() > 0) ? uri : null;
519
if (fNeedPushNSContext) {
520
fNeedPushNSContext = false;
521
fNamespaceContext.pushContext();
523
fNamespaceContext.declarePrefix(prefixSymbol, uriSymbol);
524
if (fContentHandler != null) {
525
fContentHandler.startPrefixMapping(prefix, uri);
529
public void endPrefixMapping(String prefix) throws SAXException {
530
if (fContentHandler != null) {
531
fContentHandler.endPrefixMapping(prefix);
535
public void startElement(String uri, String localName, String qName,
536
Attributes atts) throws SAXException {
537
if (fNeedPushNSContext) {
538
fNamespaceContext.pushContext();
540
fNeedPushNSContext = true;
542
// Fill element QName
543
fillQName(fElementQName, uri, localName, qName);
545
// Fill XMLAttributes
546
if (atts instanceof Attributes2) {
547
fillXMLAttributes2((Attributes2) atts);
550
fillXMLAttributes(atts);
554
fSchemaValidator.startElement(fElementQName, fAttributes, null);
556
catch (XMLParseException e) {
557
throw Util.toSAXParseException(e);
559
catch (XNIException e) {
560
throw Util.toSAXException(e);
564
public void endElement(String uri, String localName, String qName)
565
throws SAXException {
566
fillQName(fElementQName, uri, localName, qName);
568
fSchemaValidator.endElement(fElementQName, null);
570
catch (XMLParseException e) {
571
throw Util.toSAXParseException(e);
573
catch (XNIException e) {
574
throw Util.toSAXException(e);
577
fNamespaceContext.popContext();
581
public void characters(char[] ch, int start, int length)
582
throws SAXException {
584
fTempString.setValues(ch, start, length);
585
fSchemaValidator.characters(fTempString, null);
587
catch (XMLParseException e) {
588
throw Util.toSAXParseException(e);
590
catch (XNIException e) {
591
throw Util.toSAXException(e);
595
public void ignorableWhitespace(char[] ch, int start, int length)
596
throws SAXException {
598
fTempString.setValues(ch, start, length);
599
fSchemaValidator.ignorableWhitespace(fTempString, null);
601
catch (XMLParseException e) {
602
throw Util.toSAXParseException(e);
604
catch (XNIException e) {
605
throw Util.toSAXException(e);
609
public void processingInstruction(String target, String data)
610
throws SAXException {
612
* Processing instructions do not participate in schema validation,
613
* so just forward the event to the application's content
616
if (fContentHandler != null) {
617
fContentHandler.processingInstruction(target, data);
621
public void skippedEntity(String name) throws SAXException {
622
// there seems to be no corresponding method on XMLDocumentFilter.
623
// just pass it down to the output, if any.
624
if (fContentHandler != null) {
625
fContentHandler.skippedEntity(name);
633
public void notationDecl(String name, String publicId,
634
String systemId) throws SAXException {}
636
public void unparsedEntityDecl(String name, String publicId,
637
String systemId, String notationName) throws SAXException {
638
if (fUnparsedEntities == null) {
639
fUnparsedEntities = new HashMap();
641
fUnparsedEntities.put(name, name);
645
* ValidatorHelper methods
648
public void validate(Source source, Result result)
649
throws SAXException, IOException {
650
if (result instanceof SAXResult || result == null) {
651
final SAXSource saxSource = (SAXSource) source;
652
final SAXResult saxResult = (SAXResult) result;
654
LexicalHandler lh = null;
655
if (result != null) {
656
ContentHandler ch = saxResult.getHandler();
657
lh = saxResult.getLexicalHandler();
658
/** If the lexical handler is not set try casting the ContentHandler. **/
659
if (lh == null && ch instanceof LexicalHandler) {
660
lh = (LexicalHandler) ch;
662
setContentHandler(ch);
666
XMLReader reader = saxSource.getXMLReader();
669
SAXParserFactory spf = SAXParserFactory.newInstance();
670
spf.setNamespaceAware(true);
672
reader = spf.newSAXParser().getXMLReader();
673
// If this is a Xerces SAX parser, set the security manager if there is one
674
if (reader instanceof org.apache.xerces.parsers.SAXParser) {
675
SecurityManager securityManager = (SecurityManager) fComponentManager.getProperty(SECURITY_MANAGER);
676
if (securityManager != null) {
678
reader.setProperty(SECURITY_MANAGER, securityManager);
680
// Ignore the exception if the security manager cannot be set.
681
catch (SAXException exc) {}
684
} catch( Exception e ) {
685
// this is impossible, but better safe than sorry
686
throw new FactoryConfigurationError(e);
690
// If XML names and Namespace URIs are already internalized we
691
// can avoid running them through the SymbolTable.
693
fStringsInternalized = reader.getFeature(STRING_INTERNING);
695
catch (SAXException exc) {
696
// The feature isn't recognized or getting it is not supported.
697
// In either case, assume that strings are not internalized.
698
fStringsInternalized = false;
701
ErrorHandler errorHandler = fComponentManager.getErrorHandler();
702
reader.setErrorHandler(errorHandler != null ? errorHandler : DraconianErrorHandler.getInstance());
703
reader.setEntityResolver(fResolutionForwarder);
704
fResolutionForwarder.setEntityResolver(fComponentManager.getResourceResolver());
705
reader.setContentHandler(this);
706
reader.setDTDHandler(this);
708
reader.setProperty(LEXICAL_HANDLER, lh);
710
// Ignore the exception if the lexical handler cannot be set.
711
catch (SAXException exc) {}
713
InputSource is = saxSource.getInputSource();
717
// release the reference to user's handler ASAP
718
setContentHandler(null);
722
throw new IllegalArgumentException(JAXPValidationMessageFormatter.formatMessage(Locale.getDefault(),
723
"SourceResultMismatch",
724
new Object [] {source.getClass().getName(), result.getClass().getName()}));
728
* PSVIProvider methods
731
public ElementPSVI getElementPSVI() {
732
return fTypeInfoProvider.getElementPSVI();
735
public AttributePSVI getAttributePSVI(int index) {
736
return fTypeInfoProvider.getAttributePSVI(index);
739
public AttributePSVI getAttributePSVIByName(String uri, String localname) {
740
return fTypeInfoProvider.getAttributePSVIByName(uri, localname);
749
/** Fills in a QName object. */
750
private void fillQName(QName toFill, String uri, String localpart, String raw) {
751
if (!fStringsInternalized) {
752
uri = (uri != null && uri.length() > 0) ? fSymbolTable.addSymbol(uri) : null;
753
localpart = (localpart != null) ? fSymbolTable.addSymbol(localpart) : XMLSymbols.EMPTY_STRING;
754
raw = (raw != null) ? fSymbolTable.addSymbol(raw) : XMLSymbols.EMPTY_STRING;
757
if (uri != null && uri.length() == 0) {
760
if (localpart == null) {
761
localpart = XMLSymbols.EMPTY_STRING;
764
raw = XMLSymbols.EMPTY_STRING;
767
String prefix = XMLSymbols.EMPTY_STRING;
768
int prefixIdx = raw.indexOf(':');
769
if (prefixIdx != -1) {
770
prefix = fSymbolTable.addSymbol(raw.substring(0, prefixIdx));
772
toFill.setValues(prefix, localpart, raw, uri);
775
/** Fills in the XMLAttributes object. */
776
private void fillXMLAttributes(Attributes att) {
777
fAttributes.removeAllAttributes();
778
final int len = att.getLength();
779
for (int i = 0; i < len; ++i) {
780
fillXMLAttribute(att, i);
781
fAttributes.setSpecified(i, true);
785
/** Fills in the XMLAttributes object. */
786
private void fillXMLAttributes2(Attributes2 att) {
787
fAttributes.removeAllAttributes();
788
final int len = att.getLength();
789
for (int i = 0; i < len; ++i) {
790
fillXMLAttribute(att, i);
791
fAttributes.setSpecified(i, att.isSpecified(i));
792
if (att.isDeclared(i)) {
793
fAttributes.getAugmentations(i).putItem(Constants.ATTRIBUTE_DECLARED, Boolean.TRUE);
798
/** Adds an attribute to the XMLAttributes object. */
799
private void fillXMLAttribute(Attributes att, int index) {
800
fillQName(fAttributeQName, att.getURI(index), att.getLocalName(index), att.getQName(index));
801
String type = att.getType(index);
802
fAttributes.addAttributeNS(fAttributeQName, (type != null) ? type : XMLSymbols.fCDATASymbol, att.getValue(index));
806
* {@link TypeInfoProvider} implementation.
808
* REVISIT: I'm not sure if this code should belong here.
810
private final XMLSchemaTypeInfoProvider fTypeInfoProvider = new XMLSchemaTypeInfoProvider();
811
private static class XMLSchemaTypeInfoProvider extends TypeInfoProvider {
813
/** Element augmentations: contains ElementPSVI. **/
814
private Augmentations fElementAugs;
816
/** Attributes: augmentations for each attribute contain AttributePSVI. **/
817
private XMLAttributes fAttributes;
819
/** In start element. **/
820
private boolean fInStartElement = false;
822
/** Initializes the TypeInfoProvider with type information for the current element. **/
823
void beginStartElement(Augmentations elementAugs, XMLAttributes attributes) {
824
fInStartElement = true;
825
fElementAugs = elementAugs;
826
fAttributes = attributes;
829
/** Cleanup at the end of start element. **/
830
void finishStartElement() {
831
fInStartElement = false;
836
/** Initializes the TypeInfoProvider with type information for the current element. **/
837
void beginEndElement(Augmentations elementAugs) {
838
fElementAugs = elementAugs;
841
/** Cleanup at the end of end element. **/
842
void finishEndElement() {
847
* Throws a {@link IllegalStateException} if we are not in
848
* the startElement callback. the JAXP API requires this
849
* for most of the public methods.
851
private void checkState() {
852
if( !fInStartElement ) {
853
throw new IllegalStateException(JAXPValidationMessageFormatter.formatMessage(Locale.getDefault(),
854
"TypeInfoProviderIllegalState", null));
858
public TypeInfo getAttributeTypeInfo(int index) {
860
return getAttributeType(index);
863
private TypeInfo getAttributeType( int index ) {
865
if( index<0 || fAttributes.getLength()<=index )
866
throw new IndexOutOfBoundsException(Integer.toString(index));
867
Augmentations augs = fAttributes.getAugmentations(index);
868
if (augs == null) return null;
869
AttributePSVI psvi = (AttributePSVI)augs.getItem(Constants.ATTRIBUTE_PSVI);
870
return getTypeInfoFromPSVI(psvi);
873
public TypeInfo getAttributeTypeInfo(String attributeUri, String attributeLocalName) {
875
return getAttributeTypeInfo(fAttributes.getIndex(attributeUri,attributeLocalName));
878
public TypeInfo getAttributeTypeInfo(String attributeQName) {
880
return getAttributeTypeInfo(fAttributes.getIndex(attributeQName));
883
public TypeInfo getElementTypeInfo() {
885
if (fElementAugs == null) return null;
886
ElementPSVI psvi = (ElementPSVI)fElementAugs.getItem(Constants.ELEMENT_PSVI);
887
return getTypeInfoFromPSVI(psvi);
890
private TypeInfo getTypeInfoFromPSVI( ItemPSVI psvi ) {
891
if(psvi==null) return null;
893
// TODO: make sure if this is correct.
894
// TODO: since the number of types in a schema is quite limited,
895
// TypeInfoImpl should be pooled. Even better, it should be a part
896
// of the element decl.
897
if( psvi.getValidity()== ElementPSVI.VALIDITY_VALID ) {
898
XSTypeDefinition t = psvi.getMemberTypeDefinition();
900
return (t instanceof TypeInfo) ? (TypeInfo) t : null;
904
XSTypeDefinition t = psvi.getTypeDefinition();
905
// TODO: can t be null?
907
return (t instanceof TypeInfo) ? (TypeInfo) t : null;
912
public boolean isIdAttribute(int index) {
914
XSSimpleType type = (XSSimpleType)getAttributeType(index);
915
if(type==null) return false;
916
return type.isIDType();
919
public boolean isSpecified(int index) {
921
return fAttributes.isSpecified(index);
928
// PSVIProvider support
929
ElementPSVI getElementPSVI() {
930
return (fElementAugs != null) ? (ElementPSVI) fElementAugs.getItem(Constants.ELEMENT_PSVI) : null;
933
AttributePSVI getAttributePSVI(int index) {
934
if (fAttributes != null) {
935
Augmentations augs = fAttributes.getAugmentations(index);
937
return (AttributePSVI) augs.getItem(Constants.ATTRIBUTE_PSVI);
943
AttributePSVI getAttributePSVIByName(String uri, String localname) {
944
if (fAttributes != null) {
945
Augmentations augs = fAttributes.getAugmentations(uri, localname);
947
return (AttributePSVI) augs.getItem(Constants.ATTRIBUTE_PSVI);
954
/** SAX adapter for an LSResourceResolver. */
955
private final ResolutionForwarder fResolutionForwarder = new ResolutionForwarder(null);
956
static final class ResolutionForwarder
957
implements EntityResolver2 {
963
/** XML 1.0 type constant according to DOM L3 LS REC spec "http://www.w3.org/TR/2004/REC-DOM-Level-3-LS-20040407/" */
964
private static final String XML_TYPE = "http://www.w3.org/TR/REC-xml";
966
/** The DOM entity resolver. */
967
protected LSResourceResolver fEntityResolver;
973
/** Default constructor. */
974
public ResolutionForwarder() {}
976
/** Wraps the specified DOM entity resolver. */
977
public ResolutionForwarder(LSResourceResolver entityResolver) {
978
setEntityResolver(entityResolver);
985
/** Sets the DOM entity resolver. */
986
public void setEntityResolver(LSResourceResolver entityResolver) {
987
fEntityResolver = entityResolver;
988
} // setEntityResolver(LSResourceResolver)
990
/** Returns the DOM entity resolver. */
991
public LSResourceResolver getEntityResolver() {
992
return fEntityResolver;
993
} // getEntityResolver():LSResourceResolver
996
* Always returns <code>null</code>. An LSResourceResolver has no corresponding method.
998
public InputSource getExternalSubset(String name, String baseURI)
999
throws SAXException, IOException {
1004
* Resolves the given resource and adapts the <code>LSInput</code>
1005
* returned into an <code>InputSource</code>.
1007
public InputSource resolveEntity(String name, String publicId,
1008
String baseURI, String systemId) throws SAXException, IOException {
1009
if (fEntityResolver != null) {
1010
LSInput lsInput = fEntityResolver.resolveResource(XML_TYPE, null, publicId, systemId, baseURI);
1011
if (lsInput != null) {
1012
final String pubId = lsInput.getPublicId();
1013
final String sysId = lsInput.getSystemId();
1014
final String baseSystemId = lsInput.getBaseURI();
1015
final Reader charStream = lsInput.getCharacterStream();
1016
final InputStream byteStream = lsInput.getByteStream();
1017
final String data = lsInput.getStringData();
1018
final String encoding = lsInput.getEncoding();
1021
* An LSParser looks at inputs specified in LSInput in
1022
* the following order: characterStream, byteStream,
1023
* stringData, systemId, publicId. For consistency
1024
* with the DOM Level 3 Load and Save Recommendation
1025
* use the same lookup order here.
1027
InputSource inputSource = new InputSource();
1028
inputSource.setPublicId(pubId);
1029
inputSource.setSystemId((baseSystemId != null) ? resolveSystemId(sysId, baseSystemId) : sysId);
1031
if (charStream != null) {
1032
inputSource.setCharacterStream(charStream);
1034
else if (byteStream != null) {
1035
inputSource.setByteStream(byteStream);
1037
else if (data != null && data.length() != 0) {
1038
inputSource.setCharacterStream(new StringReader(data));
1040
inputSource.setEncoding(encoding);
1047
/** Delegates to EntityResolver2.resolveEntity(String, String, String, String). */
1048
public InputSource resolveEntity(String publicId, String systemId)
1049
throws SAXException, IOException {
1050
return resolveEntity(null, publicId, null, systemId);
1053
/** Resolves a system identifier against a base URI. */
1054
private String resolveSystemId(String systemId, String baseURI) {
1056
return XMLEntityManager.expandSystemId(systemId, baseURI, false);
1058
// In the event that resolution failed against the
1059
// base URI, just return the system id as is. There's not
1060
// much else we can do.
1061
catch (URI.MalformedURIException ex) {