/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.xerces.parsers;

import java.io.File;
import java.io.FileInputStream;
import java.io.FilterInputStream;
import java.io.FilterReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.net.URL;
import java.util.Properties;

import org.apache.xerces.impl.Constants;
import org.apache.xerces.impl.XMLEntityDescription;
import org.apache.xerces.impl.XMLErrorReporter;
import org.apache.xerces.impl.dtd.XMLDTDProcessor;
import org.apache.xerces.impl.msg.XMLMessageFormatter;
import org.apache.xerces.util.SecurityManager;
import org.apache.xerces.util.SymbolTable;
import org.apache.xerces.xni.Augmentations;
import org.apache.xerces.xni.XMLDTDHandler;
import org.apache.xerces.xni.XMLLocator;
import org.apache.xerces.xni.XMLResourceIdentifier;
import org.apache.xerces.xni.XMLString;
import org.apache.xerces.xni.XNIException;
import org.apache.xerces.xni.grammars.XMLGrammarPool;
import org.apache.xerces.xni.parser.XMLComponentManager;
import org.apache.xerces.xni.parser.XMLConfigurationException;
import org.apache.xerces.xni.parser.XMLDTDFilter;
import org.apache.xerces.xni.parser.XMLDTDScanner;
import org.apache.xerces.xni.parser.XMLDTDSource;
import org.apache.xerces.xni.parser.XMLEntityResolver;
import org.apache.xerces.xni.parser.XMLInputSource;

This configuration enhances Xerces support for the JAXP secure processing feature.
Author:Michael Glavassevich, IBM
Version:$Id: SecureProcessingConfiguration.java 1718451 2015-12-07 20:17:23Z mrglavas $
/** * This configuration enhances Xerces support for the JAXP secure processing feature. * * @author Michael Glavassevich, IBM * * @version $Id: SecureProcessingConfiguration.java 1718451 2015-12-07 20:17:23Z mrglavas $ */
public final class SecureProcessingConfiguration extends XIncludeAwareParserConfiguration { // // Constants //
Property identifier: security manager.
/** Property identifier: security manager. */
private static final String SECURITY_MANAGER_PROPERTY = Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY;
Property identifier: entity resolver.
/** Property identifier: entity resolver. */
private static final String ENTITY_RESOLVER_PROPERTY = Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
Feature identifier: external general entities.
/** Feature identifier: external general entities. */
private static final String EXTERNAL_GENERAL_ENTITIES = Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_GENERAL_ENTITIES_FEATURE;
Feature identifier: external parameter entities.
/** Feature identifier: external parameter entities. */
private static final String EXTERNAL_PARAMETER_ENTITIES = Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE;
Feature identifier: load external DTD.
/** Feature identifier: load external DTD. */
private static final String LOAD_EXTERNAL_DTD = Constants.XERCES_FEATURE_PREFIX + Constants.LOAD_EXTERNAL_DTD_FEATURE;
Set to true for debugging
/** Set to true for debugging */
private static final boolean DEBUG = isDebugEnabled();
Cache the contents of the jaxp.properties file, if used.
/** Cache the contents of the jaxp.properties file, if used. */
private static Properties jaxpProperties = null;
Cache the timestamp of the jaxp.properties file, if used.
/** Cache the timestamp of the jaxp.properties file, if used. */
private static long lastModified = -1;
Xerces SecurityManager default value for entity expansion limit.
/** Xerces SecurityManager default value for entity expansion limit. **/
private static final int SECURITY_MANAGER_DEFAULT_ENTITY_EXPANSION_LIMIT = 100000;
Xerces SecurityManager default value of number of nodes created.
/** Xerces SecurityManager default value of number of nodes created. **/
private static final int SECURITY_MANAGER_DEFAULT_MAX_OCCUR_NODE_LIMIT = 3000; private static final String ENTITY_EXPANSION_LIMIT_PROPERTY_NAME = "jdk.xml.entityExpansionLimit"; private static final String MAX_OCCUR_LIMIT_PROPERTY_NAME = "jdk.xml.maxOccur"; private static final String TOTAL_ENTITY_SIZE_LIMIT_PROPERTY_NAME = "jdk.xml.totalEntitySizeLimit"; private static final String MAX_GENERAL_ENTITY_SIZE_LIMIT_PROPERTY_NAME = "jdk.xml.maxGeneralEntitySizeLimit"; private static final String MAX_PARAMETER_ENTITY_SIZE_LIMIT_PROPERTY_NAME = "jdk.xml.maxParameterEntitySizeLimit"; private static final String RESOLVE_EXTERNAL_ENTITIES_PROPERTY_NAME = "jdk.xml.resolveExternalEntities"; private static final int ENTITY_EXPANSION_LIMIT_DEFAULT_VALUE = 64000; private static final int MAX_OCCUR_LIMIT_DEFAULT_VALUE = 5000; private static final int TOTAL_ENTITY_SIZE_LIMIT_DEFAULT_VALUE = 50000000; private static final int MAX_GENERAL_ENTITY_SIZE_LIMIT_DEFAULT_VALUE = Integer.MAX_VALUE; private static final int MAX_PARAMETER_ENTITY_SIZE_LIMIT_DEFAULT_VALUE = Integer.MAX_VALUE; private static final boolean RESOLVE_EXTERNAL_ENTITIES_DEFAULT_VALUE = true; protected final int ENTITY_EXPANSION_LIMIT_SYSTEM_VALUE; protected final int MAX_OCCUR_LIMIT_SYSTEM_VALUE; protected final int TOTAL_ENTITY_SIZE_LIMIT_SYSTEM_VALUE; protected final int MAX_GENERAL_ENTITY_SIZE_LIMIT_SYSTEM_VALUE; protected final int MAX_PARAMETER_ENTITY_SIZE_LIMIT_SYSTEM_VALUE; protected final boolean RESOLVE_EXTERNAL_ENTITIES_SYSTEM_VALUE; // // Fields // private final boolean fJavaSecurityManagerEnabled; private boolean fLimitSpecified; private SecurityManager fSecurityManager; private InternalEntityMonitor fInternalEntityMonitor; private final ExternalEntityMonitor fExternalEntityMonitor; private int fTotalEntitySize = 0;
Default constructor.
/** Default constructor. */
public SecureProcessingConfiguration() { this(null, null, null); } // <init>()
Constructs a parser configuration using the specified symbol table.
Params:
  • symbolTable – The symbol table to use.
/** * Constructs a parser configuration using the specified symbol table. * * @param symbolTable The symbol table to use. */
public SecureProcessingConfiguration(SymbolTable symbolTable) { this(symbolTable, null, null); } // <init>(SymbolTable)
Constructs a parser configuration using the specified symbol table and grammar pool.

Params:
  • symbolTable – The symbol table to use.
  • grammarPool – The grammar pool to use.
/** * Constructs a parser configuration using the specified symbol table and * grammar pool. * <p> * * @param symbolTable The symbol table to use. * @param grammarPool The grammar pool to use. */
public SecureProcessingConfiguration( SymbolTable symbolTable, XMLGrammarPool grammarPool) { this(symbolTable, grammarPool, null); } // <init>(SymbolTable,XMLGrammarPool)
Constructs a parser configuration using the specified symbol table, grammar pool, and parent settings.

Params:
  • symbolTable – The symbol table to use.
  • grammarPool – The grammar pool to use.
  • parentSettings – The parent settings.
/** * Constructs a parser configuration using the specified symbol table, * grammar pool, and parent settings. * <p> * * @param symbolTable The symbol table to use. * @param grammarPool The grammar pool to use. * @param parentSettings The parent settings. */
public SecureProcessingConfiguration( SymbolTable symbolTable, XMLGrammarPool grammarPool, XMLComponentManager parentSettings) { super(symbolTable, grammarPool, parentSettings); fJavaSecurityManagerEnabled = (System.getSecurityManager() != null); ENTITY_EXPANSION_LIMIT_SYSTEM_VALUE = getPropertyValue(ENTITY_EXPANSION_LIMIT_PROPERTY_NAME, ENTITY_EXPANSION_LIMIT_DEFAULT_VALUE); MAX_OCCUR_LIMIT_SYSTEM_VALUE = getPropertyValue(MAX_OCCUR_LIMIT_PROPERTY_NAME, MAX_OCCUR_LIMIT_DEFAULT_VALUE); TOTAL_ENTITY_SIZE_LIMIT_SYSTEM_VALUE = getPropertyValue(TOTAL_ENTITY_SIZE_LIMIT_PROPERTY_NAME, TOTAL_ENTITY_SIZE_LIMIT_DEFAULT_VALUE); MAX_GENERAL_ENTITY_SIZE_LIMIT_SYSTEM_VALUE = getPropertyValue(MAX_GENERAL_ENTITY_SIZE_LIMIT_PROPERTY_NAME, MAX_GENERAL_ENTITY_SIZE_LIMIT_DEFAULT_VALUE); MAX_PARAMETER_ENTITY_SIZE_LIMIT_SYSTEM_VALUE = getPropertyValue(MAX_PARAMETER_ENTITY_SIZE_LIMIT_PROPERTY_NAME, MAX_PARAMETER_ENTITY_SIZE_LIMIT_DEFAULT_VALUE); RESOLVE_EXTERNAL_ENTITIES_SYSTEM_VALUE = getPropertyValue(RESOLVE_EXTERNAL_ENTITIES_PROPERTY_NAME, RESOLVE_EXTERNAL_ENTITIES_DEFAULT_VALUE); if (fJavaSecurityManagerEnabled || fLimitSpecified) { if (!RESOLVE_EXTERNAL_ENTITIES_SYSTEM_VALUE) { super.setFeature(EXTERNAL_GENERAL_ENTITIES, false); super.setFeature(EXTERNAL_PARAMETER_ENTITIES, false); super.setFeature(LOAD_EXTERNAL_DTD, false); } fSecurityManager = new org.apache.xerces.util.SecurityManager(); fSecurityManager.setEntityExpansionLimit(ENTITY_EXPANSION_LIMIT_SYSTEM_VALUE); fSecurityManager.setMaxOccurNodeLimit(MAX_OCCUR_LIMIT_SYSTEM_VALUE); super.setProperty(SECURITY_MANAGER_PROPERTY, fSecurityManager); } fExternalEntityMonitor = new ExternalEntityMonitor(); super.setProperty(ENTITY_RESOLVER_PROPERTY, fExternalEntityMonitor); } protected void checkEntitySizeLimits(int sizeOfEntity, int delta, boolean isPE) { fTotalEntitySize += delta; if (fTotalEntitySize > TOTAL_ENTITY_SIZE_LIMIT_SYSTEM_VALUE) { fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, "TotalEntitySizeLimitExceeded", new Object[] {new Integer(TOTAL_ENTITY_SIZE_LIMIT_SYSTEM_VALUE)}, XMLErrorReporter.SEVERITY_FATAL_ERROR); } if (isPE) { if (sizeOfEntity > MAX_PARAMETER_ENTITY_SIZE_LIMIT_SYSTEM_VALUE) { fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, "MaxParameterEntitySizeLimitExceeded", new Object[] {new Integer(MAX_PARAMETER_ENTITY_SIZE_LIMIT_SYSTEM_VALUE)}, XMLErrorReporter.SEVERITY_FATAL_ERROR); } } else if (sizeOfEntity > MAX_GENERAL_ENTITY_SIZE_LIMIT_SYSTEM_VALUE) { fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, "MaxGeneralEntitySizeLimitExceeded", new Object[] {new Integer(MAX_GENERAL_ENTITY_SIZE_LIMIT_SYSTEM_VALUE)}, XMLErrorReporter.SEVERITY_FATAL_ERROR); } }
Returns the value of a property.
Params:
  • propertyId – The property identifier.
Throws:
  • XMLConfigurationException – Thrown for configuration error. In general, components should only throw this exception if it is really a critical error.
Returns:the value of the property
/** * Returns the value of a property. * * @param propertyId The property identifier. * @return the value of the property * * @throws XMLConfigurationException Thrown for configuration error. * In general, components should * only throw this exception if * it is <strong>really</strong> * a critical error. */
public Object getProperty(String propertyId) throws XMLConfigurationException { if (SECURITY_MANAGER_PROPERTY.equals(propertyId)) { return fSecurityManager; } else if (ENTITY_RESOLVER_PROPERTY.equals(propertyId)) { return fExternalEntityMonitor; } return super.getProperty(propertyId); }
setProperty
Params:
  • propertyId –
  • value –
/** * setProperty * * @param propertyId * @param value */
public void setProperty(String propertyId, Object value) throws XMLConfigurationException { if (SECURITY_MANAGER_PROPERTY.equals(propertyId)) { // Do not allow the Xerces SecurityManager to be // removed if the Java SecurityManager has been installed. if (value == null && fJavaSecurityManagerEnabled) { return; } fSecurityManager = (SecurityManager) value; if (fSecurityManager != null) { // Override SecurityManager default values with the system property / jaxp.properties / config default determined values. if (fSecurityManager.getEntityExpansionLimit() == SECURITY_MANAGER_DEFAULT_ENTITY_EXPANSION_LIMIT) { fSecurityManager.setEntityExpansionLimit(ENTITY_EXPANSION_LIMIT_SYSTEM_VALUE); } if (fSecurityManager.getMaxOccurNodeLimit() == SECURITY_MANAGER_DEFAULT_MAX_OCCUR_NODE_LIMIT) { fSecurityManager.setMaxOccurNodeLimit(MAX_OCCUR_LIMIT_SYSTEM_VALUE); } } } else if (ENTITY_RESOLVER_PROPERTY.equals(propertyId)) { fExternalEntityMonitor.setEntityResolver((XMLEntityResolver) value); return; } super.setProperty(propertyId, value); }
Configures the XML 1.0 pipeline.
/** Configures the XML 1.0 pipeline. */
protected void configurePipeline() { super.configurePipeline(); configurePipelineCommon(true); }
Configures the XML 1.1 pipeline.
/** Configures the XML 1.1 pipeline. */
protected void configureXML11Pipeline() { super.configureXML11Pipeline(); configurePipelineCommon(false); } private void configurePipelineCommon(boolean isXML10) { if (fSecurityManager != null) { fTotalEntitySize = 0; if (fInternalEntityMonitor == null) { fInternalEntityMonitor = new InternalEntityMonitor(); } // Reconfigure DTD pipeline. Insert internal entity decl monitor. final XMLDTDScanner dtdScanner; final XMLDTDProcessor dtdProcessor; if (isXML10) { dtdScanner = fDTDScanner; dtdProcessor = fDTDProcessor; } else { dtdScanner = fXML11DTDScanner; dtdProcessor = fXML11DTDProcessor; } dtdScanner.setDTDHandler(fInternalEntityMonitor); fInternalEntityMonitor.setDTDSource(dtdScanner); fInternalEntityMonitor.setDTDHandler(dtdProcessor); dtdProcessor.setDTDSource(fInternalEntityMonitor); } } private int getPropertyValue(String propertyName, int defaultValue) { // Step #1: Use the system property first try { String propertyValue = SecuritySupport.getSystemProperty(propertyName); if (propertyValue != null && propertyValue.length() > 0) { if (DEBUG) { debugPrintln("found system property \"" + propertyName + "\", value=" + propertyValue); } final int intValue = Integer.parseInt(propertyValue); fLimitSpecified = true; if (intValue > 0) { return intValue; } // Treat 0 and negative numbers as no limit (i.e. max integer). return Integer.MAX_VALUE; } } // The VM ran out of memory or there was some other serious problem. Re-throw. catch (VirtualMachineError vme) { throw vme; } // ThreadDeath should always be re-thrown catch (ThreadDeath td) { throw td; } catch (Throwable e) { // Ignore all other exceptions/errors and continue w/ next location if (DEBUG) { debugPrintln(e.getClass().getName() + ": " + e.getMessage()); e.printStackTrace(); } } // Step #2: Use $java.home/lib/jaxp.properties try { boolean fExists = false; File f = null; try { String javah = SecuritySupport.getSystemProperty("java.home"); String configFile = javah + File.separator + "lib" + File.separator + "jaxp.properties"; f = new File(configFile); fExists = SecuritySupport.getFileExists(f); } catch (SecurityException se) { // If there is a security exception, move on to next location. lastModified = -1; jaxpProperties = null; } synchronized (SecureProcessingConfiguration.class) { boolean runBlock = false; FileInputStream fis = null; try { if (lastModified >= 0) { // File has been modified, or didn't previously exist. // Need to reload properties if ((fExists) && (lastModified < (lastModified = SecuritySupport.getLastModified(f)))) { runBlock = true; } else { if (!fExists) { // file existed, but it's been deleted. lastModified = -1; jaxpProperties = null; } } } else { if (fExists) { // File didn't exist, but it does now. runBlock = true; lastModified = SecuritySupport.getLastModified(f); } } if (runBlock == true) { // Try to read from $java.home/lib/jaxp.properties jaxpProperties = new Properties(); fis = SecuritySupport.getFileInputStream(f); jaxpProperties.load(fis); } } catch (Exception x) { lastModified = -1; jaxpProperties = null; // assert(x instanceof FileNotFoundException // || x instanceof SecurityException) // In both cases, ignore and return the default value } finally { // try to close the input stream if one was opened. if (fis != null) { try { fis.close(); } // Ignore the exception. catch (IOException exc) {} } } } if (jaxpProperties != null) { String propertyValue = jaxpProperties.getProperty(propertyName); if (propertyValue != null && propertyValue.length() > 0) { if (DEBUG) { debugPrintln("found \"" + propertyName + "\" in jaxp.properties, value=" + propertyValue); } final int intValue = Integer.parseInt(propertyValue); fLimitSpecified = true; if (intValue > 0) { return intValue; } // Treat 0 and negative numbers as no limit (i.e. max integer). return Integer.MAX_VALUE; } } } // The VM ran out of memory or there was some other serious problem. Re-throw. catch (VirtualMachineError vme) { throw vme; } // ThreadDeath should always be re-thrown catch (ThreadDeath td) { throw td; } catch (Throwable e) { // Ignore all other exceptions/errors and return the default value. if (DEBUG) { debugPrintln(e.getClass().getName() + ": " + e.getMessage()); e.printStackTrace(); } } // Step #3: Return the default value. return defaultValue; } private boolean getPropertyValue(String propertyName, boolean defaultValue) { // Step #1: Use the system property first try { String propertyValue = SecuritySupport.getSystemProperty(propertyName); if (propertyValue != null && propertyValue.length() > 0) { if (DEBUG) { debugPrintln("found system property \"" + propertyName + "\", value=" + propertyValue); } final boolean booleanValue = Boolean.valueOf(propertyValue).booleanValue(); fLimitSpecified = true; return booleanValue; } } // The VM ran out of memory or there was some other serious problem. Re-throw. catch (VirtualMachineError vme) { throw vme; } // ThreadDeath should always be re-thrown catch (ThreadDeath td) { throw td; } catch (Throwable e) { // Ignore all other exceptions/errors and continue w/ next location if (DEBUG) { debugPrintln(e.getClass().getName() + ": " + e.getMessage()); e.printStackTrace(); } } // Step #2: Use $java.home/lib/jaxp.properties try { boolean fExists = false; File f = null; try { String javah = SecuritySupport.getSystemProperty("java.home"); String configFile = javah + File.separator + "lib" + File.separator + "jaxp.properties"; f = new File(configFile); fExists = SecuritySupport.getFileExists(f); } catch (SecurityException se) { // If there is a security exception, move on to next location. lastModified = -1; jaxpProperties = null; } synchronized (SecureProcessingConfiguration.class) { boolean runBlock = false; FileInputStream fis = null; try { if (lastModified >= 0) { // File has been modified, or didn't previously exist. // Need to reload properties if ((fExists) && (lastModified < (lastModified = SecuritySupport.getLastModified(f)))) { runBlock = true; } else { if (!fExists) { // file existed, but it's been deleted. lastModified = -1; jaxpProperties = null; } } } else { if (fExists) { // File didn't exist, but it does now. runBlock = true; lastModified = SecuritySupport.getLastModified(f); } } if (runBlock == true) { // Try to read from $java.home/lib/jaxp.properties jaxpProperties = new Properties(); fis = SecuritySupport.getFileInputStream(f); jaxpProperties.load(fis); } } catch (Exception x) { lastModified = -1; jaxpProperties = null; // assert(x instanceof FileNotFoundException // || x instanceof SecurityException) // In both cases, ignore and return the default value } finally { // try to close the input stream if one was opened. if (fis != null) { try { fis.close(); } // Ignore the exception. catch (IOException exc) {} } } } if (jaxpProperties != null) { String propertyValue = jaxpProperties.getProperty(propertyName); if (propertyValue != null && propertyValue.length() > 0) { if (DEBUG) { debugPrintln("found \"" + propertyName + "\" in jaxp.properties, value=" + propertyValue); } final boolean booleanValue = Boolean.valueOf(propertyValue).booleanValue(); fLimitSpecified = true; return booleanValue; } } } // The VM ran out of memory or there was some other serious problem. Re-throw. catch (VirtualMachineError vme) { throw vme; } // ThreadDeath should always be re-thrown catch (ThreadDeath td) { throw td; } catch (Throwable e) { // Ignore all other exceptions/errors and return the default value. if (DEBUG) { debugPrintln(e.getClass().getName() + ": " + e.getMessage()); e.printStackTrace(); } } // Step #3: Return the default value. return defaultValue; } // // Private static methods //
Returns true if debug has been enabled.
/** Returns true if debug has been enabled. */
private static boolean isDebugEnabled() { try { String val = SecuritySupport.getSystemProperty("xerces.debug"); // Allow simply setting the prop to turn on debug return (val != null && (!"false".equals(val))); } catch (SecurityException se) {} return false; } // isDebugEnabled()
Prints a message to standard error if debugging is enabled.
/** Prints a message to standard error if debugging is enabled. */
private static void debugPrintln(String msg) { if (DEBUG) { System.err.println("XERCES: " + msg); } } // debugPrintln(String)
XMLDTDFilter which checks limits imposed by the application on the sizes of general and parameter entities.
/** * XMLDTDFilter which checks limits imposed by the application * on the sizes of general and parameter entities. */
final class InternalEntityMonitor implements XMLDTDFilter {
DTD source and handler.
/** DTD source and handler. **/
private XMLDTDSource fDTDSource; private XMLDTDHandler fDTDHandler; public InternalEntityMonitor() {} /* * XMLDTDHandler methods */ public void startDTD(XMLLocator locator, Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { fDTDHandler.startDTD(locator, augmentations); } } public void startParameterEntity(String name, XMLResourceIdentifier identifier, String encoding, Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { fDTDHandler.startParameterEntity(name, identifier, encoding, augmentations); } } public void textDecl(String version, String encoding, Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { fDTDHandler.textDecl(version, encoding, augmentations); } } public void endParameterEntity(String name, Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { fDTDHandler.endParameterEntity(name, augmentations); } } public void startExternalSubset(XMLResourceIdentifier identifier, Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { fDTDHandler.startExternalSubset(identifier, augmentations); } } public void endExternalSubset(Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { fDTDHandler.endExternalSubset(augmentations); } } public void comment(XMLString text, Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { fDTDHandler.comment(text, augmentations); } } public void processingInstruction(String target, XMLString data, Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { fDTDHandler.processingInstruction(target, data, augmentations); } } public void elementDecl(String name, String contentModel, Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { fDTDHandler.elementDecl(name, contentModel, augmentations); } } public void startAttlist(String elementName, Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { fDTDHandler.startAttlist(elementName, augmentations); } } public void attributeDecl(String elementName, String attributeName, String type, String[] enumeration, String defaultType, XMLString defaultValue, XMLString nonNormalizedDefaultValue, Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { fDTDHandler.attributeDecl(elementName, attributeName, type, enumeration, defaultType, defaultValue, nonNormalizedDefaultValue, augmentations); } } public void endAttlist(Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { fDTDHandler.endAttlist(augmentations); } } public void internalEntityDecl(String name, XMLString text, XMLString nonNormalizedText, Augmentations augmentations) throws XNIException { checkEntitySizeLimits(text.length, text.length, name != null && name.startsWith("%")); if (fDTDHandler != null) { fDTDHandler.internalEntityDecl(name, text, nonNormalizedText, augmentations); } } public void externalEntityDecl(String name, XMLResourceIdentifier identifier, Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { fDTDHandler.externalEntityDecl(name, identifier, augmentations); } } public void unparsedEntityDecl(String name, XMLResourceIdentifier identifier, String notation, Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { fDTDHandler.unparsedEntityDecl(name, identifier, notation, augmentations); } } public void notationDecl(String name, XMLResourceIdentifier identifier, Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { fDTDHandler.notationDecl(name, identifier, augmentations); } } public void startConditional(short type, Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { fDTDHandler.startConditional(type, augmentations); } } public void ignoredCharacters(XMLString text, Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { fDTDHandler.ignoredCharacters(text, augmentations); } } public void endConditional(Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { fDTDHandler.endConditional(augmentations); } } public void endDTD(Augmentations augmentations) throws XNIException { if (fDTDHandler != null) { fDTDHandler.endDTD(augmentations); } } public void setDTDSource(XMLDTDSource source) { fDTDSource = source; } public XMLDTDSource getDTDSource() { return fDTDSource; } /* * XMLDTDSource methods */ public void setDTDHandler(XMLDTDHandler handler) { fDTDHandler = handler; } public XMLDTDHandler getDTDHandler() { return fDTDHandler; } }
XMLEntityResolver which checks limits imposed by the application on the sizes of general and parameter entities.
/** * XMLEntityResolver which checks limits imposed by the application * on the sizes of general and parameter entities. */
final class ExternalEntityMonitor implements XMLEntityResolver {
java.io.InputStream wrapper which check entity size limits.
/** * java.io.InputStream wrapper which check entity size limits. */
final class InputStreamMonitor extends FilterInputStream { private final boolean isPE; private int size = 0; protected InputStreamMonitor(InputStream in, boolean isPE) { super(in); this.isPE = isPE; } public int read() throws IOException { int i = super.read(); if (i != -1) { ++size; checkEntitySizeLimits(size, 1, isPE); } return i; } public int read(byte[] b, int off, int len) throws IOException { int i = super.read(b, off, len); if (i > 0) { size += i; checkEntitySizeLimits(size, i, isPE); } return i; } }
java.io.Reader wrapper which check entity size limits.
/** * java.io.Reader wrapper which check entity size limits. */
final class ReaderMonitor extends FilterReader { private final boolean isPE; private int size = 0; protected ReaderMonitor(Reader in, boolean isPE) { super(in); this.isPE = isPE; } public int read() throws IOException { int i = super.read(); if (i != -1) { ++size; checkEntitySizeLimits(size, 1, isPE); } return i; } public int read(char[] cbuf, int off, int len) throws IOException { int i = super.read(cbuf, off, len); if (i > 0) { size += i; checkEntitySizeLimits(size, i, isPE); } return i; } } private XMLEntityResolver fEntityResolver; public XMLInputSource resolveEntity(XMLResourceIdentifier resourceIdentifier) throws XNIException, IOException { XMLInputSource source = null; if (fEntityResolver != null) { source = fEntityResolver.resolveEntity(resourceIdentifier); } if (fSecurityManager != null && resourceIdentifier instanceof XMLEntityDescription) { String name = ((XMLEntityDescription) resourceIdentifier).getEntityName(); boolean isPE = name != null && name.startsWith("%"); if (source == null) { String publicId = resourceIdentifier.getPublicId(); String systemId = resourceIdentifier.getExpandedSystemId(); String baseSystemId = resourceIdentifier.getBaseSystemId(); source = new XMLInputSource(publicId, systemId, baseSystemId); } Reader reader = source.getCharacterStream(); if (reader != null) { source.setCharacterStream(new ReaderMonitor(reader, isPE)); } else { InputStream stream = source.getByteStream(); if (stream != null) { source.setByteStream(new InputStreamMonitor(stream, isPE)); } else { String systemId = resourceIdentifier.getExpandedSystemId(); URL url = new URL(systemId); stream = url.openStream(); source.setByteStream(new InputStreamMonitor(stream, isPE)); } } } return source; }
Sets the XNI entity resolver.
/** Sets the XNI entity resolver. */
public void setEntityResolver(XMLEntityResolver entityResolver) { fEntityResolver = entityResolver; } // setEntityResolver(XMLEntityResolver)
Returns the XNI entity resolver.
/** Returns the XNI entity resolver. */
public XMLEntityResolver getEntityResolver() { return fEntityResolver; } // getEntityResolver():XMLEntityResolver } }