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