diff options
Diffstat (limited to 'src/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/ValidatorHandlerImpl.java')
-rw-r--r-- | src/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/ValidatorHandlerImpl.java | 1069 |
1 files changed, 1069 insertions, 0 deletions
diff --git a/src/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/ValidatorHandlerImpl.java b/src/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/ValidatorHandlerImpl.java new file mode 100644 index 0000000..529c603 --- /dev/null +++ b/src/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/ValidatorHandlerImpl.java @@ -0,0 +1,1069 @@ +/* + * reserved comment block + * DO NOT REMOVE OR ALTER! + */ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed 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 com.sun.org.apache.xerces.internal.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.XMLConstants; +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 com.sun.org.apache.xerces.internal.impl.Constants; +import com.sun.org.apache.xerces.internal.impl.XMLEntityManager; +import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter; +import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType; +import com.sun.org.apache.xerces.internal.impl.validation.EntityState; +import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager; +import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator; +import com.sun.org.apache.xerces.internal.util.AttributesProxy; +import com.sun.org.apache.xerces.internal.util.SAXLocatorWrapper; +import com.sun.org.apache.xerces.internal.util.SAXMessageFormatter; +import com.sun.org.apache.xerces.internal.util.Status; +import com.sun.org.apache.xerces.internal.util.SymbolTable; +import com.sun.org.apache.xerces.internal.util.SecurityManager; +import com.sun.org.apache.xerces.internal.util.URI; +import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl; +import com.sun.org.apache.xerces.internal.util.XMLSymbols; +import com.sun.org.apache.xerces.internal.xni.Augmentations; +import com.sun.org.apache.xerces.internal.xni.NamespaceContext; +import com.sun.org.apache.xerces.internal.xni.QName; +import com.sun.org.apache.xerces.internal.xni.XMLAttributes; +import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler; +import com.sun.org.apache.xerces.internal.xni.XMLLocator; +import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; +import com.sun.org.apache.xerces.internal.xni.XMLString; +import com.sun.org.apache.xerces.internal.xni.XNIException; +import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; +import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource; +import com.sun.org.apache.xerces.internal.xni.parser.XMLParseException; +import com.sun.org.apache.xerces.internal.xs.AttributePSVI; +import com.sun.org.apache.xerces.internal.xs.ElementPSVI; +import com.sun.org.apache.xerces.internal.xs.ItemPSVI; +import com.sun.org.apache.xerces.internal.xs.PSVIProvider; +import com.sun.org.apache.xerces.internal.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; + +/** + * <p>Implementation of ValidatorHandler for W3C XML Schemas and + * also a validator helper for <code>SAXSource</code>s.</p> + * + * @author Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + * @author Michael Glavassevich, IBM + * + * @version $Id: ValidatorHandlerImpl.java,v 1.10 2010-11-01 04:40:08 joehw Exp $ + */ +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. */ + protected static final String STRING_INTERNING = + Constants.SAX_FEATURE_PREFIX + Constants.STRING_INTERNING_FEATURE; + + // property identifiers + + /** Property identifier: error reporter. */ + private static final String ERROR_REPORTER = + Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_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 XMLErrorReporter fErrorReporter; + + /** The namespace context of this document: stores namespaces in scope */ + private NamespaceContext fNamespaceContext; + + /** Schema validator. **/ + private XMLSchemaValidator fSchemaValidator; + + /** Symbol table **/ + private SymbolTable fSymbolTable; + + /** Validation manager. */ + private ValidationManager fValidationManager; + + /** Component manager. **/ + private 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(); + } + try { + return fComponentManager.getFeature(name); + } + catch (XMLConfigurationException e) { + final String identifier = e.getIdentifier(); + final String key = e.getType() == Status.NOT_RECOGNIZED ? + "feature-not-recognized" : "feature-not-supported"; + throw new SAXNotRecognizedException( + SAXMessageFormatter.formatMessage(fComponentManager.getLocale(), + key, new Object [] {identifier})); + } + } + + public void setFeature(String name, boolean value) + throws SAXNotRecognizedException, SAXNotSupportedException { + if (name == null) { + throw new NullPointerException(); + } + try { + fComponentManager.setFeature(name, value); + } + catch (XMLConfigurationException e) { + final String identifier = e.getIdentifier(); + final String key; + if (e.getType() == Status.NOT_ALLOWED) { + //for now, the identifier can only be (XMLConstants.FEATURE_SECURE_PROCESSING) + throw new SAXNotSupportedException( + SAXMessageFormatter.formatMessage(fComponentManager.getLocale(), + "jaxp-secureprocessing-feature", null)); + } else if (e.getType() == Status.NOT_RECOGNIZED) { + key = "feature-not-recognized"; + } else { + key = "feature-not-supported"; + } + throw new SAXNotRecognizedException( + SAXMessageFormatter.formatMessage(fComponentManager.getLocale(), + key, new Object [] {identifier})); + } + } + + public Object getProperty(String name) + throws SAXNotRecognizedException, SAXNotSupportedException { + if (name == null) { + throw new NullPointerException(); + } + try { + return fComponentManager.getProperty(name); + } + catch (XMLConfigurationException e) { + final String identifier = e.getIdentifier(); + final String key = e.getType() == Status.NOT_RECOGNIZED ? + "property-not-recognized" : "property-not-supported"; + throw new SAXNotRecognizedException( + SAXMessageFormatter.formatMessage(fComponentManager.getLocale(), + key, new Object [] {identifier})); + } + } + + public void setProperty(String name, Object object) + throws SAXNotRecognizedException, SAXNotSupportedException { + if (name == null) { + throw new NullPointerException(); + } + try { + fComponentManager.setProperty(name, object); + } + catch (XMLConfigurationException e) { + final String identifier = e.getIdentifier(); + final String key = e.getType() == Status.NOT_RECOGNIZED ? + "property-not-recognized" : "property-not-supported"; + throw new SAXNotRecognizedException( + SAXMessageFormatter.formatMessage(fComponentManager.getLocale(), + key, 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; + + if (result != null) { + setContentHandler(saxResult.getHandler()); + } + + try { + XMLReader 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 com.sun.org.apache.xerces.internal.parsers.SAXParser) { + SecurityManager securityManager = (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); + + InputSource is = saxSource.getInputSource(); + reader.parse(is); + } + finally { + // release the reference to user's handler ASAP + setContentHandler(null); + } + 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; + + /** In end element. **/ + 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. + */ + private void checkState(boolean forElementInfo) { + if (! (fInStartElement || (fInEndElement && forElementInfo))) { + throw new IllegalStateException(JAXPValidationMessageFormatter.formatMessage(fComponentManager.getLocale(), + "TypeInfoProviderIllegalState", null)); + } + } + + public TypeInfo getAttributeTypeInfo(int index) { + checkState(false); + return getAttributeType(index); + } + + private TypeInfo getAttributeType( int index ) { + checkState(false); + 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) { + checkState(false); + return getAttributeTypeInfo(fAttributes.getIndex(attributeUri,attributeLocalName)); + } + + public TypeInfo getAttributeTypeInfo(String attributeQName) { + checkState(false); + return getAttributeTypeInfo(fAttributes.getIndex(attributeQName)); + } + + public TypeInfo getElementTypeInfo() { + checkState(true); + 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()== ElementPSVI.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) { + checkState(false); + XSSimpleType type = (XSSimpleType)getAttributeType(index); + if(type==null) return false; + return type.isIDType(); + } + + public boolean isSpecified(int index) { + checkState(false); + 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 <code>null</code>. 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 <code>LSInput</code> + * returned into an <code>InputSource</code>. + */ + 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(systemId, baseSystemId) : systemId); + + 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; + } + } + } +} |