[java-shib-profile] branch main updated: JSPROF-1 - Move RelyingParty "layer" into java-shib-profile

Scott Cantor cantor.2 at osu.edu
Tue Feb 14 20:53:03 UTC 2023


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

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

View the commit online:
http://git.shibboleth.net/view/?p=java-shib-profile.git;a=commit;h=8cb6e08cd87a110f8d2256daf3e1dfa002309464

The following commit(s) were added to refs/heads/main by this push:
     new 8cb6e08  JSPROF-1 - Move RelyingParty "layer" into java-shib-profile
8cb6e08 is described below

commit 8cb6e08cd87a110f8d2256daf3e1dfa002309464
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Feb 14 15:53:00 2023 -0500

    JSPROF-1 - Move RelyingParty "layer" into java-shib-profile
    
    https://shibboleth.atlassian.net/browse/JSPROF-1
    
    Migrate in remaining generic lookup functions.
---
 shib-profile-api/pom.xml                           |  36 +-
 ...DefaultSecurityConfigurationLookupFunction.java |  73 ++++
 ...pClientSecurityConfigurationLookupFunction.java |  74 ++++
 ...ignatureSigningConfigurationLookupFunction.java |  76 ++++
 ...atureValidationConfigurationLookupFunction.java |  76 ++++
 .../config/navigate/messaging/package-info.java    |  22 ++
 .../navigate/RelyingPartyIdLookupFunction.java     |   2 +-
 .../navigate/ScriptedContextLookupFunction.java    | 391 +++++++++++++++++++++
 ...ServletRequestProfileRequestContextLookup.java} |  28 +-
 .../SpringExpressionContextLookupFunction.java     |  74 ++++
 .../AbstractRelyingPartyLookupFunction.java        | 132 +++++++
 .../context/navigate/messaging/package-info.java   |  21 ++
 .../ScriptedContextLookupFunctionTest.java         |  86 +++++
 .../SpringExpressionContextLookupFunctionTest.java |  67 ++++
 14 files changed, 1134 insertions(+), 24 deletions(-)

diff --git a/shib-profile-api/pom.xml b/shib-profile-api/pom.xml
index fcd35ad..dc55e2d 100644
--- a/shib-profile-api/pom.xml
+++ b/shib-profile-api/pom.xml
@@ -43,18 +43,21 @@
             <groupId>${shib-shared.groupId}</groupId>
             <artifactId>shib-service</artifactId>
         </dependency>
+        <dependency>
+            <groupId>${shib-shared.groupId}</groupId>
+            <artifactId>shib-spring</artifactId>
+        </dependency>
 
         <!-- Provided Dependencies -->
+        <dependency>
+            <groupId>jakarta.servlet</groupId>
+            <artifactId>jakarta.servlet-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
 
         <!-- Runtime Dependencies -->
 
         <!-- Test Dependencies -->
-        <dependency>
-            <groupId>${shib-shared.groupId}</groupId>
-            <artifactId>shib-spring</artifactId>
-            <scope>test</scope>
-        </dependency>
-
         <dependency>
             <groupId>${spring.groupId}</groupId>
             <artifactId>spring-context</artifactId>
@@ -63,4 +66,25 @@
 
     </dependencies>
 
+    <profiles>
+        <!--
+            Pull in a Javascript engine for testing in Java
+            versions where the JDK doesn't provide one.
+        -->
+        <profile>
+            <id>get-nashorn</id>
+            <activation>
+                <jdk>[15,</jdk>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>org.openjdk.nashorn</groupId>
+                    <artifactId>nashorn-core</artifactId>
+                    <version>${nashorn.jdk.version}</version>
+                    <scope>test</scope>
+                </dependency>
+            </dependencies>
+        </profile>
+    </profiles>
+
 </project>
diff --git a/shib-profile-api/src/main/java/net/shibboleth/profile/config/navigate/messaging/AbstractDefaultSecurityConfigurationLookupFunction.java b/shib-profile-api/src/main/java/net/shibboleth/profile/config/navigate/messaging/AbstractDefaultSecurityConfigurationLookupFunction.java
new file mode 100644
index 0000000..f343036
--- /dev/null
+++ b/shib-profile-api/src/main/java/net/shibboleth/profile/config/navigate/messaging/AbstractDefaultSecurityConfigurationLookupFunction.java
@@ -0,0 +1,73 @@
+/*
+ * 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 net.shibboleth.profile.config.navigate.messaging;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.security.config.SecurityConfiguration;
+import org.slf4j.Logger;
+
+import net.shibboleth.profile.context.navigate.messaging.AbstractRelyingPartyLookupFunction;
+import net.shibboleth.profile.relyingparty.RelyingPartyConfigurationResolver;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.service.ReloadableService;
+import net.shibboleth.shared.service.ServiceException;
+import net.shibboleth.shared.service.ServiceableComponent;
+
+/**
+ * Base class for lookup functions that require access to the default security configuration
+ * for a profile via the {@link RelyingPartyConfigurationResolver} interface.
+ * 
+ * @param <T> function return type
+ */
+public abstract class AbstractDefaultSecurityConfigurationLookupFunction<T> 
+        extends AbstractRelyingPartyLookupFunction<T> {
+    
+    /** Class logger. */
+    @Nonnull private Logger log = LoggerFactory.getLogger(AbstractDefaultSecurityConfigurationLookupFunction.class);
+    
+    /** A resolver for default security configurations. */
+    @Nullable private ReloadableService<RelyingPartyConfigurationResolver> rpResolver;
+    
+    /**
+     * Set the resolver for default security configurations.
+     * 
+     * @param resolver the resolver to use
+     */
+    public void setRelyingPartyConfigurationResolver(
+            @Nullable final ReloadableService<RelyingPartyConfigurationResolver> resolver) {
+        rpResolver = resolver;
+    }
+
+    @Nullable protected SecurityConfiguration getDefaultSecurityConfiguration(
+            @Nonnull @NotEmpty final String profileId) {
+        
+        if (rpResolver != null) {
+            try (final ServiceableComponent<RelyingPartyConfigurationResolver> component =
+                    rpResolver.getServiceableComponent()) {
+                return component.getComponent().getDefaultSecurityConfiguration(profileId);
+            } catch (final ServiceException e) {
+                log.error("RelyingPartyConfigurationResolver was invalid", e.getMessage());
+            }
+        }
+        
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/shib-profile-api/src/main/java/net/shibboleth/profile/config/navigate/messaging/HttpClientSecurityConfigurationLookupFunction.java b/shib-profile-api/src/main/java/net/shibboleth/profile/config/navigate/messaging/HttpClientSecurityConfigurationLookupFunction.java
new file mode 100644
index 0000000..07efd2c
--- /dev/null
+++ b/shib-profile-api/src/main/java/net/shibboleth/profile/config/navigate/messaging/HttpClientSecurityConfigurationLookupFunction.java
@@ -0,0 +1,74 @@
+/*
+ * 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 net.shibboleth.profile.config.navigate.messaging;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.security.config.SecurityConfiguration;
+import org.opensaml.security.httpclient.HttpClientSecurityConfiguration;
+import org.opensaml.security.httpclient.HttpClientSecuritySupport;
+
+import net.shibboleth.profile.config.ProfileConfiguration;
+import net.shibboleth.profile.context.RelyingPartyContext;
+
+/**
+ * A {@link MessageContext} function that returns a {@link HttpClientSecurityConfiguration} list 
+ * by way of various lookup strategies.
+ * 
+ * <p>If a specific setting is unavailable, a null value is returned.</p>
+ */
+public class HttpClientSecurityConfigurationLookupFunction
+        extends AbstractDefaultSecurityConfigurationLookupFunction<List<HttpClientSecurityConfiguration>> {
+
+    /** {@inheritDoc} */
+    @Nullable public List<HttpClientSecurityConfiguration> apply(@Nullable final MessageContext input) {
+        
+        final List<HttpClientSecurityConfiguration> configs = new ArrayList<>();
+        
+        final RelyingPartyContext rpc = getRelyingPartyContext(input);
+        if (rpc != null) {
+            final ProfileConfiguration pc = rpc.getProfileConfig();
+            if (pc != null) {
+                final SecurityConfiguration sc = pc.getSecurityConfiguration(getProfileRequestContext(input));
+                if (sc != null && sc.getHttpClientSecurityConfiguration() != null) {
+                    configs.add(sc.getHttpClientSecurityConfiguration());
+                }
+            }
+            
+            // Check for a per-profile default (relying party independent) config.
+            if (pc != null) {
+                final String id = pc.getId();
+                if (id != null) {
+                    final SecurityConfiguration defaultConfig = getDefaultSecurityConfiguration(id);
+                    if (defaultConfig != null && defaultConfig.getHttpClientSecurityConfiguration() != null) {
+                        configs.add(defaultConfig.getHttpClientSecurityConfiguration());
+                    }
+                }
+            }
+        }
+
+        configs.add(HttpClientSecuritySupport.getGlobalHttpClientSecurityConfiguration());
+        
+        return configs;
+    }
+    
+}
\ No newline at end of file
diff --git a/shib-profile-api/src/main/java/net/shibboleth/profile/config/navigate/messaging/SignatureSigningConfigurationLookupFunction.java b/shib-profile-api/src/main/java/net/shibboleth/profile/config/navigate/messaging/SignatureSigningConfigurationLookupFunction.java
new file mode 100644
index 0000000..7e68ff8
--- /dev/null
+++ b/shib-profile-api/src/main/java/net/shibboleth/profile/config/navigate/messaging/SignatureSigningConfigurationLookupFunction.java
@@ -0,0 +1,76 @@
+/*
+ * 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 net.shibboleth.profile.config.navigate.messaging;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.security.config.SecurityConfiguration;
+import org.opensaml.xmlsec.SecurityConfigurationSupport;
+import org.opensaml.xmlsec.SignatureSigningConfiguration;
+import org.opensaml.xmlsec.config.XMLSecurityConfiguration;
+
+import net.shibboleth.profile.config.ProfileConfiguration;
+import net.shibboleth.profile.context.RelyingPartyContext;
+
+/**
+ * A {@link MessageContext} function that returns a {@link SignatureSigningConfiguration} list 
+ * by way of various lookup strategies.
+ * 
+ * <p>If a specific setting is unavailable, a null value is returned.</p>
+ */
+public class SignatureSigningConfigurationLookupFunction
+        extends AbstractDefaultSecurityConfigurationLookupFunction<List<SignatureSigningConfiguration>> {
+    
+    /** {@inheritDoc} */
+    @Nullable public List<SignatureSigningConfiguration> apply(@Nullable final MessageContext input) {
+        
+        final List<SignatureSigningConfiguration> configs = new ArrayList<>();
+        
+        final RelyingPartyContext rpc = getRelyingPartyContext(input);
+        if (rpc != null) {
+            final ProfileConfiguration pc = rpc.getProfileConfig();
+            if (pc != null) {
+                final SecurityConfiguration sc = pc.getSecurityConfiguration(getProfileRequestContext(input));
+                if (sc instanceof XMLSecurityConfiguration xsc && xsc.getSignatureSigningConfiguration() != null) {
+                    configs.add(xsc.getSignatureSigningConfiguration());
+                }
+            }
+            
+            // Check for a per-profile default (relying party independent) config.
+            if (pc != null) {
+                final String id = pc.getId();
+                if (id != null) {
+                    final SecurityConfiguration defaultConfig = getDefaultSecurityConfiguration(id);
+                    if (defaultConfig instanceof XMLSecurityConfiguration xsc &&
+                            xsc.getSignatureSigningConfiguration() != null) {
+                        configs.add(xsc.getSignatureSigningConfiguration());
+                    }
+                }
+            }
+        }
+
+        configs.add(SecurityConfigurationSupport.getGlobalSignatureSigningConfiguration());
+        
+        return configs;
+    }
+
+}
\ No newline at end of file
diff --git a/shib-profile-api/src/main/java/net/shibboleth/profile/config/navigate/messaging/SignatureValidationConfigurationLookupFunction.java b/shib-profile-api/src/main/java/net/shibboleth/profile/config/navigate/messaging/SignatureValidationConfigurationLookupFunction.java
new file mode 100644
index 0000000..2daa939
--- /dev/null
+++ b/shib-profile-api/src/main/java/net/shibboleth/profile/config/navigate/messaging/SignatureValidationConfigurationLookupFunction.java
@@ -0,0 +1,76 @@
+/*
+ * 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 net.shibboleth.profile.config.navigate.messaging;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.security.config.SecurityConfiguration;
+import org.opensaml.xmlsec.SecurityConfigurationSupport;
+import org.opensaml.xmlsec.SignatureValidationConfiguration;
+import org.opensaml.xmlsec.config.XMLSecurityConfiguration;
+
+import net.shibboleth.profile.config.ProfileConfiguration;
+import net.shibboleth.profile.context.RelyingPartyContext;
+
+/**
+ * A {@link MessageContext} function that returns a {@link SignatureValidationConfiguration} list 
+ * by way of various lookup strategies.
+ * 
+ * <p>If a specific setting is unavailable, a null value is returned.</p>
+ */
+public class SignatureValidationConfigurationLookupFunction
+        extends AbstractDefaultSecurityConfigurationLookupFunction<List<SignatureValidationConfiguration>> {
+    
+    /** {@inheritDoc} */
+    @Nullable public List<SignatureValidationConfiguration> apply(@Nullable final MessageContext input) {
+        
+        final List<SignatureValidationConfiguration> configs = new ArrayList<>();
+        
+        final RelyingPartyContext rpc = getRelyingPartyContext(input);
+        if (rpc != null) {
+            final ProfileConfiguration pc = rpc.getProfileConfig();
+            if (pc != null) {
+                final SecurityConfiguration sc = pc.getSecurityConfiguration(getProfileRequestContext(input));
+                if (sc instanceof XMLSecurityConfiguration xsc && xsc.getSignatureValidationConfiguration() != null) {
+                    configs.add(xsc.getSignatureValidationConfiguration());
+                }
+            }
+            
+            // Check for a per-profile default (relying party independent) config.
+            if (pc != null) {
+                final String id = pc.getId();
+                if (id != null) {
+                    final SecurityConfiguration defaultConfig = getDefaultSecurityConfiguration(id);
+                    if (defaultConfig instanceof XMLSecurityConfiguration xsc &&
+                            xsc.getSignatureValidationConfiguration() != null) {
+                        configs.add(xsc.getSignatureValidationConfiguration());
+                    }
+                }
+            }
+        }
+
+        configs.add(SecurityConfigurationSupport.getGlobalSignatureValidationConfiguration());
+        
+        return configs;
+    }
+
+}
\ No newline at end of file
diff --git a/shib-profile-api/src/main/java/net/shibboleth/profile/config/navigate/messaging/package-info.java b/shib-profile-api/src/main/java/net/shibboleth/profile/config/navigate/messaging/package-info.java
new file mode 100644
index 0000000..c33e005
--- /dev/null
+++ b/shib-profile-api/src/main/java/net/shibboleth/profile/config/navigate/messaging/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.
+ */
+
+/**
+ * Lookup functions for accessing profile configuration and related settings via
+ * a message context.
+ */
+package net.shibboleth.profile.config.navigate.messaging;
\ No newline at end of file
diff --git a/shib-profile-api/src/main/java/net/shibboleth/profile/context/navigate/RelyingPartyIdLookupFunction.java b/shib-profile-api/src/main/java/net/shibboleth/profile/context/navigate/RelyingPartyIdLookupFunction.java
index a3dcf2f..078da5f 100644
--- a/shib-profile-api/src/main/java/net/shibboleth/profile/context/navigate/RelyingPartyIdLookupFunction.java
+++ b/shib-profile-api/src/main/java/net/shibboleth/profile/context/navigate/RelyingPartyIdLookupFunction.java
@@ -34,7 +34,7 @@ public class RelyingPartyIdLookupFunction extends AbstractRelyingPartyLookupFunc
     /** {@inheritDoc} */
     @Nullable public String apply(@Nullable final ProfileRequestContext input) {
         if (input != null) {
-            final RelyingPartyContext rpc = getRelyingPartyContextLookupStrategy().apply(input);
+            final RelyingPartyContext rpc = getRelyingPartyContext(input);
             if (rpc != null) {
                 return rpc.getRelyingPartyId();
             }
diff --git a/shib-profile-api/src/main/java/net/shibboleth/profile/context/navigate/ScriptedContextLookupFunction.java b/shib-profile-api/src/main/java/net/shibboleth/profile/context/navigate/ScriptedContextLookupFunction.java
new file mode 100644
index 0000000..0cedf0d
--- /dev/null
+++ b/shib-profile-api/src/main/java/net/shibboleth/profile/context/navigate/ScriptedContextLookupFunction.java
@@ -0,0 +1,391 @@
+/*
+ * 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 net.shibboleth.profile.context.navigate;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.script.ScriptContext;
+import javax.script.ScriptException;
+
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.scripting.AbstractScriptEvaluator;
+import net.shibboleth.shared.scripting.EvaluableScript;
+
+import org.opensaml.messaging.context.BaseContext;
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.context.navigate.ContextDataLookupFunction;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.springframework.core.io.Resource;
+
+/**
+ * A {@link java.util.function.Function} over a {@link BaseContext}
+ * which calls out to a supplied script.
+ * 
+ * @param <T> the specific type of context
+ */
+ at SuppressWarnings("removal")
+public class ScriptedContextLookupFunction<T extends BaseContext> extends AbstractScriptEvaluator
+        implements ContextDataLookupFunction<T,Object> {
+
+    /** What class we want the input to test against. */
+    @Nonnull private final Class<T> inputClass;
+
+    /**
+     * Constructor.
+     * 
+     * @param inClass the class we accept as input.
+     * @param theScript the script we will evaluate.
+     * @param extraInfo debugging information.
+     */
+    protected ScriptedContextLookupFunction(@Nonnull final Class<T> inClass, @Nonnull final EvaluableScript theScript,
+            @Nullable final String extraInfo) {
+        super(theScript);
+        inputClass = Constraint.isNotNull(inClass, "Supplied inputClass cannot be null");
+        setLogPrefix("Scripted Function from " + extraInfo + ":");
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param inClass the class we accept as input.
+     * @param theScript the script we will evaluate.
+     */
+    protected ScriptedContextLookupFunction(@Nonnull final Class<T> inClass, @Nonnull final EvaluableScript theScript) {
+        super(theScript);
+        inputClass = Constraint.isNotNull(inClass, "Supplied inputClass cannot be null");
+        setLogPrefix("Anonymous Scripted Function:");
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param inClass the class we accept as input.
+     * @param theScript the script we will evaluate.
+     * @param extraInfo debugging information.
+     * @param outputType the type to test against.
+     */
+    protected ScriptedContextLookupFunction(@Nonnull final Class<T> inClass, @Nonnull final EvaluableScript theScript,
+            @Nullable final String extraInfo, @Nullable final Class<?> outputType) {
+        this(inClass, theScript, extraInfo);
+        setOutputType(outputType);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    @Nullable public Object getCustomObject() {
+        return super.getCustomObject();
+    }
+
+    /** {@inheritDoc} */
+    public Object apply(@Nullable final T context) {
+
+        if (null != context && !inputClass.isInstance(context)) {
+            throw new ClassCastException(getLogPrefix() + " Input was type " + context.getClass()
+                    + " which is not an instance of " + inputClass);
+        }
+        
+        return evaluate(context);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected void prepareContext(@Nonnull final ScriptContext scriptContext, @Nullable final Object... input) {
+        // We don't actually know that the context is a PRC, but we'll keep this for compatibility.
+        // We can't use the variable name "context" because Rhino appears to reserve that name.
+        scriptContext.setAttribute("profileContext", input != null ? input[0] : null, ScriptContext.ENGINE_SCOPE);
+        scriptContext.setAttribute("input", input != null ? input[0] : null, ScriptContext.ENGINE_SCOPE);
+    }
+    
+    /**
+     * Factory to create {@link ScriptedContextLookupFunction} for {@link ProfileRequestContext}s from a
+     * {@link Resource}.
+     * 
+     * @param resource the resource to look at
+     * @param engineName the language
+     * @return the function
+     * @throws ScriptException if the compile fails
+     * @throws IOException if the file doesn't exist.
+     */
+    @Nonnull
+    public static ScriptedContextLookupFunction<ProfileRequestContext> resourceScript(
+            @Nonnull @NotEmpty final String engineName, @Nonnull final Resource resource) throws ScriptException,
+            IOException {
+        return resourceScript(engineName, resource, null);
+    }
+
+    /**
+     * Factory to create {@link ScriptedContextLookupFunction} for {@link ProfileRequestContext}s from a
+     * {@link Resource}.
+     * 
+     * @param resource the resource to look at
+     * @param engineName the language
+     * @param outputType the type to test against.
+     * @return the function
+     * @throws ScriptException if the compile fails
+     * @throws IOException if the file doesn't exist.
+     */
+    @Nonnull
+    public static ScriptedContextLookupFunction<ProfileRequestContext> resourceScript(
+            @Nonnull @NotEmpty final String engineName, @Nonnull final Resource resource,
+            @Nullable final Class<?> outputType) throws ScriptException, IOException {
+        try (InputStream is = resource.getInputStream()) {
+            final EvaluableScript script = new EvaluableScript();
+            script.setEngineName(engineName);
+            script.setScript(is);
+            script.initializeWithScriptException();
+            return new ScriptedContextLookupFunction<>(ProfileRequestContext.class, script, resource.getDescription(),
+                outputType);
+        }
+    }
+
+    /**
+     * Factory to create {@link ScriptedContextLookupFunction} from a {@link Resource}.
+     * 
+     * @param resource the resource to look at
+     * @return the function
+     * @throws ScriptException if the compile fails
+     * @throws IOException if the file doesn't exist.
+     */
+    @Nonnull
+    public static ScriptedContextLookupFunction<ProfileRequestContext> resourceScript(@Nonnull final Resource resource)
+            throws ScriptException, IOException {
+        return resourceScript(DEFAULT_ENGINE, resource, null);
+    }
+
+    /**
+     * Factory to create {@link ScriptedContextLookupFunction} for {@link ProfileRequestContext}s from a
+     * {@link Resource}.
+     * 
+     * @param resource the resource to look at
+     * @param outputType the type to test against.
+     * @return the function
+     * @throws ScriptException if the compile fails
+     * @throws IOException if the file doesn't exist.
+     */
+    @Nonnull
+    public static ScriptedContextLookupFunction<ProfileRequestContext> resourceScript(@Nonnull final Resource resource,
+            @Nullable final Class<?> outputType) throws ScriptException, IOException {
+        return resourceScript(DEFAULT_ENGINE, resource, outputType);
+    }
+
+    /**
+     * Factory to create {@link ScriptedContextLookupFunction} for {@link ProfileRequestContext}s from inline data.
+     * 
+     * @param scriptSource the script, as a string
+     * @param engineName the language
+     * @return the function
+     * @throws ScriptException if the compile fails
+     */
+    @Nonnull
+    public static ScriptedContextLookupFunction<ProfileRequestContext> inlineScript(
+            @Nonnull @NotEmpty final String engineName, @Nonnull @NotEmpty final String scriptSource)
+            throws ScriptException {
+        final EvaluableScript script = new EvaluableScript();
+        script.setEngineName(engineName);
+        script.setScript(scriptSource);
+        script.initializeWithScriptException();
+        return new ScriptedContextLookupFunction<>(ProfileRequestContext.class, script, "Inline");
+    }
+
+    /**
+     * Factory to create {@link ScriptedContextLookupFunction} for {@link ProfileRequestContext}s from inline data.
+     * 
+     * @param scriptSource the script, as a string
+     * @param engineName the language
+     * @param outputType the type to test against.
+     * @return the function
+     * @throws ScriptException if the compile fails
+     */
+    @Nonnull
+    public static ScriptedContextLookupFunction<ProfileRequestContext> inlineScript(
+            @Nonnull @NotEmpty final String engineName, @Nonnull @NotEmpty final String scriptSource,
+            @Nullable final Class<?> outputType) throws ScriptException {
+        final EvaluableScript script = new EvaluableScript();
+        script.setEngineName(engineName);
+        script.setScript(scriptSource);
+        script.initializeWithScriptException();
+        return new ScriptedContextLookupFunction<>(ProfileRequestContext.class, script, "Inline", outputType);
+    }
+
+    /**
+     * Factory to create {@link ScriptedContextLookupFunction} for {@link ProfileRequestContext}s from inline data.
+     * 
+     * @param scriptSource the script, as a string
+     * @return the function
+     * @throws ScriptException if the compile fails
+     */
+    @Nonnull
+    public static ScriptedContextLookupFunction<ProfileRequestContext> inlineScript(
+            @Nonnull @NotEmpty final String scriptSource) throws ScriptException {
+        return inlineScript(DEFAULT_ENGINE, scriptSource);
+    }
+
+    /**
+     * Factory to create {@link ScriptedContextLookupFunction} for {@link ProfileRequestContext}s from inline data.
+     * 
+     * @param scriptSource the script, as a string
+     * @param outputType the type to test against.
+     * @return the function
+     * @throws ScriptException if the compile fails
+     */
+    @Nonnull
+    public static ScriptedContextLookupFunction<ProfileRequestContext> inlineScript(
+            @Nonnull @NotEmpty final String scriptSource, @Nullable final Class<?> outputType) throws ScriptException {
+        return inlineScript(DEFAULT_ENGINE, scriptSource, outputType);
+    }
+
+    /**
+     * Factory to create {@link ScriptedContextLookupFunction} for {@link MessageContext}s from a {@link Resource}.
+     * 
+     * @param resource the resource to look at
+     * @param engineName the language
+     * @return the function
+     * @throws ScriptException if the compile fails
+     * @throws IOException if the file doesn't exist.
+     */
+    @Nonnull
+    public static ScriptedContextLookupFunction<MessageContext> resourceMessageContextScript(
+            @Nonnull @NotEmpty final String engineName, @Nonnull final Resource resource) throws ScriptException,
+            IOException {
+        return resourceMessageContextScript(engineName, resource, null);
+    }
+
+    /**
+     * Factory to create {@link ScriptedContextLookupFunction} for {@link MessageContext}s from a {@link Resource}.
+     * 
+     * @param resource the resource to look at
+     * @param engineName the language
+     * @param outputType the type to test against.
+     * @return the function
+     * @throws ScriptException if the compile fails
+     * @throws IOException if the file doesn't exist.
+     */
+    @Nonnull
+    public static ScriptedContextLookupFunction<MessageContext> resourceMessageContextScript(
+            @Nonnull @NotEmpty final String engineName, @Nonnull final Resource resource,
+            @Nullable final Class<?> outputType) throws ScriptException, IOException {
+        try (InputStream is = resource.getInputStream()) {
+            final EvaluableScript script = new EvaluableScript();
+            script.setEngineName(engineName);
+            script.setScript(is);
+            script.initializeWithScriptException();
+            return new ScriptedContextLookupFunction<>(MessageContext.class, script, resource.getDescription(),
+                    outputType);
+        }
+    }
+
+    /**
+     * Factory to create {@link ScriptedContextLookupFunction} for {@link MessageContext}s from a {@link Resource}.
+     * 
+     * @param resource the resource to look at
+     * @return the function
+     * @throws ScriptException if the compile fails
+     * @throws IOException if the file doesn't exist.
+     */
+    @Nonnull
+    public static ScriptedContextLookupFunction<MessageContext> resourceMessageContextScript(
+            @Nonnull final Resource resource) throws ScriptException, IOException {
+        return resourceMessageContextScript(DEFAULT_ENGINE, resource, null);
+    }
+
+    /**
+     * Factory to create {@link ScriptedContextLookupFunction} for {@link MessageContext}s from a {@link Resource}.
+     * 
+     * @param resource the resource to look at
+     * @param outputType the type to test against.
+     * @return the function
+     * @throws ScriptException if the compile fails
+     * @throws IOException if the file doesn't exist.
+     */
+    @Nonnull
+    public static ScriptedContextLookupFunction<MessageContext> resourceMessageContextScript(
+            @Nonnull final Resource resource, @Nullable final Class<?> outputType) throws ScriptException, IOException {
+        return resourceMessageContextScript(DEFAULT_ENGINE, resource, outputType);
+    }
+
+    /**
+     * Factory to create {@link ScriptedContextLookupFunction} for {@link MessageContext}s from inline data.
+     * 
+     * @param scriptSource the script, as a string
+     * @param engineName the language
+     * @return the function
+     * @throws ScriptException if the compile fails
+     */
+    @Nonnull
+    public static ScriptedContextLookupFunction<MessageContext> inlineMessageContextScript(
+            @Nonnull @NotEmpty final String engineName, @Nonnull @NotEmpty final String scriptSource)
+            throws ScriptException {
+        final EvaluableScript script = new EvaluableScript();
+        script.setEngineName(engineName);
+        script.setScript(scriptSource);
+        script.initializeWithScriptException();
+        return new ScriptedContextLookupFunction<>(MessageContext.class, script, "Inline");
+    }
+
+    /**
+     * Factory to create {@link ScriptedContextLookupFunction} for {@link MessageContext}s from inline data.
+     * 
+     * @param scriptSource the script, as a string
+     * @param engineName the language
+     * @param outputType the type to test against.
+     * @return the function
+     * @throws ScriptException if the compile fails
+     */
+    @Nonnull
+    public static ScriptedContextLookupFunction<MessageContext> inlineMessageContextScript(
+            @Nonnull @NotEmpty final String engineName, @Nonnull @NotEmpty final String scriptSource,
+            @Nullable final Class<?> outputType) throws ScriptException {
+        final EvaluableScript script = new EvaluableScript();
+        script.setEngineName(engineName);
+        script.setScript(scriptSource);
+        script.initializeWithScriptException();
+        return new ScriptedContextLookupFunction<>(MessageContext.class, script, "Inline", outputType);
+    }
+
+    /**
+     * Factory to create {@link ScriptedContextLookupFunction} for {@link MessageContext}s from inline data.
+     * 
+     * @param scriptSource the script, aMessageContexts a string
+     * @return the function
+     * @throws ScriptException if the compile fails
+     */
+    @Nonnull
+    public static ScriptedContextLookupFunction<MessageContext> inlineMessageContextScript(
+            @Nonnull @NotEmpty final String scriptSource) throws ScriptException {
+        return inlineMessageContextScript(DEFAULT_ENGINE, scriptSource);
+    }
+
+    /**
+     * Factory to create {@link ScriptedContextLookupFunction} for {@link MessageContext}s from inline data.
+     * 
+     * @param scriptSource the script, as a string
+     * @param outputType the type to test against.
+     * @return the function
+     * @throws ScriptException if the compile fails
+     */
+    @Nonnull
+    public static ScriptedContextLookupFunction<MessageContext> inlineMessageContextScript(
+            @Nonnull @NotEmpty final String scriptSource, @Nullable final Class<?> outputType) throws ScriptException {
+        return inlineMessageContextScript(DEFAULT_ENGINE, scriptSource, outputType);
+    }
+
+}
\ No newline at end of file
diff --git a/shib-profile-api/src/main/java/net/shibboleth/profile/context/navigate/RelyingPartyIdLookupFunction.java b/shib-profile-api/src/main/java/net/shibboleth/profile/context/navigate/ServletRequestProfileRequestContextLookup.java
similarity index 57%
copy from shib-profile-api/src/main/java/net/shibboleth/profile/context/navigate/RelyingPartyIdLookupFunction.java
copy to shib-profile-api/src/main/java/net/shibboleth/profile/context/navigate/ServletRequestProfileRequestContextLookup.java
index a3dcf2f..27e555c 100644
--- a/shib-profile-api/src/main/java/net/shibboleth/profile/context/navigate/RelyingPartyIdLookupFunction.java
+++ b/shib-profile-api/src/main/java/net/shibboleth/profile/context/navigate/ServletRequestProfileRequestContextLookup.java
@@ -17,30 +17,24 @@
 
 package net.shibboleth.profile.context.navigate;
 
-import javax.annotation.Nullable;
-
 import org.opensaml.profile.context.ProfileRequestContext;
 
-import net.shibboleth.profile.context.RelyingPartyContext;
+import java.util.function.Function;
+
+import javax.annotation.Nullable;
+import jakarta.servlet.ServletRequest;
 
 /**
- * A function that returns {@link RelyingPartyContext#getRelyingPartyId()} from a
- * {@link RelyingPartyContext} obtained via a lookup function, by default a child of the {@link ProfileRequestContext}.
- * 
- * <p>If a specific setting is unavailable, a null value is returned.</p>
+ * Looks up the profile request context from a servlet request attribute.
+ *
+ * @author Marvin S. Addison
  */
-public class RelyingPartyIdLookupFunction extends AbstractRelyingPartyLookupFunction<String> {
+public class ServletRequestProfileRequestContextLookup implements Function<ServletRequest,ProfileRequestContext> {
 
     /** {@inheritDoc} */
-    @Nullable public String apply(@Nullable final ProfileRequestContext input) {
-        if (input != null) {
-            final RelyingPartyContext rpc = getRelyingPartyContextLookupStrategy().apply(input);
-            if (rpc != null) {
-                return rpc.getRelyingPartyId();
-            }
-        }
-        
-        return null;
+    @Nullable
+    public ProfileRequestContext apply(final ServletRequest input) {
+        return (ProfileRequestContext) input.getAttribute(ProfileRequestContext.BINDING_KEY);
     }
 
 }
\ No newline at end of file
diff --git a/shib-profile-api/src/main/java/net/shibboleth/profile/context/navigate/SpringExpressionContextLookupFunction.java b/shib-profile-api/src/main/java/net/shibboleth/profile/context/navigate/SpringExpressionContextLookupFunction.java
new file mode 100644
index 0000000..6e9f71d
--- /dev/null
+++ b/shib-profile-api/src/main/java/net/shibboleth/profile/context/navigate/SpringExpressionContextLookupFunction.java
@@ -0,0 +1,74 @@
+/*
+ * 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 net.shibboleth.profile.context.navigate;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.BaseContext;
+import org.opensaml.messaging.context.navigate.ContextDataLookupFunction;
+
+import net.shibboleth.shared.annotation.ParameterName;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.spring.expression.SpringExpressionFunction;
+
+/**
+ * A {@link java.util.function.Function} over a {@link BaseContext}
+ * which calls out to a Spring Expression.
+ * 
+ * @param <T> the specific type of context
+ * @param <U> output type
+ * @since 3.3.0
+ */
+public class SpringExpressionContextLookupFunction<T extends BaseContext,U> extends SpringExpressionFunction<T,U>
+        implements ContextDataLookupFunction<T,U> {
+
+    /**
+     * Constructor.
+     * 
+     * @param inClass the class we accept as input.
+     * @param expression the expression to evaluate.
+     */
+    public SpringExpressionContextLookupFunction(@Nonnull @ParameterName(name="inClass") final Class<T> inClass,
+            @Nonnull @NotEmpty @ParameterName(name="expression") final String expression) {
+        super(expression);
+        setInputType(Constraint.isNotNull(inClass, "Supplied inputClass cannot be null"));
+        
+        if(!BaseContext.class.isAssignableFrom(inClass)) {
+            LoggerFactory.getLogger(SpringExpressionContextLookupFunction.class).
+                warn("inClass {} is not derived from {}", inClass, BaseContext.class);
+        }
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param inClass the class we accept as input.
+     * @param expression the expression to evaluate.
+     * @param outputType the type to test against.
+     */
+    public SpringExpressionContextLookupFunction(@Nonnull @ParameterName(name="inClass") final Class<T> inClass,
+            @Nonnull @NotEmpty @ParameterName(name="expression") final String expression, 
+            @ParameterName(name="outputType") @Nullable final Class<U> outputType) {
+        this(inClass, expression);
+        setOutputType(outputType);
+    }
+
+}
\ No newline at end of file
diff --git a/shib-profile-api/src/main/java/net/shibboleth/profile/context/navigate/messaging/AbstractRelyingPartyLookupFunction.java b/shib-profile-api/src/main/java/net/shibboleth/profile/context/navigate/messaging/AbstractRelyingPartyLookupFunction.java
new file mode 100644
index 0000000..aa442ad
--- /dev/null
+++ b/shib-profile-api/src/main/java/net/shibboleth/profile/context/navigate/messaging/AbstractRelyingPartyLookupFunction.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 net.shibboleth.profile.context.navigate.messaging;
+
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.InOutOperationContext;
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.context.navigate.ChildContextLookup;
+import org.opensaml.messaging.context.navigate.ContextDataLookupFunction;
+import org.opensaml.messaging.context.navigate.RecursiveTypedParentContextLookup;
+import org.opensaml.profile.context.ProfileRequestContext;
+
+import net.shibboleth.profile.context.RelyingPartyContext;
+import net.shibboleth.shared.logic.Constraint;
+
+/**
+ * Abstract base class for a function that requires a {@link ProfileRequestContext} obtained
+ * via a lookup function, by default the parent of the specified {@link MessageContext}, and
+ * a {@link RelyingPartyContext} obtained via a lookup function, by default a child of the
+ * aforementioned parent.
+ * 
+ * @param <ResultType> return type of function
+ */
+public abstract class AbstractRelyingPartyLookupFunction<ResultType>
+        implements ContextDataLookupFunction<MessageContext,ResultType> {
+
+    /**
+     * Strategy used to locate the {@link RelyingPartyContext} associated with a given {@link MessageContext}.
+     */
+    @Nonnull private Function<MessageContext,RelyingPartyContext> relyingPartyContextLookupStrategy;
+
+    /**
+     * Strategy used to locate the {@link ProfileRequestContext} associated with a given {@link MessageContext}.
+     */
+    @Nonnull private Function<MessageContext,ProfileRequestContext> profileRequestContextLookupStrategy;
+    
+    /** Constructor. */
+    public AbstractRelyingPartyLookupFunction() {
+        profileRequestContextLookupStrategy =
+                new RecursiveTypedParentContextLookup<>(ProfileRequestContext.class);
+        
+        relyingPartyContextLookupStrategy =
+                new ChildContextLookup<>(RelyingPartyContext.class).compose(
+                        new RecursiveTypedParentContextLookup<>(InOutOperationContext.class));
+    }
+
+    /**
+     * Get the strategy used to locate the {@link RelyingPartyContext} associated with a given
+     * {@link MessageContext}.
+     * 
+     * @return lookup strategy
+     */
+    @Nonnull public Function<MessageContext,RelyingPartyContext> getRelyingPartyContextLookupStrategy() {
+        return relyingPartyContextLookupStrategy;
+    }
+
+    /**
+     * Set the strategy used to locate the {@link RelyingPartyContext} associated with a given
+     * {@link MessageContext}.
+     * 
+     * @param strategy lookup strategy
+     */
+    public void setRelyingPartyContextLookupStrategy(
+            @Nonnull final Function<MessageContext,RelyingPartyContext> strategy) {
+        relyingPartyContextLookupStrategy =
+                Constraint.isNotNull(strategy, "RelyingPartyContext lookup strategy cannot be null");
+    }
+    
+    /**
+     * Get the strategy used to locate the {@link ProfileRequestContext} associated with a given
+     * {@link MessageContext}.
+     * 
+     * @return lookup strategy
+     */
+    @Nonnull public Function<MessageContext,ProfileRequestContext> getProfileRequestContextLookupStrategy() {
+        return profileRequestContextLookupStrategy;
+    }
+
+    /**
+     * Set the strategy used to locate the {@link ProfileRequestContext} associated with a given
+     * {@link MessageContext}.
+     * 
+     * @param strategy lookup strategy
+     */
+    public void setProfileRequestContextLookupStrategy(
+            @Nonnull final Function<MessageContext,ProfileRequestContext> strategy) {
+        profileRequestContextLookupStrategy =
+                Constraint.isNotNull(strategy, "ProfileRequestContext lookup strategy cannot be null");
+    }
+
+    /**
+     * Return the result of applying the lookup function to obtain the {@link RelyingPartyContext}.
+     * 
+     * @param input message context
+     * 
+     * @return the {@link RelyingPartyContext} or null
+     */
+    @Nullable protected RelyingPartyContext getRelyingPartyContext(@Nullable final MessageContext input) {
+        return relyingPartyContextLookupStrategy.apply(input);
+    }
+    
+    /**
+     * Return the result of applying the lookup function to obtain the {@link ProfileRequestContext}.
+     * 
+     * @param input message context
+     * 
+     * @return the {@link ProfileRequestContext} or null
+     */
+    @Nullable protected ProfileRequestContext getProfileRequestContext(@Nullable final MessageContext input) {
+        return profileRequestContextLookupStrategy.apply(input);
+    }
+    
+}
\ No newline at end of file
diff --git a/shib-profile-api/src/main/java/net/shibboleth/profile/context/navigate/messaging/package-info.java b/shib-profile-api/src/main/java/net/shibboleth/profile/context/navigate/messaging/package-info.java
new file mode 100644
index 0000000..ad3a370
--- /dev/null
+++ b/shib-profile-api/src/main/java/net/shibboleth/profile/context/navigate/messaging/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+/**
+ * Context navigation using messaging contexts.
+ */
+package net.shibboleth.profile.context.navigate.messaging;
\ No newline at end of file
diff --git a/shib-profile-api/src/test/java/net/shibboleth/profile/context/navigate/ScriptedContextLookupFunctionTest.java b/shib-profile-api/src/test/java/net/shibboleth/profile/context/navigate/ScriptedContextLookupFunctionTest.java
new file mode 100644
index 0000000..ec4e446
--- /dev/null
+++ b/shib-profile-api/src/test/java/net/shibboleth/profile/context/navigate/ScriptedContextLookupFunctionTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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 net.shibboleth.profile.context.navigate;
+
+import javax.script.ScriptException;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * Unit test for {@link ScriptedContextLookupFunction}.
+ */
+ at SuppressWarnings("javadoc")
+public class ScriptedContextLookupFunctionTest {
+    
+    static final String STRING_RETURN = "JavaString=Java.type(\"java.lang.String\"); new JavaString(\"String\");";
+    static final String INTEGER_RETURN = "JavaInteger=Java.type(\"java.lang.Integer\"); new JavaInteger(37);";
+       
+    @Test public void simpleScript() throws ScriptException {
+        final ProfileRequestContext prc = new ProfileRequestContext();
+        
+        final Object string = ScriptedContextLookupFunction.inlineScript(STRING_RETURN).apply(prc);
+
+        String s = (String) string;
+        Assert.assertEquals(s, "String");
+        
+        final Integer integer = (Integer) ScriptedContextLookupFunction.inlineScript(INTEGER_RETURN).apply(prc);
+        Assert.assertEquals(integer.intValue(), 37);
+    }
+    
+    @Test public void custom() throws ScriptException {
+        final ProfileRequestContext prc = new ProfileRequestContext();
+        
+        final ScriptedContextLookupFunction<ProfileRequestContext> script =
+                ScriptedContextLookupFunction.inlineScript("custom;");
+        script.setCustomObject("String");
+        Assert.assertEquals(script.apply(prc), "String");
+ 
+        script.setCustomObject(Integer.valueOf(37));
+        Assert.assertEquals(script.apply(prc), Integer.valueOf(37));
+    }    
+    
+    
+    @Test public void withType() throws Exception {
+        final ProfileRequestContext prc = new ProfileRequestContext();
+
+        final ScriptedContextLookupFunction<ProfileRequestContext> script1 =
+                ScriptedContextLookupFunction.inlineScript(STRING_RETURN, Object.class);
+        
+        final String string = (String) script1.apply(prc);
+        Assert.assertEquals(string, "String");
+        
+        Assert.assertEquals(ScriptedContextLookupFunction.inlineScript(STRING_RETURN, String.class).apply(prc), "String");
+        
+        Assert.assertNull(ScriptedContextLookupFunction.inlineScript(STRING_RETURN, Integer.class).apply(prc));
+        
+        final Integer integer = (Integer) ScriptedContextLookupFunction.inlineScript(INTEGER_RETURN).apply(prc);
+        Assert.assertEquals(integer.intValue(), 37);
+        
+    }
+
+    @Test public void messageContext() throws ScriptException {
+        final ScriptedContextLookupFunction<MessageContext> script1 =
+                ScriptedContextLookupFunction.inlineMessageContextScript(STRING_RETURN, Object.class);
+        
+        Assert.assertEquals(script1.apply(new MessageContext()), "String");
+        Assert.assertEquals(script1.apply(null), "String");
+    }
+}
diff --git a/shib-profile-api/src/test/java/net/shibboleth/profile/context/navigate/SpringExpressionContextLookupFunctionTest.java b/shib-profile-api/src/test/java/net/shibboleth/profile/context/navigate/SpringExpressionContextLookupFunctionTest.java
new file mode 100644
index 0000000..d84084a
--- /dev/null
+++ b/shib-profile-api/src/test/java/net/shibboleth/profile/context/navigate/SpringExpressionContextLookupFunctionTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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 net.shibboleth.profile.context.navigate;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * Test for {@link SpringExpressionContextLookupFunction}.
+ */
+ at SuppressWarnings("javadoc")
+public class SpringExpressionContextLookupFunctionTest {
+
+    
+    @Test public void simpleTest() {
+        SpringExpressionContextLookupFunction<ProfileRequestContext,Integer> func =
+                new SpringExpressionContextLookupFunction<>(ProfileRequestContext.class, "99", Integer.class);
+        Assert.assertEquals(func.apply(null), Integer.valueOf(99));
+    }
+    
+    @Test public void customTest() {
+        SpringExpressionContextLookupFunction<ProfileRequestContext,Integer> func =
+                new SpringExpressionContextLookupFunction<>(ProfileRequestContext.class, "#custom + 1", Integer.class);
+        func.setCustomObject(Integer.valueOf(99));
+        Assert.assertEquals(func.apply(null), Integer.valueOf(100));
+    }    
+    
+    @Test public void invalidOutputTest() {
+        SpringExpressionContextLookupFunction<ProfileRequestContext,Integer> func =
+                new SpringExpressionContextLookupFunction<>(ProfileRequestContext.class, "'foo'", Integer.class);
+        func.setReturnOnError(-1);
+        Assert.assertEquals(func.apply(null), Integer.valueOf(-1));
+    }
+    
+    @Test public void exceptionTest() {
+        SpringExpressionContextLookupFunction<ProfileRequestContext,Integer> func =
+                new SpringExpressionContextLookupFunction<>(ProfileRequestContext.class, "1/0", Integer.class);
+        func.setReturnOnError(-1);
+
+        try {
+            func.apply(null);
+            Assert.fail("Expression should have raised exception");
+        } catch (final Exception e) {
+            
+        }
+        
+        func.setHideExceptions(true);
+        Assert.assertEquals(func.apply(null), Integer.valueOf(-1));
+    }
+
+}
\ No newline at end of file

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


More information about the commits mailing list