blob: 12895ff602fd1086026caaa563bc4fa475bab15a [file] [log] [blame]
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 1999,2000 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xerces" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 1999, International
* Business Machines, Inc., http://www.apache.org. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.xerces.parsers;
import org.apache.xerces.framework.XMLAttrList;
import org.apache.xerces.framework.XMLContentSpec;
import org.apache.xerces.framework.XMLDocumentHandler;
import org.apache.xerces.framework.XMLParser;
import org.apache.xerces.readers.XMLEntityHandler;
import org.apache.xerces.utils.QName;
import org.apache.xerces.utils.StringPool;
import org.apache.xerces.validators.common.XMLAttributeDecl;
import org.apache.xerces.validators.common.XMLElementDecl;
import org.xml.sax.Attributes;
import org.xml.sax.AttributeList;
import org.xml.sax.ContentHandler;
import org.xml.sax.DocumentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.Parser;
import org.xml.sax.XMLReader;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.ext.DeclHandler;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.AttributesImpl;
// REVISIT: [SAX2beta] ContentHandler#skippedEntity(String)
/**
* SAXParser provides a parser which implements the SAX1 and SAX2
* parser APIs.
*
* @version $Id$
*/
public class SAXParser
extends XMLParser
implements XMLDocumentHandler, XMLDocumentHandler.DTDHandler,
Parser, XMLReader {
//
// Constants
//
// private
/** Features recognized by this parser. */
private static final String RECOGNIZED_FEATURES[] = {
// SAX2 core
/*"http://xml.org/sax/features/normalize-text",*/
/*"http://xml.org/sax/features/use-locator",*/
"http://xml.org/sax/features/namespace-prefixes",
"http://xml.org/sax/features/string-interning",
// Xerces
};
/** Properties recognized by this parser. */
private static final String RECOGNIZED_PROPERTIES[] = {
// SAX2 core
"http://xml.org/sax/properties/lexical-handler",
"http://xml.org/sax/properties/declaration-handler",
"http://xml.org/sax/properties/dom-node",
// Xerces
};
// debugging
/** Set to true and recompile to debug callbacks. */
private static final boolean DEBUG_CALLBACKS = false;
//
// Data
//
// parser handlers
/** Document handler. */
private DocumentHandler fDocumentHandler;
// parser/xmlreader handlers
/** DTD handler. */
private org.xml.sax.DTDHandler fDTDHandler;
// xmlreader handlers
/** Content handler. */
private ContentHandler fContentHandler;
/** Decl handler. */
private DeclHandler fDeclHandler;
/** Lexical handler. */
private LexicalHandler fLexicalHandler;
private boolean fNamespacePrefixes = false;
// temp
private transient AttributesImpl fAttributes = new AttributesImpl();
//
// Constructors
//
/** Default constructor. */
public SAXParser() {
initHandlers(true, this, this);
}
//
// Public methods
//
// features and properties
/**
* Returns a list of features that this parser recognizes.
* This method will never return null; if no features are
* recognized, this method will return a zero length array.
*
* @see #isFeatureRecognized
* @see #setFeature
* @see #getFeature
*/
public String[] getFeaturesRecognized() {
// get features that super/this recognizes
String superRecognized[] = super.getFeaturesRecognized();
String thisRecognized[] = RECOGNIZED_FEATURES;
// is one or the other the empty set?
int thisLength = thisRecognized.length;
if (thisLength == 0) {
return superRecognized;
}
int superLength = superRecognized.length;
if (superLength == 0) {
return thisRecognized;
}
// combine the two lists and return
String recognized[] = new String[superLength + thisLength];
System.arraycopy(superRecognized, 0, recognized, 0, superLength);
System.arraycopy(thisRecognized, 0, recognized, superLength, thisLength);
return recognized;
} // getFeaturesRecognized():String[]
/**
* Returns a list of properties that this parser recognizes.
* This method will never return null; if no properties are
* recognized, this method will return a zero length array.
*
* @see #isPropertyRecognized
* @see #setProperty
* @see #getProperty
*/
public String[] getPropertiesRecognized() {
// get properties that super/this recognizes
String superRecognized[] = super.getPropertiesRecognized();
String thisRecognized[] = RECOGNIZED_PROPERTIES;
// is one or the other the empty set?
int thisLength = thisRecognized.length;
if (thisLength == 0) {
return superRecognized;
}
int superLength = superRecognized.length;
if (superLength == 0) {
return thisRecognized;
}
// combine the two lists and return
String recognized[] = new String[superLength + thisLength];
System.arraycopy(superRecognized, 0, recognized, 0, superLength);
System.arraycopy(thisRecognized, 0, recognized, superLength, thisLength);
return recognized;
}
//
// Protected methods
//
// SAX2 core features
/**
* <b>Note: Currently, the parser does not support this feature.</b>
* Setting this feature to true will throw a SAXNotSupportedException.
* <p>
* Ensures that all consecutive text is returned in a single callback
* to the DocumentHandler.characters or DocumentHandler.ignorableWhitespace
* methods.
* <p>
* This method is the equivalent to the feature:
* <pre>
* http://xml.org/sax/features/normalize-text
* <pre>
*
* @param normalize True to normalize; false not to normalize.
*
* @see #getNormalizeText
* @see #setFeature
*/
/*
protected void setNormalizeText(boolean normalize)
throws SAXNotRecognizedException, SAXNotSupportedException {
if (normalize) {
throw new SAXNotSupportedException("http://xml.org/sax/features/normalize-text");
}
}
*/
/**
* <b>Note: This feature is always false.</b>
* <p>
* Returns true if the parser normalizes all consecutive text into
* a single callback to the DocumentHandler.characters or
* DocumentHandler.ignorableWhitespace methods.
*
* @see #setNormalizeText
*/
/*
protected boolean getNormalizeText()
throws SAXNotRecognizedException, SAXNotSupportedException {
return false;
}
*/
/**
* <b>Note: Currently, this parser always sets the locator.</b>
* Setting this feature to false will throw a SAXNotSupportedException.
* <p>
* Provide a Locator using the DocumentHandler.setDocumentLocator
* callback (true), or explicitly do not provide one (false).
* <p>
* This method is the equivalent to the feature:
* <pre>
* http://xml.org/sax/features/use-locator
* </pre>
*
* @see #getUseLocator
* @see #setFeature
*/
/*
protected void setUseLocator(boolean use)
throws SAXNotRecognizedException, SAXNotSupportedException {
if (!use) {
throw new SAXNotSupportedException("http://xml.org/sax/features/use-locator");
}
}
*/
/**
* <b>Note: This feature is always true.</b>
* <p>
* Returns true if the locator is always set.
*
* @see #setUseLocator
*/
/*
protected boolean getUseLocator()
throws SAXNotRecognizedException, SAXNotSupportedException {
return true;
}
*/
// SAX2 core properties
/**
* Set the DTD declaration event handler.
* <p>
* This method is the equivalent to the property:
* <pre>
* http://xml.org/sax/properties/declaration-handler
* </pre>
*
* @param handler The new handler.
*
* @see #getDeclHandler
* @see #setProperty
*/
protected void setDeclHandler(DeclHandler handler)
throws SAXNotRecognizedException, SAXNotSupportedException {
if (fParseInProgress) {
throw new SAXNotSupportedException(
"PAR011 Feature: http://xml.org/sax/properties/declaration-handler"
+" is not supported during parse."
+"\nhttp://xml.org/sax/properties/declaration-handler");
}
fDeclHandler = handler;
}
/**
* Returns the DTD declaration event handler.
*
* @see #setDeclHandler
*/
protected DeclHandler getDeclHandler()
throws SAXNotRecognizedException, SAXNotSupportedException {
return fDeclHandler;
}
/**
* Set the lexical event handler.
* <p>
* This method is the equivalent to the property:
* <pre>
* http://xml.org/sax/properties/lexical-handler
* </pre>
*
* @param handler lexical event handler
*
* @see #getLexicalHandler
* @see #setProperty
*/
protected void setLexicalHandler(LexicalHandler handler)
throws SAXNotRecognizedException, SAXNotSupportedException {
if (fParseInProgress) {
throw new SAXNotSupportedException(
"PAR011 Feature: http://xml.org/sax/properties/lexical-handler"
+" is not supported during parse."
+"\nhttp://xml.org/sax/properties/lexical-handler");
}
fLexicalHandler = handler;
}
/**
* Returns the lexical handler.
*
* @see #setLexicalHandler
*/
protected LexicalHandler getLexicalHandler()
throws SAXNotRecognizedException, SAXNotSupportedException {
return fLexicalHandler;
}
//
// Parser methods
//
/** Sets the document handler. */
public void setDocumentHandler(DocumentHandler handler) {
fDocumentHandler = handler;
}
//
// Parser/XMLReader methods
//
/**
* Allow an application to register a DTD event handler.
*
* <p>If the application does not register a DTD handler, all DTD
* events reported by the SAX parser will be silently ignored.</p>
*
* <p>Applications may register a new or different handler in the
* middle of a parse, and the SAX parser must begin using the new
* handler immediately.</p>
*
* @param handler The DTD handler.
* @exception java.lang.NullPointerException If the handler
* argument is null.
* @see #getDTDHandler
*/
public void setDTDHandler(org.xml.sax.DTDHandler handler) {
fDTDHandler = handler;
}
/**
* Return the current DTD handler.
*
* @return The current DTD handler, or null if none
* has been registered.
* @see #setDTDHandler
*/
public org.xml.sax.DTDHandler getDTDHandler() {
return fDTDHandler;
}
/**
* Sets how the parser reports raw prefixed names,
* and whether xmlns attributes are reported.
* <p>
* This method is the equivalent to the feature:
* <pre>
* http://xml.org/sax/features/namespaces-prefixes
* <pre>
*
* @param process True to process namespaces; false to not process.
*
* @see #getNamespaces
* @see #setFeature
*/
protected void setNamespacePrefixes(boolean process)
throws SAXNotRecognizedException, SAXNotSupportedException {
if (fParseInProgress) {
throw new SAXNotSupportedException("PAR004 Cannot setFeature(http://xml.org/sax/features/namespace-prefixes): parse is in progress.\n"+
"http://xml.org/sax/features/namespace-prefixes");
}
fNamespacePrefixes = process;
}
/**
* Returns the http://xml.org/features/namespace-prefixes
* value.
*
* @see #setNamespacePrefixes
*/
protected boolean getNamespacePrefixes()
throws SAXNotRecognizedException, SAXNotSupportedException {
return fNamespacePrefixes;
}
//
// XMLReader methods
//
/**
* Set the state of any feature in a SAX2 parser. The parser
* might not recognize the feature, and if it does recognize
* it, it might not be able to fulfill the request.
*
* @param featureId The unique identifier (URI) of the feature.
* @param state The requested state of the feature (true or false).
*
* @exception SAXNotRecognizedException If the
* requested feature is not known.
* @exception SAXNotSupportedException If the
* requested feature is known, but the requested
* state is not supported.
*/
public void setFeature(String featureId, boolean state)
throws SAXNotRecognizedException, SAXNotSupportedException {
//
// SAX2 Features
//
if (featureId.startsWith(SAX2_FEATURES_PREFIX)) {
String feature = featureId.substring(SAX2_FEATURES_PREFIX.length());
/*
//
// http://xml.org/sax/features/normalize-text
// Ensure that all consecutive text is returned in a single callback to
// DocumentHandler.characters or DocumentHandler.ignorableWhitespace
// (true) or explicitly do not require it (false).
//
if (feature.equals("normalize-text")) {
setNormalizeText(state);
return;
}
*/
/*
//
// http://xml.org/sax/features/use-locator
// Provide a Locator using the DocumentHandler.setDocumentLocator
// callback (true), or explicitly do not provide one (false).
//
if (feature.equals("use-locator")) {
setUseLocator(state);
return;
}
*/
// http://xml.org/sax/features/namespace-prefixes
// controls the reporting of raw prefixed names and Namespace
// declarations (xmlns* attributes): when this feature is false
// (the default), raw prefixed names may optionally be reported,
// and xmlns* attributes must not be reported.
//
if (feature.equals("namespace-prefixes")) {
setNamespacePrefixes(state);
return;
}
// http://xml.org/sax/features/string-interning
// controls the use of java.lang.String#intern() for strings
// passed to SAX handlers.
//
if (feature.equals("string-interning")) {
if (state) {
throw new SAXNotSupportedException(
"PAR018 "+state+" state for feature \""+featureId+"\" is not supported.\n"+
state+'\t'+featureId
);
}
return;
}
//
// Drop through and perform default processing
//
}
//
// Xerces Features
//
/*
else if (featureId.startsWith(XERCES_FEATURES_PREFIX)) {
String feature = featureId.substring(XERCES_FEATURES_PREFIX.length());
//
// Drop through and perform default processing
//
}
*/
//
// Perform default processing
//
super.setFeature(featureId, state);
} // setFeature(String,boolean)
/**
* Query the state of a feature.
*
* Query the current state of any feature in a SAX2 parser. The
* parser might not recognize the feature.
*
* @param featureId The unique identifier (URI) of the feature
* being set.
* @return The current state of the feature.
* @exception org.xml.sax.SAXNotRecognizedException If the
* requested feature is not known.
* @exception SAXNotSupportedException If the
* requested feature is known but not supported.
*/
public boolean getFeature(String featureId)
throws SAXNotRecognizedException, SAXNotSupportedException {
//
// SAX2 Features
//
if (featureId.startsWith(SAX2_FEATURES_PREFIX)) {
String feature = featureId.substring(SAX2_FEATURES_PREFIX.length());
/*
//
// http://xml.org/sax/features/normalize-text
// Ensure that all consecutive text is returned in a single callback to
// DocumentHandler.characters or DocumentHandler.ignorableWhitespace
// (true) or explicitly do not require it (false).
//
if (feature.equals("normalize-text")) {
return getNormalizeText();
}
*/
/*
//
// http://xml.org/sax/features/use-locator
// Provide a Locator using the DocumentHandler.setDocumentLocator
// callback (true), or explicitly do not provide one (false).
//
if (feature.equals("use-locator")) {
return getUseLocator();
}
*/
// http://xml.org/sax/features/namespace-prefixes
// controls the reporting of raw prefixed names and Namespace
// declarations (xmlns* attributes): when this feature is false
// (the default), raw prefixed names may optionally be reported,
// and xmlns* attributes must not be reported.
//
if (feature.equals("namespace-prefixes")) {
return getNamespacePrefixes();
}
// http://xml.org/sax/features/string-interning
// controls the use of java.lang.String#intern() for strings
// passed to SAX handlers.
//
if (feature.equals("string-interning")) {
return false;
}
//
// Drop through and perform default processing
//
}
//
// Xerces Features
//
/*
else if (featureId.startsWith(XERCES_FEATURES_PREFIX)) {
//
// Drop through and perform default processing
//
}
*/
//
// Perform default processing
//
return super.getFeature(featureId);
} // getFeature(String):boolean
/**
* Set the value of any property in a SAX2 parser. The parser
* might not recognize the property, and if it does recognize
* it, it might not support the requested value.
*
* @param propertyId The unique identifier (URI) of the property
* being set.
* @param Object The value to which the property is being set.
*
* @exception SAXNotRecognizedException If the
* requested property is not known.
* @exception SAXNotSupportedException If the
* requested property is known, but the requested
* value is not supported.
*/
public void setProperty(String propertyId, Object value)
throws SAXNotRecognizedException, SAXNotSupportedException {
//
// SAX2 core properties
//
if (propertyId.startsWith(SAX2_PROPERTIES_PREFIX)) {
String property = propertyId.substring(SAX2_PROPERTIES_PREFIX.length());
//
// http://xml.org/sax/properties/lexical-handler
// Value type: org.xml.sax.ext.LexicalHandler
// Access: read/write, pre-parse only
// Set the lexical event handler.
//
if (property.equals("lexical-handler")) {
try {
setLexicalHandler((LexicalHandler)value);
}
catch (ClassCastException e) {
throw new SAXNotSupportedException(
"PAR012 For propertyID \""
+propertyId+"\", the value \""
+value+"\" cannot be cast to LexicalHandler."
+'\n'+propertyId+'\t'+value+"\tLexicalHandler");
}
return;
}
//
// http://xml.org/sax/properties/declaration-handler
// Value type: org.xml.sax.ext.DeclHandler
// Access: read/write, pre-parse only
// Set the DTD declaration event handler.
//
if (property.equals("declaration-handler")) {
try {
setDeclHandler((DeclHandler)value);
}
catch (ClassCastException e) {
throw new SAXNotSupportedException(
"PAR012 For propertyID \""
+propertyId+"\", the value \""
+value+"\" cannot be cast to DeclHandler."
+'\n'+propertyId+'\t'+value+"\tDeclHandler"
);
}
return;
}
//
// http://xml.org/sax/properties/dom-node
// Value type: DOM Node
// Access: read-only
// Get the DOM node currently being visited, if the SAX parser is
// iterating over a DOM tree. If the parser recognises and supports
// this property but is not currently visiting a DOM node, it should
// return null (this is a good way to check for availability before the
// parse begins).
//
if (property.equals("dom-node")) {
throw new SAXNotSupportedException(
"PAR013 Property \""+propertyId+"\" is read only."
+'\n'+propertyId
); // read-only property
}
//
// Drop through and perform default processing
//
}
//
// Xerces Properties
//
/*
else if (propertyId.startsWith(XERCES_PROPERTIES_PREFIX)) {
//
// Drop through and perform default processing
//
}
*/
//
// Perform default processing
//
super.setProperty(propertyId, value);
} // setProperty(String,Object)
/**
* Query the value of a property.
*
* Return the current value of a property in a SAX2 parser.
* The parser might not recognize the property.
*
* @param propertyId The unique identifier (URI) of the property
* being set.
* @return The current value of the property.
* @exception org.xml.sax.SAXNotRecognizedException If the
* requested property is not known.
* @exception SAXNotSupportedException If the
* requested property is known but not supported.
*/
public Object getProperty(String propertyId)
throws SAXNotRecognizedException, SAXNotSupportedException {
//
// SAX2 core properties
//
if (propertyId.startsWith(SAX2_PROPERTIES_PREFIX)) {
String property = propertyId.substring(SAX2_PROPERTIES_PREFIX.length());
//
// http://xml.org/sax/properties/lexical-handler
// Value type: org.xml.sax.ext.LexicalHandler
// Access: read/write, pre-parse only
// Set the lexical event handler.
//
if (property.equals("lexical-handler")) {
return getLexicalHandler();
}
//
// http://xml.org/sax/properties/declaration-handler
// Value type: org.xml.sax.ext.DeclHandler
// Access: read/write, pre-parse only
// Set the DTD declaration event handler.
//
if (property.equals("declaration-handler")) {
return getDeclHandler();
}
//
// http://xml.org/sax/properties/dom-node
// Value type: DOM Node
// Access: read-only
// Get the DOM node currently being visited, if the SAX parser is
// iterating over a DOM tree. If the parser recognises and supports
// this property but is not currently visiting a DOM node, it should
// return null (this is a good way to check for availability before the
// parse begins).
//
if (property.equals("dom-node")) {
throw new SAXNotSupportedException(
"PAR014 Cannot getProperty(\""+propertyId
+"\". No DOM Tree exists.\n"+propertyId
); // we are not iterating a DOM tree
}
//
// Drop through and perform default processing
//
}
//
// Xerces properties
//
/*
else if (propertyId.startsWith(XERCES_PROPERTIES_PREFIX)) {
//
// Drop through and perform default processing
//
}
*/
//
// Perform default processing
//
return super.getProperty(propertyId);
} // getProperty(String):Object
/**
* Allow an application to register a content event handler.
*
* <p>If the application does not register a content handler, all
* content events reported by the SAX parser will be silently
* ignored.</p>
*
* <p>Applications may register a new or different handler in the
* middle of a parse, and the SAX parser must begin using the new
* handler immediately.</p>
*
* @param handler The content handler.
* @exception java.lang.NullPointerException If the handler
* argument is null.
* @see #getContentHandler
*/
public void setContentHandler(ContentHandler handler) {
if (handler == null) {
throw new NullPointerException();
}
fContentHandler = handler;
}
/**
* Return the current content handler.
*
* @return The current content handler, or null if none
* has been registered.
* @see #setContentHandler
*/
public ContentHandler getContentHandler() {
return fContentHandler;
}
//
// XMLParser methods
//
/**
* This function will be called when a &lt;!DOCTYPE...&gt; declaration is
* encountered.
*/
public void startDTD(QName rootElement, int publicId, int systemId) throws Exception {
if (fLexicalHandler != null || DEBUG_CALLBACKS) {
// strings
String name = fStringPool.toString(rootElement.rawname);
String pubid = fStringPool.toString(publicId);
String sysid = fStringPool.toString(systemId);
// perform callback
if (DEBUG_CALLBACKS) {
System.err.println("startDTD(" + name + ", " + pubid + ", " + sysid + ")");
}
if (fLexicalHandler != null) {
fLexicalHandler.startDTD(name, pubid, sysid);
}
}
}
/**
* This function will be called at the end of the DTD.
*/
public void endDTD() throws Exception {
if (DEBUG_CALLBACKS) {
System.err.println("endDTD()");
}
if (fLexicalHandler != null) {
fLexicalHandler.endDTD();
}
}
/**
* Report an element type declaration.
*
* The content model will consist of the string "EMPTY", the
* string "ANY", or a parenthesised group, optionally followed
* by an occurrence indicator. The model will be normalized so
* that all whitespace is removed.
*
* @param name The element type name.
* @param model The content model as a normalized string.
* @exception SAXException The application may raise an exception.
*/
public void elementDecl(QName elementDecl,
int contentSpecType,
int contentSpecIndex,
XMLContentSpec.Provider contentSpecProvider) throws Exception {
if (fDeclHandler != null || DEBUG_CALLBACKS) {
// strings
String name = fStringPool.toString(elementDecl.rawname);
String contentModel;
if (contentSpecType == XMLElementDecl.TYPE_ANY) {
contentModel = "ANY";
}
else if (contentSpecType == XMLElementDecl.TYPE_EMPTY) {
contentModel = "EMPTY";
}
else {
contentModel = XMLContentSpec.toString(contentSpecProvider,
fStringPool,
contentSpecIndex);
}
// perform callback
if (DEBUG_CALLBACKS) {
System.err.println("elementDecl(" + name + ", " + contentModel + ")");
}
if (fDeclHandler != null) {
fDeclHandler.elementDecl(name, contentModel);
}
}
}
/**
* Report an attribute type declaration.
*
* Only the effective (first) declaration for an attribute will
* be reported. The type will be one of the strings "CDATA",
* "ID", "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY",
* "ENTITIES", or "NOTATION", or a parenthesized token group with
* the separator "|" and all whitespace removed.
*
* @param eName The name of the associated element.
* @param aName The name of the attribute.
* @param type A string representing the attribute type.
* @param valueDefault A string representing the attribute default
* ("#IMPLIED", "#REQUIRED", or "#FIXED") or null if
* none of these applies.
* @param value A string representing the attribute's default value,
* or null if there is none.
* @exception SAXException The application may raise an exception.
*/
public void attlistDecl(QName elementDecl, QName attributeDecl,
int attType, boolean attList, String enumString,
int attDefaultType,
int attDefaultValue) throws Exception
{
if (fDeclHandler != null || DEBUG_CALLBACKS) {
// strings
String eName = fStringPool.toString(elementDecl.rawname);
String aName = fStringPool.toString(attributeDecl.rawname);
String aType = enumString;
if (attType != XMLAttributeDecl.TYPE_ENUMERATION) {
switch (attType) {
case XMLAttributeDecl.TYPE_CDATA: {
aType = "CDATA";
break;
}
case XMLAttributeDecl.TYPE_ENTITY: {
aType = attList ? "ENTITIES" : "ENTITY";
break;
}
case XMLAttributeDecl.TYPE_ID: {
aType = "ID";
break;
}
case XMLAttributeDecl.TYPE_IDREF: {
aType = attList ? "IDREFS" : "IDREF";
break;
}
case XMLAttributeDecl.TYPE_NMTOKEN: {
aType = attList ? "NMTOKENS" : "NMTOKEN";
break;
}
case XMLAttributeDecl.TYPE_NOTATION: {
aType = "NOTATION";
break;
}
}
}
String aDefaultType = "";
switch (attDefaultType) {
case XMLAttributeDecl.DEFAULT_TYPE_FIXED: {
aDefaultType = "#FIXED";
break;
}
case XMLAttributeDecl.DEFAULT_TYPE_IMPLIED: {
aDefaultType = "#IMPLIED";
break;
}
case XMLAttributeDecl.DEFAULT_TYPE_REQUIRED: {
aDefaultType = "#REQUIRED";
break;
}
}
String aDefaultValue = fStringPool.toString(attDefaultValue);
// perform callback
if (DEBUG_CALLBACKS) {
System.err.println("attributeDecl(" +
eName + ", " +
aName + ", " +
aType + ", " +
aDefaultType + ", " +
aDefaultValue + ")");
}
if (fDeclHandler != null) {
fDeclHandler.attributeDecl(eName, aName, aType, aDefaultType, aDefaultValue);
}
}
}
/**
* Report an internal parameter entity declaration.
*/
public void internalPEDecl(int entityName, int entityValue) throws Exception {
if (fDeclHandler != null || DEBUG_CALLBACKS) {
// strings
String name = "%" + fStringPool.toString(entityName);
String value = fStringPool.toString(entityValue);
// perform callback
if (DEBUG_CALLBACKS) {
System.err.println("internalEntityDecl(" + name + ", " + value + ")");
}
if (fDeclHandler != null) {
fDeclHandler.internalEntityDecl(name, value);
}
}
}
/**
* Report a parsed external parameter entity declaration.
*/
public void externalPEDecl(int entityName, int publicId, int systemId) throws Exception {
if (fDeclHandler != null || DEBUG_CALLBACKS) {
// strings
String name = "%" + fStringPool.toString(entityName);
String pubid = fStringPool.toString(publicId);
String sysid = fStringPool.toString(systemId);
// perform callback
if (DEBUG_CALLBACKS) {
System.err.println("externalEntityDecl(" + name + ", " + pubid + ", " + sysid + ")");
}
if (fDeclHandler != null) {
fDeclHandler.externalEntityDecl(name, pubid, sysid);
}
}
}
/**
* Report an internal general entity declaration.
*/
public void internalEntityDecl(int entityName, int entityValue) throws Exception {
if (fDeclHandler != null || DEBUG_CALLBACKS) {
// strings
String name = fStringPool.toString(entityName);
String value = fStringPool.toString(entityValue);
// perform callback
if (DEBUG_CALLBACKS) {
System.err.println("internalEntityDecl(" + name + ", " + value + ")");
}
if (fDeclHandler != null) {
fDeclHandler.internalEntityDecl(name, value);
}
}
}
/**
* Report a parsed external general entity declaration.
*/
public void externalEntityDecl(int entityName, int publicId, int systemId) throws Exception {
if (fDeclHandler != null || DEBUG_CALLBACKS) {
// strings
String name = fStringPool.toString(entityName);
String pubid = fStringPool.toString(publicId);
String sysid = fStringPool.toString(systemId);
// perform callback
if (DEBUG_CALLBACKS) {
System.err.println("externalEntityDecl(" + name + ", " + pubid + ", " + sysid + ")");
}
if (fDeclHandler != null) {
fDeclHandler.externalEntityDecl(name, pubid, sysid);
}
}
}
/**
* Receive notification of an unparsed entity declaration event.
*/
public void unparsedEntityDecl(int entityName, int publicId, int systemId, int notationName) throws Exception {
if (fDTDHandler != null || DEBUG_CALLBACKS) {
// strings
String name = fStringPool.toString(entityName);
String pubid = fStringPool.toString(publicId);
String sysid = fStringPool.toString(systemId);
String notation = fStringPool.toString(notationName);
// perform callback
if (DEBUG_CALLBACKS) {
System.err.println("unparsedEntityDecl(" + name + ", " + pubid + ", " + sysid + ", " + notation + ")");
}
if (fDTDHandler != null) {
fDTDHandler.unparsedEntityDecl(name, pubid, sysid, notation);
}
}
}
/**
* Receive notification of a notation declaration event.
*/
public void notationDecl(int notationName, int publicId, int systemId) throws Exception {
if (fDTDHandler != null || DEBUG_CALLBACKS) {
// strings
String name = fStringPool.toString(notationName);
String pubid = fStringPool.toString(publicId);
String sysid = fStringPool.toString(systemId);
// perform callback
if (DEBUG_CALLBACKS) {
System.err.println("notationDecl(" + name + ", " + pubid + ", " + sysid + ")");
}
if (fDTDHandler != null) {
fDTDHandler.notationDecl(name, pubid, sysid);
}
}
}
/** Start document. */
public void startDocument() throws Exception {
// perform callbacks
if (DEBUG_CALLBACKS) {
System.err.println("setDocumentLocator(<locator>)");
System.err.println("startDocument()");
}
if (fDocumentHandler != null) {
fDocumentHandler.setDocumentLocator(getLocator());
fDocumentHandler.startDocument();
}
if (fContentHandler != null) {
fContentHandler.setDocumentLocator(getLocator());
fContentHandler.startDocument();
}
} // startDocument()
/** End document. */
public void endDocument() throws Exception {
// perform callback
if (DEBUG_CALLBACKS) {
System.err.println("endDocument()");
}
if (fDocumentHandler != null) {
fDocumentHandler.endDocument();
}
if (fContentHandler != null) {
fContentHandler.endDocument();
}
} // endDocument()
/** XML declaration. */
public void xmlDecl(int versionIndex, int encodingIndex, int standaloneIndex) throws Exception {
// perform callbacks
if (DEBUG_CALLBACKS) {
String notes = "";
if (versionIndex != -1)
notes += " version='" + fStringPool.toString(versionIndex) + "'";
if (encodingIndex != -1)
notes += " encoding='" + fStringPool.toString(encodingIndex) + "'";
if (standaloneIndex != -1)
notes += " standalone='" + fStringPool.toString(standaloneIndex) + "'";
System.err.println("xmlDecl(<?xml" + notes + "?>)");
}
// release strings
fStringPool.releaseString(versionIndex);
fStringPool.releaseString(encodingIndex);
fStringPool.releaseString(standaloneIndex);
}
/** Text declaration. */
public void textDecl(int versionIndex, int encodingIndex) throws Exception {
// perform callbacks
if (DEBUG_CALLBACKS) {
String notes = "";
if (versionIndex != -1)
notes += " version='" + fStringPool.toString(versionIndex) + "'";
if (encodingIndex != -1)
notes += " encoding='" + fStringPool.toString(encodingIndex) + "'";
System.err.println("textDecl(<?xml" + notes + "?>)");
}
// release strings
fStringPool.releaseString(versionIndex);
fStringPool.releaseString(encodingIndex);
}
/**
* Report the start of the scope of a namespace declaration.
*/
public void startNamespaceDeclScope(int prefix, int uri) throws Exception {
if (fContentHandler != null || DEBUG_CALLBACKS) {
// strings
String p = fStringPool.toString(prefix);
String ns = fStringPool.toString(uri);
// perform callback
if (DEBUG_CALLBACKS) {
System.err.println("startNamespaceDeclScope(" + p + ", " + ns + ")");
}
if (fContentHandler != null) {
fContentHandler.startPrefixMapping(p, ns);
}
}
}
/**
* Report the end of the scope of a namespace declaration.
*/
public void endNamespaceDeclScope(int prefix) throws Exception {
if (fContentHandler != null || DEBUG_CALLBACKS) {
// strings
String p = fStringPool.toString(prefix);
// perform callback
if (DEBUG_CALLBACKS) {
System.err.println("endNamespaceDeclScope(" + p + ")");
}
if (fContentHandler != null) {
fContentHandler.endPrefixMapping(p);
}
}
}
/** New callback from DOM Level 2. There is no corresponding SAX callout for this yet. */
public void internalSubset(int internalSubset) {
}
/** Start element */
public void startElement(QName element,
XMLAttrList attrList, int attrListIndex)
throws Exception {
// parameters
String name = fStringPool.toString(element.rawname);
AttributeList attrs = attrList.getAttributeList(attrListIndex);
// perform callback
if (DEBUG_CALLBACKS) {
String atts = attrs.getLength() > 0 ? "" : " ";
for (int i = 0; i < attrs.getLength(); i++) {
atts += " " + attrs.getName(i) + "='" + attrs.getValue(i) + "'";
}
System.err.println("startElement(" + name + "," + atts + ")");
}
if (fDocumentHandler != null) {
fDocumentHandler.startElement(name, attrs);
}
if (fContentHandler != null) {
boolean namespaces = getNamespaces();
int uriIndex = element.uri;
String uri = uriIndex != -1 && namespaces
? fStringPool.toString(uriIndex) : "";
int localIndex = element.localpart;
String local = localIndex != -1 && namespaces
? fStringPool.toString(localIndex) : "";
String raw = name;
fAttributes.clear();
for (int attrIndex = attrList.getFirstAttr(attrListIndex);
attrIndex != -1;
attrIndex = attrList.getNextAttr(attrIndex)) {
int attrNameIndex = attrList.getAttrName(attrIndex);
int attrUriIndex = attrList.getAttrURI(attrIndex);
String attrUri = attrUriIndex != -1 && namespaces
? fStringPool.toString(attrUriIndex) : "";
int attrLocalIndex = attrList.getAttrLocalpart(attrIndex);
String attrLocal = attrLocalIndex != -1 && namespaces
? fStringPool.toString(attrLocalIndex) : "";
String attrRaw = fStringPool.toString(attrNameIndex);
String attrType = fStringPool.toString(attrList.getAttType(attrIndex));
String attrValue = fStringPool.toString(attrList.getAttValue(attrIndex));
//int attrPrefix = fStringPool.getPrefixForQName(attrNameIndex);
int attrPrefix = attrList.getAttrPrefix(attrIndex);
boolean namespacePrefixes = getNamespacePrefixes();
if (!namespaces || namespacePrefixes ||
(attrPrefix != fStringPool.addSymbol("xmlns")
&& attrLocalIndex != fStringPool.addSymbol("xmlns")
))
fAttributes.addAttribute(attrUri, attrLocal, attrRaw,
attrType, attrValue);
}
fContentHandler.startElement(uri, local, raw, fAttributes);
}
// free attribute list
attrList.releaseAttrList(attrListIndex);
} // startElement(QName,XMLAttrList,int)
/** End element. */
public void endElement(QName element) throws Exception {
// perform callback
if (DEBUG_CALLBACKS) {
System.err.println("endElement(" + fStringPool.toString(element.rawname) + ")");
}
if (fDocumentHandler != null) {
fDocumentHandler.endElement(fStringPool.toString(element.rawname));
}
if (fContentHandler != null) {
boolean namespaces = getNamespaces();
int uriIndex = element.uri;
String uri = uriIndex != -1 && namespaces
? fStringPool.toString(uriIndex) : "";
int localIndex = element.localpart;
String local = localIndex != -1 && namespaces
? fStringPool.toString(localIndex) : "";
String raw = fStringPool.toString(element.rawname);
fContentHandler.endElement(uri, local, raw);
}
} // endElement(QName)
/** Start entity reference. */
public void startEntityReference(int entityName, int entityType, int entityContext) throws Exception {
if (fLexicalHandler != null || DEBUG_CALLBACKS) {
switch (entityType) {
case XMLEntityHandler.ENTITYTYPE_INTERNAL_PE:
case XMLEntityHandler.ENTITYTYPE_EXTERNAL_PE:
if (DEBUG_CALLBACKS) {
System.err.println("startEntity(%" + fStringPool.toString(entityName) + ")");
}
if (fLexicalHandler != null) {
fLexicalHandler.startEntity("%" + fStringPool.toString(entityName));
}
break;
case XMLEntityHandler.ENTITYTYPE_INTERNAL:
case XMLEntityHandler.ENTITYTYPE_EXTERNAL:
if (DEBUG_CALLBACKS) {
System.err.println("startEntity(" + fStringPool.toString(entityName) + ")");
}
if (fLexicalHandler != null) {
fLexicalHandler.startEntity(fStringPool.toString(entityName));
}
break;
case XMLEntityHandler.ENTITYTYPE_UNPARSED: // these are mentioned by name, not referenced
throw new RuntimeException(
"PAR015 startEntityReference(): ENTITYTYPE_UNPARSED");
case XMLEntityHandler.ENTITYTYPE_DOCUMENT:
break; // not reported
case XMLEntityHandler.ENTITYTYPE_EXTERNAL_SUBSET:
if (DEBUG_CALLBACKS) {
System.err.println("startEntity(\"[dtd]\")");
}
if (fLexicalHandler != null) {
fLexicalHandler.startEntity("[dtd]");
}
break;
}
}
}
/** End entity reference. */
public void endEntityReference(int entityName, int entityType, int entityContext) throws Exception {
if (fLexicalHandler != null || DEBUG_CALLBACKS) {
switch (entityType) {
case XMLEntityHandler.ENTITYTYPE_INTERNAL_PE:
case XMLEntityHandler.ENTITYTYPE_EXTERNAL_PE:
if (DEBUG_CALLBACKS) {
System.err.println("endEntity(%" + fStringPool.toString(entityName) + ")");
}
if (fLexicalHandler != null) {
fLexicalHandler.endEntity("%" + fStringPool.toString(entityName));
}
break;
case XMLEntityHandler.ENTITYTYPE_INTERNAL:
case XMLEntityHandler.ENTITYTYPE_EXTERNAL:
if (DEBUG_CALLBACKS) {
System.err.println("endEntity(" + fStringPool.toString(entityName) + ")");
}
if (fLexicalHandler != null) {
fLexicalHandler.endEntity(fStringPool.toString(entityName));
}
break;
case XMLEntityHandler.ENTITYTYPE_UNPARSED: // these are mentioned by name, not referenced
throw new RuntimeException("PAR016 endEntityReference(): ENTITYTYPE_UNPARSED");
case XMLEntityHandler.ENTITYTYPE_DOCUMENT:
break; // not reported
case XMLEntityHandler.ENTITYTYPE_EXTERNAL_SUBSET:
if (DEBUG_CALLBACKS) {
System.err.println("endEntity(\"[dtd]\")");
}
if (fLexicalHandler != null) {
fLexicalHandler.endEntity("[dtd]");
}
break;
}
}
}
/** Start CDATA section. */
public void startCDATA() throws Exception {
if (DEBUG_CALLBACKS) {
System.err.println("startCDATA()");
}
if (fLexicalHandler != null) {
fLexicalHandler.startCDATA();
}
}
/** End CDATA section. */
public void endCDATA() throws Exception {
if (DEBUG_CALLBACKS) {
System.err.println("endCDATA()");
}
if (fLexicalHandler != null) {
fLexicalHandler.endCDATA();
}
}
/** Not called. */
public void characters(int dataIndex) throws Exception {
throw new RuntimeException("PAR017 cannot happen 5\n5");
}
/** Not called. */
public void ignorableWhitespace(int dataIndex) throws Exception {
throw new RuntimeException("PAR017 cannot happen 6\n6");
}
/** Processing instruction. */
public void processingInstruction(int piTarget, int piData) throws Exception {
if (fDocumentHandler != null || fContentHandler != null || DEBUG_CALLBACKS) {
//
// REVISIT - I keep running into SAX apps that expect
// null data to be an empty string, which is contrary
// to the comment for this method in the SAX API.
//
// strings
String target = fStringPool.orphanString(piTarget);
String data = piData == -1 ? "" : fStringPool.orphanString(piData);
// perform callback
if (DEBUG_CALLBACKS) {
System.err.println("processingInstruction(" + target + ", " + data + ")");
}
if (fDocumentHandler != null) {
fDocumentHandler.processingInstruction(target, data);
}
if (fContentHandler != null) {
fContentHandler.processingInstruction(target, data);
}
}
else {
fStringPool.releaseString(piTarget);
fStringPool.releaseString(piData);
}
}
/** Comment. */
public void comment(int dataIndex) throws Exception {
if (fLexicalHandler != null || DEBUG_CALLBACKS) {
// strings
String data = fStringPool.orphanString(dataIndex);
// perform callback
if (DEBUG_CALLBACKS) {
System.err.println("comment(" + data + ")");
}
if (fLexicalHandler != null) {
fLexicalHandler.comment(data.toCharArray(), 0, data.length());
}
} else {
fStringPool.releaseString(dataIndex);
}
}
/** Characters. */
public void characters(char ch[], int start, int length) throws Exception {
// perform callback
if (DEBUG_CALLBACKS) {
System.err.println("characters(<char-data>) length " + length);
}
if (fDocumentHandler != null) {
fDocumentHandler.characters(ch, start, length);
}
if (fContentHandler != null) {
fContentHandler.characters(ch, start, length);
}
}
/** Ignorable whitespace. */
public void ignorableWhitespace(char ch[], int start, int length) throws Exception {
// perform callback
if (DEBUG_CALLBACKS) {
System.err.println("ignorableWhitespace(<white-space>)");
}
if (fDocumentHandler != null) {
fDocumentHandler.ignorableWhitespace(ch, start, length);
}
if (fContentHandler != null) {
fContentHandler.ignorableWhitespace(ch, start, length);
}
}
} // class SAXParser