Home » Xerces-J-src.2.9.1 » org.apache.xerces » parsers » [javadoc | source]

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    * 
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    * 
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   
   18   package org.apache.xerces.parsers;
   19   
   20   import java.io.IOException;
   21   import java.util.Enumeration;
   22   import java.util.Hashtable;
   23   import java.util.Locale;
   24   
   25   import org.apache.xerces.impl.Constants;
   26   import org.apache.xerces.impl.XMLEntityManager;
   27   import org.apache.xerces.impl.XMLErrorReporter;
   28   import org.apache.xerces.util.SymbolTable;
   29   import org.apache.xerces.xni.XNIException;
   30   import org.apache.xerces.xni.grammars.Grammar;
   31   import org.apache.xerces.xni.grammars.XMLGrammarDescription;
   32   import org.apache.xerces.xni.grammars.XMLGrammarLoader;
   33   import org.apache.xerces.xni.grammars.XMLGrammarPool;
   34   import org.apache.xerces.xni.parser.XMLEntityResolver;
   35   import org.apache.xerces.xni.parser.XMLErrorHandler;
   36   import org.apache.xerces.xni.parser.XMLInputSource;
   37   
   38   /**
   39    * <p> This class provides an easy way for a user to preparse grammars
   40    * of various types.  By default, it knows how to preparse external
   41    * DTD's and schemas; it provides an easy way for user applications to
   42    * register classes that know how to parse additional grammar types.
   43    * By default, it does no grammar caching; but it provides ways for
   44    * user applications to do so.
   45    *
   46    * @author Neil Graham, IBM
   47    *
   48    * @version $Id: XMLGrammarPreparser.java 521449 2007-03-22 20:35:42Z mrglavas $
   49    */
   50   public class XMLGrammarPreparser {
   51   
   52       //
   53       // Constants
   54       //
   55   
   56       // feature:  continue-after-fatal-error
   57       private final static String CONTINUE_AFTER_FATAL_ERROR =
   58           Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
   59   
   60       /** Property identifier: symbol table. */
   61       protected static final String SYMBOL_TABLE =
   62           Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
   63   
   64       /** Property identifier: error reporter. */
   65       protected static final String ERROR_REPORTER =
   66           Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
   67   
   68       /** Property identifier: error handler. */
   69       protected static final String ERROR_HANDLER =
   70           Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
   71   
   72       /** Property identifier: entity resolver. */
   73       protected static final String ENTITY_RESOLVER =
   74           Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
   75   
   76       /** Property identifier: grammar pool . */
   77       protected static final String GRAMMAR_POOL =
   78           Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
   79   
   80       // the "built-in" grammar loaders
   81       private static final Hashtable KNOWN_LOADERS = new Hashtable();
   82   
   83       static {
   84           KNOWN_LOADERS.put(XMLGrammarDescription.XML_SCHEMA,
   85               "org.apache.xerces.impl.xs.XMLSchemaLoader");
   86           KNOWN_LOADERS.put(XMLGrammarDescription.XML_DTD,
   87               "org.apache.xerces.impl.dtd.XMLDTDLoader");
   88       }
   89   
   90       /** Recognized properties. */
   91       private static final String[] RECOGNIZED_PROPERTIES = {
   92           SYMBOL_TABLE,
   93           ERROR_REPORTER,
   94           ERROR_HANDLER,
   95           ENTITY_RESOLVER,
   96           GRAMMAR_POOL,
   97       };
   98   
   99       // Data
  100       protected SymbolTable fSymbolTable;
  101       protected XMLErrorReporter fErrorReporter;
  102       protected XMLEntityResolver fEntityResolver;
  103       protected XMLGrammarPool fGrammarPool;
  104   
  105       protected Locale fLocale;
  106   
  107       // Hashtable holding our loaders
  108       private Hashtable fLoaders;
  109       
  110       // The number of times the configuration has been modified.
  111       private int fModCount = 1;
  112   
  113       //
  114       // Constructors
  115       //
  116   
  117       /** Default constructor. */
  118       public XMLGrammarPreparser() {
  119           this(new SymbolTable());
  120       } // <init>()
  121   
  122       /**
  123        * Constructs a preparser using the specified symbol table.
  124        *
  125        * @param symbolTable The symbol table to use.
  126        */
  127       public XMLGrammarPreparser (SymbolTable symbolTable) {
  128           fSymbolTable = symbolTable;
  129   
  130           fLoaders = new Hashtable();
  131           setLocale(Locale.getDefault());
  132           fErrorReporter = new XMLErrorReporter();
  133           fErrorReporter.setLocale(fLocale);
  134           fEntityResolver = new XMLEntityManager();
  135           // those are all the basic properties...
  136       } // <init>(SymbolTable)
  137   
  138       //
  139       // Public methods
  140       //
  141   
  142       /*
  143       * Register a type of grammar to make it preparsable.   If
  144       * the second parameter is null, the parser will use its  built-in
  145       * facilities for that grammar type.
  146       * This should be called by the application immediately
  147       * after creating this object and before initializing any properties/features.
  148       * @param type   URI identifying the type of the grammar
  149       * @param loader an object capable of preparsing that type; null if the ppreparser should use built-in knowledge.
  150       * @return true if successful; false if no built-in knowledge of
  151       *       the type or if unable to instantiate the string we know about
  152       */
  153       public boolean registerPreparser(String grammarType, XMLGrammarLoader loader) {
  154           if(loader == null) { // none specified!
  155               if(KNOWN_LOADERS.containsKey(grammarType)) {
  156                   // got one; just instantiate it...
  157                   String loaderName = (String)KNOWN_LOADERS.get(grammarType);
  158                   try {
  159                       ClassLoader cl = ObjectFactory.findClassLoader();
  160                       XMLGrammarLoader gl = (XMLGrammarLoader)(ObjectFactory.newInstance(loaderName, cl, true));
  161                       fLoaders.put(grammarType, new XMLGrammarLoaderContainer(gl));
  162                   } catch (Exception e) {
  163                       return false;
  164                   }
  165                   return true;
  166               }
  167               return false;
  168           }
  169           // were given one
  170           fLoaders.put(grammarType, new XMLGrammarLoaderContainer(loader));
  171           return true;
  172       } // registerPreparser(String, XMLGrammarLoader):  boolean
  173   
  174       /**
  175        * Parse a grammar from a location identified by an
  176        * XMLInputSource.
  177        * This method also adds this grammar to the XMLGrammarPool
  178        *
  179        * @param type The type of the grammar to be constructed
  180        * @param is The XMLInputSource containing this grammar's
  181        * information
  182        * <strong>If a URI is included in the systemId field, the parser will not expand this URI or make it
  183        * available to the EntityResolver</strong>
  184        * @return The newly created <code>Grammar</code>.
  185        * @exception XNIException thrown on an error in grammar
  186        * construction
  187        * @exception IOException thrown if an error is encountered
  188        * in reading the file
  189        */
  190       public Grammar preparseGrammar(String type, XMLInputSource
  191                   is) throws XNIException, IOException {
  192           if (fLoaders.containsKey(type)) {
  193               XMLGrammarLoaderContainer xglc = (XMLGrammarLoaderContainer) fLoaders.get(type);
  194               XMLGrammarLoader gl = xglc.loader;
  195               if (xglc.modCount != fModCount) {
  196                   // make sure gl's been set up with all the "basic" properties:
  197                   gl.setProperty(SYMBOL_TABLE, fSymbolTable);
  198                   gl.setProperty(ENTITY_RESOLVER, fEntityResolver);
  199                   gl.setProperty(ERROR_REPORTER, fErrorReporter);
  200                   // potentially, not all will support this one...
  201                   if (fGrammarPool != null) {
  202                       try {
  203                           gl.setProperty(GRAMMAR_POOL, fGrammarPool);
  204                       } catch(Exception e) {
  205                           // too bad...
  206                       }
  207                   }
  208                   xglc.modCount = fModCount;
  209               }
  210               return gl.loadGrammar(is);
  211           }
  212           return null;
  213       } // preparseGrammar(String, XMLInputSource):  Grammar
  214   
  215       /**
  216        * Set the locale to use for messages.
  217        *
  218        * @param locale The locale object to use for localization of messages.
  219        *
  220        * @exception XNIException Thrown if the parser does not support the
  221        *                         specified locale.
  222        */
  223       public void setLocale(Locale locale) {
  224           fLocale = locale;
  225       } // setLocale(Locale)
  226   
  227       /** Return the Locale the XMLGrammarLoader is using. */
  228       public Locale getLocale() {
  229           return fLocale;
  230       } // getLocale():  Locale
  231   
  232   
  233       /**
  234        * Sets the error handler.
  235        *
  236        * @param errorHandler The error handler.
  237        */
  238       public void setErrorHandler(XMLErrorHandler errorHandler) {
  239           fErrorReporter.setProperty(ERROR_HANDLER, errorHandler);
  240       } // setErrorHandler(XMLErrorHandler)
  241   
  242       /** Returns the registered error handler.  */
  243       public XMLErrorHandler getErrorHandler() {
  244           return fErrorReporter.getErrorHandler();
  245       } // getErrorHandler():  XMLErrorHandler
  246   
  247       /**
  248        * Sets the entity resolver.
  249        *
  250        * @param entityResolver The new entity resolver.
  251        */
  252       public void setEntityResolver(XMLEntityResolver entityResolver) {
  253           if (fEntityResolver != entityResolver) {
  254               // Overflow. We actually need to reset the 
  255               // modCount on every XMLGrammarLoaderContainer.
  256               if (++fModCount < 0) {
  257                   clearModCounts();
  258               }
  259               fEntityResolver = entityResolver;
  260           }
  261       } // setEntityResolver(XMLEntityResolver)
  262   
  263       /** Returns the registered entity resolver.  */
  264       public XMLEntityResolver getEntityResolver() {
  265           return fEntityResolver;
  266       } // getEntityResolver():  XMLEntityResolver
  267   
  268       /**
  269        * Sets the grammar pool.
  270        *
  271        * @param grammarPool The new grammar pool.
  272        */
  273       public void setGrammarPool(XMLGrammarPool grammarPool) {
  274           if (fGrammarPool != grammarPool) {
  275               // Overflow. We actually need to reset the 
  276               // modCount on every XMLGrammarLoaderContainer.
  277               if (++fModCount < 0) {
  278                   clearModCounts();
  279               }
  280               fGrammarPool = grammarPool;
  281           }
  282       } // setGrammarPool(XMLGrammarPool)
  283   
  284       /** Returns the registered grammar pool.  */
  285       public XMLGrammarPool getGrammarPool() {
  286           return fGrammarPool;
  287       } // getGrammarPool():  XMLGrammarPool
  288   
  289       // it's possible the application may want access to a certain loader to do
  290       // some custom work.
  291       public XMLGrammarLoader getLoader(String type) {
  292           XMLGrammarLoaderContainer xglc = (XMLGrammarLoaderContainer) fLoaders.get(type);
  293           return (xglc != null) ? xglc.loader : null;
  294       } // getLoader(String):  XMLGrammarLoader
  295   
  296       // set a feature.  This method tries to set it on all
  297       // registered loaders; it eats any resulting exceptions.  If
  298       // an app needs to know if a particular feature is supported
  299       // by a grammar loader of a particular type, it will have
  300       // to retrieve that loader and use the loader's setFeature method.
  301       public void setFeature(String featureId, boolean value) {
  302           Enumeration loaders = fLoaders.elements();
  303           while (loaders.hasMoreElements()) {
  304               XMLGrammarLoader gl = ((XMLGrammarLoaderContainer)loaders.nextElement()).loader;
  305               try {
  306                   gl.setFeature(featureId, value);
  307               } catch(Exception e) {
  308                   // eat it up...
  309               }
  310           }
  311           // since our error reporter is a property we set later,
  312           // make sure features it understands are also set.
  313           if(featureId.equals(CONTINUE_AFTER_FATAL_ERROR)) {
  314               fErrorReporter.setFeature(CONTINUE_AFTER_FATAL_ERROR, value);
  315           }
  316       } //setFeature(String, boolean)
  317   
  318       // set a property.  This method tries to set it on all
  319       // registered loaders; it eats any resulting exceptions.  If
  320       // an app needs to know if a particular property is supported
  321       // by a grammar loader of a particular type, it will have
  322       // to retrieve that loader and use the loader's setProperty method.
  323       // <p> <strong>An application should use the explicit method
  324       // in this class to set "standard" properties like error handler etc.</strong>
  325       public void setProperty(String propId, Object value) {
  326           Enumeration loaders = fLoaders.elements();
  327           while (loaders.hasMoreElements()) {
  328               XMLGrammarLoader gl = ((XMLGrammarLoaderContainer)loaders.nextElement()).loader;
  329               try {
  330                   gl.setProperty(propId, value);
  331               } catch(Exception e) {
  332                   // eat it up...
  333               }
  334           }
  335       } //setProperty(String, Object)
  336   
  337       // get status of feature in a particular loader.  This
  338       // catches no exceptions--including NPE's--so the application had
  339       // better make sure the loader exists and knows about this feature.
  340       // @param type type of grammar to look for the feature in.
  341       // @param featureId the feature string to query.
  342       // @return the value of the feature.
  343       public boolean getFeature(String type, String featureId) {
  344           XMLGrammarLoader gl = ((XMLGrammarLoaderContainer)fLoaders.get(type)).loader;
  345           return gl.getFeature(featureId);
  346       } // getFeature (String, String):  boolean
  347   
  348       // get status of property in a particular loader.  This
  349       // catches no exceptions--including NPE's--so the application had
  350       // better make sure the loader exists and knows about this property.
  351       // <strong>For standard properties--that will be supported
  352       // by all loaders--the specific methods should be queried!</strong>
  353       // @param type type of grammar to look for the property in.
  354       // @param propertyId the property string to query.
  355       // @return the value of the property.
  356       public Object getProperty(String type, String propertyId) {
  357           XMLGrammarLoader gl = ((XMLGrammarLoaderContainer)fLoaders.get(type)).loader;
  358           return gl.getProperty(propertyId);
  359       } // getProperty(String, String):  Object
  360       
  361       /** 
  362        * Container for an XMLGrammarLoader. Also holds the modCount 
  363        * that the XMLGrammarPreparser had the last time it was used.
  364        */
  365       static class XMLGrammarLoaderContainer {
  366           public final XMLGrammarLoader loader;
  367           public int modCount = 0;
  368           public XMLGrammarLoaderContainer(XMLGrammarLoader loader) {
  369               this.loader = loader;
  370           }
  371       }
  372       
  373       private void clearModCounts() {
  374           Enumeration loaders = fLoaders.elements();
  375           while (loaders.hasMoreElements()) {
  376               XMLGrammarLoaderContainer xglc = (XMLGrammarLoaderContainer) loaders.nextElement();
  377               xglc.modCount = 0;
  378           }
  379           fModCount = 1;
  380       }
  381       
  382   } // class XMLGrammarPreparser

Home » Xerces-J-src.2.9.1 » org.apache.xerces » parsers » [javadoc | source]