[java-opensaml] branch main updated: Convert tests to use EmbeddedJetty fixture.

Codeberg noreply at shibboleth.net
Mon Jul 13 18:00:51 UTC 2026


This is an automated email from the git hooks/post-receive script.

codeberg pushed a commit to branch main
in repository java-opensaml.

View the commit online:
https://codeberg.org/Shibboleth/java-opensaml/commit/52c52f64179e103f683253156fbde7f26e141cc2

The following commit(s) were added to refs/heads/main by this push:
     new 52c52f641 Convert tests to use EmbeddedJetty fixture.
52c52f641 is described below

commit 52c52f64179e103f683253156fbde7f26e141cc2
Author: Scott Cantor <scott at restingparrotsoftware.com>
AuthorDate: Mon Jul 13 14:00:31 2026 -0400

    Convert tests to use EmbeddedJetty fixture.
---
 .../resolver/filter/impl/EntityRoleFilterTest.java |  25 +-
 .../impl/FileBackedHTTPMetadataResolverTest.java   | 134 ++++++----
 ...ctionDrivenDynamicHTTPMetadataResolverTest.java | 273 +++++++++++----------
 .../resolver/impl/HTTPMetadataResolverTest.java    |  89 ++++---
 .../saml/metadata/resolver/impl/localhost-sp.xml   |  49 ++++
 .../support/tests/DetachedSignatureTest.java       |  37 ++-
 6 files changed, 389 insertions(+), 218 deletions(-)

diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/metadata/resolver/filter/impl/EntityRoleFilterTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/metadata/resolver/filter/impl/EntityRoleFilterTest.java
index c3704760f..94228f52e 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/metadata/resolver/filter/impl/EntityRoleFilterTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/metadata/resolver/filter/impl/EntityRoleFilterTest.java
@@ -27,18 +27,23 @@ import org.opensaml.saml.saml2.metadata.AttributeAuthorityDescriptor;
 import org.opensaml.saml.saml2.metadata.IDPSSODescriptor;
 import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
 import org.opensaml.security.httpclient.HttpClientSecurityParameters;
+import org.springframework.core.io.ClassPathResource;
+import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 import net.shibboleth.shared.httpclient.HttpClientBuilder;
-import net.shibboleth.shared.testing.RepositorySupport;
+import net.shibboleth.shared.spring.resource.ResourceHelper;
+import net.shibboleth.shared.testing.EmbeddedJetty;
 
 /**
  * Unit tests for {@link EntityRoleFilter}.
  */
 @SuppressWarnings("javadoc")
 public class EntityRoleFilterTest extends XMLObjectBaseTestCase {
+
+    private EmbeddedJetty jetty;
     
     private HttpClient httpClient;
 
@@ -53,15 +58,27 @@ public class EntityRoleFilterTest extends XMLObjectBaseTestCase {
     
     @BeforeClass
     protected void setUpClass() throws Exception {
+        jetty = new EmbeddedJetty();
+        jetty.startServer(new EmbeddedJetty.ResourceHandler(200,
+                ResourceHelper.of(new ClassPathResource("org/opensaml/saml/saml2/metadata/InCommon-metadata.xml"))));
+        
+        inCommonMDURL = "https://localhost:8443/InCommon-metadata.xml";
+        
         httpClientBuilder = new HttpClientBuilder();
         httpClientBuilder.setConnectionTimeout(Duration.ofSeconds(5));
         httpClientBuilder.setTLSSocketFactory(HTTPMetadataResolverTest.buildSocketFactory());
         httpClient = httpClientBuilder.buildClient();
 
         httpClientParams = new HttpClientSecurityParameters();
-        httpClientParams.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine("repo-entity.crt"));
-
-        inCommonMDURL = RepositorySupport.buildHTTPSResourceURL("java-opensaml", "opensaml-saml-impl/src/test/resources/org/opensaml/saml/saml2/metadata/InCommon-metadata.xml");
+        httpClientParams.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine(EmbeddedJetty.getServerCertficateResource()));
+    }
+    
+    @AfterClass
+    protected void tearDownClass() {
+        if (jetty != null) {
+            jetty.stopServer();
+            jetty = null;
+        }
     }
 
     @BeforeMethod
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/metadata/resolver/impl/FileBackedHTTPMetadataResolverTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/metadata/resolver/impl/FileBackedHTTPMetadataResolverTest.java
index 91233488f..55fb2bc47 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/metadata/resolver/impl/FileBackedHTTPMetadataResolverTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/metadata/resolver/impl/FileBackedHTTPMetadataResolverTest.java
@@ -17,6 +17,8 @@ package org.opensaml.saml.metadata.resolver.impl;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.net.SocketException;
+import java.net.UnknownHostException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.time.Duration;
@@ -34,8 +36,11 @@ import org.opensaml.saml.metadata.resolver.filter.MetadataFilterContext;
 import org.opensaml.saml.metadata.resolver.filter.data.impl.MetadataSource;
 import org.opensaml.saml.saml2.metadata.EntityDescriptor;
 import org.opensaml.security.httpclient.HttpClientSecurityParameters;
+import org.springframework.core.io.ClassPathResource;
 import org.testng.Assert;
+import org.testng.annotations.AfterClass;
 import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
@@ -43,9 +48,12 @@ import com.google.common.io.Resources;
 
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.httpclient.HttpClientBuilder;
+import net.shibboleth.shared.primitive.NonnullSupplier;
 import net.shibboleth.shared.resolver.CriteriaSet;
 import net.shibboleth.shared.resolver.ResolverException;
-import net.shibboleth.shared.testing.RepositorySupport;
+import net.shibboleth.shared.resource.Resource;
+import net.shibboleth.shared.spring.resource.ResourceHelper;
+import net.shibboleth.shared.testing.EmbeddedJetty;
 
 
 /**
@@ -54,13 +62,16 @@ import net.shibboleth.shared.testing.RepositorySupport;
 @SuppressWarnings("javadoc")
 public class FileBackedHTTPMetadataResolverTest extends XMLObjectBaseTestCase {
     
+    private EmbeddedJetty jetty;
+    private int jettyStatus;
+    
     private HttpClientBuilder httpClientBuilder;
 
     private String metadataURLHttps;
     private String metadataURLHttp;
-    private String relativeMDResource;
-    private String relativeMDResourceExpired;
-    private String relativeMDResourceBad;
+    private Resource relativeMDResource;
+    private Resource relativeMDResourceExpired;
+    private Resource relativeMDResourceBad;
     private String badMDURL;
     private String backupFilePath;
     private File backupFile;
@@ -68,18 +79,41 @@ public class FileBackedHTTPMetadataResolverTest extends XMLObjectBaseTestCase {
     private String entityID;
     private CriteriaSet criteriaSet;
 
+    @BeforeClass
+    public void startJetty() throws UnknownHostException, SocketException {
+        relativeMDResource = ResourceHelper.of(new ClassPathResource("org/opensaml/saml/metadata/resolver/impl/08ced64cddc9f1578598b2cf71ae747b11d11472.xml"));
+        relativeMDResourceExpired = ResourceHelper.of(new ClassPathResource("org/opensaml/saml/metadata/resolver/impl/08ced64cddc9f1578598b2cf71ae747b11d11473-expired.xml"));
+        relativeMDResourceBad = ResourceHelper.of(new ClassPathResource("org/opensaml/saml/metadata/resolver/impl/08ced64cddc9f1578598b2cf71ae747b11d11473-bad.xml"));
+        metadataURLHttps = "https://localhost:8443/metadata.xml";
+        metadataURLHttp = "http://localhost:8080/metadata.xml";
+
+        jetty = new EmbeddedJetty();
+        jetty.startServer(new EmbeddedJetty.ResourceHandler(
+                new NonnullSupplier<Integer>() {
+                    @Nonnull public Integer get() {
+                        return jettyStatus;
+                    }
+                },
+                NonnullSupplier.of(relativeMDResource)
+                ));
+    }
+    
+    @AfterClass
+    public void stopJetty() {
+        if (jetty != null) {
+            jetty.stopServer();
+            jetty = null;
+        }
+    }
+    
     @BeforeMethod
     protected void setUp() throws Exception {
-        httpClientBuilder = new HttpClientBuilder();
+        jettyStatus = 200;
         
-        relativeMDResource = "org/opensaml/saml/metadata/resolver/impl/08ced64cddc9f1578598b2cf71ae747b11d11472.xml";
-        relativeMDResourceExpired = "org/opensaml/saml/metadata/resolver/impl/08ced64cddc9f1578598b2cf71ae747b11d11473-expired.xml";
-        relativeMDResourceBad = "org/opensaml/saml/metadata/resolver/impl/08ced64cddc9f1578598b2cf71ae747b11d11473-bad.xml";
-        metadataURLHttps = RepositorySupport.buildHTTPSResourceURL("java-opensaml", String.format("opensaml-saml-impl/src/test/resources/%s", relativeMDResource));
-        metadataURLHttp = RepositorySupport.buildHTTPResourceURL("java-opensaml", String.format("opensaml-saml-impl/src/test/resources/%s", relativeMDResource), false);
+        httpClientBuilder = new HttpClientBuilder();
         
         entityID = "https://www.example.org/sp";
-        badMDURL = "https://test.shibboleth.net/foo/bar/baz/samlmd";
+        badMDURL = "http://localhost:8080/foo/bar/baz/samlmd";
         backupFilePath = System.getProperty("java.io.tmpdir") + System.getProperty("file.separator") 
                 + "filebacked-http-metadata.xml";
         backupFile = new File(backupFilePath);
@@ -149,6 +183,10 @@ public class FileBackedHTTPMetadataResolverTest extends XMLObjectBaseTestCase {
      */
     @Test
     public void testFailFastBadURL() throws Exception {
+        
+        // Trigger failure.
+        jettyStatus = 404;
+        
         metadataProvider = new FileBackedHTTPMetadataResolver(httpClientBuilder.buildClient(), badMDURL, backupFilePath);
         
         metadataProvider.setFailFastInitialization(true);
@@ -173,8 +211,12 @@ public class FileBackedHTTPMetadataResolverTest extends XMLObjectBaseTestCase {
      */
     @Test
     public void testNoFailFastBadURL() throws Exception {
-        metadataProvider = new FileBackedHTTPMetadataResolver(httpClientBuilder.buildClient(), badMDURL, backupFilePath);
         
+        // Trigger failure.
+        jettyStatus = 404;
+
+        metadataProvider = new FileBackedHTTPMetadataResolver(httpClientBuilder.buildClient(), badMDURL, backupFilePath);
+
         metadataProvider.setFailFastInitialization(false);
         metadataProvider.setId("test");
         metadataProvider.setParserPool(parserPool);
@@ -190,7 +232,7 @@ public class FileBackedHTTPMetadataResolverTest extends XMLObjectBaseTestCase {
             Assert.fail("Provider failed init with fail-fast=false");
         }
         
-        EntityDescriptor descriptor = metadataProvider.resolveSingle(criteriaSet);
+        final EntityDescriptor descriptor = metadataProvider.resolveSingle(criteriaSet);
         Assert.assertNull(descriptor);
     }
     
@@ -201,11 +243,12 @@ public class FileBackedHTTPMetadataResolverTest extends XMLObjectBaseTestCase {
      */
     @Test
     public void testFailFastBadBackupFile() throws Exception {
+        
         try {
             // Use a known existing directory as backup file path, which is an invalid argument.
             metadataProvider = new FileBackedHTTPMetadataResolver(httpClientBuilder.buildClient(), metadataURLHttp, System.getProperty("java.io.tmpdir"));
         } catch (final ResolverException e) {
-            Assert.fail("Provider failed bad backup file in constructor");
+            Assert.fail("Provider failed due to bad backup file in constructor");
             
         }
         metadataProvider.setFailFastInitialization(true);
@@ -228,11 +271,12 @@ public class FileBackedHTTPMetadataResolverTest extends XMLObjectBaseTestCase {
      */
     @Test
     public void testNoFailFastBadBackupFile() throws Exception {
+        
         try {
             // Use a known existing directory as backup file path, which is an invalid argument.
             metadataProvider = new FileBackedHTTPMetadataResolver(httpClientBuilder.buildClient(), metadataURLHttp, System.getProperty("java.io.tmpdir"));
-        } catch (ResolverException e) {
-            Assert.fail("Provider failed bad backup file in constructor");
+        } catch (final ResolverException e) {
+            Assert.fail("Provider failed due to bad backup file in constructor");
             
         }
         metadataProvider.setFailFastInitialization(false);
@@ -262,12 +306,12 @@ public class FileBackedHTTPMetadataResolverTest extends XMLObjectBaseTestCase {
     @Test
     public void testInitFromBackupFile() throws Exception {
         try (FileOutputStream backupFileOutputStream = new FileOutputStream(backupFile)) {
-            Resources.copy(Resources.getResource(relativeMDResource), backupFileOutputStream);
+            Resources.copy(relativeMDResource.getURL(), backupFileOutputStream);
         }
         
         Assert.assertTrue(backupFile.exists(), "Backup file was not created");
         Assert.assertTrue(backupFile.length() > 0, "Backup file contains no data");
-        
+
         final MockContextTrackingFilter mockFilter = new MockContextTrackingFilter();
 
         metadataProvider = new FileBackedHTTPMetadataResolver(httpClientBuilder.buildClient(), metadataURLHttp, backupFilePath);
@@ -318,12 +362,12 @@ public class FileBackedHTTPMetadataResolverTest extends XMLObjectBaseTestCase {
     @Test
     public void testInitFromExpiredBackupFile() throws Exception {
         try (FileOutputStream backupFileOutputStream = new FileOutputStream(backupFile)) {
-            Resources.copy(Resources.getResource(relativeMDResourceExpired), backupFileOutputStream);
+            Resources.copy(relativeMDResourceExpired.getURL(), backupFileOutputStream);
         }
         
         Assert.assertTrue(backupFile.exists(), "Backup file was not created");
         Assert.assertTrue(backupFile.length() > 0, "Backup file contains no data");
-        
+
         metadataProvider = new FileBackedHTTPMetadataResolver(httpClientBuilder.buildClient(), metadataURLHttp, backupFilePath);
         metadataProvider.setParserPool(parserPool);
         metadataProvider.setFailFastInitialization(true);
@@ -371,12 +415,12 @@ public class FileBackedHTTPMetadataResolverTest extends XMLObjectBaseTestCase {
     @Test
     public void testInitFromBadBackupFileNonFailFast() throws Exception {
         try (FileOutputStream backupFileOutputStream = new FileOutputStream(backupFile)) {
-            Resources.copy(Resources.getResource(relativeMDResourceBad), backupFileOutputStream);
+            Resources.copy(relativeMDResourceBad.getURL(), backupFileOutputStream);
         }
         
         Assert.assertTrue(backupFile.exists(), "Backup file was not created");
         Assert.assertTrue(backupFile.length() > 0, "Backup file contains no data");
-        
+
         metadataProvider = new FileBackedHTTPMetadataResolver(httpClientBuilder.buildClient(), metadataURLHttp, backupFilePath);
         metadataProvider.setParserPool(parserPool);
         metadataProvider.setFailFastInitialization(false);
@@ -421,14 +465,15 @@ public class FileBackedHTTPMetadataResolverTest extends XMLObjectBaseTestCase {
     @Test
     public void testNoBackupFileLoadWhenMetadataCached() throws Exception {
         try (FileOutputStream backupFileOutputStream = new FileOutputStream(backupFile)) {
-            Resources.copy(Resources.getResource(relativeMDResource), backupFileOutputStream);
+            Resources.copy(relativeMDResource.getURL(), backupFileOutputStream);
         }
         
         Assert.assertTrue(backupFile.exists(), "Backup file was not created");
         Assert.assertTrue(backupFile.length() > 0, "Backup file contains no data");
-        
-        httpClientBuilder.setConnectionDisregardTLSCertificate(true);
-        
+
+        // Trigger error.
+        jettyStatus = 404;
+
         metadataProvider = new FileBackedHTTPMetadataResolver(httpClientBuilder.buildClient(), badMDURL, backupFilePath);
         metadataProvider.setParserPool(parserPool);
         metadataProvider.setFailFastInitialization(true);
@@ -482,15 +527,15 @@ public class FileBackedHTTPMetadataResolverTest extends XMLObjectBaseTestCase {
     }
     
     @Test
-    public void testTrustEngineSocketFactoryNoHTTPSWithTrustEngine() throws Exception  {
-        // Make sure resolver works when TrustEngine socket factory is configured but just using an HTTP URL.
+    public void testTrustEngineSocketFactoryHTTPSWithTrustEngine() throws Exception  {
+        // Make sure resolver works when TrustEngine socket factory is configured and using an HTTPS URL.
         httpClientBuilder.setTLSSocketFactory(HTTPMetadataResolverTest.buildSocketFactory());
-        
+
         metadataProvider = new FileBackedHTTPMetadataResolver(httpClientBuilder.buildClient(), metadataURLHttps, backupFilePath);
         metadataProvider.setParserPool(parserPool);
         metadataProvider.setId("test");
         final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
-        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine("repo-entity.crt"));
+        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine(EmbeddedJetty.getServerCertficateResource()));
         metadataProvider.setHttpClientSecurityParameters(params);
         metadataProvider.initialize();
         
@@ -506,8 +551,8 @@ public class FileBackedHTTPMetadataResolverTest extends XMLObjectBaseTestCase {
     @Test
     public void testHTTPSNoTrustEngine() throws Exception  {
         try {
-            System.setProperty("javax.net.ssl.trustStore", getClass().getResource("repo.truststore.jks").getFile());
-            System.setProperty("javax.net.ssl.trustStorePassword", "shibboleth");
+            System.setProperty("javax.net.ssl.trustStore", EmbeddedJetty.getServerKeystoreResource().getFile().getPath());
+            System.setProperty("javax.net.ssl.trustStorePassword", EmbeddedJetty.getServerKeystorePassword());
             
             httpClientBuilder.setTLSSocketFactory(HTTPMetadataResolverTest.buildSocketFactory(false));
 
@@ -526,7 +571,6 @@ public class FileBackedHTTPMetadataResolverTest extends XMLObjectBaseTestCase {
         } finally {
             System.setProperty("javax.net.ssl.trustStore", "");
             System.setProperty("javax.net.ssl.trustStorePassword", "");
-
         }
     }
     
@@ -538,7 +582,7 @@ public class FileBackedHTTPMetadataResolverTest extends XMLObjectBaseTestCase {
         metadataProvider.setParserPool(parserPool);
         metadataProvider.setId("test");
         final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
-        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine("repo-entity.crt"));
+        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine(EmbeddedJetty.getServerCertficateResource()));
         metadataProvider.setHttpClientSecurityParameters(params);
         metadataProvider.initialize();
         
@@ -560,7 +604,9 @@ public class FileBackedHTTPMetadataResolverTest extends XMLObjectBaseTestCase {
         metadataProvider.setParserPool(parserPool);
         metadataProvider.setId("test");
         final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
-        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine("badKey.crt"));
+        params.setTLSTrustEngine(
+                HTTPMetadataResolverTest.buildExplicitKeyTrustEngine(
+                        ResourceHelper.of(new ClassPathResource(HTTPMetadataResolverTest.DATA_PATH + "badKey.crt"))));
         metadataProvider.setHttpClientSecurityParameters(params);
         
         try {
@@ -583,7 +629,7 @@ public class FileBackedHTTPMetadataResolverTest extends XMLObjectBaseTestCase {
         metadataProvider.setId("test");
         
         final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
-        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildPKIXTrustEngine("repo-rootCA.crt", null, false));
+        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildPKIXTrustEngine(EmbeddedJetty.getServerCertficateResource(), null, false));
         metadataProvider.setHttpClientSecurityParameters(params);
 
         metadataProvider.initialize();
@@ -600,12 +646,12 @@ public class FileBackedHTTPMetadataResolverTest extends XMLObjectBaseTestCase {
     @Test
     public void testHTTPSTrustEngineValidPKIXExplicitName() throws Exception  {
         httpClientBuilder.setTLSSocketFactory(HTTPMetadataResolverTest.buildSocketFactory());
-        
+
         metadataProvider = new FileBackedHTTPMetadataResolver(httpClientBuilder.buildClient(), metadataURLHttps, backupFilePath);
         metadataProvider.setParserPool(parserPool);
         metadataProvider.setId("test");
         final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
-        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildPKIXTrustEngine("repo-rootCA.crt", "test.shibboleth.net", true));
+        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildPKIXTrustEngine(EmbeddedJetty.getServerCertficateResource(), "localhost", true));
         metadataProvider.setHttpClientSecurityParameters(params);
 
         metadataProvider.initialize();
@@ -622,12 +668,13 @@ public class FileBackedHTTPMetadataResolverTest extends XMLObjectBaseTestCase {
     @Test
     public void testHTTPSTrustEngineInvalidPKIX() throws Exception  {
         httpClientBuilder.setTLSSocketFactory(HTTPMetadataResolverTest.buildSocketFactory());
-        
+
         metadataProvider = new FileBackedHTTPMetadataResolver(httpClientBuilder.buildClient(), metadataURLHttps, backupFilePath);
         metadataProvider.setParserPool(parserPool);
         metadataProvider.setId("test");
         final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
-        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildPKIXTrustEngine("badCA.crt", null, false));
+        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildPKIXTrustEngine(
+                ResourceHelper.of(new ClassPathResource(HTTPMetadataResolverTest.DATA_PATH + "badKey.crt")) , null, false));
         metadataProvider.setHttpClientSecurityParameters(params);
 
         try {
@@ -650,7 +697,7 @@ public class FileBackedHTTPMetadataResolverTest extends XMLObjectBaseTestCase {
         metadataProvider.setId("test");
         
         final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
-        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildPKIXTrustEngine("repo-rootCA.crt", "foobar.shibboleth.net", true));
+        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildPKIXTrustEngine(EmbeddedJetty.getServerCertficateResource(), "badlocalhost", true));
         metadataProvider.setHttpClientSecurityParameters(params);
         
         try {
@@ -666,12 +713,13 @@ public class FileBackedHTTPMetadataResolverTest extends XMLObjectBaseTestCase {
     
     @Test
     public void testHTTPSTrustEngineWrongSocketFactory() throws Exception  {
-        // Trust engine set, but appropriate socket factory not set
+        // Trust engine set, but appropriate socket factory not set        
+        
         metadataProvider = new FileBackedHTTPMetadataResolver(httpClientBuilder.buildClient(), metadataURLHttps, backupFilePath);
         metadataProvider.setParserPool(parserPool);
         metadataProvider.setId("test");
         final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
-        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine("repo-entity.crt"));
+        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine(EmbeddedJetty.getServerCertficateResource()));
         metadataProvider.setHttpClientSecurityParameters(params);
 
         try {
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/metadata/resolver/impl/FunctionDrivenDynamicHTTPMetadataResolverTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/metadata/resolver/impl/FunctionDrivenDynamicHTTPMetadataResolverTest.java
index e4b3e5307..e7243a792 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/metadata/resolver/impl/FunctionDrivenDynamicHTTPMetadataResolverTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/metadata/resolver/impl/FunctionDrivenDynamicHTTPMetadataResolverTest.java
@@ -14,10 +14,15 @@
 
 package org.opensaml.saml.metadata.resolver.impl;
 
+import java.net.SocketException;
+import java.net.UnknownHostException;
 import java.security.MessageDigest;
 import java.security.SecureRandom;
 import java.util.Arrays;
 
+import javax.annotation.Nonnull;
+
+
 import org.opensaml.core.criterion.EntityIdCriterion;
 import org.opensaml.core.testing.XMLObjectBaseTestCase;
 import org.opensaml.saml.common.binding.artifact.SAMLSourceIDArtifact;
@@ -27,8 +32,11 @@ import org.opensaml.saml.saml2.binding.artifact.SAML2ArtifactType0004;
 import org.opensaml.saml.saml2.metadata.EntityDescriptor;
 import org.opensaml.security.crypto.JCAConstants;
 import org.opensaml.security.httpclient.HttpClientSecurityParameters;
+import org.springframework.core.io.ClassPathResource;
 import org.testng.Assert;
+import org.testng.annotations.AfterClass;
 import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
@@ -38,19 +46,53 @@ import net.shibboleth.shared.codec.StringDigester;
 import net.shibboleth.shared.codec.StringDigester.OutputFormat;
 import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.httpclient.HttpClientBuilder;
+import net.shibboleth.shared.primitive.NonnullSupplier;
 import net.shibboleth.shared.resolver.CriteriaSet;
-import net.shibboleth.shared.testing.RepositorySupport;
+import net.shibboleth.shared.resource.Resource;
+import net.shibboleth.shared.spring.resource.ResourceHelper;
+import net.shibboleth.shared.testing.EmbeddedJetty;
 import net.shibboleth.shared.testing.VelocityEngine;
 
 @SuppressWarnings("javadoc")
 public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBaseTestCase {
     
+    private EmbeddedJetty jetty;
+    private int jettyStatus;
+
+    private Resource relativeMDResource;
+    
     private FunctionDrivenDynamicHTTPMetadataResolver resolver;
     
     private HttpClientBuilder httpClientBuilder;
     
+    @BeforeClass
+    public void startJetty() throws UnknownHostException, SocketException {
+        relativeMDResource = ResourceHelper.of(new ClassPathResource("org/opensaml/saml/metadata/resolver/impl/localhost-sp.xml"));
+
+        jetty = new EmbeddedJetty();
+        final var handler = new EmbeddedJetty.ResourceHandler(
+                new NonnullSupplier<Integer>() {
+                    @Nonnull public Integer get() {
+                        return jettyStatus;
+                    }
+                },
+                NonnullSupplier.of(relativeMDResource)
+                ); 
+        handler.setContentType("text/xml");
+        jetty.startServer(handler);
+    }
+    
+    @AfterClass
+    public void stopJetty() {
+        if (jetty != null) {
+            jetty.stopServer();
+            jetty = null;
+        }
+    }
+    
     @BeforeMethod
     public void setUp() {
+        jettyStatus = 200;
         httpClientBuilder = new HttpClientBuilder();
     }
     
@@ -65,11 +107,11 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
     @Test
     public void testInactive() throws Exception {
         // Repo should return 'text/xml', which is supported by default.
-        String template = RepositorySupport.buildHTTPResourceURL("java-opensaml", "opensaml-saml-impl/src/test/resources/org/opensaml/saml/metadata/resolver/impl/${entityID}.xml", false);
-        String entityID = "https://www.example.org/sp";
+        final String template = "http://localhost:8080/entities/${entityID}.xml";
+        final String entityID = "https://localhost:8443/sp";
         
         // Digesting the entityID is a little artificial for the test, but means we can test more easily against a path in the repo.
-        TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
+        final TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
                 VelocityEngine.newVelocityEngine(), 
                 template, 
                 EncodingStyle.path, 
@@ -82,20 +124,20 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
         resolver.setActivationCondition(Predicates.alwaysFalse());
         resolver.initialize();
         
-        CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
+        final CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
         
-        EntityDescriptor ed = resolver.resolveSingle(criteriaSet);
+        final EntityDescriptor ed = resolver.resolveSingle(criteriaSet);
         Assert.assertNull(ed);
     }
     
     @Test
     public void testTemplateFromRepoDefaultContentTypes() throws Exception {
-        // Repo should return 'text/xml', which is supported by default.
-        String template = RepositorySupport.buildHTTPResourceURL("java-opensaml", "opensaml-saml-impl/src/test/resources/org/opensaml/saml/metadata/resolver/impl/${entityID}.xml", false);
-        String entityID = "https://www.example.org/sp";
+        // Jetty should return 'text/xml', which is supported by default.
+        final String template = "http://localhost:8080/entities/${entityID}.xml";
+        final String entityID = "https://localhost:8443/sp";
         
         // Digesting the entityID is a little artificial for the test, but means we can test more easily against a path in the repo.
-        TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
+        final TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
                 VelocityEngine.newVelocityEngine(), 
                 template, 
                 EncodingStyle.path, 
@@ -107,52 +149,22 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
         resolver.setRequestURLBuilder(requestURLBuilder);
         resolver.initialize();
         
-        CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
+        final CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
         
         final EntityDescriptor ed = resolver.resolveSingle(criteriaSet);
         assert ed != null;
         Assert.assertEquals(ed.getEntityID(), entityID);
         Assert.assertNull(ed.getDOM());
     }
-   
-    //TODO disabled b/c gitweb currently doesn't seem to have a way to request a different MIME type
-    @Test(enabled=false)
-    public void testTemplateFromRepoWithExplicitContentType() throws Exception {
-        // Explicitly request 'text/plain', and then configure it below to be supported.  Also test case-insensitivity.
-        String template = RepositorySupport.buildHTTPResourceURL("java-opensaml", "opensaml-saml-impl/src/test/resources/org/opensaml/saml/metadata/resolver/impl/${entityID}.xml", false);
-        String entityID = "https://www.example.org/sp";
-        
-        // Digesting the entityID is a little artificial for the test, but means we can test more easily against a path in the repo.
-        TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
-                VelocityEngine.newVelocityEngine(), 
-                template, 
-                EncodingStyle.path, 
-                new StringDigester("SHA-1", OutputFormat.HEX_LOWER));
-        
-        resolver = new FunctionDrivenDynamicHTTPMetadataResolver(httpClientBuilder.buildClient());
-        resolver.setId("myDynamicResolver");
-        resolver.setParserPool(parserPool);
-        resolver.setRequestURLBuilder(requestURLBuilder);
-        resolver.setSupportedContentTypes(Arrays.asList("application/samlmetadata+xml", "application/xml", "text/xml", "TEXT/PLAIN"));
-        resolver.initialize();
-        
-        CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
-        
-        final EntityDescriptor ed = resolver.resolveSingle(criteriaSet);
-        assert ed != null;
-        Assert.assertEquals(ed.getEntityID(), entityID);
-        Assert.assertNull(ed.getDOM());
-    }
-    
-    //TODO disabled b/c gitweb currently doesn't seem to have a way to request a different MIME type
-    @Test(enabled=false)
+
+    @Test
     public void testTemplateFromRepoUnsupportedContentType() throws Exception {
         // Repo should return 'text/plain', which is not supported by default.
-        String template = RepositorySupport.buildHTTPSResourceURL("java-opensaml", "opensaml-saml-impl/src/test/resources/org/opensaml/saml/metadata/resolver/impl/${entityID}.xml");
-        String entityID = "https://www.example.org/sp";
+        final String template = "http://localhost:8080/entities/${entityID}.xml";
+        final String entityID = "https://localhost:8443/sp";
         
         // Digesting the entityID is a little artificial for the test, but means we can test more easily against a path in the repo.
-        TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
+        final TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
                 VelocityEngine.newVelocityEngine(), 
                 template, 
                 EncodingStyle.path, 
@@ -162,9 +174,10 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
         resolver.setId("myDynamicResolver");
         resolver.setParserPool(parserPool);
         resolver.setRequestURLBuilder(requestURLBuilder);
+        resolver.setSupportedContentTypes(Arrays.asList("application/samlmetadata+xml", "application/xml"));
         resolver.initialize();
         
-        CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
+        final CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
         
         final EntityDescriptor ed = resolver.resolveSingle(criteriaSet);
         Assert.assertNull(ed);
@@ -173,10 +186,10 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
     @Test
     public void testTemplateNonexistentDomain() throws Exception {
         // Unresolveable domain.  Should silently fail.
-        String template = "http://bogus.example.org/metadata?entityID=${entityID}";
-        String entityID = "https://www.example.org/sp";
+        final String template = "http://bogus.example.org/metadata?entityID=${entityID}";
+        final String entityID = "https://localhost:8443/sp";
         
-        TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
+        final TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
                 VelocityEngine.newVelocityEngine(), 
                 template, 
                 EncodingStyle.form);
@@ -187,7 +200,7 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
         resolver.setRequestURLBuilder(requestURLBuilder);
         resolver.initialize();
         
-        CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
+        final CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
         
         final EntityDescriptor ed = resolver.resolveSingle(criteriaSet);
         Assert.assertNull(ed);
@@ -195,11 +208,12 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
     
     @Test
     public void testTemplateNonexistentPath() throws Exception {
-        // Bad path, resulting in 404.  Should silently fail.
-        String template = "http://test.shibboleth.net/unittests/metadata?entityID=${entityID}";
-        String entityID = "https://www.example.org/sp";
+        jettyStatus = 404;
+        
+        final String template = "http://localhost:8080/entities/${entityID}.xml";
+        final String entityID = "https://localhost:8443/sp";
         
-        TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
+        final TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
                 VelocityEngine.newVelocityEngine(), 
                 template, 
                 EncodingStyle.form);
@@ -210,7 +224,7 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
         resolver.setRequestURLBuilder(requestURLBuilder);
         resolver.initialize();
         
-        CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
+        final CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
         
         final EntityDescriptor ed = resolver.resolveSingle(criteriaSet);
         Assert.assertNull(ed);
@@ -218,9 +232,9 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
     
     @Test
     public void testWellKnownLocation() throws Exception {
-        String entityID = "https://test.shibboleth.net/shibboleth";
+        final String entityID = "https://localhost:8443/sp";
         
-        HTTPEntityIDRequestURLBuilder requestURLBuilder = new HTTPEntityIDRequestURLBuilder();
+        final HTTPEntityIDRequestURLBuilder requestURLBuilder = new HTTPEntityIDRequestURLBuilder();
         
         httpClientBuilder.setTLSSocketFactory(HTTPMetadataResolverTest.buildSocketFactory());
         
@@ -230,12 +244,12 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
         resolver.setRequestURLBuilder(requestURLBuilder);
         
         final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
-        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine("test.shibboleth.net.crt"));
+        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine(EmbeddedJetty.getServerCertficateResource()));
         resolver.setHttpClientSecurityParameters(params);
         
         resolver.initialize();
         
-        CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
+        final CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
         
         final EntityDescriptor ed = resolver.resolveSingle(criteriaSet);
         assert ed != null;
@@ -245,10 +259,10 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
     
     @Test
     public void testMDQ() throws Exception {
-        String baseURL = "http://mdq.incommon.org";
-        String entityID = "urn:mace:incommon:osu.edu";
+        final String baseURL = "http://mdq.incommon.org";
+        final String entityID = "urn:mace:incommon:osu.edu";
         
-        MetadataQueryProtocolRequestURLBuilder requestURLBuilder = new MetadataQueryProtocolRequestURLBuilder(baseURL);
+        final MetadataQueryProtocolRequestURLBuilder requestURLBuilder = new MetadataQueryProtocolRequestURLBuilder(baseURL);
         
         httpClientBuilder.setConnectionDisregardTLSCertificate(true);
         resolver = new FunctionDrivenDynamicHTTPMetadataResolver(httpClientBuilder.buildClient());
@@ -257,7 +271,7 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
         resolver.setRequestURLBuilder(requestURLBuilder);
         resolver.initialize();
         
-        CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
+        final CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
         
         final EntityDescriptor ed = resolver.resolveSingle(criteriaSet);
         assert ed != null;
@@ -267,10 +281,10 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
     
     @Test
     public void testMDQViaArtifact() throws Exception {
-        String baseURL = "http://mdq.incommon.org";
-        String entityID = "urn:mace:incommon:osu.edu";
+        final String baseURL = "http://mdq.incommon.org";
+        final String entityID = "urn:mace:incommon:osu.edu";
         
-        MetadataQueryProtocolRequestURLBuilder requestURLBuilder = new MetadataQueryProtocolRequestURLBuilder(baseURL,
+        final MetadataQueryProtocolRequestURLBuilder requestURLBuilder = new MetadataQueryProtocolRequestURLBuilder(baseURL,
                 CollectionSupport.singletonList(new SAMLArtifactURLBuilder()));
         
         httpClientBuilder.setConnectionDisregardTLSCertificate(true);
@@ -280,12 +294,12 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
         resolver.setRequestURLBuilder(requestURLBuilder);
         resolver.initialize();
         
-        MessageDigest sha1Digester = MessageDigest.getInstance(JCAConstants.DIGEST_SHA1);
+        final MessageDigest sha1Digester = MessageDigest.getInstance(JCAConstants.DIGEST_SHA1);
         byte[] entityIDSourceID = sha1Digester.digest(entityID.getBytes("UTF-8"));
-        SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
+        final SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
         byte[] messageHandle = new byte[20];
         secureRandom.nextBytes(messageHandle);
-        SAMLSourceIDArtifact sourceIDArtifact = new SAML2ArtifactType0004(new byte[] {0, 0} , entityIDSourceID, messageHandle);
+        final SAMLSourceIDArtifact sourceIDArtifact = new SAML2ArtifactType0004(new byte[] {0, 0} , entityIDSourceID, messageHandle);
         
         final CriteriaSet criteriaSet = new CriteriaSet( new ArtifactCriterion(sourceIDArtifact));
         
@@ -297,11 +311,11 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
     
     @Test
     public void testTrustEngineSocketFactoryNoHTTPSNoTrustEngine() throws Exception {
-        String template = RepositorySupport.buildHTTPResourceURL("java-opensaml", "opensaml-saml-impl/src/test/resources/org/opensaml/saml/metadata/resolver/impl/${entityID}.xml", false);
-        String entityID = "https://www.example.org/sp";
+        final String template = "http://localhost:8080/entities/${entityID}.xml";
+        final String entityID = "https://localhost:8443/sp";
         
         // Digesting the entityID is a little artificial for the test, but means we can test more easily against a path in the repo.
-        TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
+        final TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
                 VelocityEngine.newVelocityEngine(), 
                 template, 
                 EncodingStyle.path, 
@@ -315,7 +329,7 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
         resolver.setRequestURLBuilder(requestURLBuilder);
         resolver.initialize();
         
-        CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
+        final CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
         
         final EntityDescriptor ed = resolver.resolveSingle(criteriaSet);
         assert ed != null;
@@ -325,11 +339,11 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
     
     @Test
     public void testTrustEngineSocketFactoryNoHTTPSWithTrustEngine() throws Exception  {
-        String template = RepositorySupport.buildHTTPResourceURL("java-opensaml", "opensaml-saml-impl/src/test/resources/org/opensaml/saml/metadata/resolver/impl/${entityID}.xml", false);
-        String entityID = "https://www.example.org/sp";
+        final String template = "http://localhost:8080/entities/${entityID}.xml";
+        final String entityID = "https://localhost:8443/sp";
         
         // Digesting the entityID is a little artificial for the test, but means we can test more easily against a path in the repo.
-        TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
+        final TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
                 VelocityEngine.newVelocityEngine(), 
                 template, 
                 EncodingStyle.path, 
@@ -343,12 +357,12 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
         resolver.setRequestURLBuilder(requestURLBuilder);
 
         final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
-        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine("repo-entity.crt"));
+        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine(EmbeddedJetty.getServerCertficateResource()));
         resolver.setHttpClientSecurityParameters(params);
 
         resolver.initialize();
         
-        CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
+        final CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
         
         final EntityDescriptor ed = resolver.resolveSingle(criteriaSet);
         assert ed != null;
@@ -359,14 +373,14 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
     @Test
     public void testHTTPSNoTrustEngine() throws Exception  {
         try {
-            System.setProperty("javax.net.ssl.trustStore", getClass().getResource("repo.truststore.jks").getFile());
-            System.setProperty("javax.net.ssl.trustStorePassword", "shibboleth");
+            System.setProperty("javax.net.ssl.trustStore", EmbeddedJetty.getServerKeystoreResource().getFile().getPath());
+            System.setProperty("javax.net.ssl.trustStorePassword", EmbeddedJetty.getServerKeystorePassword());
             
-            String template = RepositorySupport.buildHTTPSResourceURL("java-opensaml", "opensaml-saml-impl/src/test/resources/org/opensaml/saml/metadata/resolver/impl/${entityID}.xml");
-            String entityID = "https://www.example.org/sp";
+            final String template = "https://localhost:8443/entities/${entityID}.xml";
+            final String entityID = "https://localhost:8443/sp";
 
             // Digesting the entityID is a little artificial for the test, but means we can test more easily against a path in the repo.
-            TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
+            final TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
                     VelocityEngine.newVelocityEngine(), 
                     template, 
                     EncodingStyle.path, 
@@ -380,7 +394,7 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
             resolver.setRequestURLBuilder(requestURLBuilder);
             resolver.initialize();
 
-            CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
+            final CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
 
             final EntityDescriptor ed = resolver.resolveSingle(criteriaSet);
             assert ed != null;
@@ -394,11 +408,11 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
     
     @Test
     public void testHTTPSTrustEngineExplicitKey() throws Exception  {
-        String template = RepositorySupport.buildHTTPSResourceURL("java-opensaml", "opensaml-saml-impl/src/test/resources/org/opensaml/saml/metadata/resolver/impl/${entityID}.xml");
-        String entityID = "https://www.example.org/sp";
+        final String template = "https://localhost:8443/entities/${entityID}.xml";
+        final String entityID = "https://localhost:8443/sp";
         
         // Digesting the entityID is a little artificial for the test, but means we can test more easily against a path in the repo.
-        TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
+        final TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
                 VelocityEngine.newVelocityEngine(), 
                 template, 
                 EncodingStyle.path, 
@@ -412,12 +426,12 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
         resolver.setRequestURLBuilder(requestURLBuilder);
 
         final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
-        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine("repo-entity.crt"));
+        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine(EmbeddedJetty.getServerCertficateResource()));
         resolver.setHttpClientSecurityParameters(params);
-
+        
         resolver.initialize();
         
-        CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
+        final CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
         
         final EntityDescriptor ed = resolver.resolveSingle(criteriaSet);
         assert ed != null;
@@ -427,11 +441,11 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
     
     @Test
     public void testHTTPSTrustEngineInvalidKey()  throws Exception {
-        String template = RepositorySupport.buildHTTPSResourceURL("java-opensaml", "opensaml-saml-impl/src/test/resources/org/opensaml/saml/metadata/resolver/impl/${entityID}.xml");
-        String entityID = "https://www.example.org/sp";
+        final String template = "https://localhost:8443/entities/${entityID}.xml";
+        final String entityID = "https://localhost:8443/sp";
         
         // Digesting the entityID is a little artificial for the test, but means we can test more easily against a path in the repo.
-        TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
+        final TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
                 VelocityEngine.newVelocityEngine(), 
                 template, 
                 EncodingStyle.path, 
@@ -445,12 +459,13 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
         resolver.setRequestURLBuilder(requestURLBuilder);
 
         final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
-        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine("badKey.crt"));
+        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine(
+                ResourceHelper.of(new ClassPathResource(HTTPMetadataResolverTest.DATA_PATH + "badKey.crt"))));
         resolver.setHttpClientSecurityParameters(params);
-
+        
         resolver.initialize();
         
-        CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
+        final CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
         
         final EntityDescriptor ed = resolver.resolveSingle(criteriaSet);
         Assert.assertNull(ed);
@@ -458,11 +473,11 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
     
     @Test
     public void testHTTPSTrustEngineValidPKIX() throws Exception  {
-        String template = RepositorySupport.buildHTTPSResourceURL("java-opensaml", "opensaml-saml-impl/src/test/resources/org/opensaml/saml/metadata/resolver/impl/${entityID}.xml");
-        String entityID = "https://www.example.org/sp";
+        final String template = "https://localhost:8443/entities/${entityID}.xml";
+        final String entityID = "https://localhost:8443/sp";
         
         // Digesting the entityID is a little artificial for the test, but means we can test more easily against a path in the repo.
-        TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
+        final TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
                 VelocityEngine.newVelocityEngine(), 
                 template, 
                 EncodingStyle.path, 
@@ -476,12 +491,12 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
         resolver.setRequestURLBuilder(requestURLBuilder);
 
         final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
-        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildPKIXTrustEngine("repo-rootCA.crt", null, false));
+        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildPKIXTrustEngine(EmbeddedJetty.getServerCertficateResource(), null, false));
         resolver.setHttpClientSecurityParameters(params);
-
+        
         resolver.initialize();
         
-        CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
+        final CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
         
         final EntityDescriptor ed = resolver.resolveSingle(criteriaSet);
         assert ed != null;
@@ -491,11 +506,11 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
     
     @Test
     public void testHTTPSTrustEngineValidPKIXExplicitName() throws Exception  {
-        String template = RepositorySupport.buildHTTPSResourceURL("java-opensaml", "opensaml-saml-impl/src/test/resources/org/opensaml/saml/metadata/resolver/impl/${entityID}.xml");
-        String entityID = "https://www.example.org/sp";
+        final String template = "https://localhost:8443/entities/${entityID}.xml";
+        final String entityID = "https://localhost:8443/sp";
         
         // Digesting the entityID is a little artificial for the test, but means we can test more easily against a path in the repo.
-        TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
+        final TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
                 VelocityEngine.newVelocityEngine(), 
                 template, 
                 EncodingStyle.path, 
@@ -509,12 +524,12 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
         resolver.setRequestURLBuilder(requestURLBuilder);
 
         final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
-        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildPKIXTrustEngine("repo-rootCA.crt", "test.shibboleth.net", true));
+        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildPKIXTrustEngine(EmbeddedJetty.getServerCertficateResource(), "localhost", true));
         resolver.setHttpClientSecurityParameters(params);
-
+        
         resolver.initialize();
         
-        CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
+        final CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
         
         final EntityDescriptor ed = resolver.resolveSingle(criteriaSet);
         assert ed != null;
@@ -524,11 +539,11 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
     
     @Test
     public void testHTTPSTrustEngineInvalidPKIX() throws Exception  {
-        String template = RepositorySupport.buildHTTPSResourceURL("java-opensaml", "opensaml-saml-impl/src/test/resources/org/opensaml/saml/metadata/resolver/impl/${entityID}.xml");
-        String entityID = "https://www.example.org/sp";
+        final String template = "https://localhost:8443/entities/${entityID}.xml";
+        final String entityID = "https://localhost:8443/sp";
         
         // Digesting the entityID is a little artificial for the test, but means we can test more easily against a path in the repo.
-        TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
+        final TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
                 VelocityEngine.newVelocityEngine(), 
                 template, 
                 EncodingStyle.path, 
@@ -542,12 +557,13 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
         resolver.setRequestURLBuilder(requestURLBuilder);
 
         final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
-        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildPKIXTrustEngine("badCA.crt", null, false));
+        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildPKIXTrustEngine(
+                ResourceHelper.of(new ClassPathResource(HTTPMetadataResolverTest.DATA_PATH + "badKey.crt")), null, false));
         resolver.setHttpClientSecurityParameters(params);
-
+        
         resolver.initialize();
         
-        CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
+        final CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
         
         EntityDescriptor ed = resolver.resolveSingle(criteriaSet);
         Assert.assertNull(ed);
@@ -555,11 +571,11 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
     
     @Test
     public void testHTTPSTrustEngineValidPKIXInvalidName() throws Exception  {
-        String template = RepositorySupport.buildHTTPSResourceURL("java-opensaml", "opensaml-saml-impl/src/test/resources/org/opensaml/saml/metadata/resolver/impl/${entityID}.xml");
-        String entityID = "https://www.example.org/sp";
+        final String template = "https://localhost:8443/entities/${entityID}.xml";
+        final String entityID = "https://localhost:8443/sp";
         
         // Digesting the entityID is a little artificial for the test, but means we can test more easily against a path in the repo.
-        TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
+        final TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
                 VelocityEngine.newVelocityEngine(), 
                 template, 
                 EncodingStyle.path, 
@@ -573,24 +589,24 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
         resolver.setRequestURLBuilder(requestURLBuilder);
 
         final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
-        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildPKIXTrustEngine("repo-rootCA.crt", "foobar.shibboleth.net", true));
+        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildPKIXTrustEngine(EmbeddedJetty.getServerCertficateResource(), "localhostbad", true));
         resolver.setHttpClientSecurityParameters(params);
 
         resolver.initialize();
         
-        CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
+        final CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
         
-        EntityDescriptor ed = resolver.resolveSingle(criteriaSet);
+        final EntityDescriptor ed = resolver.resolveSingle(criteriaSet);
         Assert.assertNull(ed);
     }
     
     @Test
     public void testHTTPSTrustEngineWrongSocketFactory() throws Exception  {
-        String template = RepositorySupport.buildHTTPSResourceURL("java-opensaml", "opensaml-saml-impl/src/test/resources/org/opensaml/saml/metadata/resolver/impl/${entityID}.xml");
-        String entityID = "https://www.example.org/sp";
+        final String template = "https://localhost:8443/entities/${entityID}.xml";
+        final String entityID = "https://localhost:8443/sp";
         
         // Digesting the entityID is a little artificial for the test, but means we can test more easily against a path in the repo.
-        TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
+        final TemplateRequestURLBuilder requestURLBuilder = new TemplateRequestURLBuilder(
                 VelocityEngine.newVelocityEngine(), 
                 template, 
                 EncodingStyle.path, 
@@ -604,14 +620,15 @@ public class FunctionDrivenDynamicHTTPMetadataResolverTest extends XMLObjectBase
         resolver.setRequestURLBuilder(requestURLBuilder);
 
         final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
-        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine("repo-entity.crt"));
+        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine(EmbeddedJetty.getServerCertficateResource()));
         resolver.setHttpClientSecurityParameters(params);
 
         resolver.initialize();
         
-        CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
+        final CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
         
-        EntityDescriptor ed = resolver.resolveSingle(criteriaSet);
+        final EntityDescriptor ed = resolver.resolveSingle(criteriaSet);
         Assert.assertNull(ed);
     }
-}
+    
+}
\ No newline at end of file
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/metadata/resolver/impl/HTTPMetadataResolverTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/metadata/resolver/impl/HTTPMetadataResolverTest.java
index c8a354333..bd473f718 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/metadata/resolver/impl/HTTPMetadataResolverTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/metadata/resolver/impl/HTTPMetadataResolverTest.java
@@ -16,11 +16,16 @@ package org.opensaml.saml.metadata.resolver.impl;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.SocketException;
 import java.net.URISyntaxException;
+import java.net.UnknownHostException;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
 import java.util.Set;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 import org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory;
 import org.opensaml.core.criterion.EntityIdCriterion;
 import org.opensaml.core.testing.XMLObjectBaseTestCase;
@@ -39,7 +44,9 @@ import org.opensaml.security.x509.impl.BasicX509CredentialNameEvaluator;
 import org.opensaml.security.x509.impl.CertPathPKIXTrustEvaluator;
 import org.opensaml.security.x509.impl.PKIXX509CredentialTrustEngine;
 import org.opensaml.security.x509.impl.StaticPKIXValidationInformationResolver;
+import org.springframework.core.io.ClassPathResource;
 import org.testng.Assert;
+import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
@@ -52,13 +59,17 @@ import net.shibboleth.shared.httpclient.HttpClientBuilder;
 import net.shibboleth.shared.logic.PredicateSupport;
 import net.shibboleth.shared.resolver.CriteriaSet;
 import net.shibboleth.shared.resolver.ResolverException;
-import net.shibboleth.shared.testing.RepositorySupport;
+import net.shibboleth.shared.resource.Resource;
+import net.shibboleth.shared.spring.resource.ResourceHelper;
+import net.shibboleth.shared.testing.EmbeddedJetty;
 
 /**
  * Unit tests for {@link HTTPMetadataResolver}.
  */
 @SuppressWarnings("javadoc")
 public class HTTPMetadataResolverTest extends XMLObjectBaseTestCase {
+
+    private EmbeddedJetty jetty;
     
     private HttpClientBuilder httpClientBuilder;
 
@@ -72,11 +83,22 @@ public class HTTPMetadataResolverTest extends XMLObjectBaseTestCase {
     static final String DATA_PATH = "/org/opensaml/saml/metadata/resolver/impl/";
     
     @BeforeClass
-    protected void setUpClass() {
-        metadataURLHttps = RepositorySupport.buildHTTPSResourceURL("java-opensaml", "opensaml-saml-impl/src/test/resources/org/opensaml/saml/metadata/resolver/impl/08ced64cddc9f1578598b2cf71ae747b11d11472.xml");
-        metadataURLHttp = RepositorySupport.buildHTTPResourceURL("java-opensaml", "opensaml-saml-impl/src/test/resources/org/opensaml/saml/metadata/resolver/impl/08ced64cddc9f1578598b2cf71ae747b11d11472.xml", false);
+    protected void setUpClass() throws UnknownHostException, SocketException {
+        jetty = new EmbeddedJetty();
+        jetty.startServer(new EmbeddedJetty.ResourceHandler(200,
+                ResourceHelper.of(new ClassPathResource("org/opensaml/saml/metadata/resolver/impl/08ced64cddc9f1578598b2cf71ae747b11d11472.xml"))));
+        metadataURLHttps = "https://localhost:8443/08ced64cddc9f1578598b2cf71ae747b11d11472.xml";
+        metadataURLHttp = "http://localhost:8080/08ced64cddc9f1578598b2cf71ae747b11d11472.xml";
     }
 
+    @AfterClass
+    public void stopJetty() {
+        if (jetty != null) {
+            jetty.stopServer();
+            jetty = null;
+        }
+    }
+    
     @BeforeMethod
     protected void setUpMethod() throws Exception {
         httpClientBuilder = new HttpClientBuilder();
@@ -217,7 +239,7 @@ public class HTTPMetadataResolverTest extends XMLObjectBaseTestCase {
         metadataProvider.setId("test");
 
         final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
-        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine("repo-entity.crt"));
+        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine(EmbeddedJetty.getServerCertficateResource()));
         metadataProvider.setHttpClientSecurityParameters(params);
         metadataProvider.initialize();
         
@@ -233,8 +255,8 @@ public class HTTPMetadataResolverTest extends XMLObjectBaseTestCase {
     @Test
     public void testHTTPSNoTrustEngine() throws Exception  {
         try {
-            System.setProperty("javax.net.ssl.trustStore", getClass().getResource("repo.truststore.jks").getFile());
-            System.setProperty("javax.net.ssl.trustStorePassword", "shibboleth");
+            System.setProperty("javax.net.ssl.trustStore", EmbeddedJetty.getServerKeystoreResource().getFile().getPath());
+            System.setProperty("javax.net.ssl.trustStorePassword", EmbeddedJetty.getServerKeystorePassword());
 
             httpClientBuilder.setTLSSocketFactory(buildSocketFactory(false));
 
@@ -265,7 +287,7 @@ public class HTTPMetadataResolverTest extends XMLObjectBaseTestCase {
         metadataProvider.setId("test");
 
         final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
-        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine("repo-entity.crt"));
+        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine(EmbeddedJetty.getServerCertficateResource()));
         metadataProvider.setHttpClientSecurityParameters(params);
 
         metadataProvider.initialize();
@@ -289,7 +311,8 @@ public class HTTPMetadataResolverTest extends XMLObjectBaseTestCase {
         metadataProvider.setId("test");
 
         final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
-        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine("badKey.crt"));
+        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine(
+                ResourceHelper.of(new ClassPathResource(HTTPMetadataResolverTest.DATA_PATH + "badKey.crt"))));
         metadataProvider.setHttpClientSecurityParameters(params);
 
         try {
@@ -312,7 +335,7 @@ public class HTTPMetadataResolverTest extends XMLObjectBaseTestCase {
         metadataProvider.setId("test");
 
         final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
-        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildPKIXTrustEngine("repo-rootCA.crt", null, false));
+        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildPKIXTrustEngine(EmbeddedJetty.getServerCertficateResource(), null, false));
         metadataProvider.setHttpClientSecurityParameters(params);
 
         metadataProvider.initialize();
@@ -335,7 +358,7 @@ public class HTTPMetadataResolverTest extends XMLObjectBaseTestCase {
         metadataProvider.setId("test");
 
         final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
-        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildPKIXTrustEngine("repo-rootCA.crt", "test.shibboleth.net", true));
+        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildPKIXTrustEngine(EmbeddedJetty.getServerCertficateResource(), "localhost", true));
         metadataProvider.setHttpClientSecurityParameters(params);
 
         metadataProvider.initialize();
@@ -358,7 +381,8 @@ public class HTTPMetadataResolverTest extends XMLObjectBaseTestCase {
         metadataProvider.setId("test");
 
         final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
-        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildPKIXTrustEngine("badCA.crt", null, false));
+        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildPKIXTrustEngine(
+                ResourceHelper.of(new ClassPathResource(HTTPMetadataResolverTest.DATA_PATH + "badCA.crt")), null, false));
         metadataProvider.setHttpClientSecurityParameters(params);
 
         try {
@@ -381,7 +405,7 @@ public class HTTPMetadataResolverTest extends XMLObjectBaseTestCase {
         metadataProvider.setId("test");
 
         final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
-        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildPKIXTrustEngine("repo-rootCA.crt", "foobar.shibboleth.net", true));
+        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildPKIXTrustEngine(EmbeddedJetty.getServerCertficateResource(), "badlocalhost", true));
         metadataProvider.setHttpClientSecurityParameters(params);
 
         try {
@@ -403,7 +427,7 @@ public class HTTPMetadataResolverTest extends XMLObjectBaseTestCase {
         metadataProvider.setId("test");
 
         final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
-        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine("repo-entity.crt"));
+        params.setTLSTrustEngine(HTTPMetadataResolverTest.buildExplicitKeyTrustEngine(EmbeddedJetty.getServerCertficateResource()));
         metadataProvider.setHttpClientSecurityParameters(params);
 
         try {
@@ -418,26 +442,27 @@ public class HTTPMetadataResolverTest extends XMLObjectBaseTestCase {
     }
     
     // Helpers
-    
-    public static TrustEngine<? super X509Credential> buildPKIXTrustEngine(String cert, String name, boolean nameCheckEnabled) throws URISyntaxException, CertificateException, IOException {
-        final InputStream certStream = FileBackedHTTPMetadataResolver.class.getResourceAsStream((HTTPMetadataResolverTest.DATA_PATH + cert));
-        final X509Certificate rootCert = X509Support.decodeCertificate(ByteStreams.toByteArray(certStream));
-        final PKIXValidationInformation info = new BasicPKIXValidationInformation(CollectionSupport.singletonList(rootCert), null, 5);
-        final Set<String> trustedNames = name != null ? CollectionSupport.singleton(name) : CollectionSupport.emptySet();
-        final StaticPKIXValidationInformationResolver resolver = new StaticPKIXValidationInformationResolver(CollectionSupport.singletonList(info), trustedNames);
-        return new PKIXX509CredentialTrustEngine(resolver,
-                new CertPathPKIXTrustEvaluator(),
-                (nameCheckEnabled ? new BasicX509CredentialNameEvaluator() : null));
-    }
 
-    public static TrustEngine<? super X509Credential> buildExplicitKeyTrustEngine(String cert) throws URISyntaxException, CertificateException, IOException {
-        
-        final InputStream certStream = FileBackedHTTPMetadataResolver.class.getResourceAsStream(HTTPMetadataResolverTest.DATA_PATH + cert);
-        final X509Certificate entityCert = X509Support.decodeCertificate(ByteStreams.toByteArray(certStream));
-        final X509Credential entityCredential = new BasicX509Credential(entityCert);
-        return new ExplicitKeyTrustEngine(new StaticCredentialResolver(entityCredential));
-        
+    public static TrustEngine<? super X509Credential> buildPKIXTrustEngine(@Nonnull final Resource cert, @Nullable final String name,
+            final boolean nameCheckEnabled) throws URISyntaxException, CertificateException, IOException {
+        try (final InputStream certStream = cert.getInputStream()) {
+            final X509Certificate rootCert = X509Support.decodeCertificate(ByteStreams.toByteArray(certStream));
+            final PKIXValidationInformation info = new BasicPKIXValidationInformation(CollectionSupport.singletonList(rootCert), null, 5);
+            final Set<String> trustedNames = name != null ? CollectionSupport.singleton(name) : CollectionSupport.emptySet();
+            final StaticPKIXValidationInformationResolver resolver = new StaticPKIXValidationInformationResolver(CollectionSupport.singletonList(info), trustedNames);
+            return new PKIXX509CredentialTrustEngine(resolver,
+                    new CertPathPKIXTrustEvaluator(),
+                    (nameCheckEnabled ? new BasicX509CredentialNameEvaluator() : null));
+        }
     }
+    
+    public static TrustEngine<? super X509Credential> buildExplicitKeyTrustEngine(@Nonnull final Resource cert) throws URISyntaxException, CertificateException, IOException {
+        try (final InputStream certStream = cert.getInputStream()) {
+            final X509Certificate entityCert = X509Support.decodeCertificate(ByteStreams.toByteArray(certStream));
+            final X509Credential entityCredential = new BasicX509Credential(entityCert);
+            return new ExplicitKeyTrustEngine(new StaticCredentialResolver(entityCredential));
+        }
+    }    
 
     public static LayeredConnectionSocketFactory buildSocketFactory() {
         return buildSocketFactory(true);
diff --git a/opensaml-saml-impl/src/test/resources/org/opensaml/saml/metadata/resolver/impl/localhost-sp.xml b/opensaml-saml-impl/src/test/resources/org/opensaml/saml/metadata/resolver/impl/localhost-sp.xml
new file mode 100644
index 000000000..f9cf230b0
--- /dev/null
+++ b/opensaml-saml-impl/src/test/resources/org/opensaml/saml/metadata/resolver/impl/localhost-sp.xml
@@ -0,0 +1,49 @@
+<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_a3623fbbcb6af813c50b67a828668b1e55ae2c0f" entityID="https://localhost:8443/sp">
+
+  <md:SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol urn:oasis:names:tc:SAML:1.1:protocol urn:oasis:names:tc:SAML:1.0:protocol">
+    <md:Extensions>
+      <init:RequestInitiator xmlns:init="urn:oasis:names:tc:SAML:profiles:SSO:request-init" Binding="urn:oasis:names:tc:SAML:profiles:SSO:request-init" Location="https://www.example.org/Shibboleth.sso/Login"/>
+      <idpdisc:DiscoveryResponse xmlns:idpdisc="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Binding="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Location="https://www.example.org/Shibboleth.sso/Login" index="1"/>
+    </md:Extensions>
+    <md:KeyDescriptor>
+      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+        <ds:KeyName>https://www.example.org/shibboleth</ds:KeyName>
+        <ds:KeyName>www.example.org</ds:KeyName>
+        <ds:X509Data>
+          <ds:X509SubjectName>CN=www.example.org</ds:X509SubjectName>
+          <ds:X509Certificate>MIIDRDCCAiygAwIBAgIJAIc3DausM4oaMA0GCSqGSIb3DQEBBQUAMCUxIzAhBgNV
+BAMTGnd3dy5saWJyYXJ5Lmdlb3JnZXRvd24uZWR1MB4XDTEyMDgwOTIxMjIwNFoX
+DTMyMDgwNDIxMjIwNFowJTEjMCEGA1UEAxMad3d3LmxpYnJhcnkuZ2VvcmdldG93
+bi5lZHUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkc0sA/9cehYrs
+AR8nT0Me8JcKIFeFZlAi9jp0vhvsF8tbbhq9diZjaCeww93yfeDPC9u9wi6ya40x
+gkLHLeBinYJlDruk84QLrRImQ1di4rJQgBBt/wLr+wZQgeuo/P+es0ox9VU+fBqr
+xQRHvenkw/LKPuCz7mkhotZt/zy0UnNcq5o5t6tsZLU+BbSUWoBoB3MQXzN/PjMq
+ROks9/v90HtUCiF9J7hPDpxLLJ7qkvJ+YpfuBcQB5NevoDv423cwwfkJGBJAu3Do
+Qs2vWOfS3AwDh8Cee43wjZB5eD44y+cVIeed16WehDKnXQ+DEcKnHzxF6IRMU+d1
+4kLs+QZHAgMBAAGjdzB1MFQGA1UdEQRNMEuCGnd3dy5saWJyYXJ5Lmdlb3JnZXRv
+d24uZWR1hi1odHRwczovL3d3dy5saWJyYXJ5Lmdlb3JnZXRvd24uZWR1L3NoaWJi
+b2xldGgwHQYDVR0OBBYEFO1vnaFkb0y5fLvOjUVlqDwIOWphMA0GCSqGSIb3DQEB
+BQUAA4IBAQDBEJbbxyd3IH5Kc6ZPNEJmSNEau5AeTeU3YNv5+I7OhpWbVjxtITTy
++IOnd8s8+1YbcwFJRsPQXc+uboTiVF9B+CHlJQ+mwgUH1ePBVG9PUwaRrX0my88c
+XEQptBIVdUqaNwuBBMQzUr2/UZK6EaStRor/yRrEgZNnPUFWtsW+sCG406gGbcxU
+93RurxLa4Cv0sE+SEFMkQnnmAN7odx6qM/1I1TCQPN0t4JfWjmhj8Iez0lnGMQPh
+NWevYWCdgIDPlYhhvJ9gnHu8JOfFRlZCXpc2p+x7Nsrudb+5Hhs7x93xciVyrttQ
+Iul4vX+c2dQrUz0m7rJ8tdZDwyQvUvwd
+</ds:X509Certificate>
+        </ds:X509Data>
+      </ds:KeyInfo>
+    </md:KeyDescriptor>
+    <md:ArtifactResolutionService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://www.example.org/Shibboleth.sso/Artifact/SOAP" index="0"/>
+    <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://www.example.org/Shibboleth.sso/SLO/SOAP"/>
+    <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://www.example.org/Shibboleth.sso/SLO/Redirect"/>
+    <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://www.example.org/Shibboleth.sso/SLO/POST"/>
+    <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="https://www.example.org/Shibboleth.sso/SLO/Artifact"/>
+    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://www.example.org/Shibboleth.sso/SAML2/POST" index="0"/>
+    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" Location="https://www.example.org/Shibboleth.sso/SAML2/POST-SimpleSign" index="1"/>
+    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="https://www.example.org/Shibboleth.sso/SAML2/Artifact" index="2"/>
+    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:PAOS" Location="https://www.example.org/Shibboleth.sso/SAML2/ECP" index="3"/>
+    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:1.0:profiles:browser-post" Location="https://www.example.org/Shibboleth.sso/SAML/POST" index="4"/>
+    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:1.0:profiles:artifact-01" Location="https://www.example.org/Shibboleth.sso/SAML/Artifact" index="5"/>
+  </md:SPSSODescriptor>
+
+</md:EntityDescriptor>
diff --git a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/signature/support/tests/DetachedSignatureTest.java b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/signature/support/tests/DetachedSignatureTest.java
index 26aa35f58..351df46cd 100644
--- a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/signature/support/tests/DetachedSignatureTest.java
+++ b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/signature/support/tests/DetachedSignatureTest.java
@@ -14,6 +14,7 @@
 
 package org.opensaml.xmlsec.signature.support.tests;
 
+import java.io.IOException;
 import java.security.KeyPair;
 import java.util.List;
 
@@ -42,13 +43,15 @@ import org.opensaml.xmlsec.signature.support.SignatureValidator;
 import org.opensaml.xmlsec.signature.support.Signer;
 import org.opensaml.xmlsec.signature.support.URIContentReference;
 import org.slf4j.Logger;
+import org.springframework.core.io.ClassPathResource;
 import org.testng.Assert;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 import org.w3c.dom.Element;
 
 import net.shibboleth.shared.primitive.LoggerFactory;
-import net.shibboleth.shared.testing.RepositorySupport;
+import net.shibboleth.shared.spring.resource.ResourceHelper;
+import net.shibboleth.shared.testing.EmbeddedJetty;
 import net.shibboleth.shared.xml.SerializeSupport;
 import net.shibboleth.shared.xml.impl.BasicParserPool;
 
@@ -135,10 +138,11 @@ public class DetachedSignatureTest extends XMLObjectBaseTestCase {
      * external references used are the InCommon and InQueue metadata files.
      * 
      * @throws MarshallingException thrown if the XMLObject tree can not be marshalled
-     * @throws SignatureException ...
+     * @throws SignatureException
+     * @throws IOException 
      */
     @Test
-    public void testExternalSignatureAndVerification() throws MarshallingException, SignatureException {
+    public void testExternalSignatureAndVerification() throws MarshallingException, SignatureException, IOException {
         // This is necessary as of Santuario 2.3.0, which removed the -DirectHTTP and -LocalFilesystem resolvers by default.
         // Unfortunately it's stored in static storage and no way to clear or reset after the test.
         ResourceResolver.register(new ResolverDirectHTTP(), false);
@@ -149,21 +153,32 @@ public class DetachedSignatureTest extends XMLObjectBaseTestCase {
         signature.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA);
 
         //Note: we have to use a http URL here, not https, as current default Santuario HTTP ResourceResolver doesn't support https URLs.
-        String incommonMetadata = (RepositorySupport.buildHTTPResourceURL("java-opensaml", "opensaml-xmlsec-impl/src/test/resources/org/opensaml/xmlsec/signature/support/InCommon-metadata.xml", false));
-        URIContentReference contentReference = new URIContentReference(incommonMetadata);
+        URIContentReference contentReference = new URIContentReference("http://localhost:8080/InCommon-metadata.xml");
         contentReference.getTransforms().add(SignatureConstants.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
         contentReference.setDigestAlgorithm(SignatureConstants.ALGO_ID_DIGEST_SHA1);
         signature.getContentReferences().add(contentReference);
 
         Marshaller marshaller = XMLObjectProviderRegistrySupport.getMarshallerFactory().ensureMarshaller(signature);
         Element signatureElement = marshaller.marshall(signature);
-
-        Signer.signObject(signature);
-        if (log.isDebugEnabled()) {
-            log.debug("Marshalled deatched Signature: \n" + SerializeSupport.nodeToString(signatureElement));
+        
+        try (final EmbeddedJetty jetty = new EmbeddedJetty()) {
+            jetty.startServer(new EmbeddedJetty.ResourceHandler(200,
+                    ResourceHelper.of(new ClassPathResource("org/opensaml/xmlsec/signature/support/InCommon-metadata.xml"))));
+
+            Signer.signObject(signature);
+            if (log.isDebugEnabled()) {
+                log.debug("Marshalled deatched Signature: \n" + SerializeSupport.nodeToString(signatureElement));
+            }
+
+            SignatureValidator.validate(signature, goodCredential);
+            
+            try {
+                SignatureValidator.validate(signature, badCredential);
+                Assert.fail("Validated signature with improper public key");
+            } catch (SignatureException e) {
+                // expected
+            }
         }
-
-        SignatureValidator.validate(signature, goodCredential);
     }
 
     /**

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list