1 /*
   2  * Copyright (c) 2013, 2016, 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 package com.sun.org.apache.xerces.internal.jaxp.validation;
  21 
  22 import com.sun.org.apache.xerces.internal.impl.Constants;
  23 import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
  24 import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
  25 import com.sun.org.apache.xerces.internal.parsers.XML11Configuration;
  26 import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
  27 import com.sun.org.apache.xerces.internal.xni.XNIException;
  28 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
  29 import com.sun.org.apache.xerces.internal.xni.parser.XMLParseException;
  30 import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration;
  31 import java.io.IOException;
  32 import java.lang.ref.SoftReference;
  33 import javax.xml.XMLConstants;
  34 import javax.xml.catalog.CatalogFeatures;
  35 import javax.xml.transform.Result;
  36 import javax.xml.transform.Source;
  37 import javax.xml.transform.TransformerConfigurationException;
  38 import javax.xml.transform.TransformerFactory;
  39 import javax.xml.transform.TransformerFactoryConfigurationError;
  40 import javax.xml.transform.sax.SAXTransformerFactory;
  41 import javax.xml.transform.sax.TransformerHandler;
  42 import javax.xml.transform.stream.StreamResult;
  43 import javax.xml.transform.stream.StreamSource;
  44 import jdk.xml.internal.JdkXmlFeatures;
  45 import jdk.xml.internal.JdkXmlUtils;
  46 import org.xml.sax.SAXException;
  47 
  48 /**
  49  * <p>
  50  * A validator helper for <code>StreamSource</code>s.</p>
  51  *
  52  * @author Michael Glavassevich, IBM
  53  * @author <a href="mailto:Sunitha.Reddy@Sun.com">Sunitha Reddy</a>
  54  */
  55 final class StreamValidatorHelper implements ValidatorHelper {
  56 
  57     // feature identifiers
  58     /**
  59      * Feature identifier: parser settings.
  60      */
  61     private static final String PARSER_SETTINGS
  62             = Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS;
  63 
  64     // property identifiers
  65     /**
  66      * Property identifier: entity resolver.
  67      */
  68     private static final String ENTITY_RESOLVER
  69             = Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
  70 
  71     /**
  72      * Property identifier: error handler.
  73      */
  74     private static final String ERROR_HANDLER
  75             = Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
  76 
  77     /**
  78      * Property identifier: error reporter.
  79      */
  80     private static final String ERROR_REPORTER
  81             = Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
  82 
  83     /**
  84      * Property identifier: XML Schema validator.
  85      */
  86     private static final String SCHEMA_VALIDATOR
  87             = Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_VALIDATOR_PROPERTY;
  88 
  89     /**
  90      * Property identifier: symbol table.
  91      */
  92     private static final String SYMBOL_TABLE
  93             = Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
  94 
  95     /**
  96      * Property identifier: validation manager.
  97      */
  98     private static final String VALIDATION_MANAGER
  99             = Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
 100 
 101     private static final String DEFAULT_TRANSFORMER_IMPL
 102             = "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl";
 103 
 104     /**
 105      * Property id: security manager.
 106      */
 107     private static final String SECURITY_MANAGER
 108             = Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY;
 109 
 110     //
 111     // Data
 112     //
 113     /**
 114      * SoftReference to parser configuration. *
 115      */
 116     private SoftReference<XMLParserConfiguration> fConfiguration = new SoftReference<>(null);
 117 
 118     /**
 119      * Schema validator. *
 120      */
 121     private com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator fSchemaValidator;
 122 
 123     /**
 124      * Component manager. *
 125      */
 126     private XMLSchemaValidatorComponentManager fComponentManager;
 127 
 128     private ValidatorHandlerImpl handler = null;
 129 
 130     public StreamValidatorHelper(XMLSchemaValidatorComponentManager componentManager) {
 131         fComponentManager = componentManager;
 132         fSchemaValidator = (com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator)
 133                 fComponentManager.getProperty(SCHEMA_VALIDATOR);
 134     }
 135 
 136     public void validate(Source source, Result result)
 137             throws SAXException, IOException {
 138         if (result == null || result instanceof StreamResult) {
 139             final StreamSource streamSource = (StreamSource) source;
 140             TransformerHandler identityTransformerHandler;
 141 
 142             if (result != null) {
 143                 try {
 144                     SAXTransformerFactory tf = fComponentManager.getFeature(
 145                             Constants.ORACLE_FEATURE_SERVICE_MECHANISM) ?
 146                             (SAXTransformerFactory) SAXTransformerFactory.newInstance() :
 147                             (SAXTransformerFactory) TransformerFactory.newInstance(
 148                                     DEFAULT_TRANSFORMER_IMPL,
 149                                     StreamValidatorHelper.class.getClassLoader());
 150                     identityTransformerHandler = tf.newTransformerHandler();
 151                 } catch (TransformerConfigurationException e) {
 152                     throw new TransformerFactoryConfigurationError(e);
 153                 }
 154 
 155                 handler = new ValidatorHandlerImpl(fComponentManager);
 156                 handler.setContentHandler(identityTransformerHandler);
 157                 identityTransformerHandler.setResult(result);
 158             }
 159 
 160             XMLInputSource input = new XMLInputSource(streamSource.getPublicId(),
 161                     streamSource.getSystemId(), null, false);
 162             input.setByteStream(streamSource.getInputStream());
 163             input.setCharacterStream(streamSource.getReader());
 164 
 165             // Gets the parser configuration. We'll create and initialize a new one, if we
 166             // haven't created one before or if the previous one was garbage collected.
 167             XMLParserConfiguration config = fConfiguration.get();
 168             if (config == null) {
 169                 config = initialize();
 170             }
 171             // If settings have changed on the component manager, refresh the error handler and entity resolver.
 172             else if (fComponentManager.getFeature(PARSER_SETTINGS)) {
 173                 config.setProperty(ENTITY_RESOLVER, fComponentManager.getProperty(ENTITY_RESOLVER));
 174                 config.setProperty(ERROR_HANDLER, fComponentManager.getProperty(ERROR_HANDLER));
 175             }
 176 
 177             // prepare for parse
 178             fComponentManager.reset();
 179             fSchemaValidator.setDocumentHandler(handler);
 180 
 181             try {
 182                 config.parse(input);
 183             } catch (XMLParseException e) {
 184                 throw Util.toSAXParseException(e);
 185             } catch (XNIException e) {
 186                 throw Util.toSAXException(e);
 187             }
 188             return;
 189         }
 190         throw new IllegalArgumentException(JAXPValidationMessageFormatter.formatMessage(
 191                 fComponentManager.getLocale(),
 192                 "SourceResultMismatch",
 193                 new Object[]{source.getClass().getName(), result.getClass().getName()}));
 194     }
 195 
 196     private XMLParserConfiguration initialize() {
 197         XML11Configuration config = new XML11Configuration();
 198         if (fComponentManager.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)) {
 199             config.setProperty(SECURITY_MANAGER, new XMLSecurityManager());
 200         }
 201         config.setProperty(ENTITY_RESOLVER, fComponentManager.getProperty(ENTITY_RESOLVER));
 202         config.setProperty(ERROR_HANDLER, fComponentManager.getProperty(ERROR_HANDLER));
 203         XMLErrorReporter errorReporter = (XMLErrorReporter) fComponentManager.getProperty(ERROR_REPORTER);
 204         config.setProperty(ERROR_REPORTER, errorReporter);
 205         // add message formatters
 206         if (errorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) {
 207             XMLMessageFormatter xmft = new XMLMessageFormatter();
 208             errorReporter.putMessageFormatter(XMLMessageFormatter.XML_DOMAIN, xmft);
 209             errorReporter.putMessageFormatter(XMLMessageFormatter.XMLNS_DOMAIN, xmft);
 210         }
 211         config.setProperty(SYMBOL_TABLE, fComponentManager.getProperty(SYMBOL_TABLE));
 212         config.setProperty(VALIDATION_MANAGER, fComponentManager.getProperty(VALIDATION_MANAGER));
 213         config.setDocumentHandler(fSchemaValidator);
 214         config.setDTDHandler(null);
 215         config.setDTDContentModelHandler(null);
 216         config.setProperty(Constants.XML_SECURITY_PROPERTY_MANAGER,
 217                 fComponentManager.getProperty(Constants.XML_SECURITY_PROPERTY_MANAGER));
 218         config.setProperty(Constants.SECURITY_MANAGER,
 219                 fComponentManager.getProperty(Constants.SECURITY_MANAGER));
 220 
 221         // Passing on the CatalogFeatures settings
 222         JdkXmlUtils.catalogFeaturesConfig2Config(fComponentManager, config);
 223 
 224         config.setProperty(JdkXmlUtils.CDATA_CHUNK_SIZE,
 225                 fComponentManager.getProperty(JdkXmlUtils.CDATA_CHUNK_SIZE));
 226 
 227         fConfiguration = new SoftReference<>(config);
 228         return config;
 229     }
 230 
 231 } // StreamValidatorHelper