mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			1610 lines
		
	
	
		
			41 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			1610 lines
		
	
	
		
			41 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* SAXDriver.java --
 | |
|    Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc.
 | |
| 
 | |
| This file is part of GNU Classpath.
 | |
| 
 | |
| GNU Classpath is free software; you can redistribute it and/or modify
 | |
| it under the terms of the GNU General Public License as published by
 | |
| the Free Software Foundation; either version 2, or (at your option)
 | |
| any later version.
 | |
| 
 | |
| GNU Classpath is distributed in the hope that it will be useful, but
 | |
| WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
| General Public License for more details.
 | |
| 
 | |
| You should have received a copy of the GNU General Public License
 | |
| along with GNU Classpath; see the file COPYING.  If not, write to the
 | |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | |
| 02110-1301 USA.
 | |
| 
 | |
| Linking this library statically or dynamically with other modules is
 | |
| making a combined work based on this library.  Thus, the terms and
 | |
| conditions of the GNU General Public License cover the whole
 | |
| combination.
 | |
| 
 | |
| As a special exception, the copyright holders of this library give you
 | |
| permission to link this library with independent modules to produce an
 | |
| executable, regardless of the license terms of these independent
 | |
| modules, and to copy and distribute the resulting executable under
 | |
| terms of your choice, provided that you also meet, for each linked
 | |
| independent module, the terms and conditions of the license of that
 | |
| module.  An independent module is a module which is not derived from
 | |
| or based on this library.  If you modify this library, you may extend
 | |
| this exception to your version of the library, but you are not
 | |
| obligated to do so.  If you do not wish to do so, delete this
 | |
| exception statement from your version.
 | |
| 
 | |
| Portions derived from code which carried the following notice:
 | |
| 
 | |
|   Copyright (c) 1997, 1998 by Microstar Software Ltd.
 | |
| 
 | |
|   AElfred is free for both commercial and non-commercial use and
 | |
|   redistribution, provided that Microstar's copyright and disclaimer are
 | |
|   retained intact.  You are free to modify AElfred for your own use and
 | |
|   to redistribute AElfred with your modifications, provided that the
 | |
|   modifications are clearly documented.
 | |
| 
 | |
|   This program is distributed in the hope that it will be useful, but
 | |
|   WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|   merchantability or fitness for a particular purpose.  Please use it AT
 | |
|   YOUR OWN RISK.
 | |
| */
 | |
| 
 | |
| package gnu.xml.aelfred2;
 | |
| 
 | |
| import java.io.*;
 | |
| 
 | |
| import java.net.MalformedURLException;
 | |
| import java.net.URL;
 | |
| import java.util.Locale;
 | |
| import java.util.Stack;
 | |
| 
 | |
| import java.util.ArrayList;
 | |
| import java.util.Collections;
 | |
| import java.util.Enumeration;
 | |
| import java.util.Iterator;
 | |
| import java.util.List;
 | |
| 
 | |
| import org.xml.sax.*;
 | |
| import org.xml.sax.ext.*;
 | |
| import org.xml.sax.helpers.NamespaceSupport;
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * An enhanced SAX2 version of Microstar's Ælfred XML parser.
 | |
|  * The enhancements primarily relate to significant improvements in
 | |
|  * conformance to the XML specification, and SAX2 support.  Performance
 | |
|  * has been improved.  See the package level documentation for more
 | |
|  * information.
 | |
|  *
 | |
|  * <table border="1" width='100%' cellpadding='3' cellspacing='0'>
 | |
|  * <tr bgcolor='#ccccff'>
 | |
|  *      <th><font size='+1'>Name</font></th>
 | |
|  *      <th><font size='+1'>Notes</font></th></tr>
 | |
|  *
 | |
|  * <tr><td colspan=2><center><em>Features ... URL prefix is
 | |
|  * <b>http://xml.org/sax/features/</b></em></center></td></tr>
 | |
|  *
 | |
|  * <tr><td>(URL)/external-general-entities</td>
 | |
|  *      <td>Value defaults to <em>true</em></td></tr>
 | |
|  * <tr><td>(URL)/external-parameter-entities</td>
 | |
|  *      <td>Value defaults to <em>true</em></td></tr>
 | |
|  * <tr><td>(URL)/is-standalone</td>
 | |
|  *      <td>(PRELIMINARY) Returns true iff the document's parsing
 | |
|  *      has started (some non-error event after <em>startDocument()</em>
 | |
|  *      was reported) and the document's standalone flag is set.</td></tr>
 | |
|  * <tr><td>(URL)/namespace-prefixes</td>
 | |
|  *      <td>Value defaults to <em>false</em> (but XML 1.0 names are
 | |
|  *              always reported)</td></tr>
 | |
|  * <tr><td>(URL)/lexical-handler/parameter-entities</td>
 | |
|  *      <td>Value is fixed at <em>true</em></td></tr>
 | |
|  * <tr><td>(URL)/namespaces</td>
 | |
|  *      <td>Value defaults to <em>true</em></td></tr>
 | |
|  * <tr><td>(URL)/resolve-dtd-uris</td>
 | |
|  *      <td>(PRELIMINARY) Value defaults to <em>true</em></td></tr>
 | |
|  * <tr><td>(URL)/string-interning</td>
 | |
|  *      <td>Value is fixed at <em>true</em></td></tr>
 | |
|  * <tr><td>(URL)/use-attributes2</td>
 | |
|  *      <td>(PRELIMINARY) Value is fixed at <em>true</em></td></tr>
 | |
|  * <tr><td>(URL)/use-entity-resolver2</td>
 | |
|  *      <td>(PRELIMINARY) Value defaults to <em>true</em></td></tr>
 | |
|  * <tr><td>(URL)/validation</td>
 | |
|  *      <td>Value is fixed at <em>false</em></td></tr>
 | |
|  *
 | |
|  * <tr><td colspan=2><center><em>Handler Properties ... URL prefix is
 | |
|  * <b>http://xml.org/sax/properties/</b></em></center></td></tr>
 | |
|  *
 | |
|  * <tr><td>(URL)/declaration-handler</td>
 | |
|  *      <td>A declaration handler may be provided.  </td></tr>
 | |
|  * <tr><td>(URL)/lexical-handler</td>
 | |
|  *      <td>A lexical handler may be provided.  </td></tr>
 | |
|  * </table>
 | |
|  *
 | |
|  * <p>This parser currently implements the SAX1 Parser API, but
 | |
|  * it may not continue to do so in the future.
 | |
|  *
 | |
|  * @author Written by David Megginson (version 1.2a from Microstar)
 | |
|  * @author Updated by David Brownell <dbrownell@users.sourceforge.net>
 | |
|  * @see org.xml.sax.Parser
 | |
|  */
 | |
| final public class SAXDriver
 | |
|   implements Locator, Attributes2, XMLReader, Parser, AttributeList
 | |
| {
 | |
| 
 | |
|   private final DefaultHandler2 base = new DefaultHandler2();
 | |
|   private XmlParser parser;
 | |
| 
 | |
|   private EntityResolver entityResolver = base;
 | |
|   private EntityResolver2 resolver2 = null;
 | |
|   private ContentHandler contentHandler = base;
 | |
|   private DTDHandler dtdHandler = base;
 | |
|   private ErrorHandler errorHandler = base;
 | |
|   private DeclHandler declHandler = base;
 | |
|   private LexicalHandler lexicalHandler = base;
 | |
| 
 | |
|   private String elementName;
 | |
|   private Stack entityStack;
 | |
| 
 | |
|   // one vector (of object/struct): faster, smaller
 | |
|   private List attributesList;
 | |
| 
 | |
|   private boolean namespaces = true;
 | |
|   private boolean xmlNames = false;
 | |
|   private boolean extGE = true;
 | |
|   private boolean extPE = true;
 | |
|   private boolean resolveAll = true;
 | |
|   private boolean useResolver2 = true;
 | |
| 
 | |
|   // package private to allow (read-only) access in XmlParser
 | |
|   boolean stringInterning = true;
 | |
| 
 | |
|   private int attributeCount;
 | |
|   private boolean attributes;
 | |
|   private String[] nsTemp;
 | |
|   private NamespaceSupport prefixStack;
 | |
| 
 | |
|   //
 | |
|   // Constructor.
 | |
|   //
 | |
| 
 | |
|   /**
 | |
|    * Constructs a SAX Parser.
 | |
|    */
 | |
|   public SAXDriver()
 | |
|   {
 | |
|     reset();
 | |
|   }
 | |
| 
 | |
|   private void reset()
 | |
|   {
 | |
|     elementName = null;
 | |
|     entityStack = new Stack();
 | |
|     attributesList = Collections.synchronizedList(new ArrayList());
 | |
|     attributeCount = 0;
 | |
|     attributes = false;
 | |
|     nsTemp = new String[3];
 | |
|     prefixStack = null;
 | |
|   }
 | |
| 
 | |
| 
 | |
|   //
 | |
|   // Implementation of org.xml.sax.Parser.
 | |
|   //
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX1</b>: Sets the locale used for diagnostics; currently,
 | |
|    * only locales using the English language are supported.
 | |
|    * @param locale The locale for which diagnostics will be generated
 | |
|    */
 | |
|   public void setLocale(Locale locale)
 | |
|     throws SAXException
 | |
|   {
 | |
|     if ("en".equals(locale.getLanguage()))
 | |
|       {
 | |
|         return;
 | |
|       }
 | |
|     throw new SAXException ("AElfred2 only supports English locales.");
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX2</b>: Returns the object used when resolving external
 | |
|    * entities during parsing (both general and parameter entities).
 | |
|    */
 | |
|   public EntityResolver getEntityResolver()
 | |
|   {
 | |
|     return (entityResolver == base) ? null : entityResolver;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX1, SAX2</b>: Set the entity resolver for this parser.
 | |
|    * @param handler The object to receive entity events.
 | |
|    */
 | |
|   public void setEntityResolver(EntityResolver resolver)
 | |
|   {
 | |
|     if (resolver instanceof EntityResolver2)
 | |
|       {
 | |
|         resolver2 = (EntityResolver2) resolver;
 | |
|       }
 | |
|     else
 | |
|       {
 | |
|         resolver2 = null;
 | |
|       }
 | |
|     if (resolver == null)
 | |
|       {
 | |
|         resolver = base;
 | |
|       }
 | |
|     entityResolver = resolver;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX2</b>: Returns the object used to process declarations related
 | |
|    * to notations and unparsed entities.
 | |
|    */
 | |
|   public DTDHandler getDTDHandler()
 | |
|   {
 | |
|     return (dtdHandler == base) ? null : dtdHandler;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX1, SAX2</b>: Set the DTD handler for this parser.
 | |
|    * @param handler The object to receive DTD events.
 | |
|    */
 | |
|   public void setDTDHandler(DTDHandler handler)
 | |
|   {
 | |
|     if (handler == null)
 | |
|       {
 | |
|         handler = base;
 | |
|       }
 | |
|     this.dtdHandler = handler;
 | |
|   }
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX1</b>: Set the document handler for this parser.  If a
 | |
|    * content handler was set, this document handler will supplant it.
 | |
|    * The parser is set to report all XML 1.0 names rather than to
 | |
|    * filter out "xmlns" attributes (the "namespace-prefixes" feature
 | |
|    * is set to true).
 | |
|    *
 | |
|    * @deprecated SAX2 programs should use the XMLReader interface
 | |
|    *  and a ContentHandler.
 | |
|    *
 | |
|    * @param handler The object to receive document events.
 | |
|    */
 | |
|   public void setDocumentHandler(DocumentHandler handler)
 | |
|   {
 | |
|     contentHandler = new Adapter(handler);
 | |
|     xmlNames = true;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX2</b>: Returns the object used to report the logical
 | |
|    * content of an XML document.
 | |
|    */
 | |
|   public ContentHandler getContentHandler()
 | |
|   {
 | |
|     return (contentHandler == base) ? null : contentHandler;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX2</b>: Assigns the object used to report the logical
 | |
|    * content of an XML document.  If a document handler was set,
 | |
|    * this content handler will supplant it (but XML 1.0 style name
 | |
|    * reporting may remain enabled).
 | |
|    */
 | |
|   public void setContentHandler(ContentHandler handler)
 | |
|   {
 | |
|     if (handler == null)
 | |
|       {
 | |
|         handler = base;
 | |
|       }
 | |
|     contentHandler = handler;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX1, SAX2</b>: Set the error handler for this parser.
 | |
|    * @param handler The object to receive error events.
 | |
|    */
 | |
|   public void setErrorHandler(ErrorHandler handler)
 | |
|   {
 | |
|     if (handler == null)
 | |
|       {
 | |
|         handler = base;
 | |
|       }
 | |
|     this.errorHandler = handler;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX2</b>: Returns the object used to receive callbacks for XML
 | |
|    * errors of all levels (fatal, nonfatal, warning); this is never null;
 | |
|    */
 | |
|   public ErrorHandler getErrorHandler()
 | |
|   {
 | |
|     return (errorHandler == base) ? null : errorHandler;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX1, SAX2</b>: Auxiliary API to parse an XML document, used mostly
 | |
|    * when no URI is available.
 | |
|    * If you want anything useful to happen, you should set
 | |
|    * at least one type of handler.
 | |
|    * @param source The XML input source.  Don't set 'encoding' unless
 | |
|    *  you know for a fact that it's correct.
 | |
|    * @see #setEntityResolver
 | |
|    * @see #setDTDHandler
 | |
|    * @see #setContentHandler
 | |
|    * @see #setErrorHandler
 | |
|    * @exception SAXException The handlers may throw any SAXException,
 | |
|    *  and the parser normally throws SAXParseException objects.
 | |
|    * @exception IOException IOExceptions are normally through through
 | |
|    *  the parser if there are problems reading the source document.
 | |
|    */
 | |
|   public void parse(InputSource source)
 | |
|     throws SAXException, IOException
 | |
|   {
 | |
|     synchronized (base)
 | |
|       {
 | |
|         parser = new XmlParser();
 | |
|         if (namespaces)
 | |
|           {
 | |
|             prefixStack = new NamespaceSupport();
 | |
|           }
 | |
|         else if (!xmlNames)
 | |
|           {
 | |
|             throw new IllegalStateException();
 | |
|           }
 | |
|         parser.setHandler(this);
 | |
| 
 | |
|         try
 | |
|           {
 | |
|             Reader r = source.getCharacterStream();
 | |
|             InputStream in = source.getByteStream();
 | |
| 
 | |
|             parser.doParse(source.getSystemId(),
 | |
|                            source.getPublicId(),
 | |
|                            r,
 | |
|                            in,
 | |
|                            source.getEncoding());
 | |
|           }
 | |
|         catch (SAXException e)
 | |
|           {
 | |
|             throw e;
 | |
|           }
 | |
|         catch (IOException e)
 | |
|           {
 | |
|             throw e;
 | |
|           }
 | |
|         catch (RuntimeException e)
 | |
|           {
 | |
|             throw e;
 | |
|           }
 | |
|         catch (Exception e)
 | |
|           {
 | |
|             throw new SAXParseException(e.getMessage(), this, e);
 | |
|           }
 | |
|         finally
 | |
|           {
 | |
|             contentHandler.endDocument();
 | |
|             reset();
 | |
|           }
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX1, SAX2</b>: Preferred API to parse an XML document, using a
 | |
|    * system identifier (URI).
 | |
|    */
 | |
|   public void parse(String systemId)
 | |
|     throws SAXException, IOException
 | |
|   {
 | |
|     parse(new InputSource(systemId));
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Implementation of SAX2 "XMLReader" interface
 | |
|   //
 | |
|   static final String FEATURE = "http://xml.org/sax/features/";
 | |
|   static final String PROPERTY = "http://xml.org/sax/properties/";
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX2</b>: Tells the value of the specified feature flag.
 | |
|    *
 | |
|    * @exception SAXNotRecognizedException thrown if the feature flag
 | |
|    *  is neither built in, nor yet assigned.
 | |
|    */
 | |
|   public boolean getFeature(String featureId)
 | |
|     throws SAXNotRecognizedException, SAXNotSupportedException
 | |
|   {
 | |
|     if ((FEATURE + "validation").equals(featureId))
 | |
|       {
 | |
|         return false;
 | |
|       }
 | |
| 
 | |
|     // external entities (both types) are optionally included
 | |
|     if ((FEATURE + "external-general-entities").equals(featureId))
 | |
|       {
 | |
|         return extGE;
 | |
|       }
 | |
|     if ((FEATURE + "external-parameter-entities").equals(featureId))
 | |
|       {
 | |
|         return extPE;
 | |
|       }
 | |
| 
 | |
|     // element/attribute names are as written in document; no mangling
 | |
|     if ((FEATURE + "namespace-prefixes").equals(featureId))
 | |
|       {
 | |
|         return xmlNames;
 | |
|       }
 | |
| 
 | |
|     // report element/attribute namespaces?
 | |
|     if ((FEATURE + "namespaces").equals(featureId))
 | |
|       {
 | |
|         return namespaces;
 | |
|       }
 | |
| 
 | |
|     // all PEs and GEs are reported
 | |
|     if ((FEATURE + "lexical-handler/parameter-entities").equals(featureId))
 | |
|       {
 | |
|         return true;
 | |
|       }
 | |
| 
 | |
|     // default is true
 | |
|     if ((FEATURE + "string-interning").equals(featureId))
 | |
|       {
 | |
|         return stringInterning;
 | |
|       }
 | |
| 
 | |
|     // EXTENSIONS 1.1
 | |
| 
 | |
|     // always returns isSpecified info
 | |
|     if ((FEATURE + "use-attributes2").equals(featureId))
 | |
|       {
 | |
|         return true;
 | |
|       }
 | |
| 
 | |
|     // meaningful between startDocument/endDocument
 | |
|     if ((FEATURE + "is-standalone").equals(featureId))
 | |
|       {
 | |
|         if (parser == null)
 | |
|           {
 | |
|             throw new SAXNotSupportedException(featureId);
 | |
|           }
 | |
|         return parser.isStandalone();
 | |
|       }
 | |
| 
 | |
|     // optionally don't absolutize URIs in declarations
 | |
|     if ((FEATURE + "resolve-dtd-uris").equals(featureId))
 | |
|       {
 | |
|         return resolveAll;
 | |
|       }
 | |
| 
 | |
|     // optionally use resolver2 interface methods, if possible
 | |
|     if ((FEATURE + "use-entity-resolver2").equals(featureId))
 | |
|       {
 | |
|         return useResolver2;
 | |
|       }
 | |
| 
 | |
|     throw new SAXNotRecognizedException(featureId);
 | |
|   }
 | |
| 
 | |
|   // package private
 | |
|   DeclHandler getDeclHandler()
 | |
|   {
 | |
|     return declHandler;
 | |
|   }
 | |
| 
 | |
|   // package private
 | |
|   boolean resolveURIs()
 | |
|   {
 | |
|     return resolveAll;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX2</b>:  Returns the specified property.
 | |
|    *
 | |
|    * @exception SAXNotRecognizedException thrown if the property value
 | |
|    *  is neither built in, nor yet stored.
 | |
|    */
 | |
|   public Object getProperty(String propertyId)
 | |
|     throws SAXNotRecognizedException
 | |
|   {
 | |
|     if ((PROPERTY + "declaration-handler").equals(propertyId))
 | |
|       {
 | |
|         return (declHandler == base) ? null : declHandler;
 | |
|       }
 | |
| 
 | |
|     if ((PROPERTY + "lexical-handler").equals(propertyId))
 | |
|       {
 | |
|         return (lexicalHandler == base) ? null : lexicalHandler;
 | |
|       }
 | |
| 
 | |
|     // unknown properties
 | |
|     throw new SAXNotRecognizedException(propertyId);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX2</b>:  Sets the state of feature flags in this parser.  Some
 | |
|    * built-in feature flags are mutable.
 | |
|    */
 | |
|   public void setFeature(String featureId, boolean value)
 | |
|     throws SAXNotRecognizedException, SAXNotSupportedException
 | |
|   {
 | |
|     boolean state;
 | |
| 
 | |
|     // Features with a defined value, we just change it if we can.
 | |
|     state = getFeature (featureId);
 | |
| 
 | |
|     if (state == value)
 | |
|       {
 | |
|         return;
 | |
|       }
 | |
|     if (parser != null)
 | |
|       {
 | |
|         throw new SAXNotSupportedException("not while parsing");
 | |
|       }
 | |
| 
 | |
|     if ((FEATURE + "namespace-prefixes").equals(featureId))
 | |
|       {
 | |
|         // in this implementation, this only affects xmlns reporting
 | |
|         xmlNames = value;
 | |
|         // forcibly prevent illegal parser state
 | |
|         if (!xmlNames)
 | |
|           {
 | |
|             namespaces = true;
 | |
|           }
 | |
|         return;
 | |
|       }
 | |
| 
 | |
|     if ((FEATURE + "namespaces").equals(featureId))
 | |
|       {
 | |
|         namespaces = value;
 | |
|         // forcibly prevent illegal parser state
 | |
|         if (!namespaces)
 | |
|           {
 | |
|             xmlNames = true;
 | |
|           }
 | |
|         return;
 | |
|       }
 | |
| 
 | |
|     if ((FEATURE + "external-general-entities").equals(featureId))
 | |
|       {
 | |
|         extGE = value;
 | |
|         return;
 | |
|       }
 | |
|     if ((FEATURE + "external-parameter-entities").equals(featureId))
 | |
|       {
 | |
|         extPE = value;
 | |
|         return;
 | |
|       }
 | |
|     if ((FEATURE + "resolve-dtd-uris").equals(featureId))
 | |
|       {
 | |
|         resolveAll = value;
 | |
|         return;
 | |
|       }
 | |
| 
 | |
|     if ((FEATURE + "use-entity-resolver2").equals(featureId))
 | |
|       {
 | |
|         useResolver2 = value;
 | |
|         return;
 | |
|       }
 | |
| 
 | |
|     throw new SAXNotRecognizedException(featureId);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX2</b>:  Assigns the specified property.  Like SAX1 handlers,
 | |
|    * these may be changed at any time.
 | |
|    */
 | |
|   public void setProperty(String propertyId, Object value)
 | |
|     throws SAXNotRecognizedException, SAXNotSupportedException
 | |
|   {
 | |
|     // see if the property is recognized
 | |
|     getProperty(propertyId);
 | |
| 
 | |
|     // Properties with a defined value, we just change it if we can.
 | |
| 
 | |
|     if ((PROPERTY + "declaration-handler").equals(propertyId))
 | |
|       {
 | |
|         if (value == null)
 | |
|           {
 | |
|             declHandler = base;
 | |
|           }
 | |
|         else if (!(value instanceof DeclHandler))
 | |
|           {
 | |
|             throw new SAXNotSupportedException(propertyId);
 | |
|           }
 | |
|         else
 | |
|           {
 | |
|             declHandler = (DeclHandler) value;
 | |
|           }
 | |
|         return ;
 | |
|       }
 | |
| 
 | |
|     if ((PROPERTY + "lexical-handler").equals(propertyId))
 | |
|       {
 | |
|         if (value == null)
 | |
|           {
 | |
|             lexicalHandler = base;
 | |
|           }
 | |
|         else if (!(value instanceof LexicalHandler))
 | |
|           {
 | |
|             throw new SAXNotSupportedException(propertyId);
 | |
|           }
 | |
|         else
 | |
|           {
 | |
|             lexicalHandler = (LexicalHandler) value;
 | |
|           }
 | |
|         return;
 | |
|       }
 | |
| 
 | |
|     throw new SAXNotSupportedException(propertyId);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // This is where the driver receives XmlParser callbacks and translates
 | |
|   // them into SAX callbacks.  Some more callbacks have been added for
 | |
|   // SAX2 support.
 | |
|   //
 | |
| 
 | |
|   void startDocument()
 | |
|     throws SAXException
 | |
|   {
 | |
|     contentHandler.setDocumentLocator(this);
 | |
|     contentHandler.startDocument();
 | |
|     attributesList.clear();
 | |
|   }
 | |
| 
 | |
|   void skippedEntity(String name)
 | |
|     throws SAXException
 | |
|   {
 | |
|     contentHandler.skippedEntity(name);
 | |
|   }
 | |
| 
 | |
|   InputSource getExternalSubset(String name, String baseURI)
 | |
|     throws SAXException, IOException
 | |
|   {
 | |
|     if (resolver2 == null || !useResolver2 || !extPE)
 | |
|       {
 | |
|         return null;
 | |
|       }
 | |
|     return resolver2.getExternalSubset(name, baseURI);
 | |
|   }
 | |
| 
 | |
|   InputSource resolveEntity(boolean isPE, String name,
 | |
|                             InputSource in, String baseURI)
 | |
|     throws SAXException, IOException
 | |
|   {
 | |
|     InputSource  source;
 | |
| 
 | |
|     // external entities might be skipped
 | |
|     if (isPE && !extPE)
 | |
|       {
 | |
|         return null;
 | |
|       }
 | |
|     if (!isPE && !extGE)
 | |
|       {
 | |
|         return null;
 | |
|       }
 | |
| 
 | |
|     // ... or not
 | |
|     lexicalHandler.startEntity(name);
 | |
|     if (resolver2 != null && useResolver2)
 | |
|       {
 | |
|         source = resolver2.resolveEntity(name, in.getPublicId(),
 | |
|                                          baseURI, in.getSystemId());
 | |
|         if (source == null)
 | |
|           {
 | |
|             in.setSystemId(absolutize(baseURI,
 | |
|                                       in.getSystemId(), false));
 | |
|             source = in;
 | |
|           }
 | |
|       }
 | |
|     else
 | |
|       {
 | |
|         in.setSystemId(absolutize(baseURI,
 | |
|                                   in.getSystemId(),
 | |
|                                   entityResolver != base));
 | |
|         source = entityResolver.resolveEntity(in.getPublicId(),
 | |
|                                               in.getSystemId());
 | |
|         if (source == null)
 | |
|           {
 | |
|             source = in;
 | |
|           }
 | |
|       }
 | |
|     startExternalEntity(name, source.getSystemId(), true);
 | |
|     return source;
 | |
|   }
 | |
| 
 | |
|   // absolutize a system ID relative to the specified base URI
 | |
|   // (temporarily) package-visible for external entity decls
 | |
|   String absolutize(String baseURI, String systemId, boolean nice)
 | |
|     throws MalformedURLException, SAXException
 | |
|   {
 | |
|     // FIXME normalize system IDs -- when?
 | |
|     // - Convert to UTF-8
 | |
|     // - Map reserved and non-ASCII characters to %HH
 | |
| 
 | |
|     try
 | |
|       {
 | |
|         if (baseURI == null)
 | |
|           {
 | |
|             if (XmlParser.uriWarnings)
 | |
|               {
 | |
|                 warn ("No base URI; hope this SYSTEM id is absolute: "
 | |
|                       + systemId);
 | |
|               }
 | |
|             return new URL(systemId).toString();
 | |
|           }
 | |
|         else
 | |
|           {
 | |
|             return new URL(new URL(baseURI), systemId).toString();
 | |
|           }
 | |
|       }
 | |
|     catch (MalformedURLException e)
 | |
|       {
 | |
|         // Let unknown URI schemes pass through unless we need
 | |
|         // the JVM to map them to i/o streams for us...
 | |
|         if (!nice)
 | |
|           {
 | |
|             throw e;
 | |
|           }
 | |
| 
 | |
|         // sometimes sysids for notations or unparsed entities
 | |
|         // aren't really URIs...
 | |
|         warn("Can't absolutize SYSTEM id: " + e.getMessage());
 | |
|         return systemId;
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   void startExternalEntity(String name, String systemId, boolean stackOnly)
 | |
|     throws SAXException
 | |
|   {
 | |
|     // The following warning was deleted because the application has the
 | |
|     // option of not setting systemId. Sun's JAXP or Xerces seems to
 | |
|     // ignore this case.
 | |
|     /*
 | |
|        if (systemId == null)
 | |
|        warn ("URI was not reported to parser for entity " + name);
 | |
|      */
 | |
|     if (!stackOnly)  // spliced [dtd] needs startEntity
 | |
|       {
 | |
|         lexicalHandler.startEntity(name);
 | |
|       }
 | |
|     entityStack.push(systemId);
 | |
|   }
 | |
| 
 | |
|   void endExternalEntity(String name)
 | |
|     throws SAXException
 | |
|   {
 | |
|     if (!"[document]".equals(name))
 | |
|       {
 | |
|         lexicalHandler.endEntity(name);
 | |
|       }
 | |
|     entityStack.pop();
 | |
|   }
 | |
| 
 | |
|   void startInternalEntity(String name)
 | |
|     throws SAXException
 | |
|   {
 | |
|     lexicalHandler.startEntity(name);
 | |
|   }
 | |
| 
 | |
|   void endInternalEntity(String name)
 | |
|     throws SAXException
 | |
|   {
 | |
|     lexicalHandler.endEntity(name);
 | |
|   }
 | |
| 
 | |
|   void doctypeDecl(String name, String publicId, String systemId)
 | |
|     throws SAXException
 | |
|   {
 | |
|     lexicalHandler.startDTD(name, publicId, systemId);
 | |
| 
 | |
|     // ... the "name" is a declaration and should be given
 | |
|     // to the DeclHandler (but sax2 doesn't).
 | |
| 
 | |
|     // the IDs for the external subset are lexical details,
 | |
|     // as are the contents of the internal subset; but sax2
 | |
|     // doesn't provide the internal subset "pre-parse"
 | |
|   }
 | |
| 
 | |
|   void notationDecl(String name, String publicId, String systemId,
 | |
|                     String baseUri)
 | |
|     throws SAXException
 | |
|   {
 | |
|     try
 | |
|       {
 | |
|         dtdHandler.notationDecl(name, publicId,
 | |
|                                 (resolveAll && systemId != null)
 | |
|                                 ? absolutize(baseUri, systemId, true)
 | |
|                                 : systemId);
 | |
|       }
 | |
|     catch (IOException e)
 | |
|       {
 | |
|         // "can't happen"
 | |
|         throw new SAXParseException(e.getMessage(), this, e);
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   void unparsedEntityDecl(String name, String publicId, String systemId,
 | |
|                           String baseUri, String notation)
 | |
|     throws SAXException
 | |
|   {
 | |
|     try
 | |
|       {
 | |
|         dtdHandler.unparsedEntityDecl(name, publicId,
 | |
|                                       resolveAll
 | |
|                                       ? absolutize(baseUri, systemId, true)
 | |
|                                       : systemId,
 | |
|                                       notation);
 | |
|       }
 | |
|     catch (IOException e)
 | |
|       {
 | |
|         // "can't happen"
 | |
|         throw new SAXParseException(e.getMessage(), this, e);
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   void endDoctype()
 | |
|     throws SAXException
 | |
|   {
 | |
|     lexicalHandler.endDTD();
 | |
|   }
 | |
| 
 | |
|   private void declarePrefix(String prefix, String uri)
 | |
|     throws SAXException
 | |
|   {
 | |
|     int index = uri.indexOf(':');
 | |
| 
 | |
|     // many versions of nwalsh docbook stylesheets
 | |
|     // have bogus URLs; so this can't be an error...
 | |
|     if (index < 1 && uri.length() != 0)
 | |
|       {
 | |
|         warn("relative URI for namespace: " + uri);
 | |
|       }
 | |
| 
 | |
|     // FIXME:  char [0] must be ascii alpha; chars [1..index]
 | |
|     // must be ascii alphanumeric or in "+-." [RFC 2396]
 | |
| 
 | |
|     //Namespace Constraints
 | |
|     //name for xml prefix must be http://www.w3.org/XML/1998/namespace
 | |
|     boolean prefixEquality = prefix.equals("xml");
 | |
|     boolean uriEquality = uri.equals("http://www.w3.org/XML/1998/namespace");
 | |
|     if ((prefixEquality || uriEquality) && !(prefixEquality && uriEquality))
 | |
|       {
 | |
|         fatal("xml is by definition bound to the namespace name " +
 | |
|               "http://www.w3.org/XML/1998/namespace");
 | |
|       }
 | |
| 
 | |
|     //xmlns prefix declaration is illegal but xml prefix declaration is llegal...
 | |
|     if (prefixEquality && uriEquality)
 | |
|       {
 | |
|         return;
 | |
|       }
 | |
| 
 | |
|     //name for xmlns prefix must be http://www.w3.org/2000/xmlns/
 | |
|     prefixEquality = prefix.equals("xmlns");
 | |
|     uriEquality = uri.equals("http://www.w3.org/2000/xmlns/");
 | |
|     if ((prefixEquality || uriEquality) && !(prefixEquality && uriEquality))
 | |
|       {
 | |
|         fatal("http://www.w3.org/2000/xmlns/ is by definition bound" +
 | |
|               " to prefix xmlns");
 | |
|       }
 | |
| 
 | |
|     //even if the uri is http://www.w3.org/2000/xmlns/
 | |
|     // it is illegal to declare it
 | |
|     if (prefixEquality && uriEquality)
 | |
|       {
 | |
|         fatal ("declaring the xmlns prefix is illegal");
 | |
|       }
 | |
| 
 | |
|     uri = uri.intern();
 | |
|     prefixStack.declarePrefix(prefix, uri);
 | |
|     contentHandler.startPrefixMapping(prefix, uri);
 | |
|   }
 | |
| 
 | |
|   void attribute(String qname, String value, boolean isSpecified)
 | |
|     throws SAXException
 | |
|   {
 | |
|     if (!attributes)
 | |
|       {
 | |
|         attributes = true;
 | |
|         if (namespaces)
 | |
|           {
 | |
|             prefixStack.pushContext();
 | |
|           }
 | |
|       }
 | |
| 
 | |
|     // process namespace decls immediately;
 | |
|     // then maybe forget this as an attribute
 | |
|     if (namespaces)
 | |
|       {
 | |
|         int index;
 | |
| 
 | |
|         // default NS declaration?
 | |
|         if (stringInterning)
 | |
|           {
 | |
|             if ("xmlns" == qname)
 | |
|               {
 | |
|                 declarePrefix("", value);
 | |
|                 if (!xmlNames)
 | |
|                   {
 | |
|                     return;
 | |
|                   }
 | |
|               }
 | |
|             // NS prefix declaration?
 | |
|             else if ((index = qname.indexOf(':')) == 5
 | |
|                      && qname.startsWith("xmlns"))
 | |
|               {
 | |
|                 String prefix = qname.substring(6);
 | |
| 
 | |
|                 if (prefix.equals(""))
 | |
|                   {
 | |
|                     fatal("missing prefix " +
 | |
|                           "in namespace declaration attribute");
 | |
|                   }
 | |
|                 if (value.length() == 0)
 | |
|                   {
 | |
|                     verror("missing URI in namespace declaration attribute: "
 | |
|                            + qname);
 | |
|                   }
 | |
|                 else
 | |
|                   {
 | |
|                     declarePrefix(prefix, value);
 | |
|                   }
 | |
|                 if (!xmlNames)
 | |
|                   {
 | |
|                     return;
 | |
|                   }
 | |
|               }
 | |
|           }
 | |
|         else
 | |
|           {
 | |
|             if ("xmlns".equals(qname))
 | |
|               {
 | |
|                 declarePrefix("", value);
 | |
|                 if (!xmlNames)
 | |
|                   {
 | |
|                     return;
 | |
|                   }
 | |
|               }
 | |
|             // NS prefix declaration?
 | |
|             else if ((index = qname.indexOf(':')) == 5
 | |
|                      && qname.startsWith("xmlns"))
 | |
|               {
 | |
|                 String prefix = qname.substring(6);
 | |
| 
 | |
|                 if (value.length() == 0)
 | |
|                   {
 | |
|                     verror("missing URI in namespace decl attribute: "
 | |
|                            + qname);
 | |
|                   }
 | |
|                 else
 | |
|                   {
 | |
|                     declarePrefix(prefix, value);
 | |
|                   }
 | |
|                 if (!xmlNames)
 | |
|                   {
 | |
|                     return;
 | |
|                   }
 | |
|               }
 | |
|           }
 | |
|       }
 | |
|     // remember this attribute ...
 | |
|     attributeCount++;
 | |
| 
 | |
|     // attribute type comes from querying parser's DTD records
 | |
|     attributesList.add(new Attribute(qname, value, isSpecified));
 | |
| 
 | |
|   }
 | |
| 
 | |
|   void startElement(String elname)
 | |
|     throws SAXException
 | |
|   {
 | |
|     ContentHandler handler = contentHandler;
 | |
| 
 | |
|     //
 | |
|     // NOTE:  this implementation of namespace support adds something
 | |
|     // like six percent to parsing CPU time, in a large (~50 MB)
 | |
|     // document that doesn't use namespaces at all.  (Measured by PC
 | |
|     // sampling, with a bug where endElement processing was omitted.)
 | |
|     // [Measurement referred to older implementation, older JVM ...]
 | |
|     //
 | |
|     // It ought to become notably faster in such cases.  Most
 | |
|     // costs are the prefix stack calling Hashtable.get() (2%),
 | |
|     // String.hashCode() (1.5%) and about 1.3% each for pushing
 | |
|     // the context, and two chunks of name processing.
 | |
|     //
 | |
| 
 | |
|     if (!attributes)
 | |
|       {
 | |
|         if (namespaces)
 | |
|           {
 | |
|             prefixStack.pushContext();
 | |
|           }
 | |
|       }
 | |
|     else if (namespaces)
 | |
|       {
 | |
| 
 | |
|         // now we can patch up namespace refs; we saw all the
 | |
|         // declarations, so now we'll do the Right Thing
 | |
|         Iterator itt = attributesList.iterator();
 | |
|         while (itt.hasNext())
 | |
|           {
 | |
|             Attribute attribute = (Attribute) itt.next();
 | |
|             String qname = attribute.name;
 | |
|             int index;
 | |
| 
 | |
|             // default NS declaration?
 | |
|             if (stringInterning)
 | |
|               {
 | |
|                 if ("xmlns" == qname)
 | |
|                   {
 | |
|                     continue;
 | |
|                   }
 | |
|               }
 | |
|             else
 | |
|               {
 | |
|                 if ("xmlns".equals(qname))
 | |
|                   {
 | |
|                     continue;
 | |
|                   }
 | |
|               }
 | |
|             //Illegal in the new Namespaces Draft
 | |
|             //should it be only in 1.1 docs??
 | |
|             if (qname.equals (":"))
 | |
|               {
 | |
|                 fatal("namespace names consisting of a single colon " +
 | |
|                       "character are invalid");
 | |
|               }
 | |
|             index = qname.indexOf(':');
 | |
| 
 | |
|             // NS prefix declaration?
 | |
|             if (index == 5 && qname.startsWith("xmlns"))
 | |
|               {
 | |
|                 continue;
 | |
|               }
 | |
| 
 | |
|             // it's not a NS decl; patch namespace info items
 | |
|             if (prefixStack.processName(qname, nsTemp, true) == null)
 | |
|               {
 | |
|                 fatal("undeclared attribute prefix in: " + qname);
 | |
|               }
 | |
|             else
 | |
|               {
 | |
|                 attribute.nameSpace = nsTemp[0];
 | |
|                 attribute.localName = nsTemp[1];
 | |
|               }
 | |
|           }
 | |
|       }
 | |
| 
 | |
|     // save element name so attribute callbacks work
 | |
|     elementName = elname;
 | |
|     if (namespaces)
 | |
|       {
 | |
|         if (prefixStack.processName(elname, nsTemp, false) == null)
 | |
|           {
 | |
|             fatal("undeclared element prefix in: " + elname);
 | |
|             nsTemp[0] = nsTemp[1] = "";
 | |
|           }
 | |
|         handler.startElement(nsTemp[0], nsTemp[1], elname, this);
 | |
|       }
 | |
|     else
 | |
|       {
 | |
|         handler.startElement("", "", elname, this);
 | |
|       }
 | |
|     // elementName = null;
 | |
| 
 | |
|     // elements with no attributes are pretty common!
 | |
|     if (attributes)
 | |
|       {
 | |
|         attributesList.clear();
 | |
|         attributeCount = 0;
 | |
|         attributes = false;
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   void endElement(String elname)
 | |
|     throws SAXException
 | |
|   {
 | |
|     ContentHandler handler = contentHandler;
 | |
| 
 | |
|     if (!namespaces)
 | |
|       {
 | |
|         handler.endElement("", "", elname);
 | |
|         return;
 | |
|       }
 | |
|     prefixStack.processName(elname, nsTemp, false);
 | |
|     handler.endElement(nsTemp[0], nsTemp[1], elname);
 | |
| 
 | |
|     Enumeration prefixes = prefixStack.getDeclaredPrefixes();
 | |
| 
 | |
|     while (prefixes.hasMoreElements())
 | |
|       {
 | |
|         handler.endPrefixMapping((String) prefixes.nextElement());
 | |
|       }
 | |
|     prefixStack.popContext();
 | |
|   }
 | |
| 
 | |
|   void startCDATA()
 | |
|     throws SAXException
 | |
|   {
 | |
|     lexicalHandler.startCDATA();
 | |
|   }
 | |
| 
 | |
|   void charData(char[] ch, int start, int length)
 | |
|     throws SAXException
 | |
|   {
 | |
|     contentHandler.characters(ch, start, length);
 | |
|   }
 | |
| 
 | |
|   void endCDATA()
 | |
|     throws SAXException
 | |
|   {
 | |
|     lexicalHandler.endCDATA();
 | |
|   }
 | |
| 
 | |
|   void ignorableWhitespace(char[] ch, int start, int length)
 | |
|     throws SAXException
 | |
|   {
 | |
|     contentHandler.ignorableWhitespace(ch, start, length);
 | |
|   }
 | |
| 
 | |
|   void processingInstruction(String target, String data)
 | |
|     throws SAXException
 | |
|   {
 | |
|     contentHandler.processingInstruction(target, data);
 | |
|   }
 | |
| 
 | |
|   void comment(char[] ch, int start, int length)
 | |
|     throws SAXException
 | |
|   {
 | |
|     if (lexicalHandler != base)
 | |
|       {
 | |
|         lexicalHandler.comment(ch, start, length);
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   void fatal(String message)
 | |
|     throws SAXException
 | |
|   {
 | |
|     SAXParseException fatal;
 | |
| 
 | |
|     fatal = new SAXParseException(message, this);
 | |
|     errorHandler.fatalError(fatal);
 | |
| 
 | |
|     // Even if the application can continue ... we can't!
 | |
|     throw fatal;
 | |
|   }
 | |
| 
 | |
|   // We can safely report a few validity errors that
 | |
|   // make layered SAX2 DTD validation more conformant
 | |
|   void verror(String message)
 | |
|     throws SAXException
 | |
|   {
 | |
|     SAXParseException err;
 | |
| 
 | |
|     err = new SAXParseException(message, this);
 | |
|     errorHandler.error(err);
 | |
|   }
 | |
| 
 | |
|   void warn(String message)
 | |
|     throws SAXException
 | |
|   {
 | |
|     SAXParseException err;
 | |
| 
 | |
|     err = new SAXParseException(message, this);
 | |
|     errorHandler.warning(err);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Implementation of org.xml.sax.Attributes.
 | |
|   //
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX1 AttributeList, SAX2 Attributes</b> method
 | |
|    * (don't invoke on parser);
 | |
|    */
 | |
|   public int getLength()
 | |
|   {
 | |
|     return attributesList.size();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX2 Attributes</b> method (don't invoke on parser);
 | |
|    */
 | |
|   public String getURI(int index)
 | |
|   {
 | |
|     if (index < 0 || index >= attributesList.size())
 | |
|       {
 | |
|         return null;
 | |
|       }
 | |
|     return ((Attribute) attributesList.get(index)).nameSpace;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX2 Attributes</b> method (don't invoke on parser);
 | |
|    */
 | |
|   public String getLocalName(int index)
 | |
|   {
 | |
|     if (index < 0 || index >= attributesList.size())
 | |
|       {
 | |
|         return null;
 | |
|       }
 | |
|     Attribute attr = (Attribute) attributesList.get(index);
 | |
|     // FIXME attr.localName is sometimes null, why?
 | |
|     if (namespaces && attr.localName == null)
 | |
|       {
 | |
|         // XXX fix this here for now
 | |
|         int ci = attr.name.indexOf(':');
 | |
|         attr.localName = (ci == -1) ? attr.name :
 | |
|           attr.name.substring(ci + 1);
 | |
|       }
 | |
|     return (attr.localName == null) ? "" : attr.localName;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX2 Attributes</b> method (don't invoke on parser);
 | |
|    */
 | |
|   public String getQName(int index)
 | |
|   {
 | |
|     if (index < 0 || index >= attributesList.size())
 | |
|       {
 | |
|       return null;
 | |
|       }
 | |
|     Attribute attr = (Attribute) attributesList.get(index);
 | |
|     return (attr.name == null) ? "" : attr.name;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX1 AttributeList</b> method (don't invoke on parser);
 | |
|    */
 | |
|   public String getName(int index)
 | |
|   {
 | |
|     return getQName(index);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX1 AttributeList, SAX2 Attributes</b> method
 | |
|    * (don't invoke on parser);
 | |
|    */
 | |
|   public String getType(int index)
 | |
|   {
 | |
|     if (index < 0 || index >= attributesList.size())
 | |
|       {
 | |
|         return null;
 | |
|       }
 | |
|     String type = parser.getAttributeType(elementName, getQName(index));
 | |
|     if (type == null)
 | |
|       {
 | |
|         return "CDATA";
 | |
|       }
 | |
|     // ... use DeclHandler.attributeDecl to see enumerations
 | |
|     if (type == "ENUMERATION")
 | |
|       {
 | |
|         return "NMTOKEN";
 | |
|       }
 | |
|     return type;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX1 AttributeList, SAX2 Attributes</b> method
 | |
|    * (don't invoke on parser);
 | |
|    */
 | |
|   public String getValue(int index)
 | |
|   {
 | |
|     if (index < 0 || index >= attributesList.size())
 | |
|       {
 | |
|         return null;
 | |
|       }
 | |
|     return ((Attribute) attributesList.get(index)).value;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX2 Attributes</b> method (don't invoke on parser);
 | |
|    */
 | |
|   public int getIndex(String uri, String local)
 | |
|     {
 | |
|       int length = getLength();
 | |
| 
 | |
|       for (int i = 0; i < length; i++)
 | |
|         {
 | |
|           if (!getURI(i).equals(uri))
 | |
|             {
 | |
|               continue;
 | |
|             }
 | |
|           if (getLocalName(i).equals(local))
 | |
|             {
 | |
|               return i;
 | |
|             }
 | |
|         }
 | |
|       return -1;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX2 Attributes</b> method (don't invoke on parser);
 | |
|    */
 | |
|   public int getIndex(String xmlName)
 | |
|   {
 | |
|     int length = getLength();
 | |
| 
 | |
|     for (int i = 0; i < length; i++)
 | |
|       {
 | |
|         if (getQName(i).equals(xmlName))
 | |
|           {
 | |
|             return i;
 | |
|           }
 | |
|       }
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX2 Attributes</b> method (don't invoke on parser);
 | |
|    */
 | |
|   public String getType(String uri, String local)
 | |
|   {
 | |
|     int index = getIndex(uri, local);
 | |
| 
 | |
|     if (index < 0)
 | |
|       {
 | |
|         return null;
 | |
|       }
 | |
|     return getType(index);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX1 AttributeList, SAX2 Attributes</b> method
 | |
|    * (don't invoke on parser);
 | |
|    */
 | |
|   public String getType(String xmlName)
 | |
|   {
 | |
|     int index = getIndex(xmlName);
 | |
| 
 | |
|     if (index < 0)
 | |
|       {
 | |
|         return null;
 | |
|       }
 | |
|     return getType(index);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX Attributes</b> method (don't invoke on parser);
 | |
|    */
 | |
|   public String getValue(String uri, String local)
 | |
|   {
 | |
|     int index = getIndex(uri, local);
 | |
| 
 | |
|     if (index < 0)
 | |
|       {
 | |
|         return null;
 | |
|       }
 | |
|     return getValue(index);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX1 AttributeList, SAX2 Attributes</b> method
 | |
|    * (don't invoke on parser);
 | |
|    */
 | |
|   public String getValue(String xmlName)
 | |
|   {
 | |
|     int index = getIndex(xmlName);
 | |
| 
 | |
|     if (index < 0)
 | |
|       {
 | |
|         return null;
 | |
|       }
 | |
|     return getValue(index);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Implementation of org.xml.sax.ext.Attributes2
 | |
|   //
 | |
| 
 | |
|   /** @return false unless the attribute was declared in the DTD.
 | |
|    * @throws java.lang.ArrayIndexOutOfBoundsException
 | |
|    *   When the supplied index does not identify an attribute.
 | |
|    */
 | |
|   public boolean isDeclared(int index)
 | |
|   {
 | |
|     if (index < 0 || index >= attributeCount)
 | |
|       {
 | |
|         throw new ArrayIndexOutOfBoundsException();
 | |
|       }
 | |
|     String type = parser.getAttributeType(elementName, getQName(index));
 | |
|     return (type != null);
 | |
|   }
 | |
| 
 | |
|   /** @return false unless the attribute was declared in the DTD.
 | |
|    * @throws java.lang.IllegalArgumentException
 | |
|    *   When the supplied names do not identify an attribute.
 | |
|    */
 | |
|   public boolean isDeclared(String qName)
 | |
|   {
 | |
|     int index = getIndex(qName);
 | |
|     if (index < 0)
 | |
|       {
 | |
|         throw new IllegalArgumentException();
 | |
|       }
 | |
|     String type = parser.getAttributeType(elementName, qName);
 | |
|     return (type != null);
 | |
|   }
 | |
| 
 | |
|   /** @return false unless the attribute was declared in the DTD.
 | |
|    * @throws java.lang.IllegalArgumentException
 | |
|    *   When the supplied names do not identify an attribute.
 | |
|    */
 | |
|   public boolean isDeclared(String uri, String localName)
 | |
|   {
 | |
|     int index = getIndex(uri, localName);
 | |
|     return isDeclared(index);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX-ext Attributes2</b> method (don't invoke on parser);
 | |
|    */
 | |
|   public boolean isSpecified(int index)
 | |
|   {
 | |
|     return ((Attribute) attributesList.get(index)).specified;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX-ext Attributes2</b> method (don't invoke on parser);
 | |
|    */
 | |
|   public boolean isSpecified(String uri, String local)
 | |
|   {
 | |
|     int index = getIndex (uri, local);
 | |
|     return isSpecified(index);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX-ext Attributes2</b> method (don't invoke on parser);
 | |
|    */
 | |
|   public boolean isSpecified(String xmlName)
 | |
|   {
 | |
|     int index = getIndex (xmlName);
 | |
|     return isSpecified(index);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Implementation of org.xml.sax.Locator.
 | |
|   //
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX Locator</b> method (don't invoke on parser);
 | |
|    */
 | |
|   public String getPublicId()
 | |
|   {
 | |
|     return null;   // FIXME track public IDs too
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX Locator</b> method (don't invoke on parser);
 | |
|    */
 | |
|   public String getSystemId()
 | |
|   {
 | |
|     if (entityStack.empty())
 | |
|       {
 | |
|         return null;
 | |
|       }
 | |
|     else
 | |
|       {
 | |
|         return (String) entityStack.peek();
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX Locator</b> method (don't invoke on parser);
 | |
|    */
 | |
|   public int getLineNumber()
 | |
|   {
 | |
|     return parser.getLineNumber();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <b>SAX Locator</b> method (don't invoke on parser);
 | |
|    */
 | |
|   public int getColumnNumber()
 | |
|   {
 | |
|     return parser.getColumnNumber();
 | |
|   }
 | |
| 
 | |
|   // adapter between SAX2 content handler and SAX1 document handler callbacks
 | |
|   private static class Adapter
 | |
|     implements ContentHandler
 | |
|   {
 | |
| 
 | |
|     private DocumentHandler docHandler;
 | |
| 
 | |
|     Adapter(DocumentHandler dh)
 | |
|     {
 | |
|       docHandler = dh;
 | |
|     }
 | |
| 
 | |
|     public void setDocumentLocator(Locator l)
 | |
|     {
 | |
|       docHandler.setDocumentLocator(l);
 | |
|     }
 | |
| 
 | |
|     public void startDocument()
 | |
|       throws SAXException
 | |
|     {
 | |
|       docHandler.startDocument();
 | |
|     }
 | |
| 
 | |
|     public void processingInstruction(String target, String data)
 | |
|       throws SAXException
 | |
|     {
 | |
|       docHandler.processingInstruction(target, data);
 | |
|     }
 | |
| 
 | |
|     public void startPrefixMapping(String prefix, String uri)
 | |
|     {
 | |
|       /* ignored */
 | |
|     }
 | |
| 
 | |
|     public void startElement(String namespace,
 | |
|                              String local,
 | |
|                              String name,
 | |
|                              Attributes attrs)
 | |
|       throws SAXException
 | |
|     {
 | |
|       docHandler.startElement(name, (AttributeList) attrs);
 | |
|     }
 | |
| 
 | |
|     public void characters(char[] buf, int offset, int len)
 | |
|       throws SAXException
 | |
|     {
 | |
|       docHandler.characters(buf, offset, len);
 | |
|     }
 | |
| 
 | |
|     public void ignorableWhitespace(char[] buf, int offset, int len)
 | |
|       throws SAXException
 | |
|     {
 | |
|       docHandler.ignorableWhitespace(buf, offset, len);
 | |
|     }
 | |
| 
 | |
|     public void skippedEntity(String name)
 | |
|     {
 | |
|       /* ignored */
 | |
|     }
 | |
| 
 | |
|     public void endElement(String u, String l, String name)
 | |
|       throws SAXException
 | |
|     {
 | |
|       docHandler.endElement(name);
 | |
|     }
 | |
| 
 | |
|     public void endPrefixMapping(String prefix)
 | |
|     {
 | |
|       /* ignored */
 | |
|     }
 | |
| 
 | |
|     public void endDocument()
 | |
|       throws SAXException
 | |
|     {
 | |
|       docHandler.endDocument();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   private static class Attribute
 | |
|   {
 | |
| 
 | |
|     String name;
 | |
|     String value;
 | |
|     String nameSpace;
 | |
|     String localName;
 | |
|     boolean specified;
 | |
| 
 | |
|     Attribute(String name, String value, boolean specified)
 | |
|     {
 | |
|       this.name = name;
 | |
|       this.value = value;
 | |
|       this.nameSpace = "";
 | |
|       this.specified = specified;
 | |
|     }
 | |
| 
 | |
|   }
 | |
| 
 | |
| }
 |