stevedlawrence closed pull request #59: Add new tunable
(errorOnUnsupportedJavaVersion) to allow running with older versions of Java
URL: https://github.com/apache/incubator-daffodil/pull/59
This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:
As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/compiler/Compiler.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/compiler/Compiler.scala
index 9f39bbc06..bc018ba38 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/compiler/Compiler.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/compiler/Compiler.scala
@@ -39,6 +39,7 @@ import scala.collection.mutable.Queue
import org.apache.daffodil.externalvars.ExternalVariablesLoader
import org.apache.daffodil.processors.SchemaSetRuntimeData
import org.apache.daffodil.util.CheckJavaVersion
+import org.apache.daffodil.util.InvalidJavaVersionException
import org.apache.daffodil.api.ValidationMode
import org.apache.daffodil.processors.VariableMap
import java.util.zip.GZIPInputStream
@@ -162,7 +163,14 @@ final class ProcessorFactory(val sset: SchemaSet)
rootERD,
variables,
validationMode)
- CheckJavaVersion.checkJavaVersion(ssrd)
+ val versionErrorOpt = CheckJavaVersion.checkJavaVersion()
+ if (versionErrorOpt.isDefined) {
+ if (tunable.errorOnUnsupportedJavaVersion) {
+ throw new InvalidJavaVersionException(versionErrorOpt.get)
+ } else {
+ log(LogLevel.Warning, versionErrorOpt.get + " " +
CheckJavaVersion.allowUnsupportedJavaMessage)
+ }
+ }
val dataProc = new DataProcessor(ssrd)
if (dataProc.isError) {
// NO longer printing anything here. Callers must do this.
@@ -284,7 +292,14 @@ class Compiler(var validateDFDLSchemas: Boolean = true)
val dpObj = objInput.readObject()
objInput.close()
val dp = dpObj.asInstanceOf[SerializableDataProcessor]
- CheckJavaVersion.checkJavaVersion(dp.ssrd)
+ val versionErrorOpt = CheckJavaVersion.checkJavaVersion()
+ if (versionErrorOpt.isDefined) {
+ if (dp.getTunables.errorOnUnsupportedJavaVersion) {
+ throw new InvalidJavaVersionException(versionErrorOpt.get)
+ } else {
+ log(LogLevel.Warning, versionErrorOpt.get + " " +
CheckJavaVersion.allowUnsupportedJavaMessage)
+ }
+ }
dp
} catch {
case ex: ZipException => {
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/util/CheckJavaVersion.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/util/CheckJavaVersion.scala
index 0a93da1a8..1a8f1d684 100644
---
a/daffodil-core/src/main/scala/org/apache/daffodil/util/CheckJavaVersion.scala
+++
b/daffodil-core/src/main/scala/org/apache/daffodil/util/CheckJavaVersion.scala
@@ -17,24 +17,27 @@
package org.apache.daffodil.util
-import org.apache.daffodil.exceptions.ThrowsSDE
import org.apache.daffodil.processors.charset.CharsetUtils
class InvalidJavaVersionException(msg: String, cause: Throwable = null)
extends Exception(msg, cause)
object CheckJavaVersion {
- def checkJavaVersion(context: ThrowsSDE) = {
+ def checkJavaVersion(): Option[String] = {
val jVersion = scala.util.Properties.javaVersion
- if (!scala.util.Properties.isJavaAtLeast("1.8")) {
- throw new InvalidJavaVersionException("Daffodil requires Java 8 (1.8) or
higher. You are currently running %s".format(jVersion))
- }
- //
- // Test specifically for this particular decoder bug
- //
- if (CharsetUtils.hasJava7DecoderBug) {
- throw new InvalidJavaVersionException("This Java JVM has the Java 7
Decoder Bug. Daffodil requires Java 8 or higher.")
- }
+ val errorStringOpt =
+ if (!scala.util.Properties.isJavaAtLeast("1.8")) {
+ Some("Daffodil requires Java 8 (1.8) or higher. You are currently
running %s.".format(jVersion))
+ } else if (CharsetUtils.hasJava7DecoderBug) {
+ Some("This Java JVM has the Java 7 Decoder Bug. Daffodil requires Java
8 or higher.")
+ } else {
+ None
+ }
+ errorStringOpt
}
+ val allowUnsupportedJavaMessage =
+ "Due to the tunable value of errorOnUnsupportedJavaVersion, " +
+ "processing will continue with the understanding that this is not " +
+ "fully tested and may have unexpected behavior in some circumstances."
}
diff --git
a/daffodil-lib/src/main/scala/org/apache/daffodil/api/DaffodilTunables.scala
b/daffodil-lib/src/main/scala/org/apache/daffodil/api/DaffodilTunables.scala
index c4850b043..27b090f05 100644
--- a/daffodil-lib/src/main/scala/org/apache/daffodil/api/DaffodilTunables.scala
+++ b/daffodil-lib/src/main/scala/org/apache/daffodil/api/DaffodilTunables.scala
@@ -21,18 +21,41 @@ import org.apache.daffodil.exceptions.Assert
import org.apache.daffodil.schema.annotation.props.gen.ParseUnparsePolicy
import org.apache.daffodil.util.LogLevel
import org.apache.daffodil.util.Logging
+import org.apache.daffodil.util.Misc
+import org.apache.daffodil.xml.DaffodilXMLLoader
object DaffodilTunables {
def apply(tunables: Map[String, String]): DaffodilTunables = {
- new DaffodilTunables().setTunables(tunables)
+ apply().setTunables(tunables)
}
def apply(tunable: String, value: String): DaffodilTunables = {
- new DaffodilTunables().setTunable(tunable, value)
+ apply().setTunable(tunable, value)
}
- def apply(): DaffodilTunables = new DaffodilTunables()
+ def apply(): DaffodilTunables = {
+ // override tunables from the global configuration file on the class path,
if it exists
+ val (configOpt, _) = Misc.getResourceOption("/daffodil-config.xml")
+ val configTunables: Map[String, String] =
+ if (configOpt.isDefined) {
+ val loader = new DaffodilXMLLoader()
+ val node = loader.load(new URISchemaSource(configOpt.get))
+ val trimmed = scala.xml.Utility.trim(node)
+ val tunablesNode = (trimmed \ "tunables").headOption
+ val tunablesMap: Map[String, String] = tunablesNode match {
+ case None => Map.empty
+ case Some(tunableNode) => {
+ tunableNode.child.map { n => (n.label, n.text) }.toMap
+ }
+ }
+ tunablesMap
+ } else {
+ Map.empty
+ }
+
+ new DaffodilTunables().setTunables(configTunables)
+ }
}
case class DaffodilTunables(
@@ -105,7 +128,19 @@ case class DaffodilTunables(
// This may cause a degredation of performance in path expression evaluation,
// so this should be avoided when in production. This flag is automatically
// enabled when debugging is enabled.
- val allowExternalPathExpressions: Boolean = false)
+ val allowExternalPathExpressions: Boolean = false,
+
+ // A bug exists in Java 7 that causes unexpected behavior when decode errors
+ // occur in the specific ways that Daffodil decodes data. For this reason,
+ // Daffodil throws an exception when it detects that Daffodil is not running
+ // under Java 8 or has this decoder bug. However, there are some cases where
+ // a user has no choice but to run on Java 7. Setting this tunable to false
+ // will cause Daffodil to log a warning rather than throw an exception so
+ // that a user can run Daffodil on unsupported Java versions, with the
+ // understanding that it is not fully tested and behavior may not be well
+ // defined. This boolean is experimental and should only be used by those
+ // that fully understand the risks.
+ val errorOnUnsupportedJavaVersion: Boolean = true)
extends Serializable
with Logging
with DataStreamLimits {
@@ -206,6 +241,7 @@ case class DaffodilTunables(
this.copy(suppressSchemaDefinitionWarnings = warningsList)
}
case "allowexternalpathexpressions" =>
this.copy(allowExternalPathExpressions = java.lang.Boolean.valueOf(value))
+ case "erroronunsupportedjavaversion" =>
this.copy(errorOnUnsupportedJavaVersion = java.lang.Boolean.valueOf(value))
case _ => {
log(LogLevel.Warning, "Ignoring unknown tunable: %s", tunable)
this
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
With regards,
Apache Git Services