You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@daffodil.apache.org by sl...@apache.org on 2018/05/08 12:32:28 UTC

[incubator-daffodil] branch master updated: Explicitly use the Xerces factories that use our custom catalog resolver

This is an automated email from the ASF dual-hosted git repository.

slawrence pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-daffodil.git


The following commit(s) were added to refs/heads/master by this push:
     new e79a43c  Explicitly use the Xerces factories that use our custom catalog resolver
e79a43c is described below

commit e79a43c8ce8a19992811605cf1b4f47042e071d5
Author: Steve Lawrence <sl...@apache.org>
AuthorDate: Fri Apr 13 09:30:30 2018 -0400

    Explicitly use the Xerces factories that use our custom catalog resolver
    
    The DFDLCatalogResolver is a custom resolver that extends the Xerces
    EntityResolver. This means that the SAXParserFactory's and
    SchemaFactory's that use this resolver must also be the Xerces versions
    since only they know how to use the Xerces EntityResolver correctly.
    
    The newInstance(...) method provides a parameter to state explicitly
    which SchemaFactory/SAXParserFactory instance to create so that we can
    ensure the Xerces versions are used. However, this appears to use a
    different ClassLoader than normal. This has become apparent in cases
    where the Daffodil dependencies (included Xerces) are in a "fat jar", in
    which case newInstance() fails to find the Xerces classes with a
    ClassNotFoundException, presumably because it uses a ClassLoader that
    does not understand to look in the fat jar.
    
    So, instead of using newInstance() and worrying about ClassLoaders, this
    changes all SchemaFactory and SAXParserFactory instances to directly
    instantiate the Xerces version, which will load the classes just like
    every other class instantiation.
    
    The downside with this approach is that one cannot swap out to a
    different SchemaFactory/SAXParserFactory, but that was not possible
    anyways due to our custom EntityResolver that depends on the Xerces
    version, so this isn't really a new limitation.
    
    DFDL-1924
---
 .../apache/daffodil/parsing/TestCLIParsing.scala   | 26 ++++++++++++++++++++++
 .../ExternalVariablesXMLValidator.scala            |  4 +---
 .../scala/org/apache/daffodil/util/Validator.scala |  5 +----
 .../apache/daffodil/xml/DaffodilXMLLoader.scala    |  9 ++------
 4 files changed, 30 insertions(+), 14 deletions(-)

diff --git a/daffodil-cli/src/it/scala/org/apache/daffodil/parsing/TestCLIParsing.scala b/daffodil-cli/src/it/scala/org/apache/daffodil/parsing/TestCLIParsing.scala
index 1b91b78..7281d46 100644
--- a/daffodil-cli/src/it/scala/org/apache/daffodil/parsing/TestCLIParsing.scala
+++ b/daffodil-cli/src/it/scala/org/apache/daffodil/parsing/TestCLIParsing.scala
@@ -929,5 +929,31 @@ class TestCLIparsing {
     }
   }
 
+  // These DAFFODIL_JAVA_OPTS values change the Java defaults classes like
+  // SAXParserFactory and SchemaFactory to be Java's internal classes instead
+  // of those provided by dependencies (e.g. Xerces) included with Daffodil.
+  // Some places require dependency version of these classes. This test ensures
+  // that we override defaults when necesssary
+  @Test def test_CLI_Parsing_JavaDefaults() {
+    val schemaFile = Util.daffodilPath("daffodil-test/src/test/resources/org/apache/daffodil/section06/entities/charClassEntities.dfdl.xsd")
+    val testSchemaFile = if (Util.isWindows) Util.cmdConvert(schemaFile) else schemaFile
+    val java_opts = Map("DAFFODIL_JAVA_OPTS" ->
+                          ("-Djavax.xml.parsers.SAXParserFactory=com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl " +
+                           "-Djavax.xml.xml.validation.SchemaFactory=com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory"))
+
+    val shell = Util.start("", envp = java_opts)
+
+    try {
+      val cmd = String.format("echo 0,1,2| %s parse -s %s -r matrix", Util.binPath, testSchemaFile)
+      shell.sendLine(cmd)
+
+      shell.expect(contains(output1))
+      shell.sendLine("exit")
+      shell.expect(eof)
+    } finally {
+      shell.close()
+    }
+  }
+
 
 }
diff --git a/daffodil-lib/src/main/scala/org/apache/daffodil/externalvars/ExternalVariablesXMLValidator.scala b/daffodil-lib/src/main/scala/org/apache/daffodil/externalvars/ExternalVariablesXMLValidator.scala
index 95e9ee2..acc0d75 100644
--- a/daffodil-lib/src/main/scala/org/apache/daffodil/externalvars/ExternalVariablesXMLValidator.scala
+++ b/daffodil-lib/src/main/scala/org/apache/daffodil/externalvars/ExternalVariablesXMLValidator.scala
@@ -18,7 +18,6 @@
 package org.apache.daffodil.externalvars
 
 import javax.xml.transform.stream.StreamSource
-import javax.xml.validation.SchemaFactory
 import org.xml.sax.SAXException
 import java.io.File
 
@@ -31,8 +30,7 @@ object ExternalVariablesValidator {
 
   def validate(xmlFile: File): Either[java.lang.Throwable, _] = {
     try {
-      val schemaLang = "http://www.w3.org/2001/XMLSchema"
-      val factory = SchemaFactory.newInstance(schemaLang)
+      val factory = new org.apache.xerces.jaxp.validation.XMLSchemaFactory()
       val schema = factory.newSchema(new StreamSource(extVarXsd))
       val validator = schema.newValidator()
       validator.validate(new StreamSource(xmlFile))
diff --git a/daffodil-lib/src/main/scala/org/apache/daffodil/util/Validator.scala b/daffodil-lib/src/main/scala/org/apache/daffodil/util/Validator.scala
index 1d22190..9063ff2 100644
--- a/daffodil-lib/src/main/scala/org/apache/daffodil/util/Validator.scala
+++ b/daffodil-lib/src/main/scala/org/apache/daffodil/util/Validator.scala
@@ -19,7 +19,6 @@ package org.apache.daffodil.util
 
 import javax.xml.transform.stream.StreamSource
 import javax.xml.XMLConstants
-import javax.xml.validation.SchemaFactory
 import scala.xml.parsing.NoBindingFactoryAdapter
 import java.io.StringReader
 import java.net.URI
@@ -62,9 +61,7 @@ object Validator extends NoBindingFactoryAdapter {
             }
           }
 
-          val schemaLang = "http://www.w3.org/2001/XMLSchema"
-          val factory = SchemaFactory.newInstance(schemaLang)
-          //          val hdlr = new ContentHandler()
+          val factory = new org.apache.xerces.jaxp.validation.XMLSchemaFactory()
           factory.setErrorHandler(errHandler)
           val resolver = DFDLCatalogResolver.get
           factory.setResourceResolver(resolver)
diff --git a/daffodil-lib/src/main/scala/org/apache/daffodil/xml/DaffodilXMLLoader.scala b/daffodil-lib/src/main/scala/org/apache/daffodil/xml/DaffodilXMLLoader.scala
index b8d703f..941b530 100644
--- a/daffodil-lib/src/main/scala/org/apache/daffodil/xml/DaffodilXMLLoader.scala
+++ b/daffodil-lib/src/main/scala/org/apache/daffodil/xml/DaffodilXMLLoader.scala
@@ -43,8 +43,6 @@ import org.apache.daffodil.util.Logging
 import org.apache.daffodil.util.Misc
 import org.apache.daffodil.api.DaffodilSchemaSource
 import javax.xml.XMLConstants
-import javax.xml.parsers.SAXParserFactory
-import javax.xml.validation.SchemaFactory
 import java.io.InputStream
 import java.io.BufferedInputStream
 import java.io.Reader
@@ -376,10 +374,7 @@ trait SchemaAwareLoaderMixin {
   def resolver = DFDLCatalogResolver.get
 
   override lazy val parser: SAXParser = {
-
-    // val x = new com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl
-
-    val f = SAXParserFactory.newInstance()
+    val f = new org.apache.xerces.jaxp.SAXParserFactoryImpl()
     f.setNamespaceAware(true)
     f.setFeature("http://xml.org/sax/features/namespace-prefixes", true)
 
@@ -427,7 +422,7 @@ trait SchemaAwareLoaderMixin {
    * using the below SchemaFactory and SchemaFactory.newSchema calls.  The
    * newSchema call is what forces schema validation to take place.
    */
-  protected val sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI)
+  protected val sf = new org.apache.xerces.jaxp.validation.XMLSchemaFactory()
   sf.setResourceResolver(resolver)
   sf.setErrorHandler(errorHandler)
 

-- 
To stop receiving notification emails like this one, please contact
slawrence@apache.org.