org.springframework.webflow.mvc.servlet.FlowHandlerMapping.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.webflow.mvc.servlet.FlowHandlerMapping.java

Source

/*
 * Copyright 2004-2008 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.springframework.webflow.mvc.servlet;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
import org.springframework.web.servlet.handler.AbstractHandlerMapping;
import org.springframework.webflow.context.servlet.DefaultFlowUrlHandler;
import org.springframework.webflow.context.servlet.FlowUrlHandler;
import org.springframework.webflow.definition.FlowDefinition;
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;

/**
 * Implementation of {@link org.springframework.web.servlet.HandlerMapping} that follows a simple convention for
 * creating URL path mappings from the <i>ids</i> of registered {@link FlowDefinition flow definitions}.
 * 
 * This implementation returns a FlowHandler that invokes a flow if the current request path matches the id of a flow in
 * the configured {@link FlowDefinitionRegistry}. Alternatively, a custom {@link FlowHandler} may also be registered
 * with in containing ApplicationContext with that id and it will be returned. This allows for more control over the
 * invocation of a flow from Spring MVC environment.
 * 
 * Null is returned in the case of no flow id match, allowing the next handler mapping in the chain to execute.
 * 
 * @author Keith Donald
 */
public class FlowHandlerMapping extends AbstractHandlerMapping {

    private static final Log logger = LogFactory.getLog(FlowHandlerMapping.class);

    private FlowDefinitionRegistry flowRegistry;

    private FlowUrlHandler flowUrlHandler;

    /**
     * Returns the registry of flows to query when this mapping is tested.
     * @return the flow definition registry
     */
    public FlowDefinitionRegistry getFlowRegistry() {
        return flowRegistry;
    }

    /**
     * Sets the registry of flows to query when this mapping is tested. Optional. If not set, this handler mapping will
     * look in the containing application context for a bean with id <code>flowRegistry</code>.
     * @param flowRegistry the flow definition registry
     */
    public void setFlowRegistry(FlowDefinitionRegistry flowRegistry) {
        this.flowRegistry = flowRegistry;
    }

    /**
     * Returns the configured flow url handler.
     */
    public FlowUrlHandler getFlowUrlHandler() {
        return flowUrlHandler;
    }

    /**
     * Sets the flow URL handler, which allows customization for how the flow id is determined for each request tested
     * by this mapping. Defaults to a {@link DefaultFlowUrlHandler}.
     * @param flowUrlHandler the flow URL handler
     */
    public void setFlowUrlHandler(FlowUrlHandler flowUrlHandler) {
        this.flowUrlHandler = flowUrlHandler;
    }

    protected void initServletContext(ServletContext servletContext) {
        Assert.notNull(flowRegistry, "The FlowRegistry to query when mapping requests is required");
        if (flowUrlHandler == null) {
            flowUrlHandler = new DefaultFlowUrlHandler();
        }
    }

    protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
        String flowId = flowUrlHandler.getFlowId(request);
        if (flowId == null) {
            return null;
        }
        if (getApplicationContext().containsBean(flowId)) {
            Object handler = getApplicationContext().getBean(flowId);
            if (handler instanceof FlowHandler) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Mapping request with URI '" + request.getRequestURI() + "' to flow with id '"
                            + flowId + "'; custom FlowHandler " + handler + " will manage flow execution");
                }
                return handler;
            }
        }
        if (flowRegistry.containsFlowDefinition(flowId)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Mapping request with URI '" + request.getRequestURI() + "' to flow with id '" + flowId
                        + "'");
            }
            return createDefaultFlowHandler(flowId);
        }
        if (logger.isDebugEnabled()) {
            logger.debug("No flow mapping found for request with URI '" + request.getRequestURI() + "'");
        }
        return null;
    }

    /**
     * Factory method that returns the default flow handler for the flow with the given id. Subclasses may override to
     * return their own custom default FlowHandler.
     * @param flowId the id of the flow to handle invocation of
     * @return the default flow handler
     */
    protected FlowHandler createDefaultFlowHandler(String flowId) {
        return new DefaultFlowHandler(flowId);
    }

    private static class DefaultFlowHandler extends AbstractFlowHandler {

        private String flowId;

        public DefaultFlowHandler(String flowId) {
            this.flowId = flowId;
        }

        public String getFlowId() {
            return flowId;
        }
    }

}