KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > webflow > executor > support > RequestPathFlowExecutorArgumentHandler


1 /*
2  * Copyright 2002-2006 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.springframework.webflow.executor.support;
17
18 import org.springframework.util.StringUtils;
19 import org.springframework.web.util.WebUtils;
20 import org.springframework.webflow.context.ExternalContext;
21 import org.springframework.webflow.context.servlet.ServletExternalContext;
22 import org.springframework.webflow.execution.FlowExecutionContext;
23 import org.springframework.webflow.execution.support.FlowDefinitionRedirect;
24
25 /**
26  * Flow executor argument handler that extracts arguments from the request path
27  * and exposes them in the URL path.
28  * <p>
29  * This allows for REST-style URLs to launch flows in the general format:
30  * <code>http://${host}/${context path}/${dispatcher path}/${flowId}</code>.
31  * <p>
32  * For example, the URL
33  * <code>http://localhost/springair/reservation/booking</code> would launch a
34  * new execution of the <code>booking</code> flow, assuming a context path of
35  * <code>/springair</code> and a servlet mapping of <code>/reservation/*</code>.
36  * <p>
37  * This also allows for URLs to resume flow executions in the format:
38  * <code>http://${host}/${context path}/${dispatcher path}/${key delimiter}/${flowExecutionKey}</code>.
39  * <p>
40  * For example, the URL
41  * <code>http://localhost/springair/reservation/k/ABC123XYZ</code> would
42  * resume flow execution "ABC123XYZ".
43  * <p>
44  * Note: this implementation only works with <code>ExternalContext</code>
45  * implementations that return valid
46  * {@link ExternalContext#getRequestPathInfo()} such as the
47  * {@link ServletExternalContext}. Furthermore, it assumes that the controller
48  * handling flow requests is not identified using request path information.
49  * For instance, mapping the dispatcher to "*.html" in web.xml would work since
50  * in this case the flow controller will be identified as part of the dispatcher
51  * name (e.g. "flows.html"). Mapping the dispatcher to "/html/*" in web.xml
52  * will not work since that would require the flow controller to be identified
53  * by the extra request path information (e.g. "/html/flows").
54  *
55  * @author Keith Donald
56  */

57 public class RequestPathFlowExecutorArgumentHandler extends RequestParameterFlowExecutorArgumentHandler {
58
59     /**
60      * URL path seperator ("/").
61      */

62     private static final char PATH_SEPARATOR_CHARACTER = '/';
63
64     /**
65      * Default value of the flow execution key delimiter ("k").
66      */

67     private static final String JavaDoc KEY_DELIMITER = "k";
68
69     /**
70      * The delimiter that when present in the requestPathInfo indicates the
71      * flowExecutionKey follows in the URL. Defaults to {@link #KEY_DELIMITER}.
72      */

73     private String JavaDoc keyDelimiter = KEY_DELIMITER;
74
75     /**
76      * Returns the key delimiter. Defaults to "k".
77      * @return the key delimiter
78      */

79     public String JavaDoc getKeyDelimiter() {
80         return keyDelimiter;
81     }
82
83     /**
84      * Sets the delimiter that when present in the requestPathInfo indicates the
85      * flowExecutionKey follows in the URL. Defaults to "k".
86      * @param keyDelimiter the key delimiter
87      * @see #extractFlowExecutionKey(ExternalContext)
88      */

89     public void setKeyDelimiter(String JavaDoc keyDelimiter) {
90         this.keyDelimiter = keyDelimiter;
91     }
92
93     public boolean isFlowIdPresent(ExternalContext context) {
94         String JavaDoc requestPathInfo = getRequestPathInfo(context);
95         boolean hasFileName = StringUtils.hasText(WebUtils.extractFilenameFromUrlPath(requestPathInfo));
96         return hasFileName || super.isFlowIdPresent(context);
97     }
98
99     public String JavaDoc extractFlowId(ExternalContext context) {
100         String JavaDoc requestPathInfo = getRequestPathInfo(context);
101         String JavaDoc extractedFilename = WebUtils.extractFilenameFromUrlPath(requestPathInfo);
102         return StringUtils.hasText(extractedFilename) ? extractedFilename : super.extractFlowId(context);
103     }
104
105     public boolean isFlowExecutionKeyPresent(ExternalContext context) {
106         String JavaDoc requestPathInfo = getRequestPathInfo(context);
107         return requestPathInfo.startsWith(keyPath()) || super.isFlowExecutionKeyPresent(context);
108     }
109
110     public String JavaDoc extractFlowExecutionKey(ExternalContext context) throws FlowExecutorArgumentExtractionException {
111         String JavaDoc requestPathInfo = getRequestPathInfo(context);
112         int index = requestPathInfo.indexOf(keyPath());
113         if (index != -1) {
114             return requestPathInfo.substring(index + keyPath().length());
115         }
116         else {
117             return super.extractFlowExecutionKey(context);
118         }
119     }
120
121     public String JavaDoc createFlowDefinitionUrl(FlowDefinitionRedirect flowDefinitionRedirect, ExternalContext context) {
122         StringBuffer JavaDoc flowUrl = new StringBuffer JavaDoc();
123         appendFlowExecutorPath(flowUrl, context);
124         flowUrl.append(PATH_SEPARATOR_CHARACTER);
125         flowUrl.append(flowDefinitionRedirect.getFlowDefinitionId());
126         if (!flowDefinitionRedirect.getExecutionInput().isEmpty()) {
127             flowUrl.append('?');
128             appendQueryParameters(flowUrl, flowDefinitionRedirect.getExecutionInput());
129         }
130         return flowUrl.toString();
131     }
132
133     public String JavaDoc createFlowExecutionUrl(String JavaDoc flowExecutionKey, FlowExecutionContext flowExecution,
134             ExternalContext context) {
135         StringBuffer JavaDoc flowExecutionUrl = new StringBuffer JavaDoc();
136         appendFlowExecutorPath(flowExecutionUrl, context);
137         flowExecutionUrl.append(PATH_SEPARATOR_CHARACTER);
138         flowExecutionUrl.append(keyDelimiter);
139         flowExecutionUrl.append(PATH_SEPARATOR_CHARACTER);
140         flowExecutionUrl.append(flowExecutionKey);
141         return flowExecutionUrl.toString();
142     }
143
144     // internal helpers
145

146     protected void appendFlowExecutorPath(StringBuffer JavaDoc url, ExternalContext context) {
147         url.append(context.getContextPath());
148         url.append(context.getDispatcherPath());
149     }
150
151     /**
152      * Returns the request path info for given external context. Never returns
153      * null, an empty string is returned instead.
154      */

155     private String JavaDoc getRequestPathInfo(ExternalContext context) {
156         String JavaDoc requestPathInfo = context.getRequestPathInfo();
157         return requestPathInfo != null ? requestPathInfo : "";
158     }
159     
160     /**
161      * Returns the flow execution key path in the request path info, e.g. "/k/".
162      */

163     private String JavaDoc keyPath() {
164         return PATH_SEPARATOR_CHARACTER + keyDelimiter + PATH_SEPARATOR_CHARACTER;
165     }
166 }
Popular Tags