[java-identity-provider] branch master updated: IDP-1469 - External intercept flow
Scott Cantor
cantor.2 at osu.edu
Thu Jun 20 19:39:47 EDT 2019
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch master
in repository java-identity-provider.
View the commit online:
http://git.shibboleth.net/view/?p=java-identity-provider.git;a=commit;h=682cc69aa828d11c7c4ee7f764781005e6fcee5a
The following commit(s) were added to refs/heads/master by this push:
new 682cc69 IDP-1469 - External intercept flow
682cc69 is described below
commit 682cc69aa828d11c7c4ee7f764781005e6fcee5a
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Thu Jun 20 19:37:20 2019 -0400
IDP-1469 - External intercept flow
https://issues.shibboleth.net/jira/browse/IDP-1469
---
.../conf/intercept/external-intercept-config.xml | 25 +++
.../resources/conf/intercept/profile-intercept.xml | 2 +
.../main/resources/system/conf/webflow-config.xml | 1 +
.../system/flows/intercept/external-beans.xml | 27 +++
.../system/flows/intercept/external-flow.xml | 21 +++
.../context/ExternalInterceptorContext.java | 92 ++++++++++
.../profile/interceptor/ExternalInterceptor.java | 186 +++++++++++++++++++++
.../interceptor/ExternalInterceptorException.java | 66 ++++++++
.../interceptor/impl/ExternalInterceptorImpl.java | 97 +++++++++++
9 files changed, 517 insertions(+)
diff --git a/idp-conf/src/main/resources/conf/intercept/external-intercept-config.xml b/idp-conf/src/main/resources/conf/intercept/external-intercept-config.xml
new file mode 100644
index 0000000..1d0fc29
--- /dev/null
+++ b/idp-conf/src/main/resources/conf/intercept/external-intercept-config.xml
@@ -0,0 +1,25 @@
+<?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">
+
+ <!-- Servlet context-relative path to wherever your implementation lives. -->
+ <bean id="shibboleth.intercept.externalPath" class="java.lang.String"
+ c:_0="contextRelative:intercept.jsp" />
+
+ <!--
+ Default is to always use the path in the bean above. If you want to determine it
+ dynamically, define a bean called "shibboleth.intercept.externalPathStrategy"
+ of type Function<ProfileRequestContext,String> that returns the path to use.
+ -->
+
+</beans>
diff --git a/idp-conf/src/main/resources/conf/intercept/profile-intercept.xml b/idp-conf/src/main/resources/conf/intercept/profile-intercept.xml
index 7b4c8aa..f086cfa 100644
--- a/idp-conf/src/main/resources/conf/intercept/profile-intercept.xml
+++ b/idp-conf/src/main/resources/conf/intercept/profile-intercept.xml
@@ -33,6 +33,8 @@
<bean id="intercept/attribute-release" parent="shibboleth.consent.AttributeReleaseFlow" />
<bean id="intercept/impersonate" parent="shibboleth.InterceptFlow" />
+
+ <bean id="intercept/external" parent="shibboleth.InterceptFlow" />
</list>
</property>
</bean>
diff --git a/idp-conf/src/main/resources/system/conf/webflow-config.xml b/idp-conf/src/main/resources/system/conf/webflow-config.xml
index 6b6a4b1..66ffbf7 100644
--- a/idp-conf/src/main/resources/system/conf/webflow-config.xml
+++ b/idp-conf/src/main/resources/system/conf/webflow-config.xml
@@ -123,6 +123,7 @@
<entry key="intercept/attribute-release" value="../system/flows/intercept/attribute-release-flow.xml" />
<entry key="intercept/attribute-release-query" value="../system/flows/intercept/attribute-release-query-flow.xml" />
<entry key="intercept/impersonate" value="../system/flows/intercept/impersonate-flow.xml" />
+ <entry key="intercept/external" value="../system/flows/intercept/external-flow.xml" />
<!-- Inbound security processing of SAML messages, implemented as intercept flows. -->
<entry key="security-policy.abstract" value="../system/flows/saml/security-abstract-flow.xml" />
diff --git a/idp-conf/src/main/resources/system/flows/intercept/external-beans.xml b/idp-conf/src/main/resources/system/flows/intercept/external-beans.xml
new file mode 100644
index 0000000..ebe1d98
--- /dev/null
+++ b/idp-conf/src/main/resources/system/flows/intercept/external-beans.xml
@@ -0,0 +1,27 @@
+<?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 class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"
+ p:placeholderPrefix="%{" p:placeholderSuffix="}" />
+
+ <bean class="net.shibboleth.ext.spring.config.IdentifiableBeanPostProcessor" />
+ <bean class="net.shibboleth.idp.profile.impl.ProfileActionBeanPostProcessor" />
+
+ <!-- Default strategy function to obtain the external path. -->
+ <bean id="shibboleth.intercept.externalPathStrategy" parent="shibboleth.Functions.Constant"
+ c:target-ref="shibboleth.intercept.externalPath" />
+
+ <import resource="../../../conf/intercept/external-intercept-config.xml" />
+
+</beans>
diff --git a/idp-conf/src/main/resources/system/flows/intercept/external-flow.xml b/idp-conf/src/main/resources/system/flows/intercept/external-flow.xml
new file mode 100644
index 0000000..49ff7fc
--- /dev/null
+++ b/idp-conf/src/main/resources/system/flows/intercept/external-flow.xml
@@ -0,0 +1,21 @@
+<flow xmlns="http://www.springframework.org/schema/webflow"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow.xsd"
+ parent="intercept.abstract">
+
+ <!-- Rudimentary impediment to direct execution of subflow. -->
+ <input name="calledAsSubflow" type="boolean" required="true" />
+
+ <!-- This is an interceptor flow handled outside the webflow engine. -->
+
+ <view-state id="ExternalTransfer" view="externalRedirect:#{T(net.shibboleth.idp.profile.interceptor.ExternalInterceptor).getExternalRedirect(flowRequestContext.getActiveFlow().getApplicationContext().getBean('shibboleth.intercept.externalPathStrategy').apply(opensamlProfileRequestContext), flowExecutionContext.getKey().toString())}">
+ <on-render>
+ <evaluate expression="opensamlProfileRequestContext.getSubcontext(T(net.shibboleth.idp.profile.context.ProfileInterceptorContext)).addSubcontext(new net.shibboleth.idp.profile.context.ExternalInterceptorContext(), true).setFlowExecutionUrl(flowExecutionUrl + '&_eventId_proceed=1')" />
+ <evaluate expression="externalContext.getNativeRequest().getSession().setAttribute('conversation' + flowExecutionContext.getKey().toString(), new net.shibboleth.idp.profile.interceptor.impl.ExternalInterceptorImpl(opensamlProfileRequestContext))" />
+ </on-render>
+ <transition to="#{opensamlProfileRequestContext.getSubcontext(T(net.shibboleth.idp.profile.context.ProfileInterceptorContext)).getSubcontext(T(net.shibboleth.idp.profile.context.ExternalInterceptorContext)).getEventId()}" />
+ </view-state>
+
+ <bean-import resource="external-beans.xml" />
+
+</flow>
diff --git a/idp-profile-api/src/main/java/net/shibboleth/idp/profile/context/ExternalInterceptorContext.java b/idp-profile-api/src/main/java/net/shibboleth/idp/profile/context/ExternalInterceptorContext.java
new file mode 100644
index 0000000..409522f
--- /dev/null
+++ b/idp-profile-api/src/main/java/net/shibboleth/idp/profile/context/ExternalInterceptorContext.java
@@ -0,0 +1,92 @@
+/*
+ * 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.idp.profile.context;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.BaseContext;
+import org.opensaml.profile.action.EventIds;
+
+/**
+ * A context representing the state of an externalized interceptor flow.
+ *
+ * @parent {@link ProfileInterceptorContext}
+ * @added Before dispatching control to an external interceptor flow
+ *
+ * @since 4.0.0
+ */
+public final class ExternalInterceptorContext extends BaseContext {
+
+ /** Value of flowExecutionUrl on branching from flow. */
+ @Nullable private String flowExecutionUrl;
+
+ /** Event to signal. */
+ @Nullable private String eventId;
+
+ /** Constructor. */
+ public ExternalInterceptorContext() {
+ eventId = EventIds.PROCEED_EVENT_ID;
+ }
+
+ /**
+ * Get the flow execution URL to return control to.
+ *
+ * @return return location
+ */
+ @Nullable public String getFlowExecutionUrl() {
+ return flowExecutionUrl;
+ }
+
+ /**
+ *
+ * Set the flow execution URL to return control to.
+ *
+ * @param url return location
+ *
+ * @return this context
+ */
+ @Nonnull public ExternalInterceptorContext setFlowExecutionUrl(@Nullable final String url) {
+ flowExecutionUrl = url;
+
+ return this;
+ }
+
+ /**
+ * Get the event ID to signal as the result of this flow.
+ *
+ * @return event ID
+ */
+ @Nullable public String getEventId() {
+ return eventId;
+ }
+
+ /**
+ * Set the event ID to signal as the result of this flow.
+ *
+ * @param id event ID
+ *
+ * @return this context
+ */
+ @Nonnull public ExternalInterceptorContext setEventId(@Nullable final String id) {
+ eventId = id;
+
+ return this;
+ }
+
+}
\ No newline at end of file
diff --git a/idp-profile-api/src/main/java/net/shibboleth/idp/profile/interceptor/ExternalInterceptor.java b/idp-profile-api/src/main/java/net/shibboleth/idp/profile/interceptor/ExternalInterceptor.java
new file mode 100644
index 0000000..4847dcd
--- /dev/null
+++ b/idp-profile-api/src/main/java/net/shibboleth/idp/profile/interceptor/ExternalInterceptor.java
@@ -0,0 +1,186 @@
+/*
+ * 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.idp.profile.interceptor;
+
+import java.io.IOException;
+
+import javax.annotation.Nonnull;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+import com.google.common.net.UrlEscapers;
+
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+/**
+ * Public interface supporting external interceptor flows outside the webflow engine.
+ *
+ * @since 4.0.0
+ */
+public class ExternalInterceptor {
+
+ /** Parameter supplied to identify the per-conversation structure in the session. */
+ @Nonnull @NotEmpty public static final String CONVERSATION_KEY = "conversation";
+
+ /** Request attribute to which an event ID may be bound. */
+ @Nonnull @NotEmpty public static final String EVENT_KEY = "event";
+
+ /**
+ * Computes the appropriate location to pass control to to invoke an external interceptor mechanism.
+ *
+ * <p>The input location should be suitable for use in a Spring "externalRedirect" expression, and may
+ * contain a query string. The result will include any additional parameters needed to invoke the
+ * mechanism.</p>
+ *
+ * @param baseLocation the base location to build off of
+ * @param conversationValue the value to include as a conversation ID
+ *
+ * @return the computed location
+ */
+ @Nonnull @NotEmpty public static String getExternalRedirect(@Nonnull @NotEmpty final String baseLocation,
+ @Nonnull @NotEmpty final String conversationValue) {
+ Constraint.isNotEmpty(baseLocation, "Base location cannot be null or empty");
+
+ final StringBuilder url = new StringBuilder(baseLocation);
+
+ // Add a parameter separator for the conversation ID.
+ url.append(baseLocation.indexOf('?') == -1 ? '?' : '&');
+ url.append(CONVERSATION_KEY).append('=').append(
+ UrlEscapers.urlFormParameterEscaper().escape(conversationValue));
+
+ return url.toString();
+ }
+
+ /**
+ * Initialize a request to an external interceptor by seeking out the information stored in
+ * the servlet session and exposing it as request attributes.
+ *
+ * @param request servlet request
+ *
+ * @return a handle to subsequent use of
+ * {@link #finishExternalInterceptor(java.lang.String, HttpServletRequest, HttpServletResponse)}
+ *
+ * @throws ExternalInterceptorException if an error occurs
+ */
+ @Nonnull @NotEmpty public static String startExternalInterceptor(@Nonnull final HttpServletRequest request)
+ throws ExternalInterceptorException {
+ final String conv = request.getParameter(CONVERSATION_KEY);
+ if (conv == null || conv.isEmpty()) {
+ throw new ExternalInterceptorException("No conversation key found in request");
+ }
+
+ final Object obj = request.getSession().getAttribute(CONVERSATION_KEY + conv);
+ if (obj == null || !(obj instanceof ExternalInterceptor)) {
+ throw new ExternalInterceptorException("No conversation state found in session for key (" + conv + ")");
+ }
+
+ ((ExternalInterceptor) obj).doStart(request);
+ return conv;
+ }
+
+ /**
+ * Complete a request to an external interceptor by seeking out the information stored in
+ * request attributes and transferring to the session's conversation state, and then transfer
+ * control back to the webflow.
+ *
+ * @param key the value returned by {@link #startExternalInterceptor(HttpServletRequest)}
+ * @param request servlet request
+ * @param response servlet response
+ *
+ * @throws ExternalInterceptorException if an error occurs
+ * @throws IOException if the redirect cannot be issued
+ */
+ public static void finishExternalInterceptor(@Nonnull @NotEmpty final String key,
+ @Nonnull final HttpServletRequest request, @Nonnull final HttpServletResponse response)
+ throws ExternalInterceptorException, IOException {
+
+ final Object obj = request.getSession().getAttribute(CONVERSATION_KEY + key);
+ if (obj == null || !(obj instanceof ExternalInterceptor)) {
+ throw new ExternalInterceptorException("No conversation state found in session for key (" + key + ")");
+ }
+
+ request.getSession().removeAttribute(CONVERSATION_KEY + key);
+
+ ((ExternalInterceptor) obj).doFinish(request, response);
+ }
+
+ /**
+ * Get the {@link ProfileRequestContext} associated with a request.
+ *
+ * @param key the value returned by {@link #startExternalAuthentication(HttpServletRequest)}
+ * @param request servlet request
+ *
+ * @return the profile request context
+ * @throws ExternalInterceptorException if an error occurs
+ */
+ @Nonnull public static ProfileRequestContext getProfileRequestContext(@Nonnull @NotEmpty final String key,
+ @Nonnull final HttpServletRequest request) throws ExternalInterceptorException {
+
+ final Object obj = request.getSession().getAttribute(CONVERSATION_KEY + key);
+ if (obj == null || !(obj instanceof ExternalInterceptor)) {
+ throw new ExternalInterceptorException("No conversation state found in session");
+ }
+
+ return ((ExternalInterceptor) obj).getProfileRequestContext(request);
+ }
+
+ /**
+ * Initialize a request to an external interceptor by seeking out the information stored in
+ * the servlet session and exposing it as request attributes.
+ *
+ * @param request servlet request
+ *
+ * @throws ExternalInterceptorException if an error occurs
+ */
+ protected void doStart(@Nonnull final HttpServletRequest request) throws ExternalInterceptorException {
+ throw new ExternalInterceptorException("Not implemented");
+ }
+
+ /**
+ * Complete a request to an external interceptor by seeking out the information stored in
+ * request attributes and transferring to the session's conversation state, and then transfer
+ * control back to the webflow.
+ *
+ * @param request servlet request
+ * @param response servlet response
+ *
+ * @throws ExternalInterceptorException if an error occurs
+ * @throws IOException if the redirect cannot be issued
+ */
+ protected void doFinish(@Nonnull final HttpServletRequest request, @Nonnull final HttpServletResponse response)
+ throws ExternalInterceptorException, IOException {
+ throw new ExternalInterceptorException("Not implemented");
+ }
+
+ /**
+ * Get the {@link ProfileRequestContext} associated with a request.
+ *
+ * @param request servlet request
+ *
+ * @return the profile request context
+ * @throws ExternalInterceptorException if an error occurs
+ */
+ @Nonnull protected ProfileRequestContext getProfileRequestContext(@Nonnull final HttpServletRequest request)
+ throws ExternalInterceptorException {
+ throw new ExternalInterceptorException("Not implemented");
+ }
+
+}
\ No newline at end of file
diff --git a/idp-profile-api/src/main/java/net/shibboleth/idp/profile/interceptor/ExternalInterceptorException.java b/idp-profile-api/src/main/java/net/shibboleth/idp/profile/interceptor/ExternalInterceptorException.java
new file mode 100644
index 0000000..329e60c
--- /dev/null
+++ b/idp-profile-api/src/main/java/net/shibboleth/idp/profile/interceptor/ExternalInterceptorException.java
@@ -0,0 +1,66 @@
+/*
+ * 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.idp.profile.interceptor;
+
+import javax.annotation.Nullable;
+
+/**
+ * Exception indicating a problem with the external interceptor process.
+ *
+ * @since 4.0.0
+ */
+public class ExternalInterceptorException extends Exception {
+
+ /** Generated serial UID. */
+ private static final long serialVersionUID = 2344188427329594209L;
+
+ /** Constructor. */
+ public ExternalInterceptorException() {
+
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message exception message
+ */
+ public ExternalInterceptorException(@Nullable final String message) {
+ super(message);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param wrappedException exception to be wrapped by this one
+ */
+ public ExternalInterceptorException(@Nullable final Exception wrappedException) {
+ super(wrappedException);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message exception message
+ * @param wrappedException exception to be wrapped by this one
+ */
+ public ExternalInterceptorException(@Nullable final String message,
+ @Nullable final Exception wrappedException) {
+ super(message, wrappedException);
+ }
+
+}
\ No newline at end of file
diff --git a/idp-profile-impl/src/main/java/net/shibboleth/idp/profile/interceptor/impl/ExternalInterceptorImpl.java b/idp-profile-impl/src/main/java/net/shibboleth/idp/profile/interceptor/impl/ExternalInterceptorImpl.java
new file mode 100644
index 0000000..68ae604
--- /dev/null
+++ b/idp-profile-impl/src/main/java/net/shibboleth/idp/profile/interceptor/impl/ExternalInterceptorImpl.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 net.shibboleth.idp.profile.interceptor.impl;
+
+import java.io.IOException;
+
+import javax.annotation.Nonnull;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.shibboleth.idp.profile.context.ExternalInterceptorContext;
+import net.shibboleth.idp.profile.context.ProfileInterceptorContext;
+import net.shibboleth.idp.profile.interceptor.ExternalInterceptor;
+import net.shibboleth.idp.profile.interceptor.ExternalInterceptorException;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+/**
+ * Implementation of the {@link ExternalInterceptor} API that handles moving information in and out
+ * of request attributes.
+ *
+ * @since 4.0.0
+ */
+public class ExternalInterceptorImpl extends ExternalInterceptor {
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(ExternalInterceptorImpl.class);
+
+ /** State of request to pull from. */
+ @Nonnull private final ProfileRequestContext profileRequestContext;
+
+ /**
+ * Constructor.
+ *
+ * @param input profile request context to expose
+ */
+ public ExternalInterceptorImpl(@Nonnull final ProfileRequestContext input) {
+ profileRequestContext = Constraint.isNotNull(input, "ProfileRequestContext cannot be null");
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doStart(@Nonnull final HttpServletRequest request) {
+ request.setAttribute(ProfileRequestContext.BINDING_KEY, profileRequestContext);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doFinish(@Nonnull final HttpServletRequest request, @Nonnull final HttpServletResponse response)
+ throws IOException, ExternalInterceptorException {
+ final ProfileInterceptorContext piContext =
+ profileRequestContext.getSubcontext(ProfileInterceptorContext.class);
+ if (piContext == null) {
+ throw new ExternalInterceptorException("No ProfileInterceptorContext found");
+ }
+
+ final ExternalInterceptorContext extContext = piContext.getSubcontext(ExternalInterceptorContext.class);
+ if (extContext == null) {
+ throw new ExternalInterceptorException("No ExternalInterceptorContext found");
+ } else if (extContext.getFlowExecutionUrl() == null) {
+ throw new ExternalInterceptorException("No flow execution URL found to return control");
+ }
+
+ final Object attr = request.getAttribute(EVENT_KEY);
+ if (attr != null && attr instanceof String) {
+ extContext.setEventId((String) attr);
+ }
+
+ response.sendRedirect(extContext.getFlowExecutionUrl());
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected ProfileRequestContext getProfileRequestContext(@Nonnull final HttpServletRequest request)
+ throws ExternalInterceptorException {
+ return profileRequestContext;
+ }
+
+}
\ 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