mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			374 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			374 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Java
		
	
	
	
/* XmlReader.java --
 | 
						|
   Copyright (C) 1999,2000,2001 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. */
 | 
						|
 | 
						|
package gnu.xml.aelfred2;
 | 
						|
 | 
						|
import java.io.IOException;
 | 
						|
import java.util.Locale;
 | 
						|
 | 
						|
import org.xml.sax.*;
 | 
						|
import org.xml.sax.ext.*;
 | 
						|
 | 
						|
import gnu.xml.pipeline.EventFilter;
 | 
						|
import gnu.xml.pipeline.ValidationConsumer;
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * This SAX2 parser optionally layers a validator over the Ælfred2
 | 
						|
 * SAX2 parser.  While this will not evaluate every XML validity constraint,
 | 
						|
 * it does support all the validity constraints that are of any real utility
 | 
						|
 * outside the strict SGML-compatible world.  See the documentation for the
 | 
						|
 * SAXDriver class for information about the SAX2 features and properties
 | 
						|
 * that are supported, and documentation for the ValidationConsumer for
 | 
						|
 * information about what validity constraints may not be supported.
 | 
						|
 * (Ælfred2 tests some of those, even in non-validating mode, to
 | 
						|
 * achieve better conformance.)
 | 
						|
 *
 | 
						|
 * <p> Note that due to its internal construction, you can't change most
 | 
						|
 * handlers until parse() returns.  This diverges slightly from SAX, which
 | 
						|
 * expects later binding to be supported.  Early binding involves less
 | 
						|
 * runtime overhead, which is an issue for event pipelines as used inside
 | 
						|
 * this parser.  Rather than relying on the parser to handle late binding
 | 
						|
 * to your own handlers, do it yourself.
 | 
						|
 *
 | 
						|
 * @see SAXDriver
 | 
						|
 * @see gnu.xml.pipeline.ValidationConsumer
 | 
						|
 *
 | 
						|
 * @author David Brownell
 | 
						|
 */
 | 
						|
public final class XmlReader
 | 
						|
  implements XMLReader
 | 
						|
{
 | 
						|
 | 
						|
  static class FatalErrorHandler
 | 
						|
    extends DefaultHandler2
 | 
						|
  {
 | 
						|
 | 
						|
    public void error(SAXParseException e)
 | 
						|
      throws SAXException
 | 
						|
    {
 | 
						|
      throw e;
 | 
						|
    }
 | 
						|
 | 
						|
  }
 | 
						|
 | 
						|
  private SAXDriver aelfred2 = new SAXDriver();
 | 
						|
  private EventFilter filter = new EventFilter();
 | 
						|
  private boolean isValidating;
 | 
						|
  private boolean active;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Constructs a SAX Parser.
 | 
						|
   */
 | 
						|
  public XmlReader()
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Constructs a SAX Parser, optionally treating validity errors
 | 
						|
   * as if they were fatal errors.
 | 
						|
   */
 | 
						|
  public XmlReader(boolean invalidIsFatal)
 | 
						|
  {
 | 
						|
    if (invalidIsFatal)
 | 
						|
      {
 | 
						|
        setErrorHandler(new FatalErrorHandler());
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <b>SAX2</b>: Returns the object used to report the logical
 | 
						|
   * content of an XML document.
 | 
						|
   */
 | 
						|
  public ContentHandler getContentHandler()
 | 
						|
  {
 | 
						|
    return filter.getContentHandler();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <b>SAX2</b>: Assigns the object used to report the logical
 | 
						|
   * content of an XML document.
 | 
						|
   * @exception IllegalStateException if called mid-parse
 | 
						|
   */
 | 
						|
  public void setContentHandler(ContentHandler handler)
 | 
						|
  {
 | 
						|
    if (active)
 | 
						|
      {
 | 
						|
        throw new IllegalStateException("already parsing");
 | 
						|
      }
 | 
						|
    filter.setContentHandler(handler);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <b>SAX2</b>: Returns the object used to process declarations related
 | 
						|
   * to notations and unparsed entities.
 | 
						|
   */
 | 
						|
  public DTDHandler getDTDHandler()
 | 
						|
  {
 | 
						|
    return filter.getDTDHandler();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <b>SAX1</b> Assigns DTD handler
 | 
						|
   * @exception IllegalStateException if called mid-parse
 | 
						|
   */
 | 
						|
  public void setDTDHandler(DTDHandler handler)
 | 
						|
  {
 | 
						|
    if (active)
 | 
						|
      {
 | 
						|
        throw new IllegalStateException("already parsing");
 | 
						|
      }
 | 
						|
    filter.setDTDHandler(handler);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <b>SAX2</b>: Returns the object used when resolving external
 | 
						|
   * entities during parsing (both general and parameter entities).
 | 
						|
   */
 | 
						|
  public EntityResolver getEntityResolver()
 | 
						|
  {
 | 
						|
    return aelfred2.getEntityResolver();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <b>SAX1</b> Assigns parser's entity resolver
 | 
						|
   */
 | 
						|
  public void setEntityResolver(EntityResolver handler)
 | 
						|
  {
 | 
						|
    aelfred2.setEntityResolver(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 aelfred2.getErrorHandler();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <b>SAX1</b> Assigns error handler
 | 
						|
   * @exception IllegalStateException if called mid-parse
 | 
						|
   */
 | 
						|
  public void setErrorHandler(ErrorHandler handler)
 | 
						|
  {
 | 
						|
    if (active)
 | 
						|
      {
 | 
						|
        throw new IllegalStateException("already parsing");
 | 
						|
      }
 | 
						|
    aelfred2.setErrorHandler(handler);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <b>SAX2</b>:  Assigns the specified property.
 | 
						|
   * @exception IllegalStateException if called mid-parse
 | 
						|
   */
 | 
						|
  public void setProperty(String propertyId, Object value)
 | 
						|
    throws SAXNotRecognizedException, SAXNotSupportedException
 | 
						|
  {
 | 
						|
    if (active)
 | 
						|
      {
 | 
						|
        throw new IllegalStateException("already parsing");
 | 
						|
      }
 | 
						|
    if (getProperty(propertyId) != value)
 | 
						|
      {
 | 
						|
        filter.setProperty(propertyId, value);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <b>SAX2</b>:  Returns the specified property.
 | 
						|
   */
 | 
						|
  public Object getProperty(String propertyId)
 | 
						|
    throws SAXNotRecognizedException
 | 
						|
  {
 | 
						|
    if ((SAXDriver.PROPERTY + "declaration-handler").equals(propertyId)
 | 
						|
        || (SAXDriver.PROPERTY + "lexical-handler").equals(propertyId))
 | 
						|
      {
 | 
						|
        return filter.getProperty(propertyId);
 | 
						|
      }
 | 
						|
    throw new SAXNotRecognizedException(propertyId);
 | 
						|
  }
 | 
						|
 | 
						|
  private void forceValidating()
 | 
						|
    throws SAXNotRecognizedException, SAXNotSupportedException
 | 
						|
  {
 | 
						|
    aelfred2.setFeature(SAXDriver.FEATURE + "namespace-prefixes",
 | 
						|
                        true);
 | 
						|
    aelfred2.setFeature(SAXDriver.FEATURE + "external-general-entities",
 | 
						|
                        true);
 | 
						|
    aelfred2.setFeature(SAXDriver.FEATURE + "external-parameter-entities",
 | 
						|
                        true);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <b>SAX2</b>:  Sets the state of features supported in this parser.
 | 
						|
   * Note that this parser requires reporting of namespace prefixes when
 | 
						|
   * validating.
 | 
						|
   */
 | 
						|
  public void setFeature(String featureId, boolean state)
 | 
						|
    throws SAXNotRecognizedException, SAXNotSupportedException
 | 
						|
  {
 | 
						|
    boolean value = getFeature(featureId);
 | 
						|
 | 
						|
    if (state == value)
 | 
						|
      {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
    if ((SAXDriver.FEATURE + "validation").equals(featureId))
 | 
						|
      {
 | 
						|
        if (active)
 | 
						|
          {
 | 
						|
            throw new SAXNotSupportedException("already parsing");
 | 
						|
          }
 | 
						|
        if (state)
 | 
						|
          {
 | 
						|
            forceValidating();
 | 
						|
          }
 | 
						|
        isValidating = state;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        aelfred2.setFeature(featureId, state);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <b>SAX2</b>: Tells whether this parser supports the specified feature.
 | 
						|
   * At this time, this directly parallels the underlying SAXDriver,
 | 
						|
   * except that validation is optionally supported.
 | 
						|
   *
 | 
						|
   * @see SAXDriver
 | 
						|
   */
 | 
						|
  public boolean getFeature(String featureId)
 | 
						|
    throws SAXNotRecognizedException, SAXNotSupportedException
 | 
						|
  {
 | 
						|
    if ((SAXDriver.FEATURE + "validation").equals(featureId))
 | 
						|
      {
 | 
						|
        return isValidating;
 | 
						|
      }
 | 
						|
 | 
						|
    return aelfred2.getFeature(featureId);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <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
 | 
						|
  {
 | 
						|
    aelfred2.setLocale(locale);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <b>SAX1</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));
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <b>SAX1</b>: Underlying API to parse an XML document, used
 | 
						|
   * directly when no URI is available.  When this is invoked,
 | 
						|
   * and the parser is set to validate, some features will be
 | 
						|
   * automatically reset to appropriate values:  for reporting
 | 
						|
   * namespace prefixes, and incorporating external entities.
 | 
						|
   *
 | 
						|
   * @param source The XML input source.
 | 
						|
   *
 | 
						|
   * @exception IllegalStateException if called mid-parse
 | 
						|
   * @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
 | 
						|
  {
 | 
						|
    EventFilter next;
 | 
						|
    boolean nsdecls;
 | 
						|
 | 
						|
    synchronized (aelfred2)
 | 
						|
      {
 | 
						|
        if (active)
 | 
						|
          {
 | 
						|
            throw new IllegalStateException("already parsing");
 | 
						|
          }
 | 
						|
        active = true;
 | 
						|
      }
 | 
						|
 | 
						|
    // set up the output pipeline
 | 
						|
    if (isValidating)
 | 
						|
      {
 | 
						|
        forceValidating();
 | 
						|
        next = new ValidationConsumer(filter);
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        next = filter;
 | 
						|
      }
 | 
						|
 | 
						|
    // connect pipeline and error handler
 | 
						|
    // don't let _this_ call to bind() affect xmlns* attributes
 | 
						|
    nsdecls = aelfred2.getFeature(SAXDriver.FEATURE + "namespace-prefixes");
 | 
						|
    EventFilter.bind(aelfred2, next);
 | 
						|
    if (!nsdecls)
 | 
						|
      {
 | 
						|
        aelfred2.setFeature(SAXDriver.FEATURE + "namespace-prefixes",
 | 
						|
                            false);
 | 
						|
      }
 | 
						|
 | 
						|
    // parse, clean up
 | 
						|
    try
 | 
						|
      {
 | 
						|
        aelfred2.parse(source);
 | 
						|
      }
 | 
						|
    finally
 | 
						|
      {
 | 
						|
        active = false;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
}
 |