/*
* Copyright 2002-2005 the original author or authors.
*
* Licensed 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.springmodules.workflow.osworkflow.web;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springmodules.workflow.osworkflow.OsWorkflowContext;
import org.springmodules.workflow.osworkflow.OsWorkflowContextHolder;
import org.springframework.web.bind.RequestUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
/**
* Base <code>HandlerInterceptor</code> used to set the workflow instance ID and caller in the <code>OsWorkflowContext</code>
* tranparently in a Spring MVC setting.
* <p/>
* If session storage is enabled, the workflow instance ID and caller will be transparently bound to and retrieved from the
* <code>HttpSession</code>. Session storage can be enabled and disabled using the <code>sessionStorageEnabled</code> property.
* <p/>
* If request parameter override is enabled, the workflow instance ID can be set by passing in a certain request parameter,
* by default <code>instanceId</code>. Request parameter override can be enabled and disabled using the
* <code>allowOverrideWithRequestParameter</code> property.
* <p/>
* If both session storage and request parameter override are enabled, then the workflow instance ID specified in the
* request parameter takes precendence.
* <p/>
* Subclasses should implement the <code>getCaller(HttpServletRequest)</code> to retreive the caller identity and return it for
* it to be bound to the <code>OsWorkflowContext</code>.
*
* @author Rob Harrop
* @see #setSessionStorageEnabled(boolean)
* @see #setAllowOverrideWithRequestParameter(boolean)
* @see #setOverrideRequestParameterKey(String)
*/
public abstract class AbstractWorkflowContextHandlerInterceptor extends HandlerInterceptorAdapter {
/**
* Key used to bind the workflow instance ID into the <code>HttpSession</code>.
*/
public static final String SESSION_KEY_INSTANCE_ID = "org.springmodules.workflow.osworkflow.instanceId";
/**
* Default request parameter used to set the workflow ID instance in the <code>OsWorkflowContext</code>.
*/
private static final String DEFAULT_OVERRIDE_REQUEST_PARAMETER = "instanceId";
/**
* Indicates whether the workflow instance ID should be stored in and retrieved from the <code>HttpSession</code>. Default value
* is <code>true</code> indicating that session storage will be used.
*/
private boolean sessionStorageEnabled = true;
/**
* Indicates whether a request parameter can be used to manually set the workflow instance ID in the <code>OsWorkflowContext</code>.
* Default value is <code>true</code> indicating that a request parameter can be used to set the workflow instance ID.
*
* @see #overrideRequestParameterKey
*/
private boolean allowOverrideWithRequestParameter = true;
/**
* The request parameter used to override the workflow instance ID when <code>allowOverrideWithRequestParameter</code> is
* <code>true</code>. The default value is determined by the <code>DEFAULT_OVERRIDE_REQUEST_PARAMETER</code> constant.
*
* @see DEFAULT_OVERRIDE_REQUEST_PARAMETER
*/
private String overrideRequestParameterKey = DEFAULT_OVERRIDE_REQUEST_PARAMETER;
/**
* Set to <code>true</code> to enable session storage for the workflow instance ID or <code>false</code> to disable
* session storage. When session storage enabled any workflow instance ID existing in the <code>HttpSession</code>
* at the beginning of the request will be bound to the <code>OsWorkflowContext</code>. At the end of a request any
* workflow instance ID bound to the <code>OsWorkflowContext</code> will be stored in the <code>HttpSession</code>.
*/
public void setSessionStorageEnabled(boolean sessionStorageEnabled) {
this.sessionStorageEnabled = sessionStorageEnabled;
}
/**
* Set to <code>true</code> to allow for the workflow instance ID to be overridden using a request parameter.
*
* @see #getOverrideRequestParameterKey()
* @see #setOverrideRequestParameterKey(String)
*/
public void setAllowOverrideWithRequestParameter(boolean allowOverrideWithRequestParameter) {
this.allowOverrideWithRequestParameter = allowOverrideWithRequestParameter;
}
/**
* Sets the name of the request parameter used to override the workflow instance ID.
*/
public void setOverrideRequestParameterKey(String overrideRequestParameterKey) {
this.overrideRequestParameterKey = overrideRequestParameterKey;
}
/**
* Indicates whether session storage is enabled and whether the workflow instance ID can be stored in and retrieved from
* the <code>HttpSession</code>.
*/
protected boolean isSessionStorageEnabled() {
return sessionStorageEnabled;
}
/**
* Indicates whether or not the workflow instance ID can be overridden using a request parameter.
*/
protected boolean isAllowOverrideWithRequestParameter() {
return allowOverrideWithRequestParameter;
}
/**
* Gets the name of the request parameter used to override the workflow instance ID.
*/
protected String getOverrideRequestParameterKey() {
return overrideRequestParameterKey;
}
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
OsWorkflowContext context = OsWorkflowContextHolder.getWorkflowContext();
context.setCaller(getCaller(request));
if (isAllowOverrideWithRequestParameter()) {
long instanceIdFromRequest = RequestUtils.getLongParameter(request, getOverrideRequestParameterKey(), Long.MIN_VALUE);
if (instanceIdFromRequest != Long.MIN_VALUE) {
System.out.println("Setting instance id");
context.setInstanceId(instanceIdFromRequest);
}
else if (isSessionStorageEnabled()) {
HttpSession session = request.getSession();
Object instanceId = session.getAttribute(SESSION_KEY_INSTANCE_ID);
if ((instanceId != null) && (instanceId instanceof Long)) {
context.setInstanceId(((Long) instanceId).longValue());
}
}
}
return true;
}
/**
* If session storage is enabled and the current <code>OsWorkflowContext</code> has a workflow instance ID bound to it
* then this workflow instance ID will be stored in the <code>HttpSession</code>.
*
* @see #setSessionStorageEnabled(boolean)
*/
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception {
OsWorkflowContext context = OsWorkflowContextHolder.getWorkflowContext();
if (isSessionStorageEnabled() && context.hasInstanceId()) {
HttpSession session = request.getSession();
session.setAttribute(SESSION_KEY_INSTANCE_ID, new Long(context.getInstanceId()));
}
}
/**
* Subclasses should implement this method to return the caller identity for it to be bound to the <code>OsWorkflowContext</code>.
*/
protected abstract String getCaller(HttpServletRequest request);
}