org.apache.xerces.jaxp.validation.ValidatorHandlerImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xercesImpl Show documentation
Show all versions of xercesImpl Show documentation
Xerces2 is the next generation of high performance, fully compliant XML parsers in the Apache Xerces family.
This new version of Xerces introduces the Xerces Native Interface (XNI), a complete framework for building
parser components and configurations that is extremely modular and easy to program. The Apache Xerces2 parser is
the reference implementation of XNI but other parser components, configurations, and parsers can be written
using the Xerces Native Interface. For complete design and implementation documents, refer to the XNI Manual.
Xerces2 is a fully conforming XML Schema 1.0 processor. A partial experimental implementation of the XML Schema
1.1 Structures and Datatypes Working Drafts (December 2009) and an experimental implementation of the XML Schema
Definition Language (XSD): Component Designators (SCD) Candidate Recommendation (January 2010) are provided for
evaluation. For more information, refer to the XML Schema page. Xerces2 also provides a complete implementation
of the Document Object Model Level 3 Core and Load/Save W3C Recommendations and provides a complete
implementation of the XML Inclusions (XInclude) W3C Recommendation. It also provides support for OASIS XML
Catalogs v1.1. Xerces2 is able to parse documents written according to the XML 1.1 Recommendation, except that
it does not yet provide an option to enable normalization checking as described in section 2.13 of this
specification. It also handles namespaces according to the XML Namespaces 1.1 Recommendation, and will correctly
serialize XML 1.1 documents if the DOM level 3 load/save APIs are in use.
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.xerces.jaxp.validation;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.util.HashMap;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.sax.SAXSource;
import javax.xml.validation.TypeInfoProvider;
import javax.xml.validation.ValidatorHandler;
import org.apache.xerces.impl.Constants;
import org.apache.xerces.impl.XMLEntityManager;
import org.apache.xerces.impl.XMLErrorReporter;
import org.apache.xerces.impl.dv.XSSimpleType;
import org.apache.xerces.impl.validation.EntityState;
import org.apache.xerces.impl.validation.ValidationManager;
import org.apache.xerces.impl.xs.XMLSchemaValidator;
import org.apache.xerces.util.AttributesProxy;
import org.apache.xerces.util.SAXLocatorWrapper;
import org.apache.xerces.util.SAXMessageFormatter;
import org.apache.xerces.util.SymbolTable;
import org.apache.xerces.util.URI;
import org.apache.xerces.util.XMLAttributesImpl;
import org.apache.xerces.util.XMLSymbols;
import org.apache.xerces.xni.Augmentations;
import org.apache.xerces.xni.NamespaceContext;
import org.apache.xerces.xni.QName;
import org.apache.xerces.xni.XMLAttributes;
import org.apache.xerces.xni.XMLDocumentHandler;
import org.apache.xerces.xni.XMLLocator;
import org.apache.xerces.xni.XMLResourceIdentifier;
import org.apache.xerces.xni.XMLString;
import org.apache.xerces.xni.XNIException;
import org.apache.xerces.xni.parser.XMLConfigurationException;
import org.apache.xerces.xni.parser.XMLDocumentSource;
import org.apache.xerces.xni.parser.XMLParseException;
import org.apache.xerces.xs.AttributePSVI;
import org.apache.xerces.xs.ElementPSVI;
import org.apache.xerces.xs.ItemPSVI;
import org.apache.xerces.xs.PSVIProvider;
import org.apache.xerces.xs.XSTypeDefinition;
import org.w3c.dom.TypeInfo;
import org.w3c.dom.ls.LSInput;
import org.w3c.dom.ls.LSResourceResolver;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.XMLReader;
import org.xml.sax.ext.Attributes2;
import org.xml.sax.ext.EntityResolver2;
import org.xml.sax.ext.LexicalHandler;
/**
* Implementation of ValidatorHandler for W3C XML Schemas and
* also a validator helper for SAXSource
s.
*
* @author Kohsuke Kawaguchi ([email protected])
* @author Michael Glavassevich, IBM
*
* @version $Id: ValidatorHandlerImpl.java 932646 2010-04-09 23:30:29Z mrglavas $
*/
final class ValidatorHandlerImpl extends ValidatorHandler implements
DTDHandler, EntityState, PSVIProvider, ValidatorHelper, XMLDocumentHandler {
// feature identifiers
/** Feature identifier: namespace prefixes. */
private static final String NAMESPACE_PREFIXES =
Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACE_PREFIXES_FEATURE;
/** Feature identifier: string interning. */
private static final String STRING_INTERNING =
Constants.SAX_FEATURE_PREFIX + Constants.STRING_INTERNING_FEATURE;
/** Feature identifier: strings interned. */
private static final String STRINGS_INTERNED =
Constants.XERCES_FEATURE_PREFIX + Constants.STRINGS_INTERNED_FEATURE;
// property identifiers
/** Property identifier: error reporter. */
private static final String ERROR_REPORTER =
Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
/** Property identifier: lexical handler. */
private static final String LEXICAL_HANDLER =
Constants.SAX_PROPERTY_PREFIX + Constants.LEXICAL_HANDLER_PROPERTY;
/** Property identifier: namespace context. */
private static final String NAMESPACE_CONTEXT =
Constants.XERCES_PROPERTY_PREFIX + Constants.NAMESPACE_CONTEXT_PROPERTY;
/** Property identifier: XML Schema validator. */
private static final String SCHEMA_VALIDATOR =
Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_VALIDATOR_PROPERTY;
/** Property identifier: security manager. */
private static final String SECURITY_MANAGER =
Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY;
/** Property identifier: symbol table. */
private static final String SYMBOL_TABLE =
Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
/** Property identifier: validation manager. */
private static final String VALIDATION_MANAGER =
Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
//
// Data
//
/** Error reporter. */
private final XMLErrorReporter fErrorReporter;
/** The namespace context of this document: stores namespaces in scope */
private final NamespaceContext fNamespaceContext;
/** Schema validator. **/
private final XMLSchemaValidator fSchemaValidator;
/** Symbol table **/
private final SymbolTable fSymbolTable;
/** Validation manager. */
private final ValidationManager fValidationManager;
/** Component manager. **/
private final XMLSchemaValidatorComponentManager fComponentManager;
/** XML Locator wrapper for SAX. **/
private final SAXLocatorWrapper fSAXLocatorWrapper = new SAXLocatorWrapper();
/** Flag used to track whether the namespace context needs to be pushed. */
private boolean fNeedPushNSContext = true;
/** Map for tracking unparsed entities. */
private HashMap fUnparsedEntities = null;
/** Flag used to track whether XML names and Namespace URIs have been internalized. */
private boolean fStringsInternalized = false;
/** Fields for start element, end element and characters. */
private final QName fElementQName = new QName();
private final QName fAttributeQName = new QName();
private final XMLAttributesImpl fAttributes = new XMLAttributesImpl();
private final AttributesProxy fAttrAdapter = new AttributesProxy(fAttributes);
private final XMLString fTempString = new XMLString();
//
// User Objects
//
private ContentHandler fContentHandler = null;
/*
* Constructors
*/
public ValidatorHandlerImpl(XSGrammarPoolContainer grammarContainer) {
this(new XMLSchemaValidatorComponentManager(grammarContainer));
fComponentManager.addRecognizedFeatures(new String [] {NAMESPACE_PREFIXES});
fComponentManager.setFeature(NAMESPACE_PREFIXES, false);
setErrorHandler(null);
setResourceResolver(null);
}
public ValidatorHandlerImpl(XMLSchemaValidatorComponentManager componentManager) {
fComponentManager = componentManager;
fErrorReporter = (XMLErrorReporter) fComponentManager.getProperty(ERROR_REPORTER);
fNamespaceContext = (NamespaceContext) fComponentManager.getProperty(NAMESPACE_CONTEXT);
fSchemaValidator = (XMLSchemaValidator) fComponentManager.getProperty(SCHEMA_VALIDATOR);
fSymbolTable = (SymbolTable) fComponentManager.getProperty(SYMBOL_TABLE);
fValidationManager = (ValidationManager) fComponentManager.getProperty(VALIDATION_MANAGER);
}
/*
* ValidatorHandler methods
*/
public void setContentHandler(ContentHandler receiver) {
fContentHandler = receiver;
}
public ContentHandler getContentHandler() {
return fContentHandler;
}
public void setErrorHandler(ErrorHandler errorHandler) {
fComponentManager.setErrorHandler(errorHandler);
}
public ErrorHandler getErrorHandler() {
return fComponentManager.getErrorHandler();
}
public void setResourceResolver(LSResourceResolver resourceResolver) {
fComponentManager.setResourceResolver(resourceResolver);
}
public LSResourceResolver getResourceResolver() {
return fComponentManager.getResourceResolver();
}
public TypeInfoProvider getTypeInfoProvider() {
return fTypeInfoProvider;
}
public boolean getFeature(String name)
throws SAXNotRecognizedException, SAXNotSupportedException {
if (name == null) {
throw new NullPointerException(JAXPValidationMessageFormatter.formatMessage(fComponentManager.getLocale(),
"FeatureNameNull", null));
}
if (STRINGS_INTERNED.equals(name)) {
return fStringsInternalized;
}
try {
return fComponentManager.getFeature(name);
}
catch (XMLConfigurationException e) {
final String identifier = e.getIdentifier();
if (e.getType() == XMLConfigurationException.NOT_RECOGNIZED) {
throw new SAXNotRecognizedException(
SAXMessageFormatter.formatMessage(fComponentManager.getLocale(),
"feature-not-recognized", new Object [] {identifier}));
}
else {
throw new SAXNotSupportedException(
SAXMessageFormatter.formatMessage(fComponentManager.getLocale(),
"feature-not-supported", new Object [] {identifier}));
}
}
}
public void setFeature(String name, boolean value)
throws SAXNotRecognizedException, SAXNotSupportedException {
if (name == null) {
throw new NullPointerException(JAXPValidationMessageFormatter.formatMessage(fComponentManager.getLocale(),
"FeatureNameNull", null));
}
if (STRINGS_INTERNED.equals(name)) {
fStringsInternalized = value;
return;
}
try {
fComponentManager.setFeature(name, value);
}
catch (XMLConfigurationException e) {
final String identifier = e.getIdentifier();
if (e.getType() == XMLConfigurationException.NOT_RECOGNIZED) {
throw new SAXNotRecognizedException(
SAXMessageFormatter.formatMessage(fComponentManager.getLocale(),
"feature-not-recognized", new Object [] {identifier}));
}
else {
throw new SAXNotSupportedException(
SAXMessageFormatter.formatMessage(fComponentManager.getLocale(),
"feature-not-supported", new Object [] {identifier}));
}
}
}
public Object getProperty(String name)
throws SAXNotRecognizedException, SAXNotSupportedException {
if (name == null) {
throw new NullPointerException(JAXPValidationMessageFormatter.formatMessage(fComponentManager.getLocale(),
"ProperyNameNull", null));
}
try {
return fComponentManager.getProperty(name);
}
catch (XMLConfigurationException e) {
final String identifier = e.getIdentifier();
if (e.getType() == XMLConfigurationException.NOT_RECOGNIZED) {
throw new SAXNotRecognizedException(
SAXMessageFormatter.formatMessage(fComponentManager.getLocale(),
"property-not-recognized", new Object [] {identifier}));
}
else {
throw new SAXNotSupportedException(
SAXMessageFormatter.formatMessage(fComponentManager.getLocale(),
"property-not-supported", new Object [] {identifier}));
}
}
}
public void setProperty(String name, Object object)
throws SAXNotRecognizedException, SAXNotSupportedException {
if (name == null) {
throw new NullPointerException(JAXPValidationMessageFormatter.formatMessage(fComponentManager.getLocale(),
"ProperyNameNull", null));
}
try {
fComponentManager.setProperty(name, object);
}
catch (XMLConfigurationException e) {
final String identifier = e.getIdentifier();
if (e.getType() == XMLConfigurationException.NOT_RECOGNIZED) {
throw new SAXNotRecognizedException(
SAXMessageFormatter.formatMessage(fComponentManager.getLocale(),
"property-not-recognized", new Object [] {identifier}));
}
else {
throw new SAXNotSupportedException(
SAXMessageFormatter.formatMessage(fComponentManager.getLocale(),
"property-not-supported", new Object [] {identifier}));
}
}
}
/*
* EntityState methods
*/
public boolean isEntityDeclared(String name) {
return false;
}
public boolean isEntityUnparsed(String name) {
if (fUnparsedEntities != null) {
return fUnparsedEntities.containsKey(name);
}
return false;
}
/*
* XMLDocumentHandler methods
*/
public void startDocument(XMLLocator locator, String encoding,
NamespaceContext namespaceContext, Augmentations augs)
throws XNIException {
if (fContentHandler != null) {
try {
fContentHandler.startDocument();
}
catch (SAXException e) {
throw new XNIException(e);
}
}
}
public void xmlDecl(String version, String encoding, String standalone,
Augmentations augs) throws XNIException {}
public void doctypeDecl(String rootElement, String publicId,
String systemId, Augmentations augs) throws XNIException {}
public void comment(XMLString text, Augmentations augs) throws XNIException {}
public void processingInstruction(String target, XMLString data,
Augmentations augs) throws XNIException {
if (fContentHandler != null) {
try {
fContentHandler.processingInstruction(target, data.toString());
}
catch (SAXException e) {
throw new XNIException(e);
}
}
}
public void startElement(QName element, XMLAttributes attributes,
Augmentations augs) throws XNIException {
if (fContentHandler != null) {
try {
fTypeInfoProvider.beginStartElement(augs, attributes);
fContentHandler.startElement((element.uri != null) ? element.uri : XMLSymbols.EMPTY_STRING,
element.localpart, element.rawname, fAttrAdapter);
}
catch (SAXException e) {
throw new XNIException(e);
}
finally {
fTypeInfoProvider.finishStartElement();
}
}
}
public void emptyElement(QName element, XMLAttributes attributes,
Augmentations augs) throws XNIException {
/** Split empty element event. **/
startElement(element, attributes, augs);
endElement(element, augs);
}
public void startGeneralEntity(String name,
XMLResourceIdentifier identifier, String encoding,
Augmentations augs) throws XNIException {}
public void textDecl(String version, String encoding, Augmentations augs)
throws XNIException {}
public void endGeneralEntity(String name, Augmentations augs)
throws XNIException {}
public void characters(XMLString text, Augmentations augs)
throws XNIException {
if (fContentHandler != null) {
// if the type is union it is possible that we receive
// a character call with empty data
if (text.length == 0) {
return;
}
try {
fContentHandler.characters(text.ch, text.offset, text.length);
}
catch (SAXException e) {
throw new XNIException(e);
}
}
}
public void ignorableWhitespace(XMLString text, Augmentations augs)
throws XNIException {
if (fContentHandler != null) {
try {
fContentHandler.ignorableWhitespace(text.ch, text.offset, text.length);
}
catch (SAXException e) {
throw new XNIException(e);
}
}
}
public void endElement(QName element, Augmentations augs)
throws XNIException {
if (fContentHandler != null) {
try {
fTypeInfoProvider.beginEndElement(augs);
fContentHandler.endElement((element.uri != null) ? element.uri : XMLSymbols.EMPTY_STRING,
element.localpart, element.rawname);
}
catch (SAXException e) {
throw new XNIException(e);
}
finally {
fTypeInfoProvider.finishEndElement();
}
}
}
public void startCDATA(Augmentations augs) throws XNIException {}
public void endCDATA(Augmentations augs) throws XNIException {}
public void endDocument(Augmentations augs) throws XNIException {
if (fContentHandler != null) {
try {
fContentHandler.endDocument();
}
catch (SAXException e) {
throw new XNIException(e);
}
}
}
// NO-OP
public void setDocumentSource(XMLDocumentSource source) {}
public XMLDocumentSource getDocumentSource() {
return fSchemaValidator;
}
/*
* ContentHandler methods
*/
public void setDocumentLocator(Locator locator) {
fSAXLocatorWrapper.setLocator(locator);
if (fContentHandler != null) {
fContentHandler.setDocumentLocator(locator);
}
}
public void startDocument() throws SAXException {
fComponentManager.reset();
fSchemaValidator.setDocumentHandler(this);
fValidationManager.setEntityState(this);
fTypeInfoProvider.finishStartElement(); // cleans up TypeInfoProvider
fNeedPushNSContext = true;
if (fUnparsedEntities != null && !fUnparsedEntities.isEmpty()) {
// should only clear this if the last document contained unparsed entities
fUnparsedEntities.clear();
}
fErrorReporter.setDocumentLocator(fSAXLocatorWrapper);
try {
fSchemaValidator.startDocument(fSAXLocatorWrapper, fSAXLocatorWrapper.getEncoding(), fNamespaceContext, null);
}
catch (XMLParseException e) {
throw Util.toSAXParseException(e);
}
catch (XNIException e) {
throw Util.toSAXException(e);
}
}
public void endDocument() throws SAXException {
fSAXLocatorWrapper.setLocator(null);
try {
fSchemaValidator.endDocument(null);
}
catch (XMLParseException e) {
throw Util.toSAXParseException(e);
}
catch (XNIException e) {
throw Util.toSAXException(e);
}
}
public void startPrefixMapping(String prefix, String uri)
throws SAXException {
String prefixSymbol;
String uriSymbol;
if (!fStringsInternalized) {
prefixSymbol = (prefix != null) ? fSymbolTable.addSymbol(prefix) : XMLSymbols.EMPTY_STRING;
uriSymbol = (uri != null && uri.length() > 0) ? fSymbolTable.addSymbol(uri) : null;
}
else {
prefixSymbol = (prefix != null) ? prefix : XMLSymbols.EMPTY_STRING;
uriSymbol = (uri != null && uri.length() > 0) ? uri : null;
}
if (fNeedPushNSContext) {
fNeedPushNSContext = false;
fNamespaceContext.pushContext();
}
fNamespaceContext.declarePrefix(prefixSymbol, uriSymbol);
if (fContentHandler != null) {
fContentHandler.startPrefixMapping(prefix, uri);
}
}
public void endPrefixMapping(String prefix) throws SAXException {
if (fContentHandler != null) {
fContentHandler.endPrefixMapping(prefix);
}
}
public void startElement(String uri, String localName, String qName,
Attributes atts) throws SAXException {
if (fNeedPushNSContext) {
fNamespaceContext.pushContext();
}
fNeedPushNSContext = true;
// Fill element QName
fillQName(fElementQName, uri, localName, qName);
// Fill XMLAttributes
if (atts instanceof Attributes2) {
fillXMLAttributes2((Attributes2) atts);
}
else {
fillXMLAttributes(atts);
}
try {
fSchemaValidator.startElement(fElementQName, fAttributes, null);
}
catch (XMLParseException e) {
throw Util.toSAXParseException(e);
}
catch (XNIException e) {
throw Util.toSAXException(e);
}
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
fillQName(fElementQName, uri, localName, qName);
try {
fSchemaValidator.endElement(fElementQName, null);
}
catch (XMLParseException e) {
throw Util.toSAXParseException(e);
}
catch (XNIException e) {
throw Util.toSAXException(e);
}
finally {
fNamespaceContext.popContext();
}
}
public void characters(char[] ch, int start, int length)
throws SAXException {
try {
fTempString.setValues(ch, start, length);
fSchemaValidator.characters(fTempString, null);
}
catch (XMLParseException e) {
throw Util.toSAXParseException(e);
}
catch (XNIException e) {
throw Util.toSAXException(e);
}
}
public void ignorableWhitespace(char[] ch, int start, int length)
throws SAXException {
try {
fTempString.setValues(ch, start, length);
fSchemaValidator.ignorableWhitespace(fTempString, null);
}
catch (XMLParseException e) {
throw Util.toSAXParseException(e);
}
catch (XNIException e) {
throw Util.toSAXException(e);
}
}
public void processingInstruction(String target, String data)
throws SAXException {
/**
* Processing instructions do not participate in schema validation,
* so just forward the event to the application's content
* handler.
*/
if (fContentHandler != null) {
fContentHandler.processingInstruction(target, data);
}
}
public void skippedEntity(String name) throws SAXException {
// there seems to be no corresponding method on XMLDocumentFilter.
// just pass it down to the output, if any.
if (fContentHandler != null) {
fContentHandler.skippedEntity(name);
}
}
/*
* DTDHandler methods
*/
public void notationDecl(String name, String publicId,
String systemId) throws SAXException {}
public void unparsedEntityDecl(String name, String publicId,
String systemId, String notationName) throws SAXException {
if (fUnparsedEntities == null) {
fUnparsedEntities = new HashMap();
}
fUnparsedEntities.put(name, name);
}
/*
* ValidatorHelper methods
*/
public void validate(Source source, Result result)
throws SAXException, IOException {
if (result instanceof SAXResult || result == null) {
final SAXSource saxSource = (SAXSource) source;
final SAXResult saxResult = (SAXResult) result;
LexicalHandler lh = null;
if (result != null) {
ContentHandler ch = saxResult.getHandler();
lh = saxResult.getLexicalHandler();
/** If the lexical handler is not set try casting the ContentHandler. **/
if (lh == null && ch instanceof LexicalHandler) {
lh = (LexicalHandler) ch;
}
setContentHandler(ch);
}
XMLReader reader = null;
try {
reader = saxSource.getXMLReader();
if (reader == null) {
// create one now
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
try {
reader = spf.newSAXParser().getXMLReader();
// If this is a Xerces SAX parser, set the security manager if there is one
if (reader instanceof org.apache.xerces.parsers.SAXParser) {
Object securityManager = fComponentManager.getProperty(SECURITY_MANAGER);
if (securityManager != null) {
try {
reader.setProperty(SECURITY_MANAGER, securityManager);
}
// Ignore the exception if the security manager cannot be set.
catch (SAXException exc) {}
}
}
}
catch (Exception e) {
// this is impossible, but better safe than sorry
throw new FactoryConfigurationError(e);
}
}
// If XML names and Namespace URIs are already internalized we
// can avoid running them through the SymbolTable.
try {
fStringsInternalized = reader.getFeature(STRING_INTERNING);
}
catch (SAXException exc) {
// The feature isn't recognized or getting it is not supported.
// In either case, assume that strings are not internalized.
fStringsInternalized = false;
}
ErrorHandler errorHandler = fComponentManager.getErrorHandler();
reader.setErrorHandler(errorHandler != null ? errorHandler : DraconianErrorHandler.getInstance());
reader.setEntityResolver(fResolutionForwarder);
fResolutionForwarder.setEntityResolver(fComponentManager.getResourceResolver());
reader.setContentHandler(this);
reader.setDTDHandler(this);
try {
reader.setProperty(LEXICAL_HANDLER, lh);
}
// Ignore the exception if the lexical handler cannot be set.
catch (SAXException exc) {}
InputSource is = saxSource.getInputSource();
reader.parse(is);
}
finally {
// Release the reference to user's ContentHandler ASAP
setContentHandler(null);
// Disconnect the validator and other objects from the XMLReader
if (reader != null) {
try {
reader.setContentHandler(null);
reader.setDTDHandler(null);
reader.setErrorHandler(null);
reader.setEntityResolver(null);
fResolutionForwarder.setEntityResolver(null);
reader.setProperty(LEXICAL_HANDLER, null);
}
// Ignore the exception if the lexical handler cannot be unset.
catch (Exception exc) {}
}
}
return;
}
throw new IllegalArgumentException(JAXPValidationMessageFormatter.formatMessage(fComponentManager.getLocale(),
"SourceResultMismatch",
new Object [] {source.getClass().getName(), result.getClass().getName()}));
}
/*
* PSVIProvider methods
*/
public ElementPSVI getElementPSVI() {
return fTypeInfoProvider.getElementPSVI();
}
public AttributePSVI getAttributePSVI(int index) {
return fTypeInfoProvider.getAttributePSVI(index);
}
public AttributePSVI getAttributePSVIByName(String uri, String localname) {
return fTypeInfoProvider.getAttributePSVIByName(uri, localname);
}
//
//
// helper methods
//
//
/** Fills in a QName object. */
private void fillQName(QName toFill, String uri, String localpart, String raw) {
if (!fStringsInternalized) {
uri = (uri != null && uri.length() > 0) ? fSymbolTable.addSymbol(uri) : null;
localpart = (localpart != null) ? fSymbolTable.addSymbol(localpart) : XMLSymbols.EMPTY_STRING;
raw = (raw != null) ? fSymbolTable.addSymbol(raw) : XMLSymbols.EMPTY_STRING;
}
else {
if (uri != null && uri.length() == 0) {
uri = null;
}
if (localpart == null) {
localpart = XMLSymbols.EMPTY_STRING;
}
if (raw == null) {
raw = XMLSymbols.EMPTY_STRING;
}
}
String prefix = XMLSymbols.EMPTY_STRING;
int prefixIdx = raw.indexOf(':');
if (prefixIdx != -1) {
prefix = fSymbolTable.addSymbol(raw.substring(0, prefixIdx));
}
toFill.setValues(prefix, localpart, raw, uri);
}
/** Fills in the XMLAttributes object. */
private void fillXMLAttributes(Attributes att) {
fAttributes.removeAllAttributes();
final int len = att.getLength();
for (int i = 0; i < len; ++i) {
fillXMLAttribute(att, i);
fAttributes.setSpecified(i, true);
}
}
/** Fills in the XMLAttributes object. */
private void fillXMLAttributes2(Attributes2 att) {
fAttributes.removeAllAttributes();
final int len = att.getLength();
for (int i = 0; i < len; ++i) {
fillXMLAttribute(att, i);
fAttributes.setSpecified(i, att.isSpecified(i));
if (att.isDeclared(i)) {
fAttributes.getAugmentations(i).putItem(Constants.ATTRIBUTE_DECLARED, Boolean.TRUE);
}
}
}
/** Adds an attribute to the XMLAttributes object. */
private void fillXMLAttribute(Attributes att, int index) {
fillQName(fAttributeQName, att.getURI(index), att.getLocalName(index), att.getQName(index));
String type = att.getType(index);
fAttributes.addAttributeNS(fAttributeQName, (type != null) ? type : XMLSymbols.fCDATASymbol, att.getValue(index));
}
/**
* {@link TypeInfoProvider} implementation.
*
* REVISIT: I'm not sure if this code should belong here.
*/
private final XMLSchemaTypeInfoProvider fTypeInfoProvider = new XMLSchemaTypeInfoProvider();
private class XMLSchemaTypeInfoProvider extends TypeInfoProvider {
/** Element augmentations: contains ElementPSVI. **/
private Augmentations fElementAugs;
/** Attributes: augmentations for each attribute contain AttributePSVI. **/
private XMLAttributes fAttributes;
/** In start element. **/
private boolean fInStartElement = false;
private boolean fInEndElement = false;
/** Initializes the TypeInfoProvider with type information for the current element. **/
void beginStartElement(Augmentations elementAugs, XMLAttributes attributes) {
fInStartElement = true;
fElementAugs = elementAugs;
fAttributes = attributes;
}
/** Cleanup at the end of start element. **/
void finishStartElement() {
fInStartElement = false;
fElementAugs = null;
fAttributes = null;
}
/** Initializes the TypeInfoProvider with type information for the current element. **/
void beginEndElement(Augmentations elementAugs) {
fInEndElement = true;
fElementAugs = elementAugs;
}
/** Cleanup at the end of end element. **/
void finishEndElement() {
fInEndElement = false;
fElementAugs = null;
}
/**
* Throws a {@link IllegalStateException} if we are not in
* the startElement callback. the JAXP API requires this
* for most of the public methods which access attribute
* type information.
*/
private void checkStateAttribute() {
if (!fInStartElement) {
throw new IllegalStateException(JAXPValidationMessageFormatter.formatMessage(fComponentManager.getLocale(),
"TypeInfoProviderIllegalStateAttribute", null));
}
}
/**
* Throws a {@link IllegalStateException} if we are not in
* the startElement or endElement callbacks. the JAXP API requires
* this for the public methods which access element type information.
*/
private void checkStateElement() {
if (!fInStartElement && !fInEndElement) {
throw new IllegalStateException(JAXPValidationMessageFormatter.formatMessage(fComponentManager.getLocale(),
"TypeInfoProviderIllegalStateElement", null));
}
}
public TypeInfo getAttributeTypeInfo(int index) {
checkStateAttribute();
return getAttributeType(index);
}
private TypeInfo getAttributeType( int index ) {
checkStateAttribute();
if (index < 0 || fAttributes.getLength() <= index) {
throw new IndexOutOfBoundsException(Integer.toString(index));
}
Augmentations augs = fAttributes.getAugmentations(index);
if (augs == null) {
return null;
}
AttributePSVI psvi = (AttributePSVI)augs.getItem(Constants.ATTRIBUTE_PSVI);
return getTypeInfoFromPSVI(psvi);
}
public TypeInfo getAttributeTypeInfo(String attributeUri, String attributeLocalName) {
checkStateAttribute();
return getAttributeTypeInfo(fAttributes.getIndex(attributeUri,attributeLocalName));
}
public TypeInfo getAttributeTypeInfo(String attributeQName) {
checkStateAttribute();
return getAttributeTypeInfo(fAttributes.getIndex(attributeQName));
}
public TypeInfo getElementTypeInfo() {
checkStateElement();
if (fElementAugs == null) {
return null;
}
ElementPSVI psvi = (ElementPSVI)fElementAugs.getItem(Constants.ELEMENT_PSVI);
return getTypeInfoFromPSVI(psvi);
}
private TypeInfo getTypeInfoFromPSVI(ItemPSVI psvi) {
if (psvi == null) {
return null;
}
// TODO: make sure if this is correct.
// TODO: since the number of types in a schema is quite limited,
// TypeInfoImpl should be pooled. Even better, it should be a part
// of the element decl.
if (psvi.getValidity() == ItemPSVI.VALIDITY_VALID) {
XSTypeDefinition t = psvi.getMemberTypeDefinition();
if (t != null) {
return (t instanceof TypeInfo) ? (TypeInfo) t : null;
}
}
XSTypeDefinition t = psvi.getTypeDefinition();
// TODO: can t be null?
if (t != null) {
return (t instanceof TypeInfo) ? (TypeInfo) t : null;
}
return null;
}
public boolean isIdAttribute(int index) {
checkStateAttribute();
XSSimpleType type = (XSSimpleType)getAttributeType(index);
if (type == null) {
return false;
}
return type.isIDType();
}
public boolean isSpecified(int index) {
checkStateAttribute();
return fAttributes.isSpecified(index);
}
/*
* Other methods
*/
// PSVIProvider support
ElementPSVI getElementPSVI() {
return (fElementAugs != null) ? (ElementPSVI) fElementAugs.getItem(Constants.ELEMENT_PSVI) : null;
}
AttributePSVI getAttributePSVI(int index) {
if (fAttributes != null) {
Augmentations augs = fAttributes.getAugmentations(index);
if (augs != null) {
return (AttributePSVI) augs.getItem(Constants.ATTRIBUTE_PSVI);
}
}
return null;
}
AttributePSVI getAttributePSVIByName(String uri, String localname) {
if (fAttributes != null) {
Augmentations augs = fAttributes.getAugmentations(uri, localname);
if (augs != null) {
return (AttributePSVI) augs.getItem(Constants.ATTRIBUTE_PSVI);
}
}
return null;
}
}
/** SAX adapter for an LSResourceResolver. */
private final ResolutionForwarder fResolutionForwarder = new ResolutionForwarder(null);
static final class ResolutionForwarder
implements EntityResolver2 {
//
// Data
//
/** XML 1.0 type constant according to DOM L3 LS REC spec "http://www.w3.org/TR/2004/REC-DOM-Level-3-LS-20040407/" */
private static final String XML_TYPE = "http://www.w3.org/TR/REC-xml";
/** The DOM entity resolver. */
protected LSResourceResolver fEntityResolver;
//
// Constructors
//
/** Default constructor. */
public ResolutionForwarder() {}
/** Wraps the specified DOM entity resolver. */
public ResolutionForwarder(LSResourceResolver entityResolver) {
setEntityResolver(entityResolver);
}
//
// Public methods
//
/** Sets the DOM entity resolver. */
public void setEntityResolver(LSResourceResolver entityResolver) {
fEntityResolver = entityResolver;
} // setEntityResolver(LSResourceResolver)
/** Returns the DOM entity resolver. */
public LSResourceResolver getEntityResolver() {
return fEntityResolver;
} // getEntityResolver():LSResourceResolver
/**
* Always returns null
. An LSResourceResolver has no corresponding method.
*/
public InputSource getExternalSubset(String name, String baseURI)
throws SAXException, IOException {
return null;
}
/**
* Resolves the given resource and adapts the LSInput
* returned into an InputSource
.
*/
public InputSource resolveEntity(String name, String publicId,
String baseURI, String systemId) throws SAXException, IOException {
if (fEntityResolver != null) {
LSInput lsInput = fEntityResolver.resolveResource(XML_TYPE, null, publicId, systemId, baseURI);
if (lsInput != null) {
final String pubId = lsInput.getPublicId();
final String sysId = lsInput.getSystemId();
final String baseSystemId = lsInput.getBaseURI();
final Reader charStream = lsInput.getCharacterStream();
final InputStream byteStream = lsInput.getByteStream();
final String data = lsInput.getStringData();
final String encoding = lsInput.getEncoding();
/**
* An LSParser looks at inputs specified in LSInput in
* the following order: characterStream, byteStream,
* stringData, systemId, publicId. For consistency
* with the DOM Level 3 Load and Save Recommendation
* use the same lookup order here.
*/
InputSource inputSource = new InputSource();
inputSource.setPublicId(pubId);
inputSource.setSystemId((baseSystemId != null) ? resolveSystemId(sysId, baseSystemId) : sysId);
if (charStream != null) {
inputSource.setCharacterStream(charStream);
}
else if (byteStream != null) {
inputSource.setByteStream(byteStream);
}
else if (data != null && data.length() != 0) {
inputSource.setCharacterStream(new StringReader(data));
}
inputSource.setEncoding(encoding);
return inputSource;
}
}
return null;
}
/** Delegates to EntityResolver2.resolveEntity(String, String, String, String). */
public InputSource resolveEntity(String publicId, String systemId)
throws SAXException, IOException {
return resolveEntity(null, publicId, null, systemId);
}
/** Resolves a system identifier against a base URI. */
private String resolveSystemId(String systemId, String baseURI) {
try {
return XMLEntityManager.expandSystemId(systemId, baseURI, false);
}
// In the event that resolution failed against the
// base URI, just return the system id as is. There's not
// much else we can do.
catch (URI.MalformedURIException ex) {
return systemId;
}
}
}
}