Skip to content

Commit

Permalink
Fix Resolve Schema Location for xsi:SchemaLocation in Config files
Browse files Browse the repository at this point in the history
- add comment about specific validation error from xerces that requires workaround
- fix resolveSchemaLocation so it looks up non-jar uris with a scheme
- add schema location to config to prove it doesn't cause failure
- use new File() instead of Paths.get to avoid issue with drive names in Windows

DAFFODIL-2339
  • Loading branch information
olabusayoT committed Oct 10, 2024
1 parent 11fcc71 commit cdc9b81
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,8 @@ class DaffodilXMLLoader(val errorHandler: org.xml.sax.ErrorHandler)

// We must use XMLReader setProperty() function to set the entity resolver--calling
// setEntityResolver with the Xerces XML reader causes validation to fail for some
// reason. We call the right function below, but unfortunately, scala-xml calls
// reason (we get a "cvc-elt.1.a: Cannot find the declaration of element 'schema'" error).
// We call the right function below, but unfortunately, scala-xml calls
// setEntityResolver in loadDocument(), which cannot be disabled and scala-xml does not
// want to change. To avoid this, we wrap the Xerces XMLReader in an XMLFilterImpl and
// override setEntityResolver to a no-op. However, XMLFilterImpl parse() calls
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1459,34 +1459,27 @@ Differences were (path, expected, actual):
)
}

val uriIsJustPathComponent =
uri.getScheme == null &&
uri.getAuthority == null &&
uri.getQuery == null &&
uri.getFragment == null &&
uri.getPath != null

val optResolved: Option[(URISchemaSource, Boolean)] =
if (uri.isAbsolute) {
// an absolute URI is one with a scheme. In this case, we expect to be able to resolve
// the URI and do not try anything else (e.g. filesystem, classpath). Since this function
if (uri.isAbsolute && uri.getScheme.contains("jar")) {
// an absolute URI is one with a scheme. In the case that it is a jar uri
// we expect to be able to resolve the URI and do not try anything else
// (e.g. filesystem, classpath). Since this function
// is for schemaLocation attributes, we may eventually want to disallow this, and only
// allow relative URIs (i.e. URIs without a scheme). We do have some places that use
// absolute URIs in includes/imports and cannot remove this yet.
try {
uri.toURL.openStream.close
uri.toURL.openStream.close()
val uss = URISchemaSource(Misc.uriToDiagnosticFile(uri), uri)
Some(uss, false)
} catch {
case e: IOException => None
}
} else if (!uriIsJustPathComponent) {
// this is not an absolute URI so we don't have a scheme. This should just be a path, so
// throw an IllegalArgumentException if that's not the case
val msg =
s"Non-absolute schemaLocation URI can only contain a path component: $schemaLocation"
throw new IllegalArgumentException(msg)
} else if (uri.getPath.startsWith("/")) {
}
// we want to attempt to resolve the URI whether the non-jar uri has a scheme or not,
// this is relevant for when we are validating with Xerces, and it calls resolvesEntity
// we get URIs that look like file:/path/to/not/absolute/path ex: file:/org/apache/daffodil/xsd/dafext.xsd
// that fail to be found in the above case, so we have to look them up
else if (uri.getPath.startsWith("/")) {
// The None.orElse{ ... }.orElse { ... } pattern below is useful to evaluate each
// alternative way to resolve a schema location, stopping only when a Some is returned.
// This makes for easily adding/removing/reordering resolution approaches by changing
Expand All @@ -1506,7 +1499,7 @@ Differences were (path, expected, actual):
.orElse {
// Search for the schemaLocation path on the file system. This path is absolute so it
// must exist. If it does not exist, this orElse block results in a None
val file = Paths.get(uri.getPath).toFile
val file = new File(uri.getPath)
if (file.exists) {
val uss = URISchemaSource(file, file.toURI)
Some((uss, false))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,10 @@
See the License for the specific language governing permissions and
limitations under the License.
-->

<!--
Note: Bug DAFFODIL-2339
We'd like to have these schemaLocation attributes on daf:dfdlConfig, but this breaks tests because
it tries to load the schema from the schemaLocation, and can't resolve org/apache/daffodil/xsd/dafext.xsd.
Simple things like adding an sbt dependency from daffodil-cli back to daffodil-lib, whether always or "it->test"
dependent, don't fix this.
The CLI is using DaffodilXMLLoader to load this config file, so the resolver should be doing the right thing by
finding this dafext.xsd on the class path inside of daffodil-lib's jar.
The failure seems to happen earlier. A SAX fatal error is invoked when looking up dfdl:anyOther a symbol
in the dfdl schema annotation schemas, from the XMLSchema_for_DFDL.
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext org/apache/daffodil/xsd/dafext.xsd"
-->
<daf:dfdlConfig xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext">
<daf:dfdlConfig xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext /org/apache/daffodil/xsd/dafext.xsd"
>
<daf:externalVariableBindings xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:ex="http://example.com">
<daf:bind name="ex:var1">-9</daf:bind>
Expand Down

0 comments on commit cdc9b81

Please sign in to comment.