1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Copyright 2001-2005 The Apache Software Foundation.
   7  *
   8  * Licensed under the Apache License, Version 2.0 (the "License");
   9  * you may not use this file except in compliance with the License.
  10  * You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 
  21 package com.sun.org.apache.xerces.internal.parsers;
  22 
  23 import java.io.IOException;
  24 
  25 import com.sun.org.apache.xerces.internal.impl.Constants;
  26 import com.sun.org.apache.xerces.internal.impl.dtd.DTDGrammar;
  27 import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDLoader;
  28 import com.sun.org.apache.xerces.internal.impl.xs.SchemaGrammar;
  29 import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader;
  30 import com.sun.org.apache.xerces.internal.impl.xs.XSMessageFormatter;
  31 import com.sun.org.apache.xerces.internal.util.SymbolTable;
  32 import com.sun.org.apache.xerces.internal.util.SynchronizedSymbolTable;
  33 import com.sun.org.apache.xerces.internal.util.XMLGrammarPoolImpl;
  34 import com.sun.org.apache.xerces.internal.xni.XNIException;
  35 import com.sun.org.apache.xerces.internal.xni.grammars.Grammar;
  36 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription;
  37 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
  38 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
  39 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
  40 import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver;
  41 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
  42 
  43 /**
  44  * <p> This configuration provides a generic way of using
  45  * Xerces's grammar caching facilities.  It extends the
  46  * XIncludeAwareParserConfiguration and thus may validate documents
  47  * according to XML schemas or DTD's.  It also allows the user to
  48  * preparse a grammar, and to lock the grammar pool
  49  * implementation such that no more grammars will be added.</p>
  50  * <p> Using the com.sun.org.apache.xerces.internal.xni.parser property, an
  51  * application may instantiate a Xerces SAX or DOM parser with
  52  * this configuration.  When invoked in this manner, the default
  53  * behaviour will be elicited; to use this configuration's
  54  * specific facilities, the user will need to reference it
  55  * directly.</p>
  56  * <p>
  57  * In addition to the features and properties recognized by the base
  58  * parser configuration, this class recognizes these additional
  59  * features and properties:
  60  * <ul>
  61  * </ul>
  62  *
  63  * @author Neil Graham, IBM
  64  *
  65  * @version $Id: XMLGrammarCachingConfiguration.java,v 1.6 2010-11-01 04:40:10 joehw Exp $
  66  */
  67 public class XMLGrammarCachingConfiguration
  68     extends XIncludeAwareParserConfiguration {
  69 
  70     //
  71     // Constants
  72     //
  73 
  74     // a larg(ish) prime to use for a symbol table to be shared
  75     // among
  76     // potentially man parsers.  Start one as close to 2K (20
  77     // times larger than normal) and see what happens...
  78     public static final int BIG_PRIME = 2039;
  79 
  80     // the static symbol table to be shared amongst parsers
  81     protected static final SynchronizedSymbolTable fStaticSymbolTable =
  82             new SynchronizedSymbolTable(BIG_PRIME);
  83 
  84     // the Grammar Pool to be shared similarly
  85     protected static final XMLGrammarPoolImpl fStaticGrammarPool =
  86             new XMLGrammarPoolImpl();
  87 
  88     // schema full checking constant
  89     protected static final String SCHEMA_FULL_CHECKING =
  90             Constants.XERCES_FEATURE_PREFIX+Constants.SCHEMA_FULL_CHECKING;
  91 
  92     // Data
  93 
  94     // variables needed for caching schema grammars.
  95     protected XMLSchemaLoader fSchemaLoader;
  96 
  97     // the DTD grammar loader
  98     protected XMLDTDLoader fDTDLoader;
  99 
 100     //
 101     // Constructors
 102     //
 103 
 104     /** Default constructor. */
 105     public XMLGrammarCachingConfiguration() {
 106         this(fStaticSymbolTable, fStaticGrammarPool, null);
 107     } // <init>()
 108 
 109     /**
 110      * Constructs a parser configuration using the specified symbol table.
 111      *
 112      * @param symbolTable The symbol table to use.
 113      */
 114     public XMLGrammarCachingConfiguration(SymbolTable symbolTable) {
 115         this(symbolTable, fStaticGrammarPool, null);
 116     } // <init>(SymbolTable)
 117 
 118     /**
 119      * Constructs a parser configuration using the specified symbol table and
 120      * grammar pool.
 121      * <p>
 122      * <strong>REVISIT:</strong>
 123      * Grammar pool will be updated when the new validation engine is
 124      * implemented.
 125      *
 126      * @param symbolTable The symbol table to use.
 127      * @param grammarPool The grammar pool to use.
 128      */
 129     public XMLGrammarCachingConfiguration(SymbolTable symbolTable,
 130                                        XMLGrammarPool grammarPool) {
 131         this(symbolTable, grammarPool, null);
 132     } // <init>(SymbolTable,XMLGrammarPool)
 133 
 134     /**
 135      * Constructs a parser configuration using the specified symbol table,
 136      * grammar pool, and parent settings.
 137      * <p>
 138      * <strong>REVISIT:</strong>
 139      * Grammar pool will be updated when the new validation engine is
 140      * implemented.
 141      *
 142      * @param symbolTable    The symbol table to use.
 143      * @param grammarPool    The grammar pool to use.
 144      * @param parentSettings The parent settings.
 145      */
 146     public XMLGrammarCachingConfiguration(SymbolTable symbolTable,
 147                                        XMLGrammarPool grammarPool,
 148                                        XMLComponentManager parentSettings) {
 149         super(symbolTable, grammarPool, parentSettings);
 150 
 151         // REVISIT:  may need to add some features/properties
 152         // specific to this configuration at some point...
 153 
 154         // add default recognized features
 155         // set state for default features
 156         // add default recognized properties
 157         // create and register missing components
 158         fSchemaLoader = new XMLSchemaLoader(fSymbolTable);
 159         fSchemaLoader.setProperty(XMLGRAMMAR_POOL, fGrammarPool);
 160 
 161         // and set up the DTD loader too:
 162         fDTDLoader = new XMLDTDLoader(fSymbolTable, fGrammarPool);
 163     } // <init>(SymbolTable,XMLGrammarPool, XMLComponentManager)
 164 
 165     //
 166     // Public methods
 167     //
 168 
 169     /*
 170      * lock the XMLGrammarPoolImpl object so that it does not
 171      * accept any more grammars from the validators.
 172      */
 173     public void lockGrammarPool() {
 174         fGrammarPool.lockPool();
 175     } // lockGrammarPool()
 176 
 177     /*
 178      * clear the XMLGrammarPoolImpl object so that it does not
 179      * contain any more grammars.
 180      */
 181     public void clearGrammarPool() {
 182         fGrammarPool.clear();
 183     } // clearGrammarPool()
 184 
 185     /*
 186      * unlock the XMLGrammarPoolImpl object so that it
 187      * accepts more grammars from the validators.
 188      */
 189     public void unlockGrammarPool() {
 190         fGrammarPool.unlockPool();
 191     } // unlockGrammarPool()
 192 
 193     /**
 194      * Parse a grammar from a location identified by an URI.
 195      * This method also adds this grammar to the XMLGrammarPool
 196      *
 197      * @param type The type of the grammar to be constructed
 198      * @param uri The location of the grammar to be constructed.
 199      * <strong>The parser will not expand this URI or make it
 200      * available to the EntityResolver</strong>
 201      * @return The newly created <code>Grammar</code>.
 202      * @exception XNIException thrown on an error in grammar
 203      * construction
 204      * @exception IOException thrown if an error is encountered
 205      * in reading the file
 206      */
 207     public Grammar parseGrammar(String type, String uri)
 208                               throws XNIException, IOException {
 209         XMLInputSource source = new XMLInputSource(null, uri, null);
 210         return parseGrammar(type, source);
 211 
 212     }
 213 
 214     /**
 215      * Parse a grammar from a location identified by an
 216      * XMLInputSource.
 217      * This method also adds this grammar to the XMLGrammarPool
 218      *
 219      * @param type The type of the grammar to be constructed
 220      * @param is The XMLInputSource containing this grammar's
 221      * information
 222      * <strong>If a URI is included in the systemId field, the parser will not expand this URI or make it
 223      * available to the EntityResolver</strong>
 224      * @return The newly created <code>Grammar</code>.
 225      * @exception XNIException thrown on an error in grammar
 226      * construction
 227      * @exception IOException thrown if an error is encountered
 228      * in reading the file
 229      */
 230     public Grammar parseGrammar(String type, XMLInputSource
 231                 is) throws XNIException, IOException {
 232         if(type.equals(XMLGrammarDescription.XML_SCHEMA)) {
 233             // by default, make all XMLGrammarPoolImpl's schema grammars available to fSchemaHandler
 234             return parseXMLSchema(is);
 235         } else if(type.equals(XMLGrammarDescription.XML_DTD)) {
 236             return parseDTD(is);
 237         }
 238         // don't know this grammar...
 239         return null;
 240     } // parseGrammar(String, XMLInputSource):  Grammar
 241 
 242     //
 243     // Protected methods
 244     //
 245 
 246     // package-protected methods
 247 
 248     /* This method parses an XML Schema document.
 249      * It requires a GrammarBucket parameter so that DOMASBuilder can
 250      * extract the info it needs.
 251      * Therefore, bucket must not be null!
 252      */
 253     SchemaGrammar parseXMLSchema(XMLInputSource is)
 254                 throws IOException {
 255         XMLEntityResolver resolver = getEntityResolver();
 256         if(resolver != null) {
 257             fSchemaLoader.setEntityResolver(resolver);
 258         }
 259         if (fErrorReporter.getMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN) == null) {
 260             fErrorReporter.putMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN, new XSMessageFormatter());
 261         }
 262         fSchemaLoader.setProperty(ERROR_REPORTER, fErrorReporter);
 263 
 264         String propPrefix = Constants.XERCES_PROPERTY_PREFIX;
 265         String propName = propPrefix + Constants.SCHEMA_LOCATION;
 266         fSchemaLoader.setProperty(propName, getProperty(propName));
 267         propName = propPrefix + Constants.SCHEMA_NONS_LOCATION;
 268         fSchemaLoader.setProperty(propName, getProperty(propName));
 269         propName = Constants.JAXP_PROPERTY_PREFIX+Constants.SCHEMA_SOURCE;
 270         fSchemaLoader.setProperty(propName, getProperty(propName));
 271         fSchemaLoader.setFeature(SCHEMA_FULL_CHECKING, getFeature(SCHEMA_FULL_CHECKING));
 272 
 273         // Should check whether the grammar with this namespace is already in
 274         // the grammar resolver. But since we don't know the target namespace
 275         // of the document here, we leave such check to XSDHandler
 276         SchemaGrammar grammar = (SchemaGrammar)fSchemaLoader.loadGrammar(is);
 277         // by default, hand it off to the grammar pool
 278         if (grammar != null) {
 279             fGrammarPool.cacheGrammars(XMLGrammarDescription.XML_SCHEMA,
 280                                       new Grammar[]{grammar});
 281         }
 282 
 283         return grammar;
 284 
 285     } // parseXMLSchema(XMLInputSource) :  SchemaGrammar
 286 
 287     /* This method parses an external DTD entity.
 288      */
 289     DTDGrammar parseDTD(XMLInputSource is)
 290                 throws IOException {
 291         XMLEntityResolver resolver = getEntityResolver();
 292         if(resolver != null) {
 293             fDTDLoader.setEntityResolver(resolver);
 294         }
 295         fDTDLoader.setProperty(ERROR_REPORTER, fErrorReporter);
 296 
 297         // Should check whether the grammar with this namespace is already in
 298         // the grammar resolver. But since we don't know the target namespace
 299         // of the document here, we leave such check to the application...
 300         DTDGrammar grammar = (DTDGrammar)fDTDLoader.loadGrammar(is);
 301         // by default, hand it off to the grammar pool
 302         if (grammar != null) {
 303             fGrammarPool.cacheGrammars(XMLGrammarDescription.XML_DTD,
 304                                       new Grammar[]{grammar});
 305         }
 306 
 307         return grammar;
 308 
 309     } // parseXMLDTD(XMLInputSource) :  DTDGrammar
 310 
 311 
 312 } // class XMLGrammarCachingConfiguration