blob: 1a7ca1476808110cd14c8ceff61bbb1ddc93daa5 [file] [log] [blame]
/*
* 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.impl.xs.traversers;
import com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaDOMParser;
import com.sun.org.apache.xerces.internal.util.NamespaceSupport;
import com.sun.org.apache.xerces.internal.util.SAXLocatorWrapper;
import com.sun.org.apache.xerces.internal.util.SymbolTable;
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.NamespaceContext;
import com.sun.org.apache.xerces.internal.xni.QName;
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.XMLParseException;
import org.w3c.dom.Document;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.LocatorImpl;
/**
* <p>SchemaContentHandler converts SAX events into XNI
* and passes them directly to the SchemaDOMParser.</p>
*
* @xerces.internal
*
* @author Michael Glavassevich, IBM
* @author Jack Z. Wang, IBM
*
*/
final class SchemaContentHandler implements ContentHandler {
/** Symbol table **/
private SymbolTable fSymbolTable;
/** SchemaDOMParser, events will be delegated to SchemaDOMParser to pass */
private SchemaDOMParser fSchemaDOMParser;
/** XML Locator wrapper for SAX. **/
private final SAXLocatorWrapper fSAXLocatorWrapper = new SAXLocatorWrapper();
/** The namespace context of this document: stores namespaces in scope */
private NamespaceSupport fNamespaceContext = new NamespaceSupport();
/** Indicate if push NamespaceContest is needed */
private boolean fNeedPushNSContext;
/** Flag used to track whether namespace declarations are reported as attributes. */
private boolean fNamespacePrefixes = false;
/** 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 XMLString fTempString = new XMLString();
/**
* <p>Constructs an SchemaContentHandler.</p>
*/
public SchemaContentHandler() {}
/*
* @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator)
*/
public Document getDocument() {
return fSchemaDOMParser.getDocument();
}
/*
* @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator)
*/
public void setDocumentLocator(Locator locator) {
fSAXLocatorWrapper.setLocator(locator);
}
/*
* @see org.xml.sax.ContentHandler#startDocument()
*/
public void startDocument() throws SAXException {
fNeedPushNSContext = true;
try {
fSchemaDOMParser.startDocument(fSAXLocatorWrapper, null, fNamespaceContext, null);
}
catch (XMLParseException e) {
convertToSAXParseException(e);
}
catch (XNIException e) {
convertToSAXException(e);
}
}
/*
* @see org.xml.sax.ContentHandler#endDocument()
*/
public void endDocument() throws SAXException {
fSAXLocatorWrapper.setLocator(null);
try {
fSchemaDOMParser.endDocument(null);
}
catch (XMLParseException e) {
convertToSAXParseException(e);
}
catch (XNIException e) {
convertToSAXException(e);
}
}
/*
* @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String)
*/
public void startPrefixMapping(String prefix, String uri) throws SAXException {
if (fNeedPushNSContext) {
fNeedPushNSContext = false;
fNamespaceContext.pushContext();
}
if (!fStringsInternalized) {
prefix = (prefix != null) ? fSymbolTable.addSymbol(prefix) : XMLSymbols.EMPTY_STRING;
uri = (uri != null && uri.length() > 0) ? fSymbolTable.addSymbol(uri) : null;
}
else {
if (prefix == null) {
prefix = XMLSymbols.EMPTY_STRING;
}
if (uri != null && uri.length() == 0) {
uri = null;
}
}
fNamespaceContext.declarePrefix(prefix, uri);
}
/*
* @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String)
*/
public void endPrefixMapping(String prefix) throws SAXException {
// do nothing
}
/*
* @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
*/
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
if (fNeedPushNSContext) {
fNamespaceContext.pushContext();
}
fNeedPushNSContext = true;
// Fill element QName and XMLAttributes
fillQName(fElementQName, uri, localName, qName);
fillXMLAttributes(atts);
// Add namespace declarations if necessary
if (!fNamespacePrefixes) {
final int prefixCount = fNamespaceContext.getDeclaredPrefixCount();
if (prefixCount > 0) {
addNamespaceDeclarations(prefixCount);
}
}
try {
fSchemaDOMParser.startElement(fElementQName, fAttributes, null);
}
catch (XMLParseException e) {
convertToSAXParseException(e);
}
catch (XNIException e) {
convertToSAXException(e);
}
}
/*
* @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
*/
public void endElement(String uri, String localName, String qName) throws SAXException {
fillQName(fElementQName, uri, localName, qName);
try {
fSchemaDOMParser.endElement(fElementQName, null);
}
catch (XMLParseException e) {
convertToSAXParseException(e);
}
catch (XNIException e) {
convertToSAXException(e);
}
finally {
fNamespaceContext.popContext();
}
}
/*
* @see org.xml.sax.ContentHandler#characters(char[], int, int)
*/
public void characters(char[] ch, int start, int length) throws SAXException {
try {
fTempString.setValues(ch, start, length);
fSchemaDOMParser.characters(fTempString, null);
}
catch (XMLParseException e) {
convertToSAXParseException(e);
}
catch (XNIException e) {
convertToSAXException(e);
}
}
/*
* @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int)
*/
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
try {
fTempString.setValues(ch, start, length);
fSchemaDOMParser.ignorableWhitespace(fTempString, null);
}
catch (XMLParseException e) {
convertToSAXParseException(e);
}
catch (XNIException e) {
convertToSAXException(e);
}
}
/*
* @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String, java.lang.String)
*/
public void processingInstruction(String target, String data) throws SAXException {
try {
fTempString.setValues(data.toCharArray(), 0, data.length());
fSchemaDOMParser.processingInstruction(target, fTempString, null);
}
catch (XMLParseException e) {
convertToSAXParseException(e);
}
catch (XNIException e) {
convertToSAXException(e);
}
}
/*
* @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String)
*/
public void skippedEntity(String arg) throws SAXException {
// do-nothing
}
/*
* Other methods
*/
private void fillQName(QName toFill, String uri, String localpart, String rawname) {
if (!fStringsInternalized) {
uri = (uri != null && uri.length() > 0) ? fSymbolTable.addSymbol(uri) : null;
localpart = (localpart != null) ? fSymbolTable.addSymbol(localpart) : XMLSymbols.EMPTY_STRING;
rawname = (rawname != null) ? fSymbolTable.addSymbol(rawname) : XMLSymbols.EMPTY_STRING;
}
else {
if (uri != null && uri.length() == 0) {
uri = null;
}
if (localpart == null) {
localpart = XMLSymbols.EMPTY_STRING;
}
if (rawname == null) {
rawname = XMLSymbols.EMPTY_STRING;
}
}
String prefix = XMLSymbols.EMPTY_STRING;
int prefixIdx = rawname.indexOf(':');
if (prefixIdx != -1) {
prefix = fSymbolTable.addSymbol(rawname.substring(0, prefixIdx));
// local part may be an empty string if this is a namespace declaration
if (localpart == XMLSymbols.EMPTY_STRING) {
localpart = fSymbolTable.addSymbol(rawname.substring(prefixIdx + 1));
}
}
// local part may be an empty string if this is a namespace declaration
else if (localpart == XMLSymbols.EMPTY_STRING) {
localpart = rawname;
}
toFill.setValues(prefix, localpart, rawname, uri);
}
private void fillXMLAttributes(Attributes atts) {
fAttributes.removeAllAttributes();
final int attrCount = atts.getLength();
for (int i = 0; i < attrCount; ++i) {
fillQName(fAttributeQName, atts.getURI(i), atts.getLocalName(i), atts.getQName(i));
String type = atts.getType(i);
fAttributes.addAttributeNS(fAttributeQName, (type != null) ? type : XMLSymbols.fCDATASymbol, atts.getValue(i));
fAttributes.setSpecified(i, true);
}
}
private void addNamespaceDeclarations(final int prefixCount) {
String prefix = null;
String localpart = null;
String rawname = null;
String nsPrefix = null;
String nsURI = null;
for (int i = 0; i < prefixCount; ++i) {
nsPrefix = fNamespaceContext.getDeclaredPrefixAt(i);
nsURI = fNamespaceContext.getURI(nsPrefix);
if (nsPrefix.length() > 0) {
prefix = XMLSymbols.PREFIX_XMLNS;
localpart = nsPrefix;
rawname = fSymbolTable.addSymbol(prefix + ":" + localpart);
}
else {
prefix = XMLSymbols.EMPTY_STRING;
localpart = XMLSymbols.PREFIX_XMLNS;
rawname = XMLSymbols.PREFIX_XMLNS;
}
fAttributeQName.setValues(prefix, localpart, rawname, NamespaceContext.XMLNS_URI);
fAttributes.addAttribute(fAttributeQName, XMLSymbols.fCDATASymbol, nsURI);
}
}
public void reset(SchemaDOMParser schemaDOMParser, SymbolTable symbolTable,
boolean namespacePrefixes, boolean stringsInternalized) {
fSchemaDOMParser = schemaDOMParser;
fSymbolTable = symbolTable;
fNamespacePrefixes = namespacePrefixes;
fStringsInternalized = stringsInternalized;
}
/*
* Static methods
*/
static void convertToSAXParseException(XMLParseException e) throws SAXException {
Exception ex = e.getException();
if (ex == null) {
// must be a parser exception; mine it for locator info and throw
// a SAXParseException
LocatorImpl locatorImpl = new LocatorImpl();
locatorImpl.setPublicId(e.getPublicId());
locatorImpl.setSystemId(e.getExpandedSystemId());
locatorImpl.setLineNumber(e.getLineNumber());
locatorImpl.setColumnNumber(e.getColumnNumber());
throw new SAXParseException(e.getMessage(), locatorImpl);
}
if (ex instanceof SAXException) {
// why did we create an XMLParseException?
throw (SAXException) ex;
}
throw new SAXException(ex);
}
static void convertToSAXException(XNIException e) throws SAXException {
Exception ex = e.getException();
if (ex == null) {
throw new SAXException(e.getMessage());
}
if (ex instanceof SAXException) {
throw (SAXException) ex;
}
throw new SAXException(ex);
}
} // SchemaContentHandler