Skip to content

Commit

Permalink
Merge pull request rackerlabs#140 from RackerWilliams/s9.7
Browse files Browse the repository at this point in the history
Move to Saxon 9.7.x
  • Loading branch information
Jorge Williams committed Aug 11, 2016
2 parents bfe879a + 36e8a7f commit 27e0d5b
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 43 deletions.
4 changes: 2 additions & 2 deletions pom.xml
Expand Up @@ -50,7 +50,7 @@
<dependency>
<groupId>net.sf.saxon</groupId>
<artifactId>Saxon-HE</artifactId>
<version>9.4.0-9</version>
<version>9.7.0-7</version>
<!-- Mark as optional to allow libraries to include other versions of Saxon -->
<optional>true</optional>
</dependency>
Expand Down Expand Up @@ -294,7 +294,7 @@
<dependency>
<groupId>net.sf.saxon</groupId>
<artifactId>Saxon-HE</artifactId>
<version>9.4.0-9</version>
<version>9.7.0-7</version>
</dependency>
</dependencies>
</plugin>
Expand Down
8 changes: 4 additions & 4 deletions src/main/scala/converters.scala
Expand Up @@ -7,8 +7,8 @@ import javax.xml.transform._
import javax.xml.transform.stream._
import java.io.ByteArrayInputStream

import net.sf.saxon.Controller
import net.sf.saxon.serialize.MessageWarner
import net.sf.saxon.jaxp.TransformerImpl

import org.w3c.dom.NodeList
import org.w3c.dom.Node
Expand Down Expand Up @@ -40,10 +40,10 @@ object Converters {
//
// Adds log error listener to a Saxon controller
//
implicit def toLogController(c : Controller) = new {
implicit def toLogController(t : TransformerImpl) = new {
def addLogErrorListener : Unit = {
c.asInstanceOf[Transformer].setErrorListener (new LogErrorListener)
c.setMessageEmitter(new MessageWarner())
t.setErrorListener (new LogErrorListener)
t.getUnderlyingController.setMessageEmitter(new MessageWarner())
}
}

Expand Down
29 changes: 29 additions & 0 deletions src/main/scala/util/xsl-error-dispatcher.scala
@@ -0,0 +1,29 @@
package com.rackspace.cloud.api.wadl.util

import org.xml.sax.SAXParseException
import scala.annotation.tailrec

trait XSLErrorDispatcher {
//
// The error listener may send a SAXParseException, but newer
// versions of Saxon hide this in a RunTimeException, this call
// captures the error...traverses the cause and rethrows the
// SAXParseException.
//
def handleXSLException (f : => Any) : Unit = {
try {
f
} catch {
case e : RuntimeException => handleRTException(e)
case t : Throwable => throw t
}
}

@tailrec
private def handleRTException(first : RuntimeException, e : Option[RuntimeException]=None) : Unit =
e.getOrElse(first).getCause() match {
case se : SAXParseException => throw se
case rt : RuntimeException => handleRTException(first, Some(rt))
case _ => throw first
}
}
84 changes: 49 additions & 35 deletions src/main/scala/wadl-normalizer.scala
Expand Up @@ -26,6 +26,7 @@ import Converters._

import com.rackspace.cloud.api.wadl.util.EntityCatcher
import com.rackspace.cloud.api.wadl.util.LogErrorListener
import com.rackspace.cloud.api.wadl.util.XSLErrorDispatcher

import scala.xml._

Expand Down Expand Up @@ -53,14 +54,14 @@ import org.xml.sax.SAXException

import com.typesafe.scalalogging.slf4j.LazyLogging

import net.sf.saxon.Controller
import net.sf.saxon.jaxp.TransformerImpl
import net.sf.saxon.lib.NamespaceConstant

import org.w3c.dom.Document
import org.w3c.dom.Element
import org.w3c.dom.NodeList

class WADLNormalizer(private var transformerFactory : TransformerFactory) extends LazyLogging {
class WADLNormalizer(private var transformerFactory : TransformerFactory) extends LazyLogging with XSLErrorDispatcher {

if (transformerFactory == null) {
transformerFactory = TransformerFactory.newInstance("net.sf.saxon.TransformerFactoryImpl", this.getClass.getClassLoader)
Expand Down Expand Up @@ -104,9 +105,10 @@ class WADLNormalizer(private var transformerFactory : TransformerFactory) extend
//
// Set input URL resolver
//
transformerFactory.setURIResolver (new Object() with URIResolver {
private val transformURIResolver = new Object() with URIResolver {
def resolve(href : String, base : String) = sourceMap getOrElse (href, defaultResolver.resolve(href,base))
})
}
transformerFactory.setURIResolver (transformURIResolver)

val saxTransformerFactory : SAXTransformerFactory = transformerFactory.asInstanceOf[SAXTransformerFactory]
val templates : Templates = saxTransformerFactory.newTemplates(sourceMap("normalizeWadl.xsl"))
Expand All @@ -121,7 +123,7 @@ class WADLNormalizer(private var transformerFactory : TransformerFactory) extend

def newTransformer : Transformer = {
val transformer = templates.newTransformer
transformer.asInstanceOf[Controller].addLogErrorListener
transformer.asInstanceOf[TransformerImpl].addLogErrorListener
transformer
}

Expand Down Expand Up @@ -255,45 +257,57 @@ class WADLNormalizer(private var transformerFactory : TransformerFactory) extend
val svrlTransform = svrlHandlerTemplates.newTransformer
val schEntityDoc = new DOMResult()

schTransform.asInstanceOf[Controller].addLogErrorListener
svrlTransform.asInstanceOf[Controller].addLogErrorListener
schTransform.asInstanceOf[TransformerImpl].addLogErrorListener
svrlTransform.asInstanceOf[TransformerImpl].addLogErrorListener

//
// Capture additional enitity references along the way.
//
schTransform.setURIResolver(new Object() with URIResolver {
val origSCHURIResolver = schTransform.getURIResolver
//
// This is a hack to resolve a bug in Saxson 9.7
//
val origSCHURIResolver = {
val orig = schTransform.getURIResolver
if ( orig == null) {
transformURIResolver
} else {
orig
}
}
def resolve(href : String, base : String) = {
Source(origSCHURIResolver.resolve(href, base), Some(entityCatcher))
}
})
schTransform.transform (new DOMSource(wadl.getNode, in.getSystemId()), schReport)
checkAdditionalSVRLReports(schReport.getNode().asInstanceOf[Document])
svrlTransform.setParameter ("systemIds", entityCatcher.systemIds.toArray[String])
svrlTransform.transform (new DOMSource(schReport.getNode()), schEntityDoc)

//
// Secondary check, do XSD transformation, fill in default values
//
val validWadlResult = new DOMResult()
wadlSchema.newValidator().validate(new DOMSource(wadl.getNode, in.getSystemId()), validWadlResult)
val validWadl = validWadlResult.getNode()

//
// Perform the WADL normalization, on valid WADL
//
val transformer = newTransformer(format, xsdVersion, flattenXSDs, resource_types)
if (keepSCHReport) {
val normWADLResult = new DOMResult()
transformer.transform (new DOMSource(validWadl, in.getSystemId()), normWADLResult)
val wadlDocument = normWADLResult.getNode.asInstanceOf[Document]
val wadlRoot = wadlDocument.getDocumentElement()
val reportRoot = wadlDocument.importNode (schEntityDoc.getNode.asInstanceOf[Document].getDocumentElement, true)
wadlRoot.appendChild(reportRoot)
idTransform.transform(new DOMSource(wadlDocument), out)
} else {
transformer.transform (new DOMSource(validWadl, in.getSystemId()), out)
}
handleXSLException({
schTransform.transform (new DOMSource(wadl.getNode, in.getSystemId()), schReport)
checkAdditionalSVRLReports(schReport.getNode().asInstanceOf[Document])
svrlTransform.setParameter ("systemIds", entityCatcher.systemIds.toArray[String])
svrlTransform.transform (new DOMSource(schReport.getNode()), schEntityDoc)

//
// Secondary check, do XSD transformation, fill in default values
//
val validWadlResult = new DOMResult()
wadlSchema.newValidator().validate(new DOMSource(wadl.getNode, in.getSystemId()), validWadlResult)
val validWadl = validWadlResult.getNode()

//
// Perform the WADL normalization, on valid WADL
//
val transformer = newTransformer(format, xsdVersion, flattenXSDs, resource_types)
if (keepSCHReport) {
val normWADLResult = new DOMResult()
transformer.transform (new DOMSource(validWadl, in.getSystemId()), normWADLResult)
val wadlDocument = normWADLResult.getNode.asInstanceOf[Document]
val wadlRoot = wadlDocument.getDocumentElement()
val reportRoot = wadlDocument.importNode (schEntityDoc.getNode.asInstanceOf[Document].getDocumentElement, true)
wadlRoot.appendChild(reportRoot)
idTransform.transform(new DOMSource(wadlDocument), out)
} else {
transformer.transform (new DOMSource(validWadl, in.getSystemId()), out)
}
})
}

def normalize(in: Source, out: Result,
Expand Down
7 changes: 6 additions & 1 deletion src/test/scala/test-base.scala
Expand Up @@ -36,7 +36,7 @@ import com.rackspace.cloud.api.wadl.WADLNormalizer
class SchemaAsserter(xsdSource : URL, useSaxon : Boolean = false) {
private val factory = {
if (useSaxon) {
val inst = Class.forName("com.saxonica.jaxp.SchemaFactoryImpl").newInstance.asInstanceOf[SchemaFactory]
val inst = Class.forName("com.saxonica.ee.jaxp.SchemaFactoryImpl").newInstance.asInstanceOf[SchemaFactory]
inst.setProperty("http://saxon.sf.net/feature/xsd-version","1.1")
inst
} else {
Expand Down Expand Up @@ -151,6 +151,11 @@ trait TransformHandler {
def close(result : Result) = {
result.asInstanceOf[StreamResult].getOutputStream().close()
}

//
// Return a new instance
//
def newInstance = this
})

//
Expand Down
2 changes: 1 addition & 1 deletion xsl/normalizeWadl1.xsl
Expand Up @@ -17,7 +17,7 @@
-->

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:wadl="http://wadl.dev.java.net/2009/02" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsdxt="http://docs.rackspacecloud.com/xsd-ext/v1.0" xmlns:db="http://docbook.org/ns/docbook"
exclude-result-prefixes="wadl xsd xsdxt" version="2.0">
exclude-result-prefixes="wadl xsdxt" version="2.0">

<xsl:import href="normalizeWadl2.xsl"/>
<xsl:import href="normalizeWadl3.xsl"/>
Expand Down

0 comments on commit 27e0d5b

Please sign in to comment.