validatingparser.java

来自「java jdk 1.4的源码」· Java 代码 · 共 373 行

JAVA
373
字号
/* * $Id: ValidatingParser.java,v 1.1.1.1 2000/11/23 01:53:33 edwingo Exp $ * * The Apache Software License, Version 1.1 * * * Copyright (c) 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 "Crimson" 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, Sun Microsystems, Inc.,  * http://www.sun.com.  For more information on the Apache Software  * Foundation, please see <http://www.apache.org/>. */package org.apache.crimson.parser;import java.util.Enumeration;import java.util.StringTokenizer;import java.util.Vector;import org.xml.sax.HandlerBase;import org.xml.sax.SAXException;import org.xml.sax.SAXParseException;import org.apache.crimson.util.XmlNames;/** * This parser tests XML documents against the validity constraints * specified in the XML 1.0 specification as it parses them.  It * reports violations of those constraints using the standard SAX API. * * <P><em>This parser should be configured to use an <code>ErrorHandler</code> * that reject documents with validity errors, otherwise they will be accepted * despite errors.</em>  The default error handling, as specified by SAX, * ignores all validity errors.  The simplest way to have validity errors * have a useful effect is to pass a boolean <em>true</em> value to * the parser's constructor. * * <P> Note that most validity checks are performed during parsing by * the base class, for efficiency.  They're disabled by default in * that class, and enabled by the constructor in this class. * * @author David Brownell * @version $Revision: 1.1.1.1 $ */public class ValidatingParser extends Parser2{    private SimpleHashtable	ids = new SimpleHashtable ();    /** Constructs a SAX parser object. */    public ValidatingParser ()    {	setIsValidating (true);    }    /**     * Constructs a SAX parser object, optionally assigning the error     * handler to report exceptions on recoverable errors (which include     * all validity errors) as well as fatal errors.     *     * @param rejectValidityErrors When true, the parser will use an     *	error handler which throws exceptions on recoverable errors.     *	Otherwise it uses the default SAX error handler, which ignores     *	such errors.     */    public ValidatingParser (boolean rejectValidityErrors)    {	this ();	if (rejectValidityErrors)	    setErrorHandler (new HandlerBase () {		public void error (SAXParseException x)		    throws SAXException		    { throw x; }		});    }    // REMINDER:  validation errors are not fatal, so code flow    // must continue correctly if error() returns.    // package private ... overrides base class method    void afterRoot () throws SAXException    {	// Make sure all IDREFs match declared ID attributes.  We scan	// after the document element is parsed, since XML allows forward	// references, and only now can we know if they're all resolved.	for (Enumeration e = ids.keys ();		e.hasMoreElements ();		) {	    String id = (String) e.nextElement ();	    Boolean value = (Boolean) ids.get (id);	    if (Boolean.FALSE == value)		error ("V-024", new Object [] { id });	}    }    // package private ... overrides base class method    void afterDocument ()    {	ids.clear ();    }    // package private ... overrides base class method    void validateAttributeSyntax (AttributeDecl attr, String value)    throws SAXException    {	// ID, IDREF(S) ... values are Names	if (AttributeDecl.ID == attr.type) {	    if (!XmlNames.isName (value))		error ("V-025", new Object [] { value });	    Boolean		b = (Boolean) ids.getNonInterned (value);	    if (b == null || b.equals (Boolean.FALSE))		ids.put (value.intern (), Boolean.TRUE);	    else		error ("V-026", new Object [] { value });	} else if (AttributeDecl.IDREF == attr.type) {	    if (!XmlNames.isName (value))		error ("V-027", new Object [] { value });	    Boolean		b = (Boolean) ids.getNonInterned (value);	    if (b == null)		ids.put (value.intern (), Boolean.FALSE);	} else if (AttributeDecl.IDREFS == attr.type) {	    StringTokenizer	tokenizer = new StringTokenizer (value);	    Boolean		b;	    boolean		sawValue = false;	    while (tokenizer.hasMoreTokens ()) {		value = tokenizer.nextToken ();		if (!XmlNames.isName (value))		    error ("V-027", new Object [] { value });		b = (Boolean) ids.getNonInterned (value);		if (b == null)		    ids.put (value.intern (), Boolean.FALSE);		sawValue = true;	    }	    if (!sawValue)		error ("V-039", null);	// NMTOKEN(S) ... values are Nmtoken(s)	} else if (AttributeDecl.NMTOKEN == attr.type) {	    if (!XmlNames.isNmtoken (value))		error ("V-028", new Object [] { value });	} else if (AttributeDecl.NMTOKENS == attr.type) {	    StringTokenizer	tokenizer = new StringTokenizer (value);	    boolean		sawValue = false;	    while (tokenizer.hasMoreTokens ()) {		value = tokenizer.nextToken ();		if (!XmlNames.isNmtoken (value))		    error ("V-028", new Object [] { value });		sawValue = true;	    }	    if (!sawValue)		error ("V-032", null);	// ENUMERATION ... values match one of the tokens	} else if (AttributeDecl.ENUMERATION == attr.type) {	    for (int i = 0; i < attr.values.length; i++)		if (value.equals (attr.values [i]))		    return;	    error ("V-029", new Object [] { value });	// NOTATION values match a notation name	} else if (AttributeDecl.NOTATION == attr.type) {	    //	    // XXX XML 1.0 spec should probably list references to	    // externally defined notations in standalone docs as	    // validity errors.  Ditto externally defined unparsed	    // entities; neither should show up in attributes, else	    // one needs to read the external declarations in order	    // to make sense of the document (exactly what tagging	    // a doc as "standalone" intends you won't need to do).	    //	    for (int i = 0; i < attr.values.length; i++)		if (value.equals (attr.values [i]))		    return;	    error ("V-030", new Object [] { value });	// ENTITY(IES) values match an unparsed entity(ies)	} else if (AttributeDecl.ENTITY == attr.type) {	    // see note above re standalone 	    if (!isUnparsedEntity (value))		error ("V-031", new Object [] { value });	} else if (AttributeDecl.ENTITIES == attr.type) {	    StringTokenizer	tokenizer = new StringTokenizer (value);	    boolean		sawValue = false;	    while (tokenizer.hasMoreTokens ()) {		value = tokenizer.nextToken ();		// see note above re standalone 		if (!isUnparsedEntity (value))		    error ("V-031", new Object [] { value });		sawValue = true;	    }	    if (!sawValue)		error ("V-040", null);	} else if (AttributeDecl.CDATA != attr.type)	    throw new InternalError (attr.type);    }    // package private ... overrides base class method    ContentModel newContentModel (String tag)    {	return new ContentModel (tag);    }    // package private ... overrides base class method    ContentModel newContentModel (char type, ContentModel next)    {	return new ContentModel (type, next);    }    // package private ... overrides base class method    ElementValidator newValidator (ElementDecl element)    {	if (element.validator != null)	    return element.validator;	if (element.model != null)	    return new ChildrenValidator (element);	//	// most types of content model have very simple validation	// algorithms; only "children" needs mutable state.	//	if (element.contentType == null || strANY == element.contentType)	    element.validator = ElementValidator.ANY;	else if (strEMPTY == element.contentType)	    element.validator = EMPTY;	else // (element.contentType.charAt (1) == '#')	    element.validator = new MixedValidator (element);	return element.validator;    }    private final EmptyValidator EMPTY = new EmptyValidator ();    // "EMPTY" model allows nothing    class EmptyValidator extends ElementValidator    {	public void consume (String token) throws SAXException	    { error ("V-033", null); }	public void text () throws SAXException	    { error ("V-033", null); }    }    // Mixed content models allow text with selected elements    class MixedValidator extends ElementValidator    {	private ElementDecl		element;	MixedValidator (ElementDecl element)	    { this.element = element; }	public void consume (String type) throws SAXException	{	    String model = element.contentType;	    for (int index = 8; 		// skip "(#PCDATA|"		    (index = model.indexOf (type, index + 1)) >= 9;		    ) {		char	c;		// allow this type name to suffix -- "|xxTYPE"		if (model.charAt (index -1) != '|')		    continue;		c = model.charAt (index + type.length ());		if (c == '|' || c == ')')		    return;		// allow this type name to prefix -- "|TYPExx"	    }	    error ("V-034", new Object [] { element.name, type, model });	}    }    class ChildrenValidator extends ElementValidator    {	private ContentModelState	state;	private String			name;	ChildrenValidator (ElementDecl element)	{	    state = new ContentModelState (element.model);	    name = element.name;	}	public void consume (String token) throws SAXException	{	    if (state == null)		error ("V-035", new Object [] { name, token });	    else try {		state = state.advance (token);	    } catch (EndOfInputException e) {		error ("V-036", new Object [] { name, token });	    }	}	public void text () throws SAXException	{	    error ("V-037", new Object [] { name });	}	public void done () throws SAXException	{	    if (state != null && !state.terminate ())		error ("V-038", new Object [] { name });	}    }    private boolean isUnparsedEntity (String name)    {	Object e = entities.getNonInterned (name);	if (e == null || !(e instanceof ExternalEntity))	    return false;	return ((ExternalEntity)e).notation != null;    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?