| /** | |
| * Licensed to the Apache Software Foundation (ASF) under one | |
| * or more contributor license agreements. See the NOTICE file | |
| * distributed with this work for additional information | |
| * regarding copyright ownership. The ASF licenses this file | |
| * to you under the Apache License, Version 2.0 (the | |
| * "License"); you may not use this file except in compliance | |
| * with the License. You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, | |
| * software distributed under the License is distributed on an | |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| * KIND, either express or implied. See the License for the | |
| * specific language governing permissions and limitations | |
| * under the License. | |
| */ | |
| package tests; | |
| import java.io.File; | |
| import org.apache.ws.commons.schema.XmlSchemaException; | |
| import org.apache.ws.commons.schema.resolver.DefaultURIResolver; | |
| import org.junit.Assert; | |
| import org.junit.Test; | |
| import org.xml.sax.InputSource; | |
| public class DefaultURIResolverTest extends Assert { | |
| private static File existingDirectory() { | |
| return new File(System.getProperty("java.io.tmpdir")); | |
| } | |
| @Test | |
| public void testRemoteBaseIsNotRebasedOntoCollectionBase() { | |
| DefaultURIResolver resolver = new DefaultURIResolver(); | |
| resolver.setCollectionBaseURI(existingDirectory().getAbsolutePath()); | |
| InputSource result = resolver.resolveEntity("urn:x", "sub/x.xsd", | |
| "http://example.com/dir/remote.xsd"); | |
| assertEquals("http://example.com/dir/sub/x.xsd", result.getSystemId()); | |
| } | |
| @Test | |
| public void testAbsoluteFileLocationOnRemoteBaseIsRefused() { | |
| DefaultURIResolver resolver = new DefaultURIResolver(); | |
| try { | |
| resolver.resolveEntity("urn:x", "file:///etc/passwd", | |
| "http://example.com/dir/remote.xsd"); | |
| fail("An absolute file URL from a remote base must be refused."); | |
| } catch (XmlSchemaException expected) { | |
| // expected | |
| } | |
| } | |
| @Test | |
| public void testNonLocalFileAuthorityCannotTriggerCollectionRebase() { | |
| DefaultURIResolver resolver = new DefaultURIResolver(); | |
| resolver.setCollectionBaseURI(existingDirectory().getAbsolutePath()); | |
| try { | |
| InputSource result = resolver.resolveEntity("urn:x", "../secret.xsd", | |
| "file://attacker.example/share/base.xsd"); | |
| assertFalse(result.getSystemId().startsWith("file:")); | |
| } catch (XmlSchemaException expected) { | |
| // expected | |
| } | |
| } | |
| @Test | |
| public void testJarFileAuthorityCannotTriggerCollectionRebase() { | |
| DefaultURIResolver resolver = new DefaultURIResolver(); | |
| resolver.setCollectionBaseURI(existingDirectory().getAbsolutePath()); | |
| try { | |
| InputSource result = resolver.resolveEntity("urn:x", "../secret.xsd", | |
| "jar:file://attacker.example/share/a.jar!/dir/base.xsd"); | |
| assertFalse(result.getSystemId().startsWith("file:")); | |
| } catch (XmlSchemaException expected) { | |
| // expected | |
| } | |
| } | |
| @Test | |
| public void testJarFileBaseStillResolvesInsideJar() { | |
| DefaultURIResolver resolver = new DefaultURIResolver(); | |
| String jarBase = "jar:" + new File(existingDirectory(), "x.zip").toURI() | |
| + "!/dir/base.xsd"; | |
| InputSource result = resolver.resolveEntity("urn:x", "child.xsd", jarBase); | |
| assertTrue(result.getSystemId().startsWith("jar:file:")); | |
| assertTrue(result.getSystemId().endsWith("/dir/child.xsd")); | |
| } | |
| @Test | |
| public void testRootedWindowsLocationWithoutBaseIsRefused() { | |
| DefaultURIResolver resolver = new DefaultURIResolver(); | |
| assertNull(resolver.resolveEntity("urn:x", "C:\\Windows\\System32\\config\\SAM", null)); | |
| assertNull(resolver.resolveEntity("urn:x", "C:/Windows/System32/config/SAM", null)); | |
| } | |
| @Test | |
| public void testPlainRelativeLocationWithoutBaseKeepsLegacyBehavior() { | |
| DefaultURIResolver resolver = new DefaultURIResolver(); | |
| InputSource result = resolver.resolveEntity("urn:x", "sub/x.xsd", null); | |
| assertEquals("sub/x.xsd", result.getSystemId()); | |
| } | |
| @Test | |
| public void testOpaqueBaseStillFallsBackToCollectionBase() { | |
| DefaultURIResolver resolver = new DefaultURIResolver(); | |
| resolver.setCollectionBaseURI(existingDirectory().getAbsolutePath()); | |
| InputSource result = resolver.resolveEntity("urn:x", "imported.xsd", "urn:schemas0"); | |
| assertTrue(result.getSystemId().startsWith("file:")); | |
| assertTrue(result.getSystemId().endsWith("imported.xsd")); | |
| } | |
| private static String localBase() { | |
| return new File(existingDirectory(), "base.xsd").toURI().toString(); | |
| } | |
| private static void assertSchemeRefused(String schemaLocation, String baseUri) { | |
| assertSchemeRefused(schemaLocation, baseUri, "not permitted"); | |
| } | |
| private static void assertSchemeRefused(String schemaLocation, String baseUri, | |
| String expectedMessageFragment) { | |
| DefaultURIResolver resolver = new DefaultURIResolver(); | |
| try { | |
| resolver.resolveEntity("urn:x", schemaLocation, baseUri); | |
| fail("The location \"" + schemaLocation + "\" must be refused."); | |
| } catch (XmlSchemaException expected) { | |
| assertTrue(expected.getMessage(), | |
| expected.getMessage().contains(expectedMessageFragment)); | |
| } | |
| } | |
| /** | |
| * Refused, without requiring a particular reason. Which layer refuses a location depends on the | |
| * running JDK: composing a base URI with a scheme the JDK has no handler for fails in | |
| * {@link java.net.URL} before this resolver's own checks see it. Both outcomes are a refusal, | |
| * which is what matters here. | |
| */ | |
| private static void assertRefused(String schemaLocation, String baseUri) { | |
| DefaultURIResolver resolver = new DefaultURIResolver(); | |
| try { | |
| resolver.resolveEntity("urn:x", schemaLocation, baseUri); | |
| fail("The location \"" + schemaLocation + "\" must be refused."); | |
| } catch (XmlSchemaException expected) { | |
| // expected, whichever layer refused it | |
| } | |
| } | |
| @Test | |
| public void testDisallowedSchemesAreRefusedFromALocalBase() { | |
| assertSchemeRefused("mailto:someone@example.com", localBase()); | |
| assertSchemeRefused("ftp://attacker.example/x.xsd", localBase()); | |
| // jrt: has no URL handler before Java 9, where composing it with the base fails in | |
| // java.net.URL rather than reaching the scheme check, so only require the refusal. | |
| assertRefused("jrt:/java.base/java/lang/Object.class", localBase()); | |
| // A scheme no JDK has a handler for, to cover that path on every JDK. | |
| assertRefused("nosuchscheme:/x.xsd", localBase()); | |
| } | |
| @Test | |
| public void testDisallowedSchemesAreRefusedWithoutABase() { | |
| assertSchemeRefused("mailto:someone@example.com", null); | |
| assertSchemeRefused("jrt:/java.base/java/lang/Object.class", null); | |
| assertSchemeRefused("ftp://attacker.example/x.xsd", null); | |
| } | |
| @Test | |
| public void testJarWrappingANetworkUrlIsRefusedAsThatNetworkScheme() { | |
| // "jar:ftp://..." reads as protocol "jar" but performs an FTP fetch, so the scheme | |
| // check has to look through the jar: wrapper. | |
| assertSchemeRefused("jar:ftp://attacker.example/a.jar!/x.xsd", localBase()); | |
| assertSchemeRefused("jar:ftp://attacker.example/a.jar!/x.xsd", null); | |
| } | |
| @Test | |
| public void testAllowedSchemesStillResolve() { | |
| DefaultURIResolver resolver = new DefaultURIResolver(); | |
| assertEquals("http://example.com/x.xsd", | |
| resolver.resolveEntity("urn:x", "http://example.com/x.xsd", localBase()) | |
| .getSystemId()); | |
| assertEquals("https://example.com/x.xsd", | |
| resolver.resolveEntity("urn:x", "https://example.com/x.xsd", null) | |
| .getSystemId()); | |
| assertTrue(resolver.resolveEntity("urn:x", "sibling.xsd", localBase()) | |
| .getSystemId().startsWith("file:")); | |
| assertTrue(resolver.resolveEntity("urn:x", "jar:file:///tmp/a.jar!/x.xsd", localBase()) | |
| .getSystemId().startsWith("jar:file:")); | |
| } | |
| @Test | |
| public void testPlainRelativeLocationWithoutBaseIsNotSchemeChecked() { | |
| DefaultURIResolver resolver = new DefaultURIResolver(); | |
| assertEquals("sub/x.xsd", resolver.resolveEntity("urn:x", "sub/x.xsd", null).getSystemId()); | |
| } | |
| @Test | |
| public void testFileUrlWithNonLocalAuthorityIsRefused() { | |
| // On Windows this is a UNC path, so the JVM would make an SMB connection to a host the | |
| // schema author chose. No base URI makes it reachable: an absolute location used to skip | |
| // every check but the scheme allowlist. | |
| assertSchemeRefused("file://attacker.example/share/x.xsd", localBase(), "non-local authority"); | |
| assertSchemeRefused("file://attacker.example/share/x.xsd", null, "non-local authority"); | |
| assertSchemeRefused("jar:file://attacker.example/share/a.jar!/x.xsd", localBase(), | |
| "non-local authority"); | |
| assertSchemeRefused("jar:file://attacker.example/share/a.jar!/x.xsd", null, | |
| "non-local authority"); | |
| } | |
| @Test | |
| public void testLocalFileAuthoritiesAreStillAccepted() { | |
| DefaultURIResolver resolver = new DefaultURIResolver(); | |
| assertEquals("file:///local/x.xsd", | |
| resolver.resolveEntity("urn:x", "file:///local/x.xsd", null).getSystemId()); | |
| assertEquals("file://localhost/local/x.xsd", | |
| resolver.resolveEntity("urn:x", "file://localhost/local/x.xsd", null) | |
| .getSystemId()); | |
| } | |
| @Test | |
| public void testJarOverTheNetworkIsRefused() { | |
| // JarURLConnection would fetch and cache the whole remote archive, and the URL reads as | |
| // protocol "jar" rather than "http". | |
| for (String location : new String[] {"jar:http://attacker.example/a.jar!/x.xsd", | |
| "jar:https://attacker.example/a.jar!/x.xsd"}) { | |
| assertSchemeRefused(location, localBase(), "over the network"); | |
| assertSchemeRefused(location, null, "over the network"); | |
| } | |
| } | |
| @Test | |
| public void testJarEntryNeedNotParseAsAUri() { | |
| // The archive is local; the entry after "!/" is not part of the URI that names it. | |
| DefaultURIResolver resolver = new DefaultURIResolver(); | |
| InputSource result = resolver.resolveEntity("urn:x", "jar:file:///tmp/a.jar!/has space.xsd", | |
| null); | |
| assertEquals("jar:file:///tmp/a.jar!/has space.xsd", result.getSystemId()); | |
| } | |
| @Test | |
| public void testFileUrlCarryingItsHostInThePathIsRefused() { | |
| // "file:////host/share/x.xsd" parses with a null authority and the host in the path, so an | |
| // authority-only check lets it through. On Windows that path is a UNC path. | |
| assertSchemeRefused("file:////attacker.example/share/x.xsd", null, "non-local authority"); | |
| assertSchemeRefused("file:////attacker.example/share/x.xsd", localBase(), "non-local authority"); | |
| assertSchemeRefused("file://///attacker.example/share/x.xsd", null, "non-local authority"); | |
| assertSchemeRefused("jar:file:////attacker.example/share/a.jar!/x.xsd", null, | |
| "non-local authority"); | |
| // The same shape reached by composing a relative location against a local base. | |
| assertSchemeRefused("////attacker.example/share/x.xsd", localBase(), "non-local authority"); | |
| } | |
| @Test | |
| public void testSchemeCheckSurvivesALocationUriCannotParse() { | |
| // java.net.URI rejects a space, so isAbsoluteUri() said "not absolute" and the location | |
| // fell through to the relative-path branch, which returned it unchecked. java.net.URL is | |
| // laxer, so the parser still fetched it: a space was enough to defeat the scheme allowlist. | |
| assertSchemeRefused("ftp://attacker.example/a b.xsd", null); | |
| assertSchemeRefused("mailto:someone@example.com?x= y", null); | |
| assertSchemeRefused("jrt:/java.base/a b", null); | |
| } | |
| @Test | |
| public void testUnparseableFileLocationIsRefused() { | |
| DefaultURIResolver resolver = new DefaultURIResolver(); | |
| try { | |
| resolver.resolveEntity("urn:x", "file:///\\\\attacker.example\\share\\x.xsd", null); | |
| fail("A file: location that will not parse as a URI must be refused."); | |
| } catch (XmlSchemaException expected) { | |
| // expected | |
| } | |
| } | |
| @Test | |
| public void testJarWrappingAnUnrecognisedSchemeIsRefused() { | |
| assertSchemeRefused("jar:fi%6Ce://attacker.example/a.jar!/x.xsd", null, "names no scheme"); | |
| // Against a base the URL parser rejects the unknown nested protocol before this check, | |
| // so only require that it is refused. | |
| DefaultURIResolver resolver = new DefaultURIResolver(); | |
| try { | |
| resolver.resolveEntity("urn:x", "jar:fi%6Ce://attacker.example/a.jar!/x.xsd", | |
| localBase()); | |
| fail("A jar: URL wrapping an unrecognised scheme must be refused."); | |
| } catch (XmlSchemaException expected) { | |
| // expected | |
| } | |
| } | |
| @Test | |
| public void testRelativeLocationsAreStillNotSchemeChecked() { | |
| DefaultURIResolver resolver = new DefaultURIResolver(); | |
| // No scheme: extractScheme() returns null for a colon that follows a path separator, so | |
| // these stay plain relative paths. | |
| assertEquals("sub/x.xsd", resolver.resolveEntity("urn:x", "sub/x.xsd", null).getSystemId()); | |
| assertEquals("dir/a:b.xsd", | |
| resolver.resolveEntity("urn:x", "dir/a:b.xsd", null).getSystemId()); | |
| } | |
| /** | |
| * A deployment whose schema sets are all local can turn remote fetching off without writing | |
| * its own resolver. The property is read when the resolver is constructed, as the per-fetch | |
| * bounds are, so each case builds its resolver after setting it. | |
| */ | |
| @Test | |
| public void testNetworkResolutionCanBeTurnedOff() { | |
| System.setProperty(DefaultURIResolver.ALLOW_NETWORK_PROPERTY, "false"); | |
| try { | |
| DefaultURIResolver resolver = new DefaultURIResolver(); | |
| for (String location : new String[] {"http://example.com/x.xsd", | |
| "https://example.com/x.xsd"}) { | |
| for (String base : new String[] {null, localBase()}) { | |
| try { | |
| resolver.resolveEntity("urn:x", location, base); | |
| fail("network resolution is off, so \"" + location | |
| + "\" must be refused."); | |
| } catch (XmlSchemaException expected) { | |
| assertTrue(expected.getMessage(), | |
| expected.getMessage().contains("turned off")); | |
| } | |
| } | |
| } | |
| // Local resolution is unaffected: that is the point of the switch. | |
| assertEquals("file:///legit/local.xsd", | |
| resolver.resolveEntity("urn:x", "file:///legit/local.xsd", null) | |
| .getSystemId()); | |
| assertEquals("sub/x.xsd", | |
| resolver.resolveEntity("urn:x", "sub/x.xsd", null).getSystemId()); | |
| assertTrue(resolver.resolveEntity("urn:x", "jar:file:///a.jar!/x.xsd", null) | |
| .getSystemId().startsWith("jar:file:")); | |
| } finally { | |
| System.clearProperty(DefaultURIResolver.ALLOW_NETWORK_PROPERTY); | |
| } | |
| } | |
| @Test | |
| public void testNetworkResolutionIsAllowedByDefault() { | |
| assertNull(System.getProperty(DefaultURIResolver.ALLOW_NETWORK_PROPERTY)); | |
| assertEquals("http://example.com/x.xsd", | |
| new DefaultURIResolver() | |
| .resolveEntity("urn:x", "http://example.com/x.xsd", null).getSystemId()); | |
| } | |
| @Test | |
| public void testUnparseableAllowNetworkValueLeavesResolutionOn() { | |
| // Boolean.parseBoolean would read this as false and quietly break the deployment. | |
| System.setProperty(DefaultURIResolver.ALLOW_NETWORK_PROPERTY, "no"); | |
| try { | |
| assertEquals("http://example.com/x.xsd", | |
| new DefaultURIResolver() | |
| .resolveEntity("urn:x", "http://example.com/x.xsd", null) | |
| .getSystemId()); | |
| } finally { | |
| System.clearProperty(DefaultURIResolver.ALLOW_NETWORK_PROPERTY); | |
| } | |
| } | |
| @Test | |
| public void testFileSystemResolutionCanBeTurnedOff() { | |
| System.setProperty(DefaultURIResolver.ALLOW_FILE_SYSTEM_PROPERTY, "false"); | |
| try { | |
| DefaultURIResolver resolver = new DefaultURIResolver(); | |
| assertRefusedWith(resolver, "file:///legit/local.xsd", null, "turned off"); | |
| assertRefusedWith(resolver, "file:///legit/local.xsd", localBase(), "turned off"); | |
| // jar:file: is a filesystem read too; effectiveScheme sees through the wrapper. | |
| assertRefusedWith(resolver, "jar:file:///a.jar!/x.xsd", null, "turned off"); | |
| // With no base a relative path is resolved against the working directory. | |
| assertRefusedWith(resolver, "sub/x.xsd", null, "turned off"); | |
| // The network switch is independent: this one does not touch http. | |
| assertEquals("http://example.com/x.xsd", | |
| resolver.resolveEntity("urn:x", "http://example.com/x.xsd", null) | |
| .getSystemId()); | |
| } finally { | |
| System.clearProperty(DefaultURIResolver.ALLOW_FILE_SYSTEM_PROPERTY); | |
| } | |
| } | |
| /** Both switches off is the closest the bundled resolver comes to refusing everything. */ | |
| @Test | |
| public void testBothSwitchesOffLeaveNothingToFetch() { | |
| System.setProperty(DefaultURIResolver.ALLOW_FILE_SYSTEM_PROPERTY, "false"); | |
| System.setProperty(DefaultURIResolver.ALLOW_NETWORK_PROPERTY, "false"); | |
| try { | |
| DefaultURIResolver resolver = new DefaultURIResolver(); | |
| for (String location : new String[] {"http://example.com/x.xsd", | |
| "https://example.com/x.xsd", | |
| "file:///legit/local.xsd", | |
| "jar:file:///a.jar!/x.xsd", | |
| "sub/x.xsd"}) { | |
| for (String base : new String[] {null, localBase()}) { | |
| try { | |
| resolver.resolveEntity("urn:x", location, base); | |
| fail("both switches are off, so \"" + location + "\" must be refused."); | |
| } catch (XmlSchemaException expected) { | |
| assertTrue(expected.getMessage(), | |
| expected.getMessage().contains("turned off")); | |
| } | |
| } | |
| } | |
| } finally { | |
| System.clearProperty(DefaultURIResolver.ALLOW_FILE_SYSTEM_PROPERTY); | |
| System.clearProperty(DefaultURIResolver.ALLOW_NETWORK_PROPERTY); | |
| } | |
| } | |
| @Test | |
| public void testFileSystemResolutionIsAllowedByDefault() { | |
| assertNull(System.getProperty(DefaultURIResolver.ALLOW_FILE_SYSTEM_PROPERTY)); | |
| DefaultURIResolver resolver = new DefaultURIResolver(); | |
| assertEquals("file:///legit/local.xsd", | |
| resolver.resolveEntity("urn:x", "file:///legit/local.xsd", null).getSystemId()); | |
| assertEquals("sub/x.xsd", | |
| resolver.resolveEntity("urn:x", "sub/x.xsd", null).getSystemId()); | |
| } | |
| @Test | |
| public void testUnparseableAllowFileSystemValueLeavesResolutionOn() { | |
| System.setProperty(DefaultURIResolver.ALLOW_FILE_SYSTEM_PROPERTY, "off"); | |
| try { | |
| assertEquals("file:///legit/local.xsd", | |
| new DefaultURIResolver() | |
| .resolveEntity("urn:x", "file:///legit/local.xsd", null) | |
| .getSystemId()); | |
| } finally { | |
| System.clearProperty(DefaultURIResolver.ALLOW_FILE_SYSTEM_PROPERTY); | |
| } | |
| } | |
| private static void assertRefusedWith(DefaultURIResolver resolver, String schemaLocation, | |
| String baseUri, String expectedMessageFragment) { | |
| try { | |
| resolver.resolveEntity("urn:x", schemaLocation, baseUri); | |
| fail("The location \"" + schemaLocation + "\" must be refused."); | |
| } catch (XmlSchemaException expected) { | |
| assertTrue(expected.getMessage(), | |
| expected.getMessage().contains(expectedMessageFragment)); | |
| } | |
| } | |
| /** | |
| * A local read is handed to the parser as a system id and bounded by nothing, so a named pipe | |
| * holds the parsing thread indefinitely. A directory exercises the same predicate portably -- | |
| * Java cannot create a FIFO -- and is refused for the same reason. | |
| */ | |
| @Test | |
| public void testALocalLocationThatIsNotARegularFileIsRefused() throws Exception { | |
| File directory = existingDirectory(); | |
| assertTrue(directory.isDirectory()); | |
| String asFileUrl = directory.toURI().toString(); | |
| assertSchemeRefused(asFileUrl, null, "not a regular file"); | |
| assertSchemeRefused(asFileUrl, localBase(), "not a regular file"); | |
| // The archive of a jar: URL must be a regular file too. | |
| assertSchemeRefused("jar:" + asFileUrl + "!/x.xsd", null, "not a regular file"); | |
| } | |
| /** | |
| * With no base URI, a relative location is handed to the parser as-is and opened against the | |
| * working directory, so it is a local read like any file: URL and gets the same check. | |
| */ | |
| @Test | |
| public void testARelativeLocationThatIsNotARegularFileIsRefused() { | |
| assertTrue(new File(".").isDirectory()); | |
| assertSchemeRefused(".", null, "not a regular file"); | |
| } | |
| /** | |
| * The parser resolves a relative location as a URI, decoding escapes and dropping a query or | |
| * fragment, so each of these names the directory "src" and must be checked as that. | |
| */ | |
| @Test | |
| public void testARelativeLocationIsCheckedAsTheParserReadsIt() { | |
| assertTrue(new File("src").isDirectory()); | |
| assertSchemeRefused("sr%63", null, "not a regular file"); | |
| assertSchemeRefused("src#fragment", null, "not a regular file"); | |
| assertSchemeRefused("src?query", null, "not a regular file"); | |
| } | |
| /** | |
| * "file:src", with no slash after the scheme, is an opaque URI with no path, but the JDK opens | |
| * it as src in the working directory, so it must be checked as that file. | |
| */ | |
| @Test | |
| public void testAFileLocationRelativeToTheWorkingDirectoryIsChecked() { | |
| assertTrue(new File("src").isDirectory()); | |
| assertSchemeRefused("file:src", null, "not a regular file"); | |
| assertSchemeRefused("file:./src", null, "not a regular file"); | |
| assertSchemeRefused("FILE:src", null, "not a regular file"); | |
| assertSchemeRefused("file:sr%63?query", null, "not a regular file"); | |
| assertSchemeRefused("jar:file:src!/x.xsd", null, "not a regular file"); | |
| } | |
| @Test | |
| public void testAFileLocationRelativeToTheWorkingDirectoryStillResolves() { | |
| assertTrue(new File("pom.xml").isFile()); | |
| assertEquals("file:pom.xml", | |
| new DefaultURIResolver().resolveEntity("urn:x", "file:pom.xml", null) | |
| .getSystemId()); | |
| } | |
| @Test | |
| public void testARelativeRegularFileWithAFragmentStillResolves() { | |
| assertEquals("pom.xml#fragment", | |
| new DefaultURIResolver().resolveEntity("urn:x", "pom.xml#fragment", null) | |
| .getSystemId()); | |
| } | |
| @Test | |
| public void testARelativeRegularOrMissingFileStillResolves() { | |
| assertTrue(new File("pom.xml").isFile()); | |
| assertEquals("pom.xml", | |
| new DefaultURIResolver().resolveEntity("urn:x", "pom.xml", null).getSystemId()); | |
| assertEquals("no-such-schema.xsd", | |
| new DefaultURIResolver() | |
| .resolveEntity("urn:x", "no-such-schema.xsd", null).getSystemId()); | |
| } | |
| @Test | |
| public void testARegularFileStillResolves() throws Exception { | |
| File file = File.createTempFile("schema", ".xsd"); | |
| try { | |
| assertEquals(file.toURI().toString(), | |
| new DefaultURIResolver() | |
| .resolveEntity("urn:x", file.toURI().toString(), null).getSystemId()); | |
| } finally { | |
| assertTrue(file.delete() || !file.exists()); | |
| } | |
| } | |
| /** | |
| * A location that does not exist is not this check's business: it is an ordinary missing-schema | |
| * error, and refusing it here would change what the parser reports for a typo. | |
| */ | |
| @Test | |
| public void testAMissingLocalFileIsStillResolved() { | |
| String missing = new File(existingDirectory(), "no-such-schema.xsd").toURI().toString(); | |
| assertEquals(missing, | |
| new DefaultURIResolver().resolveEntity("urn:x", missing, null).getSystemId()); | |
| } | |
| } |