/* * The Apache Software License, Version 1.1 * * * Copyright (c) 1999-2003 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 * . */ package com.sun.org.apache.xerces.internal.impl.dtd; import com.sun.org.apache.xerces.internal.impl.Constants; import com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl; import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter; import com.sun.org.apache.xerces.internal.impl.XMLEntityManager; import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter; import com.sun.org.apache.xerces.internal.util.SymbolTable; import com.sun.org.apache.xerces.internal.util.DefaultErrorHandler; import com.sun.org.apache.xerces.internal.xni.XNIException; import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool; import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarLoader; import com.sun.org.apache.xerces.internal.xni.grammars.Grammar; import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; import com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler; import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver; import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; import java.util.Locale; import java.io.IOException; import java.io.EOFException; /** * The DTD loader. The loader knows how to build grammars from XMLInputSources. * It extends the DTD processor in order to do this; it's * a separate class because DTD processors don't need to know how * to talk to the outside world in their role as instance-document * helpers. *

* This component requires the following features and properties. It * know ho to set them if no one else does:from the *

* * @author Neil Graham, IBM * * @version $Id: XMLDTDLoader.java,v 1.9 2003/10/14 14:34:26 mrglavas Exp $ */ public class XMLDTDLoader extends XMLDTDProcessor implements XMLGrammarLoader { // // Constants // // feature identifiers /** Feature identifier: standard uri conformant feature. */ protected static final String STANDARD_URI_CONFORMANT_FEATURE = Constants.XERCES_FEATURE_PREFIX + Constants.STANDARD_URI_CONFORMANT_FEATURE; // recognized features: private static final String[] RECOGNIZED_FEATURES = { VALIDATION, WARN_ON_DUPLICATE_ATTDEF, NOTIFY_CHAR_REFS, STANDARD_URI_CONFORMANT_FEATURE }; // property identifiers /** Property identifier: error handler. */ protected static final String ERROR_HANDLER = Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY; /** Property identifier: entity resolver. */ public static final String ENTITY_RESOLVER = Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY; /** Recognized properties. */ private static final String[] LOADER_RECOGNIZED_PROPERTIES = { SYMBOL_TABLE, ERROR_REPORTER, ERROR_HANDLER, ENTITY_RESOLVER, GRAMMAR_POOL, DTD_VALIDATOR, }; // enforcing strict uri? private boolean fStrictURI = false; /** Entity resolver . */ protected XMLEntityResolver fEntityResolver; // the scanner we use to actually read the DTD protected XMLDTDScannerImpl fDTDScanner; // the entity manager the scanner needs. protected XMLEntityManager fEntityManager; // what's our Locale? protected Locale fLocale; // // Constructors // /** Deny default construction; we need a SymtolTable! */ public XMLDTDLoader() { this(new SymbolTable()); } // () public XMLDTDLoader(SymbolTable symbolTable) { this(symbolTable, null); } // init(SymbolTable) public XMLDTDLoader(SymbolTable symbolTable, XMLGrammarPool grammarPool) { this(symbolTable, grammarPool, null, new XMLEntityManager()); } // init(SymbolTable, XMLGrammarPool) XMLDTDLoader(SymbolTable symbolTable, XMLGrammarPool grammarPool, XMLErrorReporter errorReporter, XMLEntityResolver entityResolver) { fSymbolTable = symbolTable; fGrammarPool = grammarPool; if(errorReporter == null) { errorReporter = new XMLErrorReporter(); errorReporter.setProperty(ERROR_HANDLER, new DefaultErrorHandler()); } fErrorReporter = errorReporter; // Add XML message formatter if there isn't one. if (fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) { XMLMessageFormatter xmft = new XMLMessageFormatter(); fErrorReporter.putMessageFormatter(XMLMessageFormatter.XML_DOMAIN, xmft); fErrorReporter.putMessageFormatter(XMLMessageFormatter.XMLNS_DOMAIN, xmft); } fEntityResolver = entityResolver; if(fEntityResolver instanceof XMLEntityManager) { fEntityManager = (XMLEntityManager)fEntityResolver; } else { fEntityManager = new XMLEntityManager(); } fEntityManager.setProperty(Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY, errorReporter); fDTDScanner = new XMLDTDScannerImpl(fSymbolTable, fErrorReporter, fEntityManager); fDTDScanner.setDTDHandler(this); fDTDScanner.setDTDContentModelHandler(this); reset(); } // init(SymbolTable, XMLGrammarPool, XMLErrorReporter, XMLEntityResolver) // XMLGrammarLoader methods /** * Sets the state of a feature. This method is called by the component * manager any time after reset when a feature changes state. *

* Note: Components should silently ignore features * that do not affect the operation of the component. * * @param featureId The feature identifier. * @param state The state of the feature. * * @throws SAXNotRecognizedException The component should not throw * this exception. * @throws SAXNotSupportedException The component should not throw * this exception. */ public void setFeature(String featureId, boolean state) throws XMLConfigurationException { if(featureId.equals(VALIDATION)) { fValidation = state; } else if(featureId.equals(WARN_ON_DUPLICATE_ATTDEF)) { fWarnDuplicateAttdef = state; } else if(featureId.equals(NOTIFY_CHAR_REFS)) { fDTDScanner.setFeature(featureId, state); } else if(featureId.equals(STANDARD_URI_CONFORMANT_FEATURE)) { fStrictURI = state; } else { throw new XMLConfigurationException(XMLConfigurationException.NOT_RECOGNIZED, featureId); } } // setFeature(String,boolean) /** * Returns a list of property identifiers that are recognized by * this component. This method may return null if no properties * are recognized by this component. */ public String[] getRecognizedProperties() { return (String[])(LOADER_RECOGNIZED_PROPERTIES.clone()); } // getRecognizedProperties():String[] /** * Returns the state of a property. * * @param propertyId The property identifier. * * @throws XMLConfigurationException Thrown on configuration error. */ public Object getProperty(String propertyId) throws XMLConfigurationException { if(propertyId.equals( SYMBOL_TABLE)) { return fSymbolTable; } else if(propertyId.equals( ERROR_REPORTER)) { return fErrorReporter; } else if(propertyId.equals( ERROR_HANDLER)) { return fErrorReporter.getErrorHandler(); } else if(propertyId.equals( ENTITY_RESOLVER)) { return fEntityResolver; } else if(propertyId.equals( GRAMMAR_POOL)) { return fGrammarPool; } else if(propertyId.equals( DTD_VALIDATOR)) { return fValidator; } throw new XMLConfigurationException(XMLConfigurationException.NOT_RECOGNIZED, propertyId); } // getProperty(String): Object /** * Sets the value of a property. This method is called by the component * manager any time after reset when a property changes value. *

* Note: Components should silently ignore properties * that do not affect the operation of the component. * * @param propertyId The property identifier. * @param value The value of the property. * * @throws SAXNotRecognizedException The component should not throw * this exception. * @throws SAXNotSupportedException The component should not throw * this exception. */ public void setProperty(String propertyId, Object value) throws XMLConfigurationException { if(propertyId.equals( SYMBOL_TABLE)) { fSymbolTable = (SymbolTable)value; fDTDScanner.setProperty(propertyId, value); fEntityManager.setProperty(propertyId, value); } else if(propertyId.equals( ERROR_REPORTER)) { fErrorReporter = (XMLErrorReporter)value; // Add XML message formatter if there isn't one. if (fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) { XMLMessageFormatter xmft = new XMLMessageFormatter(); fErrorReporter.putMessageFormatter(XMLMessageFormatter.XML_DOMAIN, xmft); fErrorReporter.putMessageFormatter(XMLMessageFormatter.XMLNS_DOMAIN, xmft); } fDTDScanner.setProperty(propertyId, value); fEntityManager.setProperty(propertyId, value); } else if(propertyId.equals( ERROR_HANDLER)) { fErrorReporter.setProperty(propertyId, value); } else if(propertyId.equals( ENTITY_RESOLVER)) { fEntityResolver = (XMLEntityResolver)value; } else if(propertyId.equals( GRAMMAR_POOL)) { fGrammarPool = (XMLGrammarPool)value; } else { throw new XMLConfigurationException(XMLConfigurationException.NOT_RECOGNIZED, propertyId); } } // setProperty(String,Object) /** * Returns the state of a feature. * * @param featureId The feature identifier. * * @throws XMLConfigurationException Thrown on configuration error. */ public boolean getFeature(String featureId) throws XMLConfigurationException { if(featureId.equals( VALIDATION)) { return fValidation; } else if(featureId.equals( WARN_ON_DUPLICATE_ATTDEF)) { return fWarnDuplicateAttdef; } else if(featureId.equals( NOTIFY_CHAR_REFS)) { return fDTDScanner.getFeature(featureId); } throw new XMLConfigurationException(XMLConfigurationException.NOT_RECOGNIZED, featureId); } //getFeature(String): boolean /** * Set the locale to use for messages. * * @param locale The locale object to use for localization of messages. * * @exception XNIException Thrown if the parser does not support the * specified locale. */ public void setLocale(Locale locale) { fLocale = locale; } // setLocale(Locale) /** Return the Locale the XMLGrammarLoader is using. */ public Locale getLocale() { return fLocale; } // getLocale(): Locale /** * Sets the error handler. * * @param errorHandler The error handler. */ public void setErrorHandler(XMLErrorHandler errorHandler) { fErrorReporter.setProperty(ERROR_HANDLER, errorHandler); } // setErrorHandler(XMLErrorHandler) /** Returns the registered error handler. */ public XMLErrorHandler getErrorHandler() { return fErrorReporter.getErrorHandler(); } // getErrorHandler(): XMLErrorHandler /** * Sets the entity resolver. * * @param entityResolver The new entity resolver. */ public void setEntityResolver(XMLEntityResolver entityResolver) { fEntityResolver = entityResolver; } // setEntityResolver(XMLEntityResolver) /** Returns the registered entity resolver. */ public XMLEntityResolver getEntityResolver() { return fEntityResolver; } // getEntityResolver(): XMLEntityResolver /** * Returns a Grammar object by parsing the contents of the * entity pointed to by source. * * @param source the location of the entity which forms * the starting point of the grammar to be constructed. * @throws IOException When a problem is encountered reading the entity * XNIException When a condition arises (such as a FatalError) that requires parsing * of the entity be terminated. */ public Grammar loadGrammar(XMLInputSource source) throws IOException, XNIException { reset(); // First chance checking strict URI String eid = XMLEntityManager.expandSystemId(source.getSystemId(), source.getBaseSystemId(), fStrictURI); fDTDGrammar = new DTDGrammar(fSymbolTable, new XMLDTDDescription(source.getPublicId(), source.getSystemId(), source.getBaseSystemId(), eid, null)); fGrammarBucket = new DTDGrammarBucket(); fGrammarBucket.setStandalone(false); fGrammarBucket.setActiveGrammar(fDTDGrammar); // no reason to use grammar bucket's "put" method--we // know which grammar it is, and we don't know the root name anyway... // actually start the parsing! try { fDTDScanner.setInputSource(source); fDTDScanner.scanDTDExternalSubset(true); } catch (EOFException e) { // expected behaviour... } finally { // Close all streams opened by the parser. fEntityManager.closeReaders(); } if(fDTDGrammar != null && fGrammarPool != null) { fGrammarPool.cacheGrammars(XMLDTDDescription.XML_DTD, new Grammar[] {fDTDGrammar}); } return fDTDGrammar; } // loadGrammar(XMLInputSource): Grammar // reset all the components that we rely upon protected void reset() { super.reset(); fDTDScanner.reset(); fEntityManager.reset(); fErrorReporter.setDocumentLocator(fEntityManager.getEntityScanner()); } } // class XMLDTDLoader