[java-opensaml] branch main updated: OSJ-353 - Move IdP Spring support for credentials/trust into new module

Scott Cantor cantor.2 at osu.edu
Tue Jul 5 14:28:08 UTC 2022


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

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

View the commit online:
http://git.shibboleth.net/view/?p=java-opensaml.git;a=commit;h=06c5567e6668bfb4028bfb59441b4d0b7db1644c

The following commit(s) were added to refs/heads/main by this push:
     new 06c5567e6 OSJ-353 - Move IdP Spring support for credentials/trust into new module
06c5567e6 is described below

commit 06c5567e6668bfb4028bfb59441b4d0b7db1644c
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Jul 5 10:27:35 2022 -0400

    OSJ-353 - Move IdP Spring support for credentials/trust into new module
    
    https://shibboleth.atlassian.net/browse/OSJ-353
---
 opensaml-bom/pom.xml                               |   5 +
 opensaml-core/.classpath                           |   1 +
 opensaml-core/.project                             |  12 +
 .../.settings/org.eclipse.wst.common.component     |   6 +
 .../org.eclipse.wst.common.project.facet.core.xml  |   5 +
 opensaml-messaging-api/.classpath                  |   1 +
 opensaml-messaging-api/.project                    |  12 +
 .../.settings/org.eclipse.wst.common.component     |   6 +
 .../org.eclipse.wst.common.project.facet.core.xml  |   5 +
 opensaml-messaging-impl/.classpath                 |   1 +
 opensaml-messaging-impl/.project                   |  12 +
 .../.settings/org.eclipse.wst.common.component     |   6 +
 .../org.eclipse.wst.common.project.facet.core.xml  |   5 +
 opensaml-parent/pom.xml                            |   2 +
 opensaml-profile-api/.classpath                    |   1 +
 opensaml-profile-api/.project                      |  12 +
 .../.settings/org.eclipse.wst.common.component     |   6 +
 .../org.eclipse.wst.common.project.facet.core.xml  |   5 +
 opensaml-profile-impl/.classpath                   |   1 +
 opensaml-profile-impl/.project                     |  12 +
 .../.settings/org.eclipse.wst.common.component     |   6 +
 .../org.eclipse.wst.common.project.facet.core.xml  |   5 +
 opensaml-saml-api/.classpath                       |   1 +
 opensaml-saml-api/.project                         |  12 +
 .../.settings/org.eclipse.wst.common.component     |   6 +
 .../org.eclipse.wst.common.project.facet.core.xml  |   5 +
 opensaml-saml-impl/.classpath                      |   1 +
 opensaml-saml-impl/.project                        |  12 +
 .../.settings/org.eclipse.wst.common.component     |   6 +
 .../org.eclipse.wst.common.project.facet.core.xml  |   5 +
 opensaml-security-api/.classpath                   |   1 +
 opensaml-security-api/.project                     |  12 +
 .../.settings/org.eclipse.wst.common.component     |   6 +
 .../org.eclipse.wst.common.project.facet.core.xml  |   5 +
 opensaml-security-impl/.classpath                  |   1 +
 opensaml-security-impl/.project                    |  12 +
 .../.settings/org.eclipse.wst.common.component     |   6 +
 .../org.eclipse.wst.common.project.facet.core.xml  |   5 +
 opensaml-soap-api/.classpath                       |   1 +
 opensaml-soap-api/.project                         |  12 +
 .../.settings/org.eclipse.wst.common.component     |   6 +
 .../org.eclipse.wst.common.project.facet.core.xml  |   5 +
 opensaml-soap-impl/.classpath                      |   1 +
 opensaml-soap-impl/.project                        |  12 +
 .../.settings/org.eclipse.wst.common.component     |   6 +
 .../org.eclipse.wst.common.project.facet.core.xml  |   5 +
 opensaml-spring/.checkstyle                        |  15 +
 .../.classpath                                     |   2 +
 opensaml-spring/.gitignore                         |   2 +
 .../.project                                       |  15 +-
 .../.settings/org.eclipse.core.resources.prefs     |   6 +
 .../.settings/org.eclipse.jdt.core.prefs           | 413 +++++++++++++++++++++
 opensaml-spring/.settings/org.eclipse.jdt.ui.prefs |  63 ++++
 .../.settings/org.eclipse.m2e.core.prefs           |   4 +
 .../.settings/org.eclipse.wst.common.component     |   6 +
 .../org.eclipse.wst.common.project.facet.core.xml  |   5 +
 opensaml-spring/pom.xml                            | 102 +++++
 .../AbstractBasicCredentialFactoryBean.java        | 207 +++++++++++
 .../credential/AbstractCredentialFactoryBean.java  | 144 +++++++
 .../AbstractX509CredentialFactoryBean.java         | 133 +++++++
 .../BasicInlineCredentialFactoryBean.java          | 126 +++++++
 .../BasicResourceCredentialFactoryBean.java        | 147 ++++++++
 .../credential/BasicX509CredentialFactoryBean.java | 224 +++++++++++
 .../X509InlineCredentialFactoryBean.java           | 147 ++++++++
 .../opensaml/spring/credential/package-info.java   |  22 ++
 .../spring/tls/TLSSocketFactoryFactoryBean.java    |  96 +++++
 .../java/org/opensaml/spring/tls/package-info.java |  22 ++
 ...AbstractBasicPKIXValidationInfoFactoryBean.java | 103 +++++
 .../ChainingSignatureTrustEngineFactoryBean.java   |  69 ++++
 .../trust/ChainingTrustEngineFactoryBean.java      |  70 ++++
 .../trust/PKIXInlineValidationInfoFactoryBean.java | 107 ++++++
 .../PKIXResourceValidationInfoFactoryBean.java     | 112 ++++++
 .../spring/trust/StaticExplicitKeyFactoryBean.java | 140 +++++++
 .../spring/trust/StaticPKIXFactoryBean.java        | 277 ++++++++++++++
 .../org/opensaml/spring/trust/package-info.java    |  22 ++
 .../BasicX509CredentialFactoryBeanTest.java        |  60 +++
 .../spring/trust/AbstractSecurityTest.java         |  97 +++++
 .../org/opensaml/spring/trust/MockTrustEngine.java |  44 +++
 .../trust/StaticExplicitKeyFactoryBeanTest.java    |  96 +++++
 .../spring/trust/StaticPKIXFactoryBeanTest.java    | 132 +++++++
 .../org/opensaml/spring/credential/bean.xml        |  28 ++
 .../org/opensaml/spring/credential/cert.pem        |  22 ++
 .../org/opensaml/spring/credential/certificate.pem |  52 +++
 .../org/opensaml/spring/credential/idp-signing.crt |  22 ++
 .../org/opensaml/spring/credential/idp-signing.key |  27 ++
 .../spring/credential/idp-signing.key.pass         |  30 ++
 .../org/opensaml/spring/credential/publicKey.pem   |   9 +
 .../static-pkix-factory-custom-failsValidation.xml |  34 ++
 .../trust/static-pkix-factory-custom-success.xml   |  30 ++
 .../spring/trust/static-pkix-factory-defaults.xml  |  24 ++
 .../opensaml/spring/trust/staticExplicitNative.xml |  28 ++
 opensaml-storage-api/.classpath                    |   1 +
 opensaml-storage-api/.project                      |  60 +--
 .../.settings/org.eclipse.wst.common.component     |   6 +
 .../org.eclipse.wst.common.project.facet.core.xml  |   5 +
 opensaml-storage-impl/.classpath                   |   1 +
 opensaml-storage-impl/.project                     |  12 +
 .../.settings/org.eclipse.wst.common.component     |   6 +
 .../org.eclipse.wst.common.project.facet.core.xml  |   5 +
 opensaml-tests-bom/pom.xml                         |   7 +
 opensaml-xmlsec-api/.classpath                     |   1 +
 opensaml-xmlsec-api/.project                       |  12 +
 .../.settings/org.eclipse.wst.common.component     |   6 +
 .../org.eclipse.wst.common.project.facet.core.xml  |   5 +
 opensaml-xmlsec-impl/.classpath                    |   1 +
 opensaml-xmlsec-impl/.project                      |  12 +
 .../.settings/org.eclipse.wst.common.component     |   6 +
 .../org.eclipse.wst.common.project.facet.core.xml  |   5 +
 108 files changed, 3930 insertions(+), 28 deletions(-)

diff --git a/opensaml-bom/pom.xml b/opensaml-bom/pom.xml
index aa0bc06bf..3d71b1dd2 100644
--- a/opensaml-bom/pom.xml
+++ b/opensaml-bom/pom.xml
@@ -73,6 +73,11 @@
                 <artifactId>opensaml-soap-impl</artifactId>
                 <version>${project.version}</version>
             </dependency>
+            <dependency>
+                <groupId>${project.groupId}</groupId>
+                <artifactId>opensaml-spring</artifactId>
+                <version>${project.version}</version>
+            </dependency>
             <dependency>
                 <groupId>${project.groupId}</groupId>
                 <artifactId>opensaml-storage-api</artifactId>
diff --git a/opensaml-core/.classpath b/opensaml-core/.classpath
index 77be441ed..8c2ac107c 100644
--- a/opensaml-core/.classpath
+++ b/opensaml-core/.classpath
@@ -32,6 +32,7 @@
 	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
 		<attributes>
 			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="org.eclipse.jst.component.nondependency" value=""/>
 		</attributes>
 	</classpathentry>
 	<classpathentry kind="output" path="target/classes"/>
diff --git a/opensaml-core/.project b/opensaml-core/.project
index 757d7c8fd..d34925c73 100644
--- a/opensaml-core/.project
+++ b/opensaml-core/.project
@@ -5,6 +5,11 @@
 	<projects>
 	</projects>
 	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 		<buildCommand>
 			<name>org.eclipse.jdt.core.javabuilder</name>
 			<arguments>
@@ -20,10 +25,17 @@
 			<arguments>
 			</arguments>
 		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 	</buildSpec>
 	<natures>
 		<nature>org.eclipse.m2e.core.maven2Nature</nature>
 		<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
 	</natures>
 </projectDescription>
diff --git a/opensaml-core/.settings/org.eclipse.wst.common.component b/opensaml-core/.settings/org.eclipse.wst.common.component
new file mode 100644
index 000000000..da1ba7740
--- /dev/null
+++ b/opensaml-core/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="opensaml-core">
+        <wb-resource deploy-path="/" source-path="/src/main/java"/>
+        <wb-resource deploy-path="/" source-path="/src/main/resources"/>
+    </wb-module>
+</project-modules>
diff --git a/opensaml-core/.settings/org.eclipse.wst.common.project.facet.core.xml b/opensaml-core/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 000000000..9ba61b70c
--- /dev/null
+++ b/opensaml-core/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <installed facet="java" version="17"/>
+  <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
diff --git a/opensaml-messaging-api/.classpath b/opensaml-messaging-api/.classpath
index 77be441ed..8c2ac107c 100644
--- a/opensaml-messaging-api/.classpath
+++ b/opensaml-messaging-api/.classpath
@@ -32,6 +32,7 @@
 	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
 		<attributes>
 			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="org.eclipse.jst.component.nondependency" value=""/>
 		</attributes>
 	</classpathentry>
 	<classpathentry kind="output" path="target/classes"/>
diff --git a/opensaml-messaging-api/.project b/opensaml-messaging-api/.project
index ff5ddf77b..16825a759 100644
--- a/opensaml-messaging-api/.project
+++ b/opensaml-messaging-api/.project
@@ -5,6 +5,11 @@
 	<projects>
 	</projects>
 	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 		<buildCommand>
 			<name>org.eclipse.jdt.core.javabuilder</name>
 			<arguments>
@@ -20,10 +25,17 @@
 			<arguments>
 			</arguments>
 		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 	</buildSpec>
 	<natures>
 		<nature>org.eclipse.m2e.core.maven2Nature</nature>
 		<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
 	</natures>
 </projectDescription>
diff --git a/opensaml-messaging-api/.settings/org.eclipse.wst.common.component b/opensaml-messaging-api/.settings/org.eclipse.wst.common.component
new file mode 100644
index 000000000..7f24b93eb
--- /dev/null
+++ b/opensaml-messaging-api/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="opensaml-messaging-api">
+        <wb-resource deploy-path="/" source-path="/src/main/java"/>
+        <wb-resource deploy-path="/" source-path="/src/main/resources"/>
+    </wb-module>
+</project-modules>
diff --git a/opensaml-messaging-api/.settings/org.eclipse.wst.common.project.facet.core.xml b/opensaml-messaging-api/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 000000000..9ba61b70c
--- /dev/null
+++ b/opensaml-messaging-api/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <installed facet="java" version="17"/>
+  <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
diff --git a/opensaml-messaging-impl/.classpath b/opensaml-messaging-impl/.classpath
index 77be441ed..8c2ac107c 100644
--- a/opensaml-messaging-impl/.classpath
+++ b/opensaml-messaging-impl/.classpath
@@ -32,6 +32,7 @@
 	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
 		<attributes>
 			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="org.eclipse.jst.component.nondependency" value=""/>
 		</attributes>
 	</classpathentry>
 	<classpathentry kind="output" path="target/classes"/>
diff --git a/opensaml-messaging-impl/.project b/opensaml-messaging-impl/.project
index c29a25afb..516d594eb 100644
--- a/opensaml-messaging-impl/.project
+++ b/opensaml-messaging-impl/.project
@@ -5,6 +5,11 @@
 	<projects>
 	</projects>
 	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 		<buildCommand>
 			<name>org.eclipse.jdt.core.javabuilder</name>
 			<arguments>
@@ -25,11 +30,18 @@
 			<arguments>
 			</arguments>
 		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 	</buildSpec>
 	<natures>
 		<nature>org.springframework.ide.eclipse.core.springnature</nature>
 		<nature>org.eclipse.m2e.core.maven2Nature</nature>
 		<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
 	</natures>
 </projectDescription>
diff --git a/opensaml-messaging-impl/.settings/org.eclipse.wst.common.component b/opensaml-messaging-impl/.settings/org.eclipse.wst.common.component
new file mode 100644
index 000000000..96089f781
--- /dev/null
+++ b/opensaml-messaging-impl/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="opensaml-messaging-impl">
+        <wb-resource deploy-path="/" source-path="/src/main/java"/>
+        <wb-resource deploy-path="/" source-path="/src/main/resources"/>
+    </wb-module>
+</project-modules>
diff --git a/opensaml-messaging-impl/.settings/org.eclipse.wst.common.project.facet.core.xml b/opensaml-messaging-impl/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 000000000..9ba61b70c
--- /dev/null
+++ b/opensaml-messaging-impl/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <installed facet="java" version="17"/>
+  <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
diff --git a/opensaml-parent/pom.xml b/opensaml-parent/pom.xml
index 741bcfe3c..a6549679f 100644
--- a/opensaml-parent/pom.xml
+++ b/opensaml-parent/pom.xml
@@ -47,6 +47,8 @@
         <module>../opensaml-xacml-saml-impl</module>
         <module>../opensaml-profile-api</module>
         <module>../opensaml-profile-impl</module>
+        
+        <module>../opensaml-spring</module>
 
         <module>../opensaml-bom</module>
         <module>../opensaml-tests-bom</module>
diff --git a/opensaml-profile-api/.classpath b/opensaml-profile-api/.classpath
index 77be441ed..8c2ac107c 100644
--- a/opensaml-profile-api/.classpath
+++ b/opensaml-profile-api/.classpath
@@ -32,6 +32,7 @@
 	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
 		<attributes>
 			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="org.eclipse.jst.component.nondependency" value=""/>
 		</attributes>
 	</classpathentry>
 	<classpathentry kind="output" path="target/classes"/>
diff --git a/opensaml-profile-api/.project b/opensaml-profile-api/.project
index b43f792bb..af049c813 100644
--- a/opensaml-profile-api/.project
+++ b/opensaml-profile-api/.project
@@ -5,6 +5,11 @@
 	<projects>
 	</projects>
 	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 		<buildCommand>
 			<name>org.eclipse.jdt.core.javabuilder</name>
 			<arguments>
@@ -25,11 +30,18 @@
 			<arguments>
 			</arguments>
 		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 	</buildSpec>
 	<natures>
 		<nature>org.springframework.ide.eclipse.core.springnature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
 		<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
 		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
 	</natures>
 </projectDescription>
diff --git a/opensaml-profile-api/.settings/org.eclipse.wst.common.component b/opensaml-profile-api/.settings/org.eclipse.wst.common.component
new file mode 100644
index 000000000..79b3cb1f5
--- /dev/null
+++ b/opensaml-profile-api/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="opensaml-profile-api">
+        <wb-resource deploy-path="/" source-path="/src/main/java"/>
+        <wb-resource deploy-path="/" source-path="/src/main/resources"/>
+    </wb-module>
+</project-modules>
diff --git a/opensaml-profile-api/.settings/org.eclipse.wst.common.project.facet.core.xml b/opensaml-profile-api/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 000000000..9ba61b70c
--- /dev/null
+++ b/opensaml-profile-api/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <installed facet="java" version="17"/>
+  <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
diff --git a/opensaml-profile-impl/.classpath b/opensaml-profile-impl/.classpath
index 77be441ed..8c2ac107c 100644
--- a/opensaml-profile-impl/.classpath
+++ b/opensaml-profile-impl/.classpath
@@ -32,6 +32,7 @@
 	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
 		<attributes>
 			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="org.eclipse.jst.component.nondependency" value=""/>
 		</attributes>
 	</classpathentry>
 	<classpathentry kind="output" path="target/classes"/>
diff --git a/opensaml-profile-impl/.project b/opensaml-profile-impl/.project
index d464fbb69..5092f09d9 100644
--- a/opensaml-profile-impl/.project
+++ b/opensaml-profile-impl/.project
@@ -5,6 +5,11 @@
 	<projects>
 	</projects>
 	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 		<buildCommand>
 			<name>org.eclipse.jdt.core.javabuilder</name>
 			<arguments>
@@ -25,11 +30,18 @@
 			<arguments>
 			</arguments>
 		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 	</buildSpec>
 	<natures>
 		<nature>org.springframework.ide.eclipse.core.springnature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
 		<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
 		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
 	</natures>
 </projectDescription>
diff --git a/opensaml-profile-impl/.settings/org.eclipse.wst.common.component b/opensaml-profile-impl/.settings/org.eclipse.wst.common.component
new file mode 100644
index 000000000..ab42e66ab
--- /dev/null
+++ b/opensaml-profile-impl/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="opensaml-profile-impl">
+        <wb-resource deploy-path="/" source-path="/src/main/java"/>
+        <wb-resource deploy-path="/" source-path="/src/main/resources"/>
+    </wb-module>
+</project-modules>
diff --git a/opensaml-profile-impl/.settings/org.eclipse.wst.common.project.facet.core.xml b/opensaml-profile-impl/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 000000000..9ba61b70c
--- /dev/null
+++ b/opensaml-profile-impl/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <installed facet="java" version="17"/>
+  <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
diff --git a/opensaml-saml-api/.classpath b/opensaml-saml-api/.classpath
index 77be441ed..8c2ac107c 100644
--- a/opensaml-saml-api/.classpath
+++ b/opensaml-saml-api/.classpath
@@ -32,6 +32,7 @@
 	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
 		<attributes>
 			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="org.eclipse.jst.component.nondependency" value=""/>
 		</attributes>
 	</classpathentry>
 	<classpathentry kind="output" path="target/classes"/>
diff --git a/opensaml-saml-api/.project b/opensaml-saml-api/.project
index 3323b390d..09f14b9f2 100644
--- a/opensaml-saml-api/.project
+++ b/opensaml-saml-api/.project
@@ -5,6 +5,11 @@
 	<projects>
 	</projects>
 	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 		<buildCommand>
 			<name>org.eclipse.jdt.core.javabuilder</name>
 			<arguments>
@@ -20,10 +25,17 @@
 			<arguments>
 			</arguments>
 		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 	</buildSpec>
 	<natures>
 		<nature>org.eclipse.m2e.core.maven2Nature</nature>
 		<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
 	</natures>
 </projectDescription>
diff --git a/opensaml-saml-api/.settings/org.eclipse.wst.common.component b/opensaml-saml-api/.settings/org.eclipse.wst.common.component
new file mode 100644
index 000000000..c0a67ab83
--- /dev/null
+++ b/opensaml-saml-api/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="opensaml-saml-api">
+        <wb-resource deploy-path="/" source-path="/src/main/java"/>
+        <wb-resource deploy-path="/" source-path="/src/main/resources"/>
+    </wb-module>
+</project-modules>
diff --git a/opensaml-saml-api/.settings/org.eclipse.wst.common.project.facet.core.xml b/opensaml-saml-api/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 000000000..9ba61b70c
--- /dev/null
+++ b/opensaml-saml-api/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <installed facet="java" version="17"/>
+  <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
diff --git a/opensaml-saml-impl/.classpath b/opensaml-saml-impl/.classpath
index 77be441ed..8c2ac107c 100644
--- a/opensaml-saml-impl/.classpath
+++ b/opensaml-saml-impl/.classpath
@@ -32,6 +32,7 @@
 	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
 		<attributes>
 			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="org.eclipse.jst.component.nondependency" value=""/>
 		</attributes>
 	</classpathentry>
 	<classpathentry kind="output" path="target/classes"/>
diff --git a/opensaml-saml-impl/.project b/opensaml-saml-impl/.project
index 4e908d873..8daa5a618 100644
--- a/opensaml-saml-impl/.project
+++ b/opensaml-saml-impl/.project
@@ -5,6 +5,11 @@
 	<projects>
 	</projects>
 	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 		<buildCommand>
 			<name>org.eclipse.jdt.core.javabuilder</name>
 			<arguments>
@@ -25,11 +30,18 @@
 			<arguments>
 			</arguments>
 		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 	</buildSpec>
 	<natures>
 		<nature>org.springframework.ide.eclipse.core.springnature</nature>
 		<nature>org.eclipse.m2e.core.maven2Nature</nature>
 		<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
 	</natures>
 </projectDescription>
diff --git a/opensaml-saml-impl/.settings/org.eclipse.wst.common.component b/opensaml-saml-impl/.settings/org.eclipse.wst.common.component
new file mode 100644
index 000000000..f51a3aba2
--- /dev/null
+++ b/opensaml-saml-impl/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="opensaml-saml-impl">
+        <wb-resource deploy-path="/" source-path="/src/main/java"/>
+        <wb-resource deploy-path="/" source-path="/src/main/resources"/>
+    </wb-module>
+</project-modules>
diff --git a/opensaml-saml-impl/.settings/org.eclipse.wst.common.project.facet.core.xml b/opensaml-saml-impl/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 000000000..9ba61b70c
--- /dev/null
+++ b/opensaml-saml-impl/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <installed facet="java" version="17"/>
+  <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
diff --git a/opensaml-security-api/.classpath b/opensaml-security-api/.classpath
index 77be441ed..8c2ac107c 100644
--- a/opensaml-security-api/.classpath
+++ b/opensaml-security-api/.classpath
@@ -32,6 +32,7 @@
 	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
 		<attributes>
 			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="org.eclipse.jst.component.nondependency" value=""/>
 		</attributes>
 	</classpathentry>
 	<classpathentry kind="output" path="target/classes"/>
diff --git a/opensaml-security-api/.project b/opensaml-security-api/.project
index fddc4a163..6c7a1c0ec 100644
--- a/opensaml-security-api/.project
+++ b/opensaml-security-api/.project
@@ -5,6 +5,11 @@
 	<projects>
 	</projects>
 	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 		<buildCommand>
 			<name>org.eclipse.jdt.core.javabuilder</name>
 			<arguments>
@@ -30,11 +35,18 @@
 			<arguments>
 			</arguments>
 		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 	</buildSpec>
 	<natures>
 		<nature>org.springframework.ide.eclipse.core.springnature</nature>
 		<nature>org.eclipse.m2e.core.maven2Nature</nature>
 		<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
 	</natures>
 </projectDescription>
diff --git a/opensaml-security-api/.settings/org.eclipse.wst.common.component b/opensaml-security-api/.settings/org.eclipse.wst.common.component
new file mode 100644
index 000000000..13893effa
--- /dev/null
+++ b/opensaml-security-api/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="opensaml-security-api">
+        <wb-resource deploy-path="/" source-path="/src/main/java"/>
+        <wb-resource deploy-path="/" source-path="/src/main/resources"/>
+    </wb-module>
+</project-modules>
diff --git a/opensaml-security-api/.settings/org.eclipse.wst.common.project.facet.core.xml b/opensaml-security-api/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 000000000..9ba61b70c
--- /dev/null
+++ b/opensaml-security-api/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <installed facet="java" version="17"/>
+  <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
diff --git a/opensaml-security-impl/.classpath b/opensaml-security-impl/.classpath
index 77be441ed..8c2ac107c 100644
--- a/opensaml-security-impl/.classpath
+++ b/opensaml-security-impl/.classpath
@@ -32,6 +32,7 @@
 	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
 		<attributes>
 			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="org.eclipse.jst.component.nondependency" value=""/>
 		</attributes>
 	</classpathentry>
 	<classpathentry kind="output" path="target/classes"/>
diff --git a/opensaml-security-impl/.project b/opensaml-security-impl/.project
index 99c378a83..b484917cf 100644
--- a/opensaml-security-impl/.project
+++ b/opensaml-security-impl/.project
@@ -5,6 +5,11 @@
 	<projects>
 	</projects>
 	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 		<buildCommand>
 			<name>org.eclipse.jdt.core.javabuilder</name>
 			<arguments>
@@ -20,10 +25,17 @@
 			<arguments>
 			</arguments>
 		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 	</buildSpec>
 	<natures>
 		<nature>org.eclipse.m2e.core.maven2Nature</nature>
 		<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
 	</natures>
 </projectDescription>
diff --git a/opensaml-security-impl/.settings/org.eclipse.wst.common.component b/opensaml-security-impl/.settings/org.eclipse.wst.common.component
new file mode 100644
index 000000000..05cdaec0a
--- /dev/null
+++ b/opensaml-security-impl/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="opensaml-security-impl">
+        <wb-resource deploy-path="/" source-path="/src/main/java"/>
+        <wb-resource deploy-path="/" source-path="/src/main/resources"/>
+    </wb-module>
+</project-modules>
diff --git a/opensaml-security-impl/.settings/org.eclipse.wst.common.project.facet.core.xml b/opensaml-security-impl/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 000000000..9ba61b70c
--- /dev/null
+++ b/opensaml-security-impl/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <installed facet="java" version="17"/>
+  <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
diff --git a/opensaml-soap-api/.classpath b/opensaml-soap-api/.classpath
index 77be441ed..8c2ac107c 100644
--- a/opensaml-soap-api/.classpath
+++ b/opensaml-soap-api/.classpath
@@ -32,6 +32,7 @@
 	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
 		<attributes>
 			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="org.eclipse.jst.component.nondependency" value=""/>
 		</attributes>
 	</classpathentry>
 	<classpathentry kind="output" path="target/classes"/>
diff --git a/opensaml-soap-api/.project b/opensaml-soap-api/.project
index 52462fae1..26d9ba4e3 100644
--- a/opensaml-soap-api/.project
+++ b/opensaml-soap-api/.project
@@ -5,6 +5,11 @@
 	<projects>
 	</projects>
 	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 		<buildCommand>
 			<name>org.eclipse.jdt.core.javabuilder</name>
 			<arguments>
@@ -20,10 +25,17 @@
 			<arguments>
 			</arguments>
 		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 	</buildSpec>
 	<natures>
 		<nature>org.eclipse.m2e.core.maven2Nature</nature>
 		<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
 	</natures>
 </projectDescription>
diff --git a/opensaml-soap-api/.settings/org.eclipse.wst.common.component b/opensaml-soap-api/.settings/org.eclipse.wst.common.component
new file mode 100644
index 000000000..4f1a24849
--- /dev/null
+++ b/opensaml-soap-api/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="opensaml-soap-api">
+        <wb-resource deploy-path="/" source-path="/src/main/java"/>
+        <wb-resource deploy-path="/" source-path="/src/main/resources"/>
+    </wb-module>
+</project-modules>
diff --git a/opensaml-soap-api/.settings/org.eclipse.wst.common.project.facet.core.xml b/opensaml-soap-api/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 000000000..9ba61b70c
--- /dev/null
+++ b/opensaml-soap-api/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <installed facet="java" version="17"/>
+  <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
diff --git a/opensaml-soap-impl/.classpath b/opensaml-soap-impl/.classpath
index 77be441ed..8c2ac107c 100644
--- a/opensaml-soap-impl/.classpath
+++ b/opensaml-soap-impl/.classpath
@@ -32,6 +32,7 @@
 	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
 		<attributes>
 			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="org.eclipse.jst.component.nondependency" value=""/>
 		</attributes>
 	</classpathentry>
 	<classpathentry kind="output" path="target/classes"/>
diff --git a/opensaml-soap-impl/.project b/opensaml-soap-impl/.project
index e8c041f4e..60754d09a 100644
--- a/opensaml-soap-impl/.project
+++ b/opensaml-soap-impl/.project
@@ -5,6 +5,11 @@
 	<projects>
 	</projects>
 	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 		<buildCommand>
 			<name>org.eclipse.jdt.core.javabuilder</name>
 			<arguments>
@@ -25,11 +30,18 @@
 			<arguments>
 			</arguments>
 		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 	</buildSpec>
 	<natures>
 		<nature>org.springframework.ide.eclipse.core.springnature</nature>
 		<nature>org.eclipse.m2e.core.maven2Nature</nature>
 		<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
 	</natures>
 </projectDescription>
diff --git a/opensaml-soap-impl/.settings/org.eclipse.wst.common.component b/opensaml-soap-impl/.settings/org.eclipse.wst.common.component
new file mode 100644
index 000000000..c16c94ff1
--- /dev/null
+++ b/opensaml-soap-impl/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="opensaml-soap-impl">
+        <wb-resource deploy-path="/" source-path="/src/main/java"/>
+        <wb-resource deploy-path="/" source-path="/src/main/resources"/>
+    </wb-module>
+</project-modules>
diff --git a/opensaml-soap-impl/.settings/org.eclipse.wst.common.project.facet.core.xml b/opensaml-soap-impl/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 000000000..9ba61b70c
--- /dev/null
+++ b/opensaml-soap-impl/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <installed facet="java" version="17"/>
+  <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
diff --git a/opensaml-spring/.checkstyle b/opensaml-spring/.checkstyle
new file mode 100644
index 000000000..c04bf97d7
--- /dev/null
+++ b/opensaml-spring/.checkstyle
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<fileset-config file-format-version="1.2.0" simple-config="false" sync-formatter="false">
+
+  <local-check-config name="Shibboleth Checkstyle" location="/opensaml-parent/resources/checkstyle/checkstyle.xml" type="project" description="">
+    <additional-data name="cache-file" value="true"/>
+    <additional-data name="cache-props-file-location" value="null_1312636288299_cache.properties"/>
+    <additional-data name="cache-file-location" value="null_1312636288299_cache.xml"/>
+  </local-check-config>
+ 
+  <fileset name="main source" enabled="true" check-config-name="Shibboleth Checkstyle" local="true">
+    <file-match-pattern match-pattern="src/main/java/.*\.java$" include-pattern="true"/>
+  </fileset>
+  
+</fileset-config>
diff --git a/opensaml-messaging-impl/.classpath b/opensaml-spring/.classpath
similarity index 92%
copy from opensaml-messaging-impl/.classpath
copy to opensaml-spring/.classpath
index 77be441ed..8ea303622 100644
--- a/opensaml-messaging-impl/.classpath
+++ b/opensaml-spring/.classpath
@@ -26,12 +26,14 @@
 	</classpathentry>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
+			<attribute name="module" value="true"/>
 			<attribute name="maven.pomderived" value="true"/>
 		</attributes>
 	</classpathentry>
 	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
 		<attributes>
 			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="org.eclipse.jst.component.nondependency" value=""/>
 		</attributes>
 	</classpathentry>
 	<classpathentry kind="output" path="target/classes"/>
diff --git a/opensaml-spring/.gitignore b/opensaml-spring/.gitignore
new file mode 100644
index 000000000..289d9e9af
--- /dev/null
+++ b/opensaml-spring/.gitignore
@@ -0,0 +1,2 @@
+/target/
+/test-output/
diff --git a/opensaml-security-api/.project b/opensaml-spring/.project
similarity index 73%
copy from opensaml-security-api/.project
copy to opensaml-spring/.project
index fddc4a163..aa177194c 100644
--- a/opensaml-security-api/.project
+++ b/opensaml-spring/.project
@@ -1,40 +1,41 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <projectDescription>
-	<name>opensaml-security-api</name>
+	<name>opensaml-spring</name>
 	<comment></comment>
 	<projects>
 	</projects>
 	<buildSpec>
 		<buildCommand>
-			<name>org.eclipse.jdt.core.javabuilder</name>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
 			<arguments>
 			</arguments>
 		</buildCommand>
 		<buildCommand>
-			<name>net.sf.eclipsecs.core.CheckstyleBuilder</name>
+			<name>org.eclipse.jdt.core.javabuilder</name>
 			<arguments>
 			</arguments>
 		</buildCommand>
 		<buildCommand>
-			<name>org.springframework.ide.eclipse.core.springbuilder</name>
+			<name>net.sf.eclipsecs.core.CheckstyleBuilder</name>
 			<arguments>
 			</arguments>
 		</buildCommand>
 		<buildCommand>
-			<name>org.springframework.ide.eclipse.boot.validation.springbootbuilder</name>
+			<name>org.eclipse.m2e.core.maven2Builder</name>
 			<arguments>
 			</arguments>
 		</buildCommand>
 		<buildCommand>
-			<name>org.eclipse.m2e.core.maven2Builder</name>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
 			<arguments>
 			</arguments>
 		</buildCommand>
 	</buildSpec>
 	<natures>
-		<nature>org.springframework.ide.eclipse.core.springnature</nature>
 		<nature>org.eclipse.m2e.core.maven2Nature</nature>
 		<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
 	</natures>
 </projectDescription>
diff --git a/opensaml-spring/.settings/org.eclipse.core.resources.prefs b/opensaml-spring/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 000000000..29abf9995
--- /dev/null
+++ b/opensaml-spring/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,6 @@
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
+encoding//src/main/resources=UTF-8
+encoding//src/test/java=UTF-8
+encoding//src/test/resources=UTF-8
+encoding/<project>=UTF-8
diff --git a/opensaml-spring/.settings/org.eclipse.jdt.core.prefs b/opensaml-spring/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 000000000..7dda60bd3
--- /dev/null
+++ b/opensaml-spring/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,413 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=ignore
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=error
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.mainOnlyProjectHasTestOnlyDependency=error
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.classpath.outputOverlappingAnotherSource=error
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=17
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.APILeak=warning
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=info
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=info
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=ignore
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=enabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
+org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=info
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=info
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.release=enabled
+org.eclipse.jdt.core.compiler.source=17
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=16
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=1
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=1
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
+org.eclipse.jdt.core.formatter.comment.line_length=120
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error
diff --git a/opensaml-spring/.settings/org.eclipse.jdt.ui.prefs b/opensaml-spring/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 000000000..86c79c4bc
--- /dev/null
+++ b/opensaml-spring/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,63 @@
+cleanup.add_default_serial_version_id=false
+cleanup.add_generated_serial_version_id=true
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=false
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=true
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=true
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=true
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=true
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.organize_imports=true
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_trailing_whitespaces=true
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_parentheses_in_expressions=true
+cleanup.use_this_for_non_static_field_access=false
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=false
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup_profile=_Shibboleth
+cleanup_settings_version=2
+eclipse.preferences.version=1
+formatter_profile=_Shibboleth
+formatter_settings_version=11
+internal.default.compliance=default
+org.eclipse.jdt.ui.exception.name=e
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.javadoc=true
+org.eclipse.jdt.ui.keywordthis=false
+org.eclipse.jdt.ui.overrideannotation=false
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return Returns the ${bare_field_name}.\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Commen [...]
diff --git a/opensaml-spring/.settings/org.eclipse.m2e.core.prefs b/opensaml-spring/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 000000000..f897a7f1c
--- /dev/null
+++ b/opensaml-spring/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/opensaml-spring/.settings/org.eclipse.wst.common.component b/opensaml-spring/.settings/org.eclipse.wst.common.component
new file mode 100644
index 000000000..8feb3fd43
--- /dev/null
+++ b/opensaml-spring/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="opensaml-spring">
+        <wb-resource deploy-path="/" source-path="/src/main/java"/>
+        <wb-resource deploy-path="/" source-path="/src/main/resources"/>
+    </wb-module>
+</project-modules>
diff --git a/opensaml-spring/.settings/org.eclipse.wst.common.project.facet.core.xml b/opensaml-spring/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 000000000..9ba61b70c
--- /dev/null
+++ b/opensaml-spring/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <installed facet="java" version="17"/>
+  <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
diff --git a/opensaml-spring/pom.xml b/opensaml-spring/pom.xml
new file mode 100644
index 000000000..3b71e1f74
--- /dev/null
+++ b/opensaml-spring/pom.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.opensaml</groupId>
+        <artifactId>opensaml-parent</artifactId>
+        <version>5.0.0-SNAPSHOT</version>
+        <relativePath>../opensaml-parent</relativePath>
+    </parent>
+
+    <name>OpenSAML :: Spring Support</name>
+    <description>Spring Support</description>
+    <artifactId>opensaml-spring</artifactId>
+    <packaging>jar</packaging>
+
+    <properties>
+        <automatic.module.name>org.opensaml.spring</automatic.module.name>
+    </properties>
+
+    <dependencies>
+        <!-- Compile Dependencies -->
+
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>opensaml-security-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>opensaml-security-impl</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>opensaml-xmlsec-impl</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>net.shibboleth.ext</groupId>
+            <artifactId>spring-extensions</artifactId>
+            <!-- Exception to usual test scope. -->
+            <scope>compile</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.code.findbugs</groupId>
+            <artifactId>jsr305</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-beans</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-core</artifactId>
+        </dependency>
+
+        <!-- Provided Dependencies -->
+
+        <!-- Runtime Dependencies -->
+
+        <!-- Test Dependencies -->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+    </dependencies>
+    
+    <scm>
+        <connection>${shibboleth.scm.connection}java-opensaml</connection>
+        <developerConnection>${shibboleth.scm.developerConnection}java-opensaml</developerConnection>
+        <url>${shibboleth.scm.url}java-opensaml.git</url>
+    </scm>
+
+    <distributionManagement>
+        <site>
+            <id>site</id>
+            <url>scp:${opensaml-module.site.url}</url>
+        </site>
+    </distributionManagement>
+
+
+</project>
diff --git a/opensaml-spring/src/main/java/org/opensaml/spring/credential/AbstractBasicCredentialFactoryBean.java b/opensaml-spring/src/main/java/org/opensaml/spring/credential/AbstractBasicCredentialFactoryBean.java
new file mode 100644
index 000000000..dd7ffe6a8
--- /dev/null
+++ b/opensaml-spring/src/main/java/org/opensaml/spring/credential/AbstractBasicCredentialFactoryBean.java
@@ -0,0 +1,207 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 org.opensaml.spring.credential;
+
+import java.io.UnsupportedEncodingException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.crypto.SecretKey;
+
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+
+import org.apache.commons.codec.binary.Base64;
+import org.bouncycastle.util.encoders.Hex;
+import org.opensaml.security.credential.BasicCredential;
+import org.opensaml.security.credential.UsageType;
+import org.opensaml.security.crypto.KeySupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.BeanCreationException;
+
+/**
+ * A factory bean to collect information to do with a {@link BasicCredential}.
+ */
+public abstract class AbstractBasicCredentialFactoryBean extends AbstractCredentialFactoryBean<BasicCredential> {
+    
+    /** Form of encoding for SecretKey info. */
+    public enum SecretKeyEncoding {
+       /** Raw binary encoding. */
+       binary,
+       /** Hexidecimal encoding. */
+       hex,
+       /** Base64 encoding. */
+       base64
+    }
+    
+    /** Log. */
+    private final Logger log = LoggerFactory.getLogger(AbstractBasicCredentialFactoryBean.class);
+
+    /** The SecretKey algorithm. */
+    @Nullable private String secretKeyAlgorithm;
+    
+    /** The SecretKey encoding used. */
+    @Nullable private SecretKeyEncoding secretKeyEncoding = SecretKeyEncoding.base64;
+    
+    /**
+     * Decode the SecretKey data, based on the specified encoding.
+     * 
+     * @param data the Secret key data
+     * @return the decoded SecretKey byte array
+     */
+    protected byte[] decodeSecretKey(final String data) {
+        Constraint.isNotNull(data, "SecretKey data was null");
+        switch (getSecretKeyEncoding()) {
+            case binary:
+                // This sort of doesn't make sense for the String input, but just assume it's UTF-8
+                try {
+                    return data.getBytes("UTF-8");
+                } catch (final UnsupportedEncodingException e) {
+                    // Can't actually happen, UTF-8 always supported.
+                    return null;
+                }
+            case hex:
+                return Hex.decode(data);
+            case base64:
+                return Base64.decodeBase64(data);
+            default:
+                throw new IllegalArgumentException("Saw unsupported encoding: " + getSecretKeyEncoding());
+            
+        }
+    }
+
+    /**
+     * Decode the SecretKey data, based on the specified encoding.
+     * 
+     * @param data the Secret key data
+     * @return the decoded SecretKey byte array
+     */
+    protected byte[] decodeSecretKey(final byte[] data) {
+        Constraint.isNotNull(data, "SecretKey data was null");
+        switch (getSecretKeyEncoding()) {
+            case binary:
+                return data;
+            case hex:
+                return Hex.decode(data);
+            case base64:
+                return Base64.decodeBase64(data);
+            default:
+                throw new IllegalArgumentException("Saw unsupported encoding: " + getSecretKeyEncoding());
+            
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected BasicCredential doCreateInstance() throws Exception {
+
+        final PrivateKey privateKey = getPrivateKey();
+        final PublicKey publicKey = getPublicKey();
+        final SecretKey secretKey = getSecretKey();
+        final BasicCredential credential;
+        
+        // Asymmetric credential
+        if (null != publicKey) {
+            if (null == privateKey) {
+                credential = new BasicCredential(publicKey);
+            } else {
+                if (!KeySupport.matchKeyPair(publicKey, privateKey)) {
+                    log.error("{}: Public and private keys do not match", getConfigDescription());
+                    throw new BeanCreationException("Public and private keys do not match");
+                }
+                credential = new BasicCredential(publicKey, privateKey);
+            }
+        // Symmetric credential
+        } else if (null != secretKey) {
+            credential = new BasicCredential(secretKey);
+        } else {
+            throw new BeanCreationException("Neither public key nor secret key specified");
+        }
+        
+        if (null != getUsageType()) {
+            credential.setUsageType(UsageType.valueOf(getUsageType()));
+        }
+        return credential;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Class<?> getObjectType() {
+        return BasicCredential.class;
+    }
+    
+    /**
+     * Get the algorithm for the SecretKey.
+     * 
+     * @return Returns the SecretKey algorithm
+     */
+    @Nullable public String getSecretKeyAlgorithm() {
+        return secretKeyAlgorithm;
+    }
+
+    /**
+     * Set the algorithm for the SecretKey.
+     * 
+     * @param algorithm The algorithm to set.
+     */
+    public void setSecretKeyAlgorithm(@Nonnull final String algorithm) {
+        secretKeyAlgorithm = Constraint.isNotNull(StringSupport.trimOrNull(algorithm), 
+                "SecretKey algorithm may not be null");
+    }
+
+    /**
+     * Get the SecretKey encoding. Defaults to: base64.
+     * 
+     * @return the encoding
+     */
+    public SecretKeyEncoding getSecretKeyEncoding() {
+        return secretKeyEncoding;
+    }
+
+    /**
+     * Set the SecretKey encoding. Defaults to: base64
+     * 
+     * @param encoding the new encoding
+     */
+    public void setSecretKeyEncoding(@Nonnull final SecretKeyEncoding encoding) {
+        secretKeyEncoding = Constraint.isNotNull(encoding, "SecretKey encoding may not be null");
+    }
+
+    /**
+     * return the configured Public Key. 
+     * 
+     * @return the key, or none if not configured.
+     */
+    @Nullable protected abstract PublicKey getPublicKey();
+
+    /**
+     * Get the configured Private key.
+     * 
+     * @return the key or null if non configured
+     */
+    @Nullable protected abstract PrivateKey getPrivateKey();
+
+    /**
+     * return the configured Secret Key. 
+     * 
+     * @return the key, or none if not configured.
+     */
+    @Nullable protected abstract SecretKey getSecretKey();
+
+}
diff --git a/opensaml-spring/src/main/java/org/opensaml/spring/credential/AbstractCredentialFactoryBean.java b/opensaml-spring/src/main/java/org/opensaml/spring/credential/AbstractCredentialFactoryBean.java
new file mode 100644
index 000000000..82a895110
--- /dev/null
+++ b/opensaml-spring/src/main/java/org/opensaml/spring/credential/AbstractCredentialFactoryBean.java
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 org.opensaml.spring.credential;
+
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.security.credential.Credential;
+
+import net.shibboleth.ext.spring.factory.AbstractComponentAwareFactoryBean;
+
+/**
+ * A factory bean to accumulate the information pertaining to an
+ * {@link org.opensaml.security.credential.AbstractCredential}.
+ * @param <T> the type of credential to create.
+ */
+public abstract class AbstractCredentialFactoryBean<T extends Credential> extends AbstractComponentAwareFactoryBean<T> {
+
+    /** Usage type of the credential. */
+    private String usageType;
+
+    /** Names for the key represented by the credential. */
+    private List<String> keyNames;
+
+    /** Identifier for the owner of the credential. */
+    private String entityID;
+    
+    /** The privateKey Password (if any). */
+    @Nullable private char[] privateKeyPassword;
+
+    /** For logging: The description of the source of the configuration.*/
+    @Nonnull private String configDescription;
+   
+    /**
+     * Gets the names for the key represented by the credential.
+     * 
+     * @return names for the key represented by the credential
+     */
+    @Nullable public List<String> getKeyNames() {
+        return keyNames;
+    }
+
+    /**
+     * Gets the usage type of the credential.
+     * 
+     * @return usage type of the credential
+     */
+    @Nullable public String getUsageType() {
+        return usageType;
+    }
+
+    /**
+     * Get the entity ID of the credential.
+     * 
+     * @return the entity ID
+     */
+    @Nullable public String getEntityID() {
+        return entityID;
+    }
+
+    /**
+     * Sets the names for the key represented by the credential.
+     * 
+     * @param names names for the key represented by the credential
+     */
+    public void setKeyNames(@Nullable final List<String> names) {
+        keyNames = names;
+    }
+
+    /**
+     * Sets the usage type of the credential.
+     * 
+     * @param type usage type of the credential
+     */
+    public void setUsageType(@Nullable final String type) {
+        if (null != type) {
+            usageType = type.toUpperCase();
+        } else {
+            usageType = type;
+        }
+    }
+
+    /**
+     * Set the entity ID of the credential.
+     * 
+     * @param newEntityID the entity ID
+     */
+    public void setEntityID(@Nullable final String newEntityID) {
+        entityID = newEntityID;
+    }
+    
+    /**
+     * Get the password for the private key.
+     * 
+     * @return Returns the privateKeyPassword.
+     */
+    @Nullable public char[] getPrivateKeyPassword() {
+        return privateKeyPassword;
+    }
+
+    /**
+     * Set the password for the private key.
+     * 
+     * @param password The password to set.
+     */
+    public void setPrivateKeyPassword(@Nullable final char[] password) {
+        if (null != password && password.length > 0) {
+            privateKeyPassword = password;
+        } else {
+            privateKeyPassword = null;
+        }
+    }
+
+    /** For logging, get the description of the resource that defined this bean.
+     * @return Returns the description.
+     */
+    public String getConfigDescription() {
+        return configDescription;
+    }
+
+    /** For logging, set the description of the resource that defined this bean.
+     * @param desc what to set.
+     */
+    public void setConfigDescription(@Nonnull final String desc) {
+        configDescription = desc;
+    }
+}
diff --git a/opensaml-spring/src/main/java/org/opensaml/spring/credential/AbstractX509CredentialFactoryBean.java b/opensaml-spring/src/main/java/org/opensaml/spring/credential/AbstractX509CredentialFactoryBean.java
new file mode 100644
index 000000000..786361dd6
--- /dev/null
+++ b/opensaml-spring/src/main/java/org/opensaml/spring/credential/AbstractX509CredentialFactoryBean.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 org.opensaml.spring.credential;
+
+import java.security.PrivateKey;
+import java.security.cert.X509CRL;
+import java.security.cert.X509Certificate;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+
+import org.opensaml.security.credential.UsageType;
+import org.opensaml.security.crypto.KeySupport;
+import org.opensaml.security.x509.BasicX509Credential;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.BeanCreationException;
+
+/**
+ * A factory bean to collect information to do with an X509 backed {@link BasicX509Credential}.
+ */
+public abstract class AbstractX509CredentialFactoryBean extends AbstractCredentialFactoryBean<BasicX509Credential> {
+
+    /** Log. */
+    private final Logger log = LoggerFactory.getLogger(AbstractX509CredentialFactoryBean.class);
+
+    /** {@inheritDoc} */
+    // Checkstyle: CyclomaticComplexity OFF
+    @Override protected BasicX509Credential doCreateInstance() throws Exception {
+
+        final List<X509Certificate> certificates = getCertificates();
+        if (null == certificates || certificates.isEmpty()) {
+            log.error("{}: No Certificates provided", getConfigDescription());
+            throw new BeanCreationException("No Certificates provided");
+        }
+
+        X509Certificate entityCertificate = getEntityCertificate();
+        if (null == entityCertificate) {
+            entityCertificate = certificates.get(0);
+        }
+
+        final PrivateKey privateKey = getPrivateKey();
+
+        final BasicX509Credential credential;
+        if (null == privateKey) {
+            credential = new BasicX509Credential(entityCertificate);
+        } else {
+            credential = new BasicX509Credential(entityCertificate, privateKey);
+
+            if (!KeySupport.matchKeyPair(entityCertificate.getPublicKey(), privateKey)) {
+                log.error("{}: Public and private keys do not match", getConfigDescription());
+                throw new BeanCreationException("Public and private keys do not match");
+            }
+        }
+
+        credential.setEntityCertificateChain(certificates);
+
+        final List<X509CRL> crls = getCRLs();
+        if (null != crls && !crls.isEmpty()) {
+            credential.setCRLs(crls);
+        }
+
+        if (null != getUsageType()) {
+            credential.setUsageType(UsageType.valueOf(getUsageType()));
+        }
+
+        if (null != getEntityID()) {
+            credential.setEntityId(getEntityID());
+        }
+
+        final List<String> keyNames = getKeyNames();
+        if (null != keyNames) {
+            credential.getKeyNames().addAll(keyNames);
+        }
+
+        return credential;
+    }
+
+    // Checkstyle: CyclomaticComplexity ON
+
+    /** {@inheritDoc} */
+    @Override public Class<BasicX509Credential> getObjectType() {
+        return BasicX509Credential.class;
+    }
+
+    /**
+     * return the explicitly configured entity certificate.
+     * 
+     * @return the certificate, or none if not configured.
+     */
+    @Nullable protected abstract X509Certificate getEntityCertificate();
+
+    /**
+     * Get the configured certificates. This <strong>MUST</strong> include the entity certificate if it was configured.
+     * 
+     * @return the certificates.
+     */
+
+    @Nonnull @NotEmpty protected abstract List<X509Certificate> getCertificates();
+
+    /**
+     * Get the configured private key.
+     * 
+     * @return the key or null if non configured
+     */
+    @Nullable protected abstract PrivateKey getPrivateKey();
+
+    /**
+     * Get the configured CRL list.
+     * 
+     * @return the crls or null
+     */
+    @Nullable protected abstract List<X509CRL> getCRLs();
+
+}
diff --git a/opensaml-spring/src/main/java/org/opensaml/spring/credential/BasicInlineCredentialFactoryBean.java b/opensaml-spring/src/main/java/org/opensaml/spring/credential/BasicInlineCredentialFactoryBean.java
new file mode 100644
index 000000000..bac2aebc0
--- /dev/null
+++ b/opensaml-spring/src/main/java/org/opensaml/spring/credential/BasicInlineCredentialFactoryBean.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 org.opensaml.spring.credential;
+
+import java.security.KeyException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+import javax.annotation.Nullable;
+import javax.crypto.SecretKey;
+
+import org.cryptacular.util.KeyPairUtil;
+import org.opensaml.security.crypto.KeySupport;
+import org.springframework.beans.factory.BeanCreationException;
+
+/**
+ * Factory bean for BasicInline Credentials. 
+ */
+public class BasicInlineCredentialFactoryBean extends AbstractBasicCredentialFactoryBean {
+
+    /** Configured public key Info. */
+    @Nullable private byte[] publicKeyInfo;
+
+    /** Configured private key Info. */
+    @Nullable private byte[] privateKeyInfo;
+
+    /** Configured secret key Info. */
+    @Nullable private byte[] secretKeyInfo;
+
+    /**
+     * Get the information used to generate the public key.
+     * 
+     * @return Returns the info.
+     */
+    @Nullable public byte[] getPublicKeyInfo() {
+        return publicKeyInfo;
+    }
+
+    /**
+     * Set the information used to generate the public key.
+     * 
+     * @param info The info to set.
+     */
+    public void setPublicKeyInfo(@Nullable final byte[] info) {
+        publicKeyInfo = info;
+    }
+
+    /**
+     * Get the information used to generate the private key.
+     * 
+     * @return Returns the info.
+     */
+    @Nullable public byte[] getPrivateKeyInfo() {
+        return privateKeyInfo;
+    }
+
+    /**
+     * Set the information used to generate the private key.
+     * 
+     * @param info The info to set.
+     */
+    public void setPrivateKeyInfo(@Nullable final byte[] info) {
+        privateKeyInfo = info;
+    }
+
+    /**
+     * Get the information used to generate the secret key.
+     * 
+     * @return Returns the info.
+     */
+    @Nullable public byte[] getSecretKeyInfo() {
+        return secretKeyInfo;
+    }
+
+    /**
+     * Set the information used to generate the secret key.
+     * 
+     * @param info The info to set.
+     */
+    public void setSecretKeyInfo(@Nullable final byte[] info) {
+        secretKeyInfo = info;
+    }
+
+    /** {@inheritDoc} */
+    @Override @Nullable protected PublicKey getPublicKey() {
+        if (null == getPublicKeyInfo()) {
+            return null;
+        }
+        return KeyPairUtil.decodePublicKey(getPublicKeyInfo());
+    }
+
+    /** {@inheritDoc} */
+    @Override @Nullable protected PrivateKey getPrivateKey() {
+        if (null == getPrivateKeyInfo()) {
+            return null;
+        }
+        return KeyPairUtil.decodePrivateKey(getPrivateKeyInfo(), getPrivateKeyPassword());
+    }
+
+    /** {@inheritDoc} */
+    @Override @Nullable protected SecretKey getSecretKey() {
+        if (null ==  getSecretKeyInfo()) {
+            return null;
+        }
+        try {
+            return KeySupport.decodeSecretKey(decodeSecretKey(getSecretKeyInfo()), getSecretKeyAlgorithm());
+        } catch (final KeyException e) {
+            throw new BeanCreationException("Could not decode secret key", e);
+        }
+    }
+}
diff --git a/opensaml-spring/src/main/java/org/opensaml/spring/credential/BasicResourceCredentialFactoryBean.java b/opensaml-spring/src/main/java/org/opensaml/spring/credential/BasicResourceCredentialFactoryBean.java
new file mode 100644
index 000000000..f70bcf263
--- /dev/null
+++ b/opensaml-spring/src/main/java/org/opensaml/spring/credential/BasicResourceCredentialFactoryBean.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 org.opensaml.spring.credential;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.KeyException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+import javax.annotation.Nullable;
+import javax.crypto.SecretKey;
+
+import org.cryptacular.util.KeyPairUtil;
+import org.opensaml.security.crypto.KeySupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.core.io.Resource;
+
+import com.google.common.io.ByteStreams;
+
+/**
+ * Spring bean factory for producing a {@link org.opensaml.security.credential.BasicCredential} from {@link Resource}s.
+ */
+public class BasicResourceCredentialFactoryBean extends AbstractBasicCredentialFactoryBean {
+
+    /** log. */
+    private final Logger log = LoggerFactory.getLogger(BasicResourceCredentialFactoryBean.class);
+
+    /** Configured public key Info. */
+    @Nullable private Resource publicKeyInfo;
+
+    /** Configured private key Info. */
+    @Nullable private Resource privateKeyInfo;
+
+    /** Configured secret key Info. */
+    @Nullable private Resource secretKeyInfo;
+
+    /**
+     * Get the information used to generate the public key.
+     * 
+     * @return Returns the info.
+     */
+    @Nullable public Resource getPublicKeyInfo() {
+        return publicKeyInfo;
+    }
+
+    /**
+     * Set the information used to generate the public key.
+     * 
+     * @param info The info to set.
+     */
+    public void setPublicKeyInfo(@Nullable final Resource info) {
+        publicKeyInfo = info;
+    }
+
+    /**
+     * Get the information used to generate the private key.
+     * 
+     * @return Returns the info.
+     */
+    @Nullable public Resource getPrivateKeyInfo() {
+        return privateKeyInfo;
+    }
+
+    /**
+     * Set the information used to generate the private key.
+     * 
+     * @param info The info to set.
+     */
+    public void setPrivateKeyInfo(@Nullable final Resource info) {
+        privateKeyInfo = info;
+    }
+
+    /**
+     * Get the information used to generate the secret key.
+     * 
+     * @return Returns the info.
+     */
+    @Nullable public Resource getSecretKeyInfo() {
+        return secretKeyInfo;
+    }
+
+    /**
+     * Set the information used to generate the secret key.
+     * 
+     * @param info The info to set.
+     */
+    public void setSecretKeyInfo(@Nullable final Resource info) {
+        secretKeyInfo = info;
+    }
+
+    /** {@inheritDoc} */
+    @Override @Nullable protected PublicKey getPublicKey() {
+        if (null == getPublicKeyInfo()) {
+            return null;
+        }
+        try (InputStream is = getPublicKeyInfo().getInputStream()) {
+            return KeyPairUtil.readPublicKey(is);
+        } catch (final IOException e) {
+            log.error("{}: Could not decode public key: {}", getConfigDescription(), e.getMessage());
+            throw new BeanCreationException("Could not decode public key", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override @Nullable protected PrivateKey getPrivateKey() {
+        if (null == getPrivateKeyInfo()) {
+            return null;
+        }
+        try (InputStream is = getPrivateKeyInfo().getInputStream()) {
+            return KeySupport.decodePrivateKey(is, getPrivateKeyPassword());
+        } catch (final KeyException | IOException e) {
+            log.error("{}: Could not decode private key: {}", getConfigDescription(), e.getMessage());
+            throw new BeanCreationException("Could not decode private key", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override @Nullable protected SecretKey getSecretKey() {
+        if (null == getSecretKeyInfo()) {
+            return null;
+        }
+        try (InputStream is = getSecretKeyInfo().getInputStream()) {
+            return KeySupport.decodeSecretKey(decodeSecretKey(ByteStreams.toByteArray(is)), getSecretKeyAlgorithm());
+        } catch (final KeyException | IOException e) {
+            log.error("{}: Could not decode secret key: {}", getConfigDescription(), e.getMessage());
+            throw new BeanCreationException("Could not decode secret key", e);
+        }
+    }
+}
diff --git a/opensaml-spring/src/main/java/org/opensaml/spring/credential/BasicX509CredentialFactoryBean.java b/opensaml-spring/src/main/java/org/opensaml/spring/credential/BasicX509CredentialFactoryBean.java
new file mode 100644
index 000000000..bbacc69e4
--- /dev/null
+++ b/opensaml-spring/src/main/java/org/opensaml/spring/credential/BasicX509CredentialFactoryBean.java
@@ -0,0 +1,224 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 org.opensaml.spring.credential;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.KeyException;
+import java.security.PrivateKey;
+import java.security.cert.CRLException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509CRL;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.collection.LazyList;
+
+import org.opensaml.security.crypto.KeySupport;
+import org.opensaml.security.x509.X509Support;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.FatalBeanException;
+import org.springframework.core.io.Resource;
+
+/**
+ * Spring bean factory for producing a {@link org.opensaml.security.x509.BasicX509Credential} from {@link Resource}s.
+ * 
+ * <p>
+ * This factory bean supports DER and PEM encoded certificate resources and encrypted and non-encrypted PKCS8, DER, or
+ * PEM encoded private key resources.
+ * </p>
+ */
+public class BasicX509CredentialFactoryBean extends AbstractX509CredentialFactoryBean {
+
+    /** log. */
+    private final Logger log = LoggerFactory.getLogger(BasicX509CredentialFactoryBean.class);
+
+    /** The specification of where the entity Resource is to be found. */
+    private Resource entityResource;
+
+    /** Where the certificates are to be found. */
+    private List<Resource> certificateResources;
+
+    /** Where the private key is to be found. */
+    private Resource privateKeyResource;
+
+    /** Where the crls are to be found. */
+    private List<Resource> crlResources;
+
+    /**
+     * Set the Resource with the entity certificate.
+     * 
+     * @param what The Resource to set.
+     */
+    public void setEntity(@Nonnull final Resource what) {
+        entityResource = what;
+    }
+
+    /**
+     * Sets the Resources which contain the certificates.
+     * 
+     * @param what The values to set.
+     */
+    public void setCertificates(@Nullable @NotEmpty final List<Resource> what) {
+        certificateResources = what;
+    }
+
+    /**
+     * Set the Resource with the entity certificate.
+     * 
+     * @param what The resource to set.
+     */
+    public void setPrivateKey(@Nullable final Resource what) {
+        privateKeyResource = what;
+    }
+
+    /**
+     * Sets the Resources which contain the crls.
+     * 
+     * @param what The value to set.
+     */
+    public void setCRLs(@Nullable @NotEmpty final List<Resource> what) {
+        crlResources = what;
+    }
+    
+    //
+    // BasicX509CredentialFactoryBean
+    //
+    /**
+     * Set the resource containing the private key.
+     * 
+     * @param res private key resource, never <code>null</code>
+     */
+    public void setPrivateKeyResource(@Nonnull final Resource res) {
+        setPrivateKey(res);
+    }
+
+    /**
+     * Set the password for the private key.
+     * 
+     * @param password password for the private key, may be null if the key is not encrypted
+     */
+    public void setPrivateKeyPassword(@Nullable final String password) {
+        setPrivateKeyPassword(password.toCharArray());
+    }
+
+    /**
+     * Set the certificate resource.
+     * 
+     * @param res certificate resource
+     */
+    public void setCertificateResource(@Nonnull final Resource res) {
+        setCertificates(Collections.singletonList(res));
+    }
+
+    /**
+     * Set the entityID for the credential.
+     * 
+     * @param id entityID
+     */
+    public void setEntityId(@Nullable final String id) {
+        setEntityID(id);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isSingleton() {
+        return true;
+    }
+
+    /** {@inheritDoc}. */
+    @Override @Nullable protected X509Certificate getEntityCertificate() {
+
+        if (null == entityResource) {
+            return null;
+        }
+        try {
+            final Collection<X509Certificate> certs = X509Support.decodeCertificates(entityResource.getInputStream());
+            if (certs.size() > 1) {
+                log.error("{}: Configuration element indicated an entityCertificate,"
+                        + " but multiple certificates were decoded", getConfigDescription());
+                throw new FatalBeanException("Configuration element indicated an entityCertificate,"
+                        + " but multiple certificates were decoded");
+            }
+            return certs.iterator().next();
+        } catch (final CertificateException | IOException e) {
+            log.error("{}: Could not decode provided Entity Certificate at {}: {}", getConfigDescription(),
+                    entityResource.getDescription(), e.getMessage());
+            throw new FatalBeanException("Could not decode provided Entity Certificate file "
+                    + entityResource.getDescription(), e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override @Nonnull protected List<X509Certificate> getCertificates() {
+        
+        if (certificateResources == null) {
+            return Collections.emptyList();
+        }
+        
+        final List<X509Certificate> certificates = new LazyList<>();
+        for (final Resource r : certificateResources) {
+            try(InputStream is = r.getInputStream()) {
+                certificates.addAll(X509Support.decodeCertificates(is));
+            } catch (final CertificateException | IOException e) {
+                log.error("{}: could not decode CertificateFile at {}: {}", getConfigDescription(),
+                        r.getDescription(), e.getMessage());
+                throw new FatalBeanException("Could not decode provided CertificateFile: " + r.getDescription(), e);
+            }
+        }
+        return certificates;
+    }
+
+    /** {@inheritDoc} */
+    @Override @Nullable protected PrivateKey getPrivateKey() {
+        if (null == privateKeyResource) {
+            return null;
+        }
+        try (InputStream is = privateKeyResource.getInputStream()) {
+            return KeySupport.decodePrivateKey(is, getPrivateKeyPassword());
+        } catch (final KeyException | IOException e) {
+            log.error("{}: Could not decode KeyFile at {}: {}", getConfigDescription(),
+                    privateKeyResource.getDescription(), e.getMessage());
+            throw new FatalBeanException("Could not decode provided KeyFile " + privateKeyResource.getDescription(), e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override @Nullable protected List<X509CRL> getCRLs() {
+        if (null == crlResources) {
+            return null;
+        }
+        final List<X509CRL> crls = new LazyList<>();
+        for (final Resource crl : crlResources) {
+            try (InputStream is = crl.getInputStream()) {
+                crls.addAll(X509Support.decodeCRLs(is));
+            } catch (final CRLException | IOException e) {
+                log.error("{}: Could not decode CRL file at {}: {}", getConfigDescription(), crl.getDescription(),
+                        e.getMessage());
+                throw new FatalBeanException("Could not decode provided CRL file " + crl.getDescription(), e);
+            }
+        }
+        return crls;
+    }
+}
diff --git a/opensaml-spring/src/main/java/org/opensaml/spring/credential/X509InlineCredentialFactoryBean.java b/opensaml-spring/src/main/java/org/opensaml/spring/credential/X509InlineCredentialFactoryBean.java
new file mode 100644
index 000000000..f5f1b80de
--- /dev/null
+++ b/opensaml-spring/src/main/java/org/opensaml/spring/credential/X509InlineCredentialFactoryBean.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 org.opensaml.spring.credential;
+
+import java.security.PrivateKey;
+import java.security.cert.CRLException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509CRL;
+import java.security.cert.X509Certificate;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.collection.LazyList;
+
+import org.cryptacular.util.KeyPairUtil;
+import org.opensaml.security.x509.X509Support;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.FatalBeanException;
+
+/**
+ * A factory bean to understand X509Inline credentials.
+ */
+public class X509InlineCredentialFactoryBean extends AbstractX509CredentialFactoryBean {
+
+    /** log. */
+    private final Logger log = LoggerFactory.getLogger(X509InlineCredentialFactoryBean.class);
+
+    /** The entity certificate. */
+    private String entityCertificate;
+
+    /** The certificates. */
+    private List<String> certificates;
+
+    /** The private key. */
+    private byte[] privateKey;
+
+    /** The crls. */
+    private List<String> crls;
+    
+    /**
+     * Set the file with the entity certificate.
+     * 
+     * @param entityCert The file to set.
+     */
+    public void setEntity(@Nonnull final String entityCert) {
+        entityCertificate = entityCert;
+    }
+
+    /**
+     * Sets the certificates.
+     * 
+     * @param certs The value to set.
+     */
+    public void setCertificates(@Nullable @NotEmpty final List<String> certs) {
+        certificates = certs;
+    }
+
+    /**
+     * Set the private key.
+     * 
+     * @param key The file to set.
+     */
+    public void setPrivateKey(@Nullable final byte[] key) {
+        privateKey = key;
+    }
+
+    /**
+     * Sets the files which contain the crls.
+     * 
+     * @param list The value to set.
+     */
+    public void setCRLs(@Nullable @NotEmpty final List<String> list) {
+        crls = list;
+    }
+
+    /** {@inheritDoc}. */
+    @Override @Nullable protected X509Certificate getEntityCertificate() {
+
+        if (null == entityCertificate) {
+            return null;
+        }
+        try {
+            return X509Support.decodeCertificate(entityCertificate);
+        } catch (final CertificateException e) {
+            log.error("{}: Could not decode provided Entity Certificate: {}", getConfigDescription(), e.getMessage());
+            throw new FatalBeanException("Could not decode provided Entity Certificate", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override @Nonnull protected List<X509Certificate> getCertificates() {
+        final List<X509Certificate> certs = new LazyList<>();
+        for (final String cert : certificates) {
+            try {
+                certs.add(X509Support.decodeCertificate(cert.trim()));
+            } catch (final CertificateException e) {
+                log.error("{}: Could not decode provided Certificate: {}", getConfigDescription(), e.getMessage());
+                throw new FatalBeanException("Could not decode provided Certificate", e);
+            }
+        }
+        return certs;
+    }
+
+    /** {@inheritDoc} */
+    @Override @Nullable protected PrivateKey getPrivateKey() {
+        if (null == privateKey) {
+            return null;
+        }
+        return KeyPairUtil.decodePrivateKey(privateKey, getPrivateKeyPassword());
+    }
+
+    /** {@inheritDoc} */
+    @Override @Nullable protected List<X509CRL> getCRLs() {
+        if (null == crls) {
+            return null;
+        }
+        final List<X509CRL> result = new LazyList<>();
+        for (final String crl : crls) {
+            try {
+                result.add(X509Support.decodeCRL(crl));
+            } catch (final CRLException | CertificateException e) {
+                log.error("{}: Could not decode provided CRL: {}", getConfigDescription(), e.getMessage());
+                throw new FatalBeanException("Could not decode provided CRL", e);
+            }
+        }
+        return result;
+    }
+}
diff --git a/opensaml-spring/src/main/java/org/opensaml/spring/credential/package-info.java b/opensaml-spring/src/main/java/org/opensaml/spring/credential/package-info.java
new file mode 100644
index 000000000..b599cb5e9
--- /dev/null
+++ b/opensaml-spring/src/main/java/org/opensaml/spring/credential/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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.
+ */
+
+/**
+ * Factory beans for various credential classes.
+ */
+
+package org.opensaml.spring.credential;
\ No newline at end of file
diff --git a/opensaml-spring/src/main/java/org/opensaml/spring/tls/TLSSocketFactoryFactoryBean.java b/opensaml-spring/src/main/java/org/opensaml/spring/tls/TLSSocketFactoryFactoryBean.java
new file mode 100644
index 000000000..3c11c406e
--- /dev/null
+++ b/opensaml-spring/src/main/java/org/opensaml/spring/tls/TLSSocketFactoryFactoryBean.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 org.opensaml.spring.tls;
+
+import javax.annotation.Nullable;
+
+import org.apache.http.client.HttpClient;
+import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
+import org.opensaml.security.httpclient.HttpClientSecurityParameters;
+import org.opensaml.security.httpclient.impl.SecurityEnhancedHttpClientSupport;
+import org.opensaml.security.trust.TrustEngine;
+import org.opensaml.security.x509.X509Credential;
+import org.springframework.beans.factory.config.AbstractFactoryBean;
+
+import net.shibboleth.utilities.java.support.httpclient.HttpClientSupport;
+
+/**
+ * A factory bean for producing instances of {@link LayeredConnectionSocketFactory} for use in {@link HttpClient}.
+ */
+public class TLSSocketFactoryFactoryBean extends AbstractFactoryBean<LayeredConnectionSocketFactory> {
+    
+    /** The optional trust engine used in evaluating server TLS credentials. */
+    private TrustEngine<?> tlsTrustEngine;
+    
+    /** The optional HttpClient security parameters instance that will be used with the HttpClient instance. */
+    private HttpClientSecurityParameters httpClientSecurityParameters;
+    
+    /** Whether the responder's SSL/TLS certificate should be ignored. */
+    private boolean connectionDisregardTLSCertificate;
+    
+    /**
+     * Sets the optional trust engine used in evaluating server TLS credentials.
+     * 
+     * @deprecated use setHttpClientSecurityParameters instead
+     * @param engine the trust engine instance to use, or null
+     */
+    @Deprecated
+    public void setTLSTrustEngine(@Nullable final TrustEngine<? super X509Credential> engine) {
+        tlsTrustEngine = engine;
+    }
+    
+    /**
+     * Sets the optional HttpClient security parameters instance that will be used with the HttpClient instance.
+     * 
+     * @param params the parameters, or null
+     */
+    public void setHttpClientSecurityParameters(@Nullable final HttpClientSecurityParameters params) {
+        httpClientSecurityParameters = params;
+    }
+
+    /**
+     * Sets whether the responder's SSL/TLS certificate should be ignored.
+     * 
+     * @param disregard whether the responder's SSL/TLS certificate should be ignored
+     */
+    public void setConnectionDisregardTLSCertificate(final boolean disregard) {
+        connectionDisregardTLSCertificate = disregard;
+    }
+
+
+    /** {@inheritDoc} */
+    @Override public Class<LayeredConnectionSocketFactory> getObjectType() {
+        return LayeredConnectionSocketFactory.class;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected LayeredConnectionSocketFactory createInstance() throws Exception {
+        final boolean haveTrustEngine = tlsTrustEngine != null 
+                || (httpClientSecurityParameters != null && httpClientSecurityParameters.getTLSTrustEngine() != null);
+        final boolean haveClientTLSCred = 
+                httpClientSecurityParameters != null && httpClientSecurityParameters.getClientTLSCredential() != null;
+        if (haveTrustEngine || haveClientTLSCred) {
+            return SecurityEnhancedHttpClientSupport.buildTLSSocketFactory(haveTrustEngine, haveClientTLSCred);
+        } else if (connectionDisregardTLSCertificate) {
+            return HttpClientSupport.buildNoTrustTLSSocketFactory();
+        } else {
+            return HttpClientSupport.buildStrictTLSSocketFactory();
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/opensaml-spring/src/main/java/org/opensaml/spring/tls/package-info.java b/opensaml-spring/src/main/java/org/opensaml/spring/tls/package-info.java
new file mode 100644
index 000000000..81404861f
--- /dev/null
+++ b/opensaml-spring/src/main/java/org/opensaml/spring/tls/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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.
+ */
+
+/**
+ * Spring support for TLS configuration.
+ */
+
+package org.opensaml.spring.tls;
\ No newline at end of file
diff --git a/opensaml-spring/src/main/java/org/opensaml/spring/trust/AbstractBasicPKIXValidationInfoFactoryBean.java b/opensaml-spring/src/main/java/org/opensaml/spring/trust/AbstractBasicPKIXValidationInfoFactoryBean.java
new file mode 100644
index 000000000..97d0a8f18
--- /dev/null
+++ b/opensaml-spring/src/main/java/org/opensaml/spring/trust/AbstractBasicPKIXValidationInfoFactoryBean.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 org.opensaml.spring.trust;
+
+import java.security.cert.X509CRL;
+import java.security.cert.X509Certificate;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.shibboleth.ext.spring.factory.AbstractComponentAwareFactoryBean;
+
+import org.opensaml.security.x509.impl.BasicPKIXValidationInformation;
+
+/**
+ * A factory bean to collect information to do with a {@link BasicPKIXValidationInformation}.
+ */
+public abstract class AbstractBasicPKIXValidationInfoFactoryBean extends
+        AbstractComponentAwareFactoryBean<BasicPKIXValidationInformation> {
+
+    /** Verification depth. */
+    @Nullable private Integer verifyDepth;
+
+    /** The description of the file with the configuration us. */
+    @Nonnull private String configDescription;
+
+    /**
+     * Get the verify Depth.
+     * 
+     * @return Returns the depth.
+     */
+    public int getVerifyDepth() {
+        return verifyDepth;
+    }
+
+    /**
+     * Set the verify Depth.
+     * 
+     * @param depth The value to set.
+     */
+    public void setVerifyDepth(final int depth) {
+        verifyDepth = depth;
+    }
+
+    /**
+     * For logging, get the description of the resource that defined this bean.
+     * 
+     * @return Returns the description.
+     */
+    public String getConfigDescription() {
+        return configDescription;
+    }
+
+    /**
+     * For logging, set the description of the resource that defined this bean.
+     * 
+     * @param desc what to set.
+     */
+    public void setConfigDescription(@Nonnull final String desc) {
+        configDescription = desc;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Class<?> getObjectType() {
+        return BasicPKIXValidationInformation.class;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected BasicPKIXValidationInformation doCreateInstance() throws Exception {
+        return new BasicPKIXValidationInformation(getCertificates(), getCRLs(), verifyDepth);
+    }
+
+    /**
+     * Get the configured certificates.
+     * 
+     * @return the certificates.
+     */
+    @Nullable protected abstract List<X509Certificate> getCertificates();
+
+    /**
+     * Get the configured CRL list.
+     * 
+     * @return the crls or null
+     */
+    @Nullable protected abstract List<X509CRL> getCRLs();
+
+}
diff --git a/opensaml-spring/src/main/java/org/opensaml/spring/trust/ChainingSignatureTrustEngineFactoryBean.java b/opensaml-spring/src/main/java/org/opensaml/spring/trust/ChainingSignatureTrustEngineFactoryBean.java
new file mode 100644
index 000000000..befba7c0d
--- /dev/null
+++ b/opensaml-spring/src/main/java/org/opensaml/spring/trust/ChainingSignatureTrustEngineFactoryBean.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 org.opensaml.spring.trust;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+import net.shibboleth.ext.spring.factory.AbstractComponentAwareFactoryBean;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+import org.opensaml.xmlsec.signature.support.SignatureTrustEngine;
+import org.opensaml.xmlsec.signature.support.impl.ChainingSignatureTrustEngine;
+
+/**
+ * Factory bean for {@link ChainingSignatureTrustEngine}. This finesses the issue that some parsers are not supported
+ * and return a bean of type object and these cannot be injected into the trust engine. This factory just filters the
+ * unsupported engines out. A warning has been issued at point of parse so no further logging is required.
+ */
+public class ChainingSignatureTrustEngineFactoryBean extends
+        AbstractComponentAwareFactoryBean<ChainingSignatureTrustEngine> {
+
+    /** The unfiltered list of putative trust engines. */
+    private final List<Object> engines;
+
+    /**
+     * Constructor.
+     * 
+     * @param list the putative trust engines.
+     */
+    public ChainingSignatureTrustEngineFactoryBean(@Nonnull final List<Object> list) {
+        engines = Constraint.isNotNull(list, "Engine list must be non null");
+    }
+
+    /** {@inheritDoc} */
+    @Override public Class<?> getObjectType() {
+        return ChainingSignatureTrustEngine.class;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected ChainingSignatureTrustEngine doCreateInstance() throws Exception {
+        final List<SignatureTrustEngine> list = new ArrayList<>(engines.size());
+
+        for (final Object engine : engines) {
+            if (engine instanceof SignatureTrustEngine) {
+                list.add((SignatureTrustEngine) engine);
+
+            }
+        }
+        return new ChainingSignatureTrustEngine(list);
+    }
+
+}
diff --git a/opensaml-spring/src/main/java/org/opensaml/spring/trust/ChainingTrustEngineFactoryBean.java b/opensaml-spring/src/main/java/org/opensaml/spring/trust/ChainingTrustEngineFactoryBean.java
new file mode 100644
index 000000000..fd1085d9b
--- /dev/null
+++ b/opensaml-spring/src/main/java/org/opensaml/spring/trust/ChainingTrustEngineFactoryBean.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 org.opensaml.spring.trust;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+import net.shibboleth.ext.spring.factory.AbstractComponentAwareFactoryBean;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+import org.opensaml.security.trust.TrustEngine;
+import org.opensaml.security.trust.impl.ChainingTrustEngine;
+
+/**
+ * Factory bean for {@link ChainingTrustEngine}. This finesses the issue that some parsers are not supported
+ * and return a bean of type object and these cannot be injected into the trust engine. This factory just filters the
+ * unsupported engines out. A warning has been issued at point of parse so no further logging is required.
+ */
+public class ChainingTrustEngineFactoryBean extends
+        AbstractComponentAwareFactoryBean<ChainingTrustEngine<?>> {
+
+    /** The unfiltered list of putative trust engines. */
+    private final List<Object> engines;
+
+    /**
+     * Constructor.
+     * 
+     * @param list the putative trust engines.
+     */
+    public ChainingTrustEngineFactoryBean(@Nonnull final List<Object> list) {
+        engines = Constraint.isNotNull(list, "Engine list must be non null");
+    }
+
+    /** {@inheritDoc} */
+    @Override public Class<?> getObjectType() {
+        return ChainingTrustEngine.class;
+    }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    @Override protected ChainingTrustEngine<?> doCreateInstance() throws Exception {
+        final List<TrustEngine<?>> list = new ArrayList<>(engines.size());
+
+        for (final Object engine : engines) {
+            if (engine instanceof TrustEngine) {
+                list.add((TrustEngine<?>) engine);
+
+            }
+        }
+        return new ChainingTrustEngine(list);
+    }
+
+}
\ No newline at end of file
diff --git a/opensaml-spring/src/main/java/org/opensaml/spring/trust/PKIXInlineValidationInfoFactoryBean.java b/opensaml-spring/src/main/java/org/opensaml/spring/trust/PKIXInlineValidationInfoFactoryBean.java
new file mode 100644
index 000000000..36f4ec0ce
--- /dev/null
+++ b/opensaml-spring/src/main/java/org/opensaml/spring/trust/PKIXInlineValidationInfoFactoryBean.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 org.opensaml.spring.trust;
+
+import java.security.cert.CRLException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509CRL;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import org.opensaml.security.x509.X509Support;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.FatalBeanException;
+
+/**
+ * File system specific bean for PKIXValidationInfo.
+ */
+public class PKIXInlineValidationInfoFactoryBean extends AbstractBasicPKIXValidationInfoFactoryBean {
+
+    /** log. */
+    private Logger log = LoggerFactory.getLogger(PKIXInlineValidationInfoFactoryBean.class);
+
+    /** The strings to be turned into the certificates. */
+    private List<String> certificateFiles;
+
+    /** The strings to be turned into the crls. */
+    private List<String> crlStrings;
+
+    /**
+     * Set the file names which we will convert into certificates.
+     * 
+     * @param certs the file names.
+     */
+    public void setCertificates(@Nullable final List<String> certs) {
+        certificateFiles = certs;
+    }
+
+    /**
+     * Set the file names which we will convert into crls.
+     * 
+     * @param crls the file names.
+     */
+    public void setCRLs(@Nullable final List<String> crls) {
+        crlStrings = crls;
+    }
+
+    /**
+     * Get the configured certificates.
+     * 
+     * @return the certificates null
+     */
+    @Override @Nullable protected List<X509Certificate> getCertificates() {
+        if (null == certificateFiles) {
+            return null;
+        }
+        final List<X509Certificate> certificates = new ArrayList<>(certificateFiles.size());
+        for (final String cert : certificateFiles) {
+            try {
+                certificates.add(X509Support.decodeCertificate(cert.trim()));
+            } catch (final CertificateException e) {
+                log.error("{}: Could not decode provided Certificate: {}", getConfigDescription(), e.getMessage());
+                throw new FatalBeanException("Could not decode provided Certificate", e);
+            }
+        }
+        return certificates;
+    }
+
+    /**
+     * Get the configured CRL list.
+     * 
+     * @return the crls or null
+     */
+    @Override @Nullable protected List<X509CRL> getCRLs() {
+        if (null == crlStrings) {
+            return null;
+        }
+        final List<X509CRL> crls = new ArrayList<>(crlStrings.size());
+        for (final String crl : crlStrings) {
+            try {
+                crls.add(X509Support.decodeCRL(crl));
+            } catch (final CRLException | CertificateException e) {
+                log.error("{}: Could not decode provided CRL: {}", getConfigDescription(), e.getMessage());
+                throw new FatalBeanException("Could not decode provided CRL", e);
+            }
+        }
+        return crls;
+    }
+}
diff --git a/opensaml-spring/src/main/java/org/opensaml/spring/trust/PKIXResourceValidationInfoFactoryBean.java b/opensaml-spring/src/main/java/org/opensaml/spring/trust/PKIXResourceValidationInfoFactoryBean.java
new file mode 100644
index 000000000..52371d63e
--- /dev/null
+++ b/opensaml-spring/src/main/java/org/opensaml/spring/trust/PKIXResourceValidationInfoFactoryBean.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 org.opensaml.spring.trust;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.cert.CRLException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509CRL;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import org.opensaml.security.x509.X509Support;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.FatalBeanException;
+import org.springframework.core.io.Resource;
+
+/**
+ * File system specific bean for PKIXValidationInfo.
+ */
+public class PKIXResourceValidationInfoFactoryBean extends AbstractBasicPKIXValidationInfoFactoryBean {
+
+    /** log. */
+    private Logger log = LoggerFactory.getLogger(PKIXResourceValidationInfoFactoryBean.class);
+
+    /** The file to be turned into the certificates. */
+    private List<Resource> certificateFiles;
+
+    /** The file to be turned into the crls. */
+    private List<Resource> crlFiles;
+
+    /**
+     * Set the file names which we will convert into certificates.
+     * 
+     * @param certs the file names.
+     */
+    public void setCertificates(@Nullable final List<Resource> certs) {
+        certificateFiles = certs;
+    }
+
+    /**
+     * Set the file names which we will convert into crls.
+     * 
+     * @param crls the file names.
+     */
+    public void setCRLs(@Nullable final List<Resource> crls) {
+        crlFiles = crls;
+    }
+
+    /**
+     * Get the configured certificates.
+     * 
+     * @return the certificates null
+     */
+    @Override @Nullable protected List<X509Certificate> getCertificates() {
+        if (null == certificateFiles) {
+            return null;
+        }
+        final List<X509Certificate> certificates = new ArrayList<>(certificateFiles.size());
+        for (final Resource f : certificateFiles) {
+            try(InputStream is = f.getInputStream()) {
+                certificates.addAll(X509Support.decodeCertificates(is));
+            } catch (final CertificateException | IOException e) {
+                log.error("{}: Could not decode Certificate at {}: {}", getConfigDescription(), f.getDescription(),
+                        e.getMessage());
+                throw new FatalBeanException("Could not decode provided CertificateFile: " + f.getDescription(), e);
+            }
+        }
+        return certificates;
+    }
+
+    /**
+     * Get the configured CRL list.
+     * 
+     * @return the crls or null
+     */
+    @Override @Nullable protected List<X509CRL> getCRLs() {
+        if (null == crlFiles) {
+            return null;
+        }
+        final List<X509CRL> crls = new ArrayList<>(crlFiles.size());
+        for (final Resource crlFile : crlFiles) {
+            try(InputStream is = crlFile.getInputStream())  {
+                crls.addAll(X509Support.decodeCRLs(is));
+            } catch (final CRLException | IOException e) {
+                log.error("{}: Could not decode CRL file at {}: {}", getConfigDescription(), crlFile.getDescription(),
+                        e.getMessage());
+                throw new FatalBeanException("Could not decode provided CRL file " + crlFile.getDescription(), e);
+            }
+        }
+        return crls;
+    }
+}
diff --git a/opensaml-spring/src/main/java/org/opensaml/spring/trust/StaticExplicitKeyFactoryBean.java b/opensaml-spring/src/main/java/org/opensaml/spring/trust/StaticExplicitKeyFactoryBean.java
new file mode 100644
index 000000000..3d80d2747
--- /dev/null
+++ b/opensaml-spring/src/main/java/org/opensaml/spring/trust/StaticExplicitKeyFactoryBean.java
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 org.opensaml.spring.trust;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.cryptacular.EncodingException;
+import org.cryptacular.StreamException;
+import org.cryptacular.util.KeyPairUtil;
+import org.opensaml.security.credential.BasicCredential;
+import org.opensaml.security.credential.Credential;
+import org.opensaml.security.credential.impl.StaticCredentialResolver;
+import org.opensaml.security.trust.impl.ExplicitKeyTrustEngine;
+import org.opensaml.security.x509.BasicX509Credential;
+import org.opensaml.security.x509.X509Support;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.FatalBeanException;
+import org.springframework.core.io.Resource;
+
+import net.shibboleth.ext.spring.factory.AbstractComponentAwareFactoryBean;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+
+/**
+ * Factory bean for simple use cases involving the {@link ExplicitKeyTrustEngine} and static credentials.
+ * 
+ * @since 3.3.0
+ */
+public class StaticExplicitKeyFactoryBean extends AbstractComponentAwareFactoryBean<ExplicitKeyTrustEngine> {
+
+    /** Class logger. */
+    @Nonnull private Logger log = LoggerFactory.getLogger(StaticExplicitKeyFactoryBean.class);
+
+    /** The resources to be turned into keys. */
+    private List<Resource> keyResources;
+
+    /** The resources to be turned into certificates. */
+    private List<Resource> certificateResources;
+
+    /** Constructor. */
+    public StaticExplicitKeyFactoryBean() {
+        keyResources = Collections.emptyList();
+        certificateResources = Collections.emptyList();
+    }
+    
+    /**
+     * Set the resources which we will convert into certificates.
+     * 
+     * @param keys the resources
+     */
+    public void setPublicKeys(@Nullable final List<Resource> keys) {
+        keyResources = keys != null ? keys : Collections.emptyList();
+    }
+    
+    /**
+     * Set the resources which we will convert into certificates.
+     * 
+     * @param certs the resources
+     */
+    public void setCertificates(@Nullable final List<Resource> certs) {
+        certificateResources = certs != null ? certs : Collections.emptyList();
+    }
+
+    /**
+     * Get the configured certificates.
+     * 
+     * @return the certificates null
+     */
+    @Nullable @NonnullElements protected List<Credential> getCredentials() {
+        
+        final List<Credential> credentials = new ArrayList<>(keyResources.size() + certificateResources.size());
+
+        for (final Resource f : keyResources) {
+            try(final InputStream is = f.getInputStream()) {
+                credentials.add(new BasicCredential(KeyPairUtil.readPublicKey(is)));
+            } catch (final EncodingException|StreamException|IOException e) {
+                log.error("Could not decode public key from {}: {}", f.getDescription(), e.getMessage());
+                throw new FatalBeanException("Could not decode public key from " + f.getDescription(), e);
+            }
+        }
+                
+        for (final Resource f : certificateResources) {
+            try(final InputStream is = f.getInputStream()) {
+                final Collection<X509Certificate> raw = X509Support.decodeCertificates(is);
+                if (raw != null) {
+                    raw.forEach(x -> {
+                        if (x != null) {
+                            credentials.add(new BasicX509Credential(x));
+                            }
+                        }
+                    );
+                }
+                
+            } catch (final CertificateException | IOException e) {
+                log.error("Could not decode certificate from {}: {}", f.getDescription(), e.getMessage());
+                throw new FatalBeanException("Could not decode certificate from " + f.getDescription(), e);
+            }
+        }
+
+        return credentials;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Class<?> getObjectType() {
+        return ExplicitKeyTrustEngine.class;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected ExplicitKeyTrustEngine doCreateInstance() throws Exception {
+        return new ExplicitKeyTrustEngine(new StaticCredentialResolver(getCredentials()));
+    }
+    
+}
\ No newline at end of file
diff --git a/opensaml-spring/src/main/java/org/opensaml/spring/trust/StaticPKIXFactoryBean.java b/opensaml-spring/src/main/java/org/opensaml/spring/trust/StaticPKIXFactoryBean.java
new file mode 100644
index 000000000..8a70ba357
--- /dev/null
+++ b/opensaml-spring/src/main/java/org/opensaml/spring/trust/StaticPKIXFactoryBean.java
@@ -0,0 +1,277 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 org.opensaml.spring.trust;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.Security;
+import java.security.cert.CRLException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509CRL;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.security.x509.PKIXTrustEvaluator;
+import org.opensaml.security.x509.X509Support;
+import org.opensaml.security.x509.impl.BasicPKIXValidationInformation;
+import org.opensaml.security.x509.impl.BasicX509CredentialNameEvaluator;
+import org.opensaml.security.x509.impl.CertPathPKIXTrustEvaluator;
+import org.opensaml.security.x509.impl.CertPathPKIXValidationOptions;
+import org.opensaml.security.x509.impl.PKIXX509CredentialTrustEngine;
+import org.opensaml.security.x509.impl.StaticPKIXValidationInformationResolver;
+import org.opensaml.security.x509.impl.X509CredentialNameEvaluator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.FatalBeanException;
+import org.springframework.core.io.Resource;
+
+
+import net.shibboleth.ext.spring.factory.AbstractComponentAwareFactoryBean;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+
+/**
+ * File system specific bean for PKIXX509CredentialTrustEngine.
+ * 
+ * @since 3.3.0
+ */
+public class StaticPKIXFactoryBean extends AbstractComponentAwareFactoryBean<PKIXX509CredentialTrustEngine> {
+
+    /** log. */
+    @Nonnull private Logger log = LoggerFactory.getLogger(StaticPKIXFactoryBean.class);
+
+    /** Certificate resources. */
+    @Nullable private List<Resource> certificateResources;
+
+    /** CRL resources. */
+    @Nullable private List<Resource> crlResources;
+
+    /** Verification depth. */
+    @Nullable private Integer verifyDepth;
+    
+    /** Explicit subject name(s) to match. */
+    @Nullable private Set<String> trustedNames;
+    
+    /** Whether to enable name checking. If true a default implementation will be used.
+     * See also: {@link #credentialNameEvaluator}. */
+    private boolean checkNames;
+
+    /** Custom instance of {@link PKIXTrustEvaluator} to use. */
+    private PKIXTrustEvaluator trustEvaluator;
+
+    /** Custom instance of {@link X509CredentialNameEvaluator} to use.
+     * A non-null value overrides {@link #checkNames}. */
+    private X509CredentialNameEvaluator credentialNameEvaluator;
+
+    /** Constructor. */
+    public StaticPKIXFactoryBean() {
+        checkNames = true;
+    }
+    
+    /** {@inheritDoc} */
+    @Override
+    public Class<?> getObjectType() {
+        return PKIXX509CredentialTrustEngine.class;
+    }
+    
+    /**
+     * Set the resources which we will convert into certificates.
+     * 
+     * @param certs the resources
+     */
+    public void setCertificates(@Nullable final List<Resource> certs) {
+        certificateResources = certs;
+    }
+
+    /**
+     * Set the resources which we will convert into CRLs.
+     * 
+     * @param crls the resources
+     */
+    public void setCRLs(@Nullable final List<Resource> crls) {
+        crlResources = crls;
+    }
+
+    /**
+     * Set the verify depth.
+     * 
+     * @param depth value to set
+     */
+    public void setVerifyDepth(final int depth) {
+        verifyDepth = depth;
+    }
+
+    /**
+     * Set whether the perform name checking in the PKIX layer.
+     *
+     * <p>
+     * Defaults to "true", should generally be disabled when used with an HTTP client
+     * that is already checking names.
+     * </p>
+     *
+     * <p>
+     * If true a default implementation will be used unless a specific name evaluator impl has been supplied.
+     * See also: {@link #setCredentialNameEvaluator(X509CredentialNameEvaluator)}.
+     * </p>
+     *
+     * @param flag flag to set
+     * 
+     * @since 3.4.0
+     */
+    public void setCheckNames(final boolean flag) {
+        checkNames = flag;
+    }
+    
+    /**
+     * Set explicitly trusted names to match against credential.
+     * 
+     * @param names explicitly trusted names
+     * 
+     * @since 3.4.0
+     */
+    public void setTrustedNames(@Nullable @NonnullElements final Collection<String> names) {
+        if (names != null) {
+            trustedNames = Set.copyOf(names);
+        } else {
+            trustedNames = null;
+        }
+    }
+
+    /**
+     * Set the custom instance of {@link PKIXTrustEvaluator} to use.
+     *
+     * @param evaluator The trustEvaluator to set.
+     */
+    public void setTrustEvaluator(@Nullable final PKIXTrustEvaluator evaluator) {
+        trustEvaluator = evaluator;
+    }
+
+    /**
+     * Set the custom instance of {@link X509CredentialNameEvaluator} to use.
+     *
+     * <p>
+     * A non-null value overrides {@link #setCheckNames(boolean)}.
+     * </p>
+     *
+     * @param evaluator The credentialNameEvaluator to set.
+     */
+    public void setCredentialNameEvaluator(@Nullable final X509CredentialNameEvaluator evaluator) {
+        credentialNameEvaluator = evaluator;
+    }
+
+    /**
+     * Get the configured certificates.
+     * 
+     * @return the certificates
+     */
+    @Nonnull @NonnullElements protected List<X509Certificate> getCertificates() {
+        if (certificateResources == null) {
+            return Collections.emptyList();
+        }
+        
+        final List<X509Certificate> certificates = new ArrayList<>(certificateResources.size());
+        for (final Resource f : certificateResources) {
+            try(final InputStream is = f.getInputStream()) {
+                certificates.addAll(X509Support.decodeCertificates(is));
+            } catch (final CertificateException | IOException e) {
+                log.error("Could not decode Certificate at {}: {}", f.getDescription(), e.getMessage());
+                throw new FatalBeanException("Could not decode provided CertificateFile: " + f.getDescription(), e);
+            }
+        }
+        return certificates;
+    }
+
+    /**
+     * Get the configured CRL list.
+     * 
+     * @return the crls
+     */
+    @Nonnull @NonnullElements protected List<X509CRL> getCRLs() {
+        if (crlResources == null) {
+            return Collections.emptyList();
+        }
+        
+        final List<X509CRL> crls = new ArrayList<>(crlResources.size());
+        for (final Resource crlFile : crlResources) {
+            try(final InputStream is = crlFile.getInputStream())  {
+                crls.addAll(X509Support.decodeCRLs(is));
+            } catch (final CRLException | IOException e) {
+                log.error("Could not decode CRL file at {}: {}", crlFile.getDescription(), e.getMessage());
+                throw new FatalBeanException("Could not decode provided CRL file " + crlFile.getDescription(), e);
+            }
+        }
+        return crls;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected PKIXX509CredentialTrustEngine doCreateInstance() throws Exception {
+        final BasicPKIXValidationInformation info =
+                new BasicPKIXValidationInformation(getCertificates(), getCRLs(), verifyDepth);
+        
+        final StaticPKIXValidationInformationResolver resolver =
+                new StaticPKIXValidationInformationResolver(Collections.singletonList(info), trustedNames, checkNames);
+
+        final PKIXTrustEvaluator pkixTrustEvaluator =
+                trustEvaluator != null ? trustEvaluator : new CertPathPKIXTrustEvaluator();
+
+        final X509CredentialNameEvaluator credNameEvaluator =
+                credentialNameEvaluator != null ? credentialNameEvaluator :
+                    (checkNames ? new BasicX509CredentialNameEvaluator() : null);
+
+        validateConfiguration(pkixTrustEvaluator);
+
+        return new PKIXX509CredentialTrustEngine(resolver, pkixTrustEvaluator, credNameEvaluator);
+    }
+
+    /**
+     * Validate the configuration of the effective {@link PKIXTrustEvaluator}.
+     *
+     * @param pkixTrustEvaluator the instance whose configuration is to be evaluated
+     *
+     * @throws Exception if configuration issues are encountered
+     */
+    protected void validateConfiguration(@Nonnull final PKIXTrustEvaluator pkixTrustEvaluator) throws Exception {
+        if (CertPathPKIXTrustEvaluator.class.isInstance(pkixTrustEvaluator)
+                && CertPathPKIXValidationOptions.class.isInstance(pkixTrustEvaluator.getPKIXValidationOptions())) {
+            
+            final CertPathPKIXValidationOptions certPathOptions =
+                    CertPathPKIXValidationOptions.class.cast(pkixTrustEvaluator.getPKIXValidationOptions());
+
+           if (certPathOptions.isForceRevocationEnabled() && certPathOptions.isRevocationEnabled()
+                   && getCRLs().isEmpty()
+                   && ! Boolean.getBoolean("com.sun.security.enableCRLDP")
+                   && ! "true".equalsIgnoreCase(StringSupport.trimOrNull(Security.getProperty("oscp.enable"))) ) {
+
+               log.error("Certificate revocation checking was force enabled, "
+                       + "but no static CRLs were supplied and both CRLDP and OCSP processing is disabled");
+
+               throw new FatalBeanException("Certificate revocation checking was force enabled, "
+                       + "but no static CRLs were supplied and both CRLDP and OCSP processing is disabled");
+           }
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/opensaml-spring/src/main/java/org/opensaml/spring/trust/package-info.java b/opensaml-spring/src/main/java/org/opensaml/spring/trust/package-info.java
new file mode 100644
index 000000000..5bf1420a2
--- /dev/null
+++ b/opensaml-spring/src/main/java/org/opensaml/spring/trust/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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.
+ */
+
+/**
+ * Factory beans for trust engines.
+ */
+
+package org.opensaml.spring.trust;
\ No newline at end of file
diff --git a/opensaml-spring/src/test/java/org/opensaml/spring/credential/BasicX509CredentialFactoryBeanTest.java b/opensaml-spring/src/test/java/org/opensaml/spring/credential/BasicX509CredentialFactoryBeanTest.java
new file mode 100644
index 000000000..adf7a4478
--- /dev/null
+++ b/opensaml-spring/src/test/java/org/opensaml/spring/credential/BasicX509CredentialFactoryBeanTest.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 org.opensaml.spring.credential;
+
+import org.opensaml.security.x509.BasicX509Credential;
+import org.springframework.context.support.GenericApplicationContext;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import net.shibboleth.ext.spring.context.FilesystemGenericApplicationContext;
+import net.shibboleth.ext.spring.util.SchemaTypeAwareXMLBeanDefinitionReader;
+
+/**
+ * Unit test for {@link BasicX509CredentialFactoryBean}.
+ */
+public class BasicX509CredentialFactoryBeanTest {
+
+    @Test public void bean() {
+        final GenericApplicationContext context = new FilesystemGenericApplicationContext();
+            context.setDisplayName("ApplicationContext: X509Credential");
+            final SchemaTypeAwareXMLBeanDefinitionReader beanDefinitionReader =
+                    new SchemaTypeAwareXMLBeanDefinitionReader(context);
+    
+            beanDefinitionReader.loadBeanDefinitions("org/opensaml/spring/credential/bean.xml");
+    
+            context.refresh();
+            
+             final BasicX509Credential cred1 = context.getBean("Credential", BasicX509Credential.class);
+            
+             final BasicX509Credential cred2 = context.getBean("EncCredential", BasicX509Credential.class);
+             
+             Assert.assertEquals("http://example.org/enc", cred2.getEntityId()); 
+             
+             final byte[] cb1 = cred1.getPrivateKey().getEncoded();
+             final byte[] cb2 = cred2.getPrivateKey().getEncoded();
+             
+             Assert.assertEquals(cb1.length, cb2.length);
+
+             for (int i = 0; i< cb1.length; i++)Assert.assertEquals(cb1[i], cb2[i]);
+             
+             Assert.assertEquals(cred2.getPublicKey(), cred2.getPublicKey());
+
+    }
+
+}
\ No newline at end of file
diff --git a/opensaml-spring/src/test/java/org/opensaml/spring/trust/AbstractSecurityTest.java b/opensaml-spring/src/test/java/org/opensaml/spring/trust/AbstractSecurityTest.java
new file mode 100644
index 000000000..5cf006221
--- /dev/null
+++ b/opensaml-spring/src/test/java/org/opensaml/spring/trust/AbstractSecurityTest.java
@@ -0,0 +1,97 @@
+
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 org.opensaml.spring.trust;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+
+import net.shibboleth.ext.spring.util.ApplicationContextBuilder;
+
+import org.springframework.context.support.GenericApplicationContext;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.mock.env.MockPropertySource;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeSuite;
+
+/**
+ * Base mechanics for Security tests using Spring.
+ */
+ at SuppressWarnings("javadoc")
+public class AbstractSecurityTest {
+
+    private static final String PATH = "/org/opensaml/spring/";
+    
+    protected static final String SP_ID = "https://sp.example.org/sp/shibboleth"; 
+    protected static final String IDP_ID = "https://idp.example.org/idp/shibboleth";
+    
+    static private String workspaceDirName;
+
+    private GenericApplicationContext pendingTeardownContext = null;
+    
+    @AfterMethod public void tearDownTestContext() {
+        if (null == pendingTeardownContext ) {
+            return;
+        }
+        pendingTeardownContext.close();
+        pendingTeardownContext = null;
+    }
+    
+    protected void setTestContext(final GenericApplicationContext context) {
+        tearDownTestContext();
+        pendingTeardownContext = context;
+    }
+   
+    @BeforeSuite public void setupDirs() throws IOException {
+        final ClassPathResource resource = new ClassPathResource(PATH);
+        workspaceDirName = resource.getFile().getAbsolutePath();
+    }
+
+    protected <T> T getBean(final Class<T> claz, final String... files) throws IOException{
+        return getBean(null, claz, files);
+    }
+
+    protected <T> T getBean(final String name, final Class<T> claz, final String... files) throws IOException{
+        final Resource[] resources = new Resource[files.length];
+        
+        for (int i = 0; i < files.length; i++) {
+            resources[i] = new ClassPathResource(PATH + files[i]);
+        }
+        
+        final ApplicationContextBuilder builder = new ApplicationContextBuilder();
+        
+        builder.setName("ApplicationContext: " + claz);
+        
+        final MockPropertySource mockEnvVars = new MockPropertySource();
+        mockEnvVars.setProperty("DIR", workspaceDirName);
+        builder.setPropertySources(Collections.singletonList(mockEnvVars));
+        
+        builder.setServiceConfigurations(Arrays.asList(resources));
+
+        final GenericApplicationContext context = builder.build();
+        
+        setTestContext(context);
+        
+        if (name != null) {
+            return context.getBean(name, claz);
+        }
+        return context.getBean(claz);
+    }
+}
\ No newline at end of file
diff --git a/opensaml-spring/src/test/java/org/opensaml/spring/trust/MockTrustEngine.java b/opensaml-spring/src/test/java/org/opensaml/spring/trust/MockTrustEngine.java
new file mode 100644
index 000000000..fc3481353
--- /dev/null
+++ b/opensaml-spring/src/test/java/org/opensaml/spring/trust/MockTrustEngine.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 org.opensaml.spring.trust;
+
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+
+import org.opensaml.security.SecurityException;
+import org.opensaml.security.trust.TrustEngine;
+
+ at SuppressWarnings("javadoc")
+public class MockTrustEngine<T> implements TrustEngine<T> {
+
+    private final boolean result;
+    
+    /**
+     * Constructor.
+     * 
+     * @param retVal ...
+     */
+    public MockTrustEngine(boolean retVal) {
+        result = retVal;
+    }
+    
+    /** {@inheritDoc} */
+    @Override public boolean validate(T token, CriteriaSet trustBasisCriteria) throws SecurityException {
+        return result;
+    }
+
+}
diff --git a/opensaml-spring/src/test/java/org/opensaml/spring/trust/StaticExplicitKeyFactoryBeanTest.java b/opensaml-spring/src/test/java/org/opensaml/spring/trust/StaticExplicitKeyFactoryBeanTest.java
new file mode 100644
index 000000000..47f1cb271
--- /dev/null
+++ b/opensaml-spring/src/test/java/org/opensaml/spring/trust/StaticExplicitKeyFactoryBeanTest.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 org.opensaml.spring.trust;
+
+import java.io.IOException;
+import java.time.Instant;
+import java.util.Iterator;
+
+import net.shibboleth.utilities.java.support.resolver.ResolverException;
+
+import org.opensaml.security.credential.Credential;
+import org.opensaml.security.credential.impl.StaticCredentialResolver;
+import org.opensaml.security.trust.TrustEngine;
+import org.opensaml.security.trust.impl.ExplicitKeyTrustEngine;
+import org.opensaml.security.x509.X509Credential;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * Test for StaticExplicitKey factory bean.
+ */
+ at SuppressWarnings("javadoc")
+public class StaticExplicitKeyFactoryBeanTest extends AbstractSecurityTest {
+ 
+    static private String TESTPATH = "trust/staticExplicitNative.xml";
+    
+    @Test public void singleKey() throws IOException, ResolverException {
+        final ExplicitKeyTrustEngine engine = (ExplicitKeyTrustEngine) getBean("staticKeySingle", TrustEngine.class, TESTPATH);
+        
+        final StaticCredentialResolver resolver = (StaticCredentialResolver) engine.getCredentialResolver();
+        Credential credential  = resolver.resolveSingle(null);
+        
+        Assert.assertNotNull(credential.getPublicKey());
+    }
+    
+    @Test public void singleCert() throws IOException, ResolverException {
+        final ExplicitKeyTrustEngine engine = (ExplicitKeyTrustEngine) getBean("staticX509Single", TrustEngine.class, TESTPATH);
+        
+        final StaticCredentialResolver resolver = (StaticCredentialResolver) engine.getCredentialResolver();
+        X509Credential credential  = (X509Credential) resolver.resolveSingle(null);
+        
+        Assert.assertEquals(credential.getEntityCertificateChain().size(), 1);
+        Assert.assertTrue(credential.getEntityCertificateChain().contains(credential.getEntityCertificate()));
+
+        Assert.assertEquals(credential.getEntityCertificate().getNotAfter().getTime(), Instant.parse("2024-04-08T13:39:18Z").toEpochMilli());
+    }
+    
+    @Test public void multipleCert() throws IOException, ResolverException {
+        final ExplicitKeyTrustEngine engine = (ExplicitKeyTrustEngine) getBean("staticX509Multiple", TrustEngine.class, TESTPATH);
+        
+        final StaticCredentialResolver resolver = (StaticCredentialResolver) engine.getCredentialResolver();
+        
+        Iterator<Credential> credentials = resolver.resolve(null).iterator();
+        
+        Assert.assertTrue(credentials.hasNext());
+        final X509Credential first = (X509Credential) credentials.next();
+        Assert.assertEquals(first.getEntityCertificateChain().size(), 1);
+
+        Assert.assertTrue(credentials.hasNext());
+        final X509Credential second = (X509Credential) credentials.next();
+        Assert.assertEquals(second.getEntityCertificateChain().size(), 1);
+    }
+
+    @Test public void mixed() throws IOException, ResolverException {
+        final ExplicitKeyTrustEngine engine = (ExplicitKeyTrustEngine) getBean("staticMixed", TrustEngine.class, TESTPATH);
+        
+        final StaticCredentialResolver resolver = (StaticCredentialResolver) engine.getCredentialResolver();
+        
+        Iterator<Credential> credentials = resolver.resolve(null).iterator();
+        
+        Assert.assertTrue(credentials.hasNext());
+        final Credential first = credentials.next();
+        Assert.assertNotNull(first.getPublicKey());
+        Assert.assertFalse(first instanceof X509Credential);
+
+        Assert.assertTrue(credentials.hasNext());
+        final X509Credential second = (X509Credential) credentials.next();
+        Assert.assertEquals(second.getEntityCertificateChain().size(), 1);
+        Assert.assertEquals(second.getEntityCertificate().getNotAfter().getTime(), Instant.parse("2024-04-08T13:39:18Z").toEpochMilli());
+    }
+}
\ No newline at end of file
diff --git a/opensaml-spring/src/test/java/org/opensaml/spring/trust/StaticPKIXFactoryBeanTest.java b/opensaml-spring/src/test/java/org/opensaml/spring/trust/StaticPKIXFactoryBeanTest.java
new file mode 100644
index 000000000..e8fa28717
--- /dev/null
+++ b/opensaml-spring/src/test/java/org/opensaml/spring/trust/StaticPKIXFactoryBeanTest.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 org.opensaml.spring.trust;
+
+import java.util.Set;
+
+import org.opensaml.security.SecurityException;
+import org.opensaml.security.x509.PKIXTrustEvaluator;
+import org.opensaml.security.x509.PKIXValidationInformation;
+import org.opensaml.security.x509.PKIXValidationOptions;
+import org.opensaml.security.x509.X509Credential;
+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.opensaml.security.x509.impl.X509CredentialNameEvaluator;
+import org.springframework.beans.FatalBeanException;
+import org.springframework.context.support.GenericApplicationContext;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import net.shibboleth.ext.spring.context.FilesystemGenericApplicationContext;
+import net.shibboleth.ext.spring.util.SchemaTypeAwareXMLBeanDefinitionReader;
+import net.shibboleth.utilities.java.support.component.AbstractInitializableComponent;
+
+/**
+ * Unit test for {@link StaticPKIXFactoryBean}.
+ */
+public class StaticPKIXFactoryBeanTest {
+
+    @Test
+    public void defaults() {
+        final GenericApplicationContext context = new FilesystemGenericApplicationContext();
+        context.setDisplayName("ApplicationContext: X509Credential");
+        final SchemaTypeAwareXMLBeanDefinitionReader beanDefinitionReader =
+                new SchemaTypeAwareXMLBeanDefinitionReader(context);
+
+        beanDefinitionReader.loadBeanDefinitions("org/opensaml/spring/trust/static-pkix-factory-defaults.xml");
+
+        context.refresh();
+
+        final PKIXX509CredentialTrustEngine trustEngine = context.getBean("StaticPKIXX509CredentialTrustEngine",
+                PKIXX509CredentialTrustEngine.class);
+        
+        Assert.assertNotNull(trustEngine);
+        
+        Assert.assertTrue(StaticPKIXValidationInformationResolver.class.isInstance((trustEngine.getPKIXResolver())));
+        
+        Assert.assertTrue(CertPathPKIXTrustEvaluator.class.isInstance((trustEngine.getPKIXTrustEvaluator())));
+        
+        Assert.assertTrue(BasicX509CredentialNameEvaluator.class.isInstance((trustEngine.getX509CredentialNameEvaluator())));
+    }
+    
+    @Test
+    public void customPropertiesSuccess() {
+        final GenericApplicationContext context = new FilesystemGenericApplicationContext();
+        context.setDisplayName("ApplicationContext: X509Credential");
+        final SchemaTypeAwareXMLBeanDefinitionReader beanDefinitionReader =
+                new SchemaTypeAwareXMLBeanDefinitionReader(context);
+
+        beanDefinitionReader.loadBeanDefinitions("org/opensaml/spring/trust/static-pkix-factory-custom-success.xml");
+
+        context.refresh();
+
+        final PKIXX509CredentialTrustEngine trustEngine = context.getBean("StaticPKIXX509CredentialTrustEngine",
+                PKIXX509CredentialTrustEngine.class);
+        
+        Assert.assertNotNull(trustEngine);
+        
+        Assert.assertTrue(StaticPKIXValidationInformationResolver.class.isInstance((trustEngine.getPKIXResolver())));
+        
+        Assert.assertTrue(MockPKIXTrustEvaluator.class.isInstance((trustEngine.getPKIXTrustEvaluator())));
+        
+        Assert.assertTrue(MockX509CredentialNameEvaluator.class.isInstance((trustEngine.getX509CredentialNameEvaluator())));
+    }
+    
+    @Test(expectedExceptions=FatalBeanException.class)
+    public void customPropertiesFailsValidation() {
+        final GenericApplicationContext context = new FilesystemGenericApplicationContext();
+        context.setDisplayName("ApplicationContext: X509Credential");
+        final SchemaTypeAwareXMLBeanDefinitionReader beanDefinitionReader =
+                new SchemaTypeAwareXMLBeanDefinitionReader(context);
+
+        beanDefinitionReader.loadBeanDefinitions("org/opensaml/spring/trust/static-pkix-factory-custom-failsValidation.xml");
+
+        context.refresh();
+    }
+    
+    
+    // 
+    // Helpers
+    //
+    
+    public static class MockPKIXTrustEvaluator extends AbstractInitializableComponent implements PKIXTrustEvaluator {
+
+        /** {@inheritDoc} */
+        public boolean validate(PKIXValidationInformation validationInfo, X509Credential untrustedCredential)
+                throws SecurityException {
+            return false;
+        }
+
+        /** {@inheritDoc} */
+        public PKIXValidationOptions getPKIXValidationOptions() {
+            return null;
+        }
+        
+    }
+    
+    public static class MockX509CredentialNameEvaluator extends AbstractInitializableComponent implements X509CredentialNameEvaluator {
+
+        /** {@inheritDoc} */
+        public boolean evaluate(X509Credential credential, Set<String> trustedNames) throws SecurityException {
+            return false;
+        }
+        
+    }
+}
diff --git a/opensaml-spring/src/test/resources/org/opensaml/spring/credential/bean.xml b/opensaml-spring/src/test/resources/org/opensaml/spring/credential/bean.xml
new file mode 100644
index 000000000..9a2d0d2d2
--- /dev/null
+++ b/opensaml-spring/src/test/resources/org/opensaml/spring/credential/bean.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xmlns:util="http://www.springframework.org/schema/util"
+       xmlns:p="http://www.springframework.org/schema/p"
+       xmlns:c="http://www.springframework.org/schema/c"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
+                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
+                           
+       default-init-method="initialize"
+       default-destroy-method="destroy">
+
+    <bean id="Credential"
+        class="org.opensaml.spring.credential.BasicX509CredentialFactoryBean"
+        p:privateKeyResource="org/opensaml/spring/credential/idp-signing.key"
+        p:certificateResource="org/opensaml/spring/credential/idp-signing.crt"
+        p:entityId="http://example.org/plain" />
+
+    <bean id="EncCredential"
+        class="org.opensaml.spring.credential.BasicX509CredentialFactoryBean"
+        p:privateKeyResource="org/opensaml/spring/credential/idp-signing.key.pass"
+        p:certificateResource="org/opensaml/spring/credential/idp-signing.crt"
+        p:privateKeyPassword="pass"
+        p:entityId="http://example.org/enc" />
+        
+</beans>
\ No newline at end of file
diff --git a/opensaml-spring/src/test/resources/org/opensaml/spring/credential/cert.pem b/opensaml-spring/src/test/resources/org/opensaml/spring/credential/cert.pem
new file mode 100644
index 000000000..c0df65bc9
--- /dev/null
+++ b/opensaml-spring/src/test/resources/org/opensaml/spring/credential/cert.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDtTCCAp2gAwIBAgIJAPmsD+VGldyPMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTQwNDExMTMzOTE4WhcNMjQwNDA4MTMzOTE4WjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAxg0TyQAP/tIvOH89EtaXuRRn8SYzTj7W1TbNY4VvBmobjkRmSkki4hH9
+x4sQpi635wn6WtXTN/FNNmkTK3N/LspmBWxfZS+n+cc7I82E5yvCAPX67QsZgqgg
+lp2W5dvK/FsMMCS6X6SVqzBLMP88NenXKxY+HMxMs0sT0UKYh1cAEqadrHRBO65a
+DBcm5a0sBVYt9K6pgaOHrp/zSIbhnR5tFFLjBbtFktDpHL3AdGBH3OYidNGKBO3t
+J3Ms7LeKXsM0+0Y4P+9fHZINL2X3E2N6GVnKs5PZTg9sP0FtIpAbYm/+zCx7Yj1E
+T/Er8mDd6tNVGSQsn9s5xUBwGqn14wIDAQABo4GnMIGkMB0GA1UdDgQWBBSiQhSu
+p9BYjD2ZuMkEiQK7w/Zq0TB1BgNVHSMEbjBsgBSiQhSup9BYjD2ZuMkEiQK7w/Zq
+0aFJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNV
+BAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAPmsD+VGldyPMAwGA1UdEwQF
+MAMBAf8wDQYJKoZIhvcNAQELBQADggEBAHZmIo9GBTSsD5DJfKkCVUvBafwR089H
+BkgVPOuVuEe803BRlKd4BVIsuxAUAy3oqdJYqf9ptPEx8Ef+ALbcDhRbWINhMgO7
+0/S4x3pS9gOn7/Y9yZplOe4Jd2q3R8QBef+hKLcD/Uv0Sqy2nilM8BnMga5tqsL+
+8oFt0blzXtQ2vcOVyNyG326uZBZv2Cf6FXFsYQX1L/tLeTBJegefgGkg2dqCTKIU
+1Qy/Kd2P3/S01kQxjDeG7UfXc9qtelJ68kvzK2d3WOJ2qmsdMxjMNfTItP7FO54M
+i8V7gp9HK+EimdSbgu7xktKlrqA2Rsn+dBoPSgOUs/LOGtCS9/biF0w=
+-----END CERTIFICATE-----
diff --git a/opensaml-spring/src/test/resources/org/opensaml/spring/credential/certificate.pem b/opensaml-spring/src/test/resources/org/opensaml/spring/credential/certificate.pem
new file mode 100644
index 000000000..d9e8f8606
--- /dev/null
+++ b/opensaml-spring/src/test/resources/org/opensaml/spring/credential/certificate.pem
@@ -0,0 +1,52 @@
+-----BEGIN CERTIFICATE-----
+MIIDSTCCArKgAwIBAgIJAKg8tR5hjVM4MA0GCSqGSIb3DQEBBQUAMHcxCzAJBgNV
+BAYTAlVTMR0wGwYDVQQIExREaXN0cmljdCBvZiBDb2x1bWJpYTETMBEGA1UEBxMK
+V2FzaGluZ3RvbjEeMBwGA1UEChMVR2VvcmdldG93biBVbml2ZXJzaXR5MRQwEgYD
+VQQDEwtleGFtcGxlLm9yZzAeFw0wNzA4MDUxMzA4MDJaFw0xNzA4MDIxMzA4MDJa
+MHcxCzAJBgNVBAYTAlVTMR0wGwYDVQQIExREaXN0cmljdCBvZiBDb2x1bWJpYTET
+MBEGA1UEBxMKV2FzaGluZ3RvbjEeMBwGA1UEChMVR2VvcmdldG93biBVbml2ZXJz
+aXR5MRQwEgYDVQQDEwtleGFtcGxlLm9yZzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEA5zKHuD5DGPEQH+yLDMIA5M46HwJk7HxlGQ7N9WmkhaI22zXPC0UO8sY4
+AJW/8nlm0pc505iQmbgslg7/JyBemBj1sI7pOp6eCUPs7NR2mwaujXBturiRaJIe
+AX1Gjr3sO+3aLvqxUEu0PWqci4m1uc8XHQCA+PlEQQQnB9UIJwcCAwEAAaOB3DCB
+2TAdBgNVHQ4EFgQUzEhylzE4wmr4FK1lZ7zjR/KmA24wgakGA1UdIwSBoTCBnoAU
+zEhylzE4wmr4FK1lZ7zjR/KmA26he6R5MHcxCzAJBgNVBAYTAlVTMR0wGwYDVQQI
+ExREaXN0cmljdCBvZiBDb2x1bWJpYTETMBEGA1UEBxMKV2FzaGluZ3RvbjEeMBwG
+A1UEChMVR2VvcmdldG93biBVbml2ZXJzaXR5MRQwEgYDVQQDEwtleGFtcGxlLm9y
+Z4IJAKg8tR5hjVM4MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAGfkM
+HUeWzHzsBkwTu+S2vX4gzlJPjiL3RzL40og/qyGz38P4KVg8IQvsGDjs1VFzzcAJ
+I5ULnSocUOTk5sCTjDKT6VILhgAYJ1jnqIo7Z+VC1r3AS9cSDakzqWTc19EFKxEw
+6jeBWaqyykdSiVhCAmG5AJsvk+K032zjkWWMo+0=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFmjCCBIKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJVUzEc
+MBoGA1UEChMTSW5Db21tb24gRmVkZXJhdGlvbjEpMCcGA1UEAxMgSW5Db21tb24g
+Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwMzMwMjAzNDAwWhcNMTQwMzI5
+MjAzNDAwWjBWMQswCQYDVQQGEwJVUzEcMBoGA1UEChMTSW5Db21tb24gRmVkZXJh
+dGlvbjEpMCcGA1UEAxMgSW5Db21tb24gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkw
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDRGjKsUM2QAupLAaWx82/C
+WPalKjKFY8UPmz0T3gf7tJPztTy1Zq8pD0WFRLcQeSBKZGCu8upe8X966b6TZ5yu
+oUDA754If0DWismuHNoMgRR/l0UvZmPWDGRWd3NBTB8/soLA4EbqFf5Xq8MOJKhP
+tzcDR33gtaAb3oilZ+ZTpnhTFFrn/qXrAKcSDBpuW2JRpi3xaF/hTPI097oUShOz
+D1Zj21UYLA6iSFVN+1wlfwilf2KFNK/+zbkCge6wgipZyXxaOAam6ncqmkxy+hy/
+OiJMmdB+6xkO0xXSBUUcqxJrOcUQhA1vntgb3q5zOJISXhC4RAReA0HyBp/wd0iD
+AgMBAAGjggJxMIICbTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd
+BgNVHQ4EFgQUky3IYRitY+ObZbOd3Y2TuufKY0UwfgYDVR0jBHcwdYAUky3IYRit
+Y+ObZbOd3Y2TuufKY0WhWqRYMFYxCzAJBgNVBAYTAlVTMRwwGgYDVQQKExNJbkNv
+bW1vbiBGZWRlcmF0aW9uMSkwJwYDVQQDEyBJbkNvbW1vbiBDZXJ0aWZpY2F0aW9u
+IEF1dGhvcml0eYIBADCBugYIKwYBBQUHAQEEga0wgaowgacGCCsGAQUFBzAChoGa
+aHR0cDovL2luY29tbW9uY2ExLmluY29tbW9uZmVkZXJhdGlvbi5vcmcvYnJpZGdl
+L2NlcnRzL2NhLWNlcnRzLnA3YgoJCUNBIElzc3VlcnMgLSBVUkk6aHR0cDovL2lu
+Y29tbW9uY2EyLmluY29tbW9uZmVkZXJhdGlvbi5vcmcvYnJpZGdlL2NlcnRzL2Nh
+LWNlcnRzLnA3YjCBjQYDVR0fBIGFMIGCMD+gPaA7hjlodHRwOi8vaW5jb21tb25j
+cmwxLmluY29tbW9uZmVkZXJhdGlvbi5vcmcvY3JsL2VlY3Jscy5jcmwwP6A9oDuG
+OWh0dHA6Ly9pbmNvbW1vbmNybDIuaW5jb21tb25mZWRlcmF0aW9uLm9yZy9jcmwv
+ZWVjcmxzLmNybDBeBgNVHSAEVzBVMFMGCysGAQQBriMBBAEBMEQwQgYIKwYBBQUH
+AgEWNmh0dHA6Ly9pbmNvbW1vbmNhLmluY29tbW9uZmVkZXJhdGlvbi5vcmcvcHJh
+Y3RpY2VzLnBkZjANBgkqhkiG9w0BAQUFAAOCAQEAZfgKUPA+Ky+Ou/vclMlFTMlU
+GspfbNSdG/fmIq+E/Lv1d2c73Am1zGhOpxgdkM8SE+BPnXW2rl71/N8gaqwgBBxk
+pwn410siumxlDTwV3HoVFvCGWylNy9o8OE1LyTCqfo8PRwrMzhwcagDgD813BIyj
+uJg/JQz1LnHMocIW/JligloSIzF1O435/+ckfWXQsmBIhvV5TmA3ZrcycrI1cHGE
+ZqrCXL0FMZLSr+Vady/tFbVojqI8pSubSMxNkZectePTBjVj1Qeb4hmG8jRv/fwy
+1Iw6OFH8RKny8nQaO5mOe/fF/swEsMVU9TDpvLIgbhTwnP7Nhfotgaxf5wG8WA==
+-----END CERTIFICATE-----
\ No newline at end of file
diff --git a/opensaml-spring/src/test/resources/org/opensaml/spring/credential/idp-signing.crt b/opensaml-spring/src/test/resources/org/opensaml/spring/credential/idp-signing.crt
new file mode 100644
index 000000000..c0df65bc9
--- /dev/null
+++ b/opensaml-spring/src/test/resources/org/opensaml/spring/credential/idp-signing.crt
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDtTCCAp2gAwIBAgIJAPmsD+VGldyPMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTQwNDExMTMzOTE4WhcNMjQwNDA4MTMzOTE4WjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAxg0TyQAP/tIvOH89EtaXuRRn8SYzTj7W1TbNY4VvBmobjkRmSkki4hH9
+x4sQpi635wn6WtXTN/FNNmkTK3N/LspmBWxfZS+n+cc7I82E5yvCAPX67QsZgqgg
+lp2W5dvK/FsMMCS6X6SVqzBLMP88NenXKxY+HMxMs0sT0UKYh1cAEqadrHRBO65a
+DBcm5a0sBVYt9K6pgaOHrp/zSIbhnR5tFFLjBbtFktDpHL3AdGBH3OYidNGKBO3t
+J3Ms7LeKXsM0+0Y4P+9fHZINL2X3E2N6GVnKs5PZTg9sP0FtIpAbYm/+zCx7Yj1E
+T/Er8mDd6tNVGSQsn9s5xUBwGqn14wIDAQABo4GnMIGkMB0GA1UdDgQWBBSiQhSu
+p9BYjD2ZuMkEiQK7w/Zq0TB1BgNVHSMEbjBsgBSiQhSup9BYjD2ZuMkEiQK7w/Zq
+0aFJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNV
+BAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAPmsD+VGldyPMAwGA1UdEwQF
+MAMBAf8wDQYJKoZIhvcNAQELBQADggEBAHZmIo9GBTSsD5DJfKkCVUvBafwR089H
+BkgVPOuVuEe803BRlKd4BVIsuxAUAy3oqdJYqf9ptPEx8Ef+ALbcDhRbWINhMgO7
+0/S4x3pS9gOn7/Y9yZplOe4Jd2q3R8QBef+hKLcD/Uv0Sqy2nilM8BnMga5tqsL+
+8oFt0blzXtQ2vcOVyNyG326uZBZv2Cf6FXFsYQX1L/tLeTBJegefgGkg2dqCTKIU
+1Qy/Kd2P3/S01kQxjDeG7UfXc9qtelJ68kvzK2d3WOJ2qmsdMxjMNfTItP7FO54M
+i8V7gp9HK+EimdSbgu7xktKlrqA2Rsn+dBoPSgOUs/LOGtCS9/biF0w=
+-----END CERTIFICATE-----
diff --git a/opensaml-spring/src/test/resources/org/opensaml/spring/credential/idp-signing.key b/opensaml-spring/src/test/resources/org/opensaml/spring/credential/idp-signing.key
new file mode 100644
index 000000000..951462f0d
--- /dev/null
+++ b/opensaml-spring/src/test/resources/org/opensaml/spring/credential/idp-signing.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAxg0TyQAP/tIvOH89EtaXuRRn8SYzTj7W1TbNY4VvBmobjkRm
+Skki4hH9x4sQpi635wn6WtXTN/FNNmkTK3N/LspmBWxfZS+n+cc7I82E5yvCAPX6
+7QsZgqgglp2W5dvK/FsMMCS6X6SVqzBLMP88NenXKxY+HMxMs0sT0UKYh1cAEqad
+rHRBO65aDBcm5a0sBVYt9K6pgaOHrp/zSIbhnR5tFFLjBbtFktDpHL3AdGBH3OYi
+dNGKBO3tJ3Ms7LeKXsM0+0Y4P+9fHZINL2X3E2N6GVnKs5PZTg9sP0FtIpAbYm/+
+zCx7Yj1ET/Er8mDd6tNVGSQsn9s5xUBwGqn14wIDAQABAoIBAHG6nLv13zmTdS5a
+UrX4qNPNVgryxs+N4kw51iPqQeFLGVvPB3ZtHSz46+SkhQEJHu37mtqCo3IijRZL
+rIhtIIG8FG3U18sBXNJgiCN9J26ggB2RI3DvyMxww5X6FOcWGjBkEFGtJaE6n//Y
+EbWnO+oxyC+j7DMZVoo2+MBYH8LHPXpMPFPhYbf12LpHY+WeNgX/eemMTlSylBln
+lfhySCtpLcgY7+juYlXaZ9Y1z37QZBcP6yYLTnXJVlhY1KcULh+/PUnmzVpHbkwU
+v/yQiFGFsve1ROp0ztB6sFufLnvGcTa3T1Oeza9ZaX/zjbMbGp3qjSGoknS23U0Q
+ZotRB+ECgYEA9EmvBYLWgEayOlZPcBwKZ3Qrwf9ip3xmtubrf9byIozEeQTKvHmA
+UvK5dKN1pwK0gTaWk5aq+n64HtwJ0+pO4bV32TJJlV/la4xd7wHdH5+S5cdQjd/r
+tuxyejp5FhqT+x2rKibskEeFKhfgIIolpkcNFIKc9xa3/VBOWPxV19kCgYEAz4vl
+xJhD8Cf97bm5hemiJPt2eQMCTGCE39O4UaY6xi5lINoySoh8qd2e59nnneG4YaNp
+tHU23oh00m68Jx8b7wMFliQ/J59lxAkfP262EkBqf/VOAVXQo/iaA8HSwq3Hfwt5
+0F4HMQEfB6qf7/LGvFHTQ8+Wn1upZGaYP1YAghsCgYBe3FILmNAExe8luihkx26+
+15y6W5qKoUMdmTQv0175TaJpwBOd9qx/CWQ8x9DDBsjjODhmnWZNmXGUAiwKz3zM
+JvSgMefjCncDOWGskxOz2PppIenE/gQBZ3XYwuYMUEvQgqfZ2X2ZVTx/qP/Ogva1
+x/drVIDxbjAKPOn/ohUPmQKBgQChW5qfZeIr7Gu3TxW1zxaIuhg5rOU0jDXB7tD2
+ac54Fcn56KoA2GxThEHu77LrRHodLvcXnamzCVQJ5p3RrJYDFM5bFIMlQv/TkWQB
+5QkY14v1P7oNv7IeSUE0epRpVsIrO7jRDsl4h+6f/z+pRY7NCrC9n77y1ki0Di9/
+zlVG0QKBgFXQkO/bf0Qs3COPWUs5nHyQ/sR0ptx1jrFDSjCdGvBC7NrDlwNP3894
+EHCUTrEHhjtAGVzyZakZ6PLAN9cf86N1QhvOdj/oasL5vddWyFK74x2/mtp59VOU
+LaCxnnbG4JoSVX96BSzUFbtRrQbf2+t5ZON9K12IPIxstMkF2j8u
+-----END RSA PRIVATE KEY-----
diff --git a/opensaml-spring/src/test/resources/org/opensaml/spring/credential/idp-signing.key.pass b/opensaml-spring/src/test/resources/org/opensaml/spring/credential/idp-signing.key.pass
new file mode 100644
index 000000000..cde1772f7
--- /dev/null
+++ b/opensaml-spring/src/test/resources/org/opensaml/spring/credential/idp-signing.key.pass
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,167811113CA00D40A7A46A79F0133598
+
+lzqV3Xcehk1mnsq4ZRXqiGZXIhYPWA7KqjqJYEHd10JvJoNUwZ7l6VmyZUtny1Xq
+nPPLjWsZ5rOVQkULOX/ZCmXCAW3YgvoIXmdjcenRlZTlbi7vNqongiNGgRleWRlS
+V/E+KrQXlt0jfV1KdW/PDe712mytL7akWoIE39rI0Z78EhD5YfGsA6J6azLmB5zS
+Ffu+wUfND7/gTR3roVlj8Vs1GWxdyNNLI3yUnK6aRd8zO/eTeTcMullSRpT1ORsI
+qhEMfTIBhG+yqC+NhDv1UJ8r8N6jiD63ciKwrt31SOGamdZNRdgxm1sCOcH/akN4
+w9DStPCx809gw46g/ZAi2V2sa0FguS8Jed/LFGwHG/6FVK/nLONzdFIzNF4gZ+B0
+rIPhrdK2kWpEHbMzPZG2KQack9mDv63HNTAJ8Xu1Sf9oHjJyEpdR7bczS+WeZNjd
+YyM6fR7z9n+UWhqa2+2VtAX5KsnNy5BP1SI2h3rVdpW7+hZO74O31Jj6j0QFe0ks
+e20X3ldx/EPJpJunLv46wLsSEoxfuooFj0bxpPEIjb76q9jOXJHr7M+57pdH6Z17
+lPZQ+nCUvUyfIDZ66EfMYpR6nGpYizhpRlvc5U35sU1ZEtngKwJ1rcwFkYD6THKG
+3Y+UVXd9Ft7EbuI7ArB3MOEsOgrw37IvIT3bAI3pvmdezs6H+j5cfb4F7cIGVXWM
+GB00ahK+qNnL0TaC2+qKuGT4bCxeUYkf8fY21JDnIVpZotjeau5qE32AfjWTjPBJ
+RRTyzVvAS3IjeA/LvsMVailUhZTv0sbgudGh14GKp1HWwLQKs4SXAgGCNCNEOaWu
+vKQT2srL5v0d9SBrVhZBi2u1zIiTREy8JIucX2fNvaDPJ9ZJDqxcEVZUnfaXui0u
+y0cinJ5OJQKM99hK6jVimchdJ+viGc4RRZPatkY/ZSiISJwVtrF/VbsAGN45SI+9
+GbAAD4PKOPDxeQ7qMck/OHQAFi3gUDeRsw//13lHOd3KvsWFQIuOcKJPusdU4jJV
+vBUBVtAJxlESJbjfyN1z6vM8mhm5k63apTuSDmzJfU9hMv7eKV7PIhH48RBNqtWl
+atTukx4eex56Jv54u+kKMVZC8AkrCukYrdho+QVdXJ9J0ZqGW0o9BscE4qBpm16K
+/7EL9IfmqZPK5JyxAJPINYeuBu8RPLhbRDFXCr9hMI1VX24O6S3jJWcQmAU8kOki
+UhnYwOUS98cgecyuLmEnzdvogQXFt81jrfFBNLoQ6v/SS1BIJpkDzTWAz+1qjKpR
+1IFdL8omj9SqVPHelUC5s0LKmhI6NLSC/RGFlSaAJ5FcbPTTdaNKH9dDrfQ+yylN
+bINRkbkWBrsVtMdw42Rba4WTSU7iNFQ8/UdNnHOLmfz4yR4x/g++8YusJys4OfD5
+rxr6Y8bAkhO/ebO1ERGmubZQO4AmdLllNXvgfxjY0M4Mpq6DCMLSFfz5Wc+lpX0E
+5ZRDbOBPZcGjJwJKXDDWPAQ95nbHotg/wNy+MeVXylpPgg+NCncdxqikIb/5gx91
+loYi7X4XgaXf6J4VPZDcaQiQul8YLaOk/BCMLopAGIzT+cDxsOi/zKkAICuuMiIn
+-----END RSA PRIVATE KEY-----
diff --git a/opensaml-spring/src/test/resources/org/opensaml/spring/credential/publicKey.pem b/opensaml-spring/src/test/resources/org/opensaml/spring/credential/publicKey.pem
new file mode 100644
index 000000000..5c4e2e78c
--- /dev/null
+++ b/opensaml-spring/src/test/resources/org/opensaml/spring/credential/publicKey.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxg0TyQAP/tIvOH89EtaX
+uRRn8SYzTj7W1TbNY4VvBmobjkRmSkki4hH9x4sQpi635wn6WtXTN/FNNmkTK3N/
+LspmBWxfZS+n+cc7I82E5yvCAPX67QsZgqgglp2W5dvK/FsMMCS6X6SVqzBLMP88
+NenXKxY+HMxMs0sT0UKYh1cAEqadrHRBO65aDBcm5a0sBVYt9K6pgaOHrp/zSIbh
+nR5tFFLjBbtFktDpHL3AdGBH3OYidNGKBO3tJ3Ms7LeKXsM0+0Y4P+9fHZINL2X3
+E2N6GVnKs5PZTg9sP0FtIpAbYm/+zCx7Yj1ET/Er8mDd6tNVGSQsn9s5xUBwGqn1
+4wIDAQAB
+-----END PUBLIC KEY-----
diff --git a/opensaml-spring/src/test/resources/org/opensaml/spring/trust/static-pkix-factory-custom-failsValidation.xml b/opensaml-spring/src/test/resources/org/opensaml/spring/trust/static-pkix-factory-custom-failsValidation.xml
new file mode 100644
index 000000000..7f0823a8c
--- /dev/null
+++ b/opensaml-spring/src/test/resources/org/opensaml/spring/trust/static-pkix-factory-custom-failsValidation.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xmlns:util="http://www.springframework.org/schema/util"
+       xmlns:p="http://www.springframework.org/schema/p"
+       xmlns:c="http://www.springframework.org/schema/c"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
+                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
+                           
+       default-init-method="initialize"
+       default-destroy-method="destroy">
+
+    <bean id="StaticPKIXX509CredentialTrustEngine"
+          class="org.opensaml.spring.trust.StaticPKIXFactoryBean">
+        <property name="certificates">
+            <list>
+                <value>org/opensaml/spring/credential/idp-signing.crt</value>
+            </list>
+          </property>
+        <property name="trustEvaluator">
+            <bean class="org.opensaml.security.x509.impl.CertPathPKIXTrustEvaluator" destroy-method="">
+                <property name="PKIXValidationOptions">
+                    <bean class="org.opensaml.security.x509.impl.CertPathPKIXValidationOptions"
+                        p:forceRevocationEnabled="true"
+                        p:revocationEnabled="true"
+                        destroy-method="" />
+                </property>
+            </bean>
+        </property>
+    </bean>
+        
+</beans>
\ No newline at end of file
diff --git a/opensaml-spring/src/test/resources/org/opensaml/spring/trust/static-pkix-factory-custom-success.xml b/opensaml-spring/src/test/resources/org/opensaml/spring/trust/static-pkix-factory-custom-success.xml
new file mode 100644
index 000000000..22e93f04c
--- /dev/null
+++ b/opensaml-spring/src/test/resources/org/opensaml/spring/trust/static-pkix-factory-custom-success.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xmlns:util="http://www.springframework.org/schema/util"
+       xmlns:p="http://www.springframework.org/schema/p"
+       xmlns:c="http://www.springframework.org/schema/c"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
+                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
+                           
+       default-init-method="initialize"
+       default-destroy-method="destroy">
+
+    <bean id="StaticPKIXX509CredentialTrustEngine"
+          class="org.opensaml.spring.trust.StaticPKIXFactoryBean">
+        <property name="certificates">
+            <list>
+                <value>org/opensaml/spring/credential/idp-signing.crt</value>
+            </list>
+          </property>
+        <property name="trustEvaluator">
+            <bean class="org.opensaml.spring.trust.StaticPKIXFactoryBeanTest.MockPKIXTrustEvaluator" />
+        </property>
+        <property name="credentialNameEvaluator">
+            <bean class="org.opensaml.spring.trust.StaticPKIXFactoryBeanTest.MockX509CredentialNameEvaluator" />
+        </property>
+    </bean>
+        
+</beans>
\ No newline at end of file
diff --git a/opensaml-spring/src/test/resources/org/opensaml/spring/trust/static-pkix-factory-defaults.xml b/opensaml-spring/src/test/resources/org/opensaml/spring/trust/static-pkix-factory-defaults.xml
new file mode 100644
index 000000000..cf186faec
--- /dev/null
+++ b/opensaml-spring/src/test/resources/org/opensaml/spring/trust/static-pkix-factory-defaults.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xmlns:util="http://www.springframework.org/schema/util"
+       xmlns:p="http://www.springframework.org/schema/p"
+       xmlns:c="http://www.springframework.org/schema/c"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
+                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
+                           
+       default-init-method="initialize"
+       default-destroy-method="destroy">
+
+    <bean id="StaticPKIXX509CredentialTrustEngine"
+          class="org.opensaml.spring.trust.StaticPKIXFactoryBean">
+        <property name="certificates">
+            <list>
+                <value>org/opensaml/spring/credential/idp-signing.crt</value>
+            </list>
+          </property>
+    </bean>
+        
+</beans>
\ No newline at end of file
diff --git a/opensaml-spring/src/test/resources/org/opensaml/spring/trust/staticExplicitNative.xml b/opensaml-spring/src/test/resources/org/opensaml/spring/trust/staticExplicitNative.xml
new file mode 100644
index 000000000..655606a74
--- /dev/null
+++ b/opensaml-spring/src/test/resources/org/opensaml/spring/trust/staticExplicitNative.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
+	xmlns:c="http://www.springframework.org/schema/c" xmlns:p="http://www.springframework.org/schema/p"
+	xmlns:context="http://www.springframework.org/schema/context"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+                            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
+                            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
+	default-init-method="initialize" default-destroy-method="destroy">
+
+    <bean id="staticKeySingle"
+        class="org.opensaml.spring.trust.StaticExplicitKeyFactoryBean"
+        p:publicKeys="classpath:/org/opensaml/spring/credential/publicKey.pem" />
+
+    <bean id="staticX509Single"
+        class="org.opensaml.spring.trust.StaticExplicitKeyFactoryBean"
+        p:certificates="classpath:/org/opensaml/spring/credential/cert.pem" />
+
+    <bean id="staticX509Multiple"
+        class="org.opensaml.spring.trust.StaticExplicitKeyFactoryBean"
+        p:certificates="classpath:/org/opensaml/spring/credential/certificate.pem" />
+
+    <bean id="staticMixed"
+        class="org.opensaml.spring.trust.StaticExplicitKeyFactoryBean"
+        p:publicKeys="classpath:/org/opensaml/spring/credential/publicKey.pem"
+        p:certificates="classpath:/org/opensaml/spring/credential/cert.pem" />
+
+</beans>
diff --git a/opensaml-storage-api/.classpath b/opensaml-storage-api/.classpath
index 77be441ed..8c2ac107c 100644
--- a/opensaml-storage-api/.classpath
+++ b/opensaml-storage-api/.classpath
@@ -32,6 +32,7 @@
 	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
 		<attributes>
 			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="org.eclipse.jst.component.nondependency" value=""/>
 		</attributes>
 	</classpathentry>
 	<classpathentry kind="output" path="target/classes"/>
diff --git a/opensaml-storage-api/.project b/opensaml-storage-api/.project
index f2eb3de06..1188543d3 100644
--- a/opensaml-storage-api/.project
+++ b/opensaml-storage-api/.project
@@ -1,23 +1,41 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <projectDescription>
-    <name>opensaml-storage-api</name>
-    <comment></comment>
-    <projects>
-    </projects>
-    <buildSpec>
-        <buildCommand>
-            <name>org.eclipse.jdt.core.javabuilder</name>
-        </buildCommand>
-        <buildCommand>
-            <name>net.sf.eclipsecs.core.CheckstyleBuilder</name>
-        </buildCommand>
-        <buildCommand>
-            <name>org.eclipse.m2e.core.maven2Builder</name>
-        </buildCommand>
-    </buildSpec>
-    <natures>
-        <nature>org.eclipse.jdt.core.javanature</nature>
-        <nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
-        <nature>org.eclipse.m2e.core.maven2Nature</nature>
-    </natures>
-</projectDescription>
\ No newline at end of file
+	<name>opensaml-storage-api</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>net.sf.eclipsecs.core.CheckstyleBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.m2e.core.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
+		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
+	</natures>
+</projectDescription>
diff --git a/opensaml-storage-api/.settings/org.eclipse.wst.common.component b/opensaml-storage-api/.settings/org.eclipse.wst.common.component
new file mode 100644
index 000000000..79f602947
--- /dev/null
+++ b/opensaml-storage-api/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="opensaml-storage-api">
+        <wb-resource deploy-path="/" source-path="/src/main/java"/>
+        <wb-resource deploy-path="/" source-path="/src/main/resources"/>
+    </wb-module>
+</project-modules>
diff --git a/opensaml-storage-api/.settings/org.eclipse.wst.common.project.facet.core.xml b/opensaml-storage-api/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 000000000..9ba61b70c
--- /dev/null
+++ b/opensaml-storage-api/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <installed facet="java" version="17"/>
+  <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
diff --git a/opensaml-storage-impl/.classpath b/opensaml-storage-impl/.classpath
index 77be441ed..8c2ac107c 100644
--- a/opensaml-storage-impl/.classpath
+++ b/opensaml-storage-impl/.classpath
@@ -32,6 +32,7 @@
 	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
 		<attributes>
 			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="org.eclipse.jst.component.nondependency" value=""/>
 		</attributes>
 	</classpathentry>
 	<classpathentry kind="output" path="target/classes"/>
diff --git a/opensaml-storage-impl/.project b/opensaml-storage-impl/.project
index 94ba85ac2..af2293e36 100644
--- a/opensaml-storage-impl/.project
+++ b/opensaml-storage-impl/.project
@@ -5,6 +5,11 @@
 	<projects>
 	</projects>
 	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 		<buildCommand>
 			<name>org.eclipse.jdt.core.javabuilder</name>
 			<arguments>
@@ -25,11 +30,18 @@
 			<arguments>
 			</arguments>
 		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 	</buildSpec>
 	<natures>
 		<nature>org.springframework.ide.eclipse.core.springnature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
 		<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
 		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
 	</natures>
 </projectDescription>
diff --git a/opensaml-storage-impl/.settings/org.eclipse.wst.common.component b/opensaml-storage-impl/.settings/org.eclipse.wst.common.component
new file mode 100644
index 000000000..1af0866c6
--- /dev/null
+++ b/opensaml-storage-impl/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="opensaml-storage-impl">
+        <wb-resource deploy-path="/" source-path="/src/main/java"/>
+        <wb-resource deploy-path="/" source-path="/src/main/resources"/>
+    </wb-module>
+</project-modules>
diff --git a/opensaml-storage-impl/.settings/org.eclipse.wst.common.project.facet.core.xml b/opensaml-storage-impl/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 000000000..9ba61b70c
--- /dev/null
+++ b/opensaml-storage-impl/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <installed facet="java" version="17"/>
+  <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
diff --git a/opensaml-tests-bom/pom.xml b/opensaml-tests-bom/pom.xml
index 2649e3e57..19866bda5 100644
--- a/opensaml-tests-bom/pom.xml
+++ b/opensaml-tests-bom/pom.xml
@@ -95,6 +95,13 @@
                 <type>test-jar</type>
                 <scope>test</scope>
             </dependency>
+            <dependency>
+                <groupId>${project.groupId}</groupId>
+                <artifactId>opensaml-spring</artifactId>
+                <version>${project.version}</version>
+                <type>test-jar</type>
+                <scope>test</scope>
+            </dependency>
             <dependency>
                 <groupId>${project.groupId}</groupId>
                 <artifactId>opensaml-storage-api</artifactId>
diff --git a/opensaml-xmlsec-api/.classpath b/opensaml-xmlsec-api/.classpath
index 77be441ed..8c2ac107c 100644
--- a/opensaml-xmlsec-api/.classpath
+++ b/opensaml-xmlsec-api/.classpath
@@ -32,6 +32,7 @@
 	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
 		<attributes>
 			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="org.eclipse.jst.component.nondependency" value=""/>
 		</attributes>
 	</classpathentry>
 	<classpathentry kind="output" path="target/classes"/>
diff --git a/opensaml-xmlsec-api/.project b/opensaml-xmlsec-api/.project
index e8b9746ff..fb48bc1ae 100644
--- a/opensaml-xmlsec-api/.project
+++ b/opensaml-xmlsec-api/.project
@@ -5,6 +5,11 @@
 	<projects>
 	</projects>
 	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 		<buildCommand>
 			<name>org.eclipse.jdt.core.javabuilder</name>
 			<arguments>
@@ -20,10 +25,17 @@
 			<arguments>
 			</arguments>
 		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 	</buildSpec>
 	<natures>
 		<nature>org.eclipse.m2e.core.maven2Nature</nature>
 		<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
 	</natures>
 </projectDescription>
diff --git a/opensaml-xmlsec-api/.settings/org.eclipse.wst.common.component b/opensaml-xmlsec-api/.settings/org.eclipse.wst.common.component
new file mode 100644
index 000000000..6e7682521
--- /dev/null
+++ b/opensaml-xmlsec-api/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="opensaml-xmlsec-api">
+        <wb-resource deploy-path="/" source-path="/src/main/java"/>
+        <wb-resource deploy-path="/" source-path="/src/main/resources"/>
+    </wb-module>
+</project-modules>
diff --git a/opensaml-xmlsec-api/.settings/org.eclipse.wst.common.project.facet.core.xml b/opensaml-xmlsec-api/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 000000000..9ba61b70c
--- /dev/null
+++ b/opensaml-xmlsec-api/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <installed facet="java" version="17"/>
+  <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
diff --git a/opensaml-xmlsec-impl/.classpath b/opensaml-xmlsec-impl/.classpath
index 77be441ed..8c2ac107c 100644
--- a/opensaml-xmlsec-impl/.classpath
+++ b/opensaml-xmlsec-impl/.classpath
@@ -32,6 +32,7 @@
 	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
 		<attributes>
 			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="org.eclipse.jst.component.nondependency" value=""/>
 		</attributes>
 	</classpathentry>
 	<classpathentry kind="output" path="target/classes"/>
diff --git a/opensaml-xmlsec-impl/.project b/opensaml-xmlsec-impl/.project
index cd8ef9240..572d9ca39 100644
--- a/opensaml-xmlsec-impl/.project
+++ b/opensaml-xmlsec-impl/.project
@@ -5,6 +5,11 @@
 	<projects>
 	</projects>
 	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 		<buildCommand>
 			<name>org.eclipse.jdt.core.javabuilder</name>
 			<arguments>
@@ -20,10 +25,17 @@
 			<arguments>
 			</arguments>
 		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 	</buildSpec>
 	<natures>
 		<nature>org.eclipse.m2e.core.maven2Nature</nature>
 		<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
 	</natures>
 </projectDescription>
diff --git a/opensaml-xmlsec-impl/.settings/org.eclipse.wst.common.component b/opensaml-xmlsec-impl/.settings/org.eclipse.wst.common.component
new file mode 100644
index 000000000..f1178b3dc
--- /dev/null
+++ b/opensaml-xmlsec-impl/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="opensaml-xmlsec-impl">
+        <wb-resource deploy-path="/" source-path="/src/main/java"/>
+        <wb-resource deploy-path="/" source-path="/src/main/resources"/>
+    </wb-module>
+</project-modules>
diff --git a/opensaml-xmlsec-impl/.settings/org.eclipse.wst.common.project.facet.core.xml b/opensaml-xmlsec-impl/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 000000000..9ba61b70c
--- /dev/null
+++ b/opensaml-xmlsec-impl/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <installed facet="java" version="17"/>
+  <installed facet="jst.utility" version="1.0"/>
+</faceted-project>

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


More information about the commits mailing list