def withValidateDFDLSchemas()

in daffodil-core/src/main/scala/org/apache/daffodil/core/compiler/Compiler.scala [201:330]


  def withValidateDFDLSchemas(value: Boolean): Compiler = copy(validateDFDLSchemas = value)

  def withTunable(tunable: String, value: String): Compiler =
    copy(tunables = tunables.withTunable(tunable, value))

  def withTunables(tunablesArg: Map[String, String]): Compiler =
    copy(tunables = tunables.withTunables(tunablesArg))

  /**
   * Controls whether we check everything in the schema, or just the element
   * we care about (and everything reachable from it.)
   *
   * You need this control, since many of the big TDML test files have many things
   * in them, some of which use unimplemented features. Each time we run exactly one
   * test from the set, we want to ignore errors in compilation of the others.
   */
  def withCheckAllTopLevel(flag: Boolean): Compiler =
    copy(checkAllTopLevel = flag)

  def reload(savedParser: File): DFDL.DataProcessor = reload(new FileInputStream(savedParser))

  def reload(savedParser: java.nio.channels.ReadableByteChannel): DFDL.DataProcessor =
    reload(Channels.newInputStream(savedParser))

  def reload(schemaSource: DaffodilSchemaSource): DFDL.DataProcessor =
    reload(schemaSource.uriForLoading)

  def reload(uri: URI): DFDL.DataProcessor = reload(uri.toURL.openStream())

  def reload(is: java.io.InputStream): DFDL.DataProcessor = {
    try {
      // Read the required prefix and version information for this saved parser
      // directly from the input stream. This information is not compressed or
      // serialized by a Java ObjectOutputStream

      val requiredDataPrefix = "DAFFODIL "
      requiredDataPrefix.foreach { c =>
        if (is.read() != c.toInt)
          throw new InvalidParserException(
            "The saved parser is only compatible with an older version of Daffodil"
          )
      }

      val ab = new ArrayBuffer[Byte]()
      var byte = -1
      while ({ byte = is.read(); byte > 0 }) {
        ab.append(byte.toByte)
      }
      if (byte == -1) {
        throw new InvalidParserException("The saved parser is corrupted")
      }
      val curVersion = Misc.getDaffodilVersion
      val savedVersion = new String(ab.toArray, "utf-8")
      if (savedVersion != curVersion) {
        throw new InvalidParserException(
          "The saved parser is only compatible with Daffodil " + savedVersion + ". Current version is " + curVersion
        )
      }

      // Decompress and deserilize the rest of the file using java object deserializtion

      val objInput = new ObjectInputStream(new GZIPInputStream(is)) {

        ///
        /// This override is here because of a bug in sbt where the wrong class loader is being
        /// used when deserializing an object.
        //  For more information, see https://github.com/sbt/sbt/issues/163
        ///
        override def resolveClass(desc: java.io.ObjectStreamClass): Class[_] = {
          try { Class.forName(desc.getName, false, getClass.getClassLoader) }
          catch { case _: ClassNotFoundException => super.resolveClass(desc) }
        }
      }

      val dpObj = objInput.readObject()
      objInput.close()
      val dp = dpObj.asInstanceOf[DataProcessor]
      // must recompile the layers since their data structure in memory
      // is not serializable
      dp.ssrd.compileLayers()
      dp
    } catch {
      case _: ZipException =>
        throw new InvalidParserException("The saved parser is corrupted")
      case _: StreamCorruptedException =>
        throw new InvalidParserException("The saved parser is corrupted")
      case ex: InvalidClassException =>
        // This should only happen if users saves a schema with one version of
        // dependency and tries to reload with a different version that is not
        // serialization-compatible (e.g. save with scala 2.12.6 but reload
        // with scala 2.12.11). We don't really know which versions of
        // dependencies maintain serialization compatibility, and we it would
        // be nice to allow users to upgrade libraries themselves for security
        // purposes. So locking Daffodil to specific versions isn't ideal. If
        // this exception is thrown, try to figure out which jar the
        // incompatible class came from and point the user towards that to help
        // figure out the issue.
        val cls = Class.forName(ex.classname)
        val src = cls.getProtectionDomain.getCodeSource
        val dependencyStr =
          if (src != null) (new File(src.getLocation.getFile)).getName else "a dependency"
        throw new InvalidParserException(
          "The saved parser was created with a different version of " + dependencyStr + " with incompatible class: " + ex.classname
        )
      //
      case ex @ (_: ClassNotFoundException | _: NoClassDefFoundError |
          _: InvalidObjectException | _: SchemaDefinitionError) =>
        // These exception happens if a class that was used when saving
        // is no longer on the classpath when reloading.
        //
        // One example of this happening is saving a schema using Java 8 but
        // then reloading on Java 7, since some features (like base64 layers)
        // rely on classes only available in Java 8.
        //
        // Another likely cause is if a user just has their classpath all wrong
        // when reloading a schema, and dependencies are just missing, or if a
        // user switches depenency versions and the new version completely
        // removes a class.
        //
        // Another example is we use a special BitsCharsetSerializationProxy to
        // serialize charsets. This proxy lets us do our own existence checks
        // during deserialization and avoids very confusions and unhelpful
        // messages from the default Java/Scala deserialization when the class
        // does not exist. This custom logic throws an InvalidObjectException if
        // the charset is not found
        throw new InvalidParserException(
          "The saved parser was created with a different set of dependencies containing a class no longer on the classpath: " + ex.getMessage
        )
    }
  }