KickJava   Java API By Example, From Geeks To Geeks.

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


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 java.io.UnsupportedEncodingException JavaDoc;
19 import java.net.URLEncoder JavaDoc;
20 import java.util.Map JavaDoc;
21
22 import org.springframework.core.JdkVersion;
23 import org.springframework.util.StringUtils;
24 import org.springframework.webflow.context.ExternalContext;
25 import org.springframework.webflow.execution.FlowExecutionContext;
26 import org.springframework.webflow.execution.support.ExternalRedirect;
27 import org.springframework.webflow.execution.support.FlowDefinitionRedirect;
28
29 /**
30  * Abstract base class for objects handling
31  * {@link org.springframework.webflow.executor.FlowExecutor} arguments. This
32  * class combines the two argument handling responsabilities of ({@link FlowExecutorArgumentExtractor extraction}
33  * and {@link FlowExecutorArgumentExposer exposing}) and makes sure they are
34  * consistent, i.e. that exposed arguments can later be extracted again.
35  * <p>
36  * All argument names are configurable. Common convenience functionality is also
37  * provided, e.g. a {@link #applyDefaultFlowId(String) default flow id},
38  * {@link #encodeValue(Object) URL encoding} and dealing with
39  * {@link #makeRedirectUrlContextRelativeIfNecessary(String, ExternalContext) relative URLs}.
40  * Subclasses are responsible for taking these settings into account when
41  * implementing actual argument extraction and exposing behavior.
42  *
43  * @see FlowExecutorArgumentExtractor
44  * @see FlowExecutorArgumentExposer
45  *
46  * @author Keith Donald
47  * @author Erwin Vervaet
48  */

49 public abstract class FlowExecutorArgumentHandler implements FlowExecutorArgumentExtractor, FlowExecutorArgumentExposer {
50
51     // data and behavior related to argument extraction
52

53     /**
54      * By default clients can send the id of the flow definition to be launched
55      * using an argument with this name ("_flowId").
56      */

57     private static final String JavaDoc FLOW_ID_ARGUMENT_NAME = "_flowId";
58
59     /**
60      * By default clients can send the key of a flow execution to be resumed
61      * using an argument with this name ("_flowExecutionKey").
62      */

63     private static final String JavaDoc FLOW_EXECUTION_KEY_ARGUMENT_NAME = "_flowExecutionKey";
64
65     /**
66      * By default clients can send the event to be signaled in an argument with
67      * this name ("_eventId").
68      */

69     private static final String JavaDoc EVENT_ID_ARGUMENT_NAME = "_eventId";
70
71     /**
72      * Identifies a flow definition to launch a new execution for, defaults to
73      * {@link #FLOW_ID_ARGUMENT_NAME}.
74      */

75     private String JavaDoc flowIdArgumentName = FLOW_ID_ARGUMENT_NAME;
76
77     /**
78      * Input argument that identifies an existing flow execution to participate
79      * in, defaults to {@link #FLOW_EXECUTION_KEY_ARGUMENT_NAME}.
80      */

81     private String JavaDoc flowExecutionKeyArgumentName = FLOW_EXECUTION_KEY_ARGUMENT_NAME;
82
83     /**
84      * Identifies an event that occured in an existing flow execution, defaults
85      * to {@link #EVENT_ID_ARGUMENT_NAME}.
86      */

87     private String JavaDoc eventIdArgumentName = EVENT_ID_ARGUMENT_NAME;
88
89     /**
90      * The flow definition id to use if no flowId argument value can be
91      * extracted during the {@link #extractFlowId(ExternalContext)} operation.
92      * Default value is <code>null</code>.
93      */

94     private String JavaDoc defaultFlowId;
95
96     /**
97      * Returns the flow id argument name, used to request a flow to launch.
98      */

99     public String JavaDoc getFlowIdArgumentName() {
100         return flowIdArgumentName;
101     }
102
103     /**
104      * Sets the flow id argument name, used to request a flow to launch.
105      */

106     public void setFlowIdArgumentName(String JavaDoc flowIdArgumentName) {
107         this.flowIdArgumentName = flowIdArgumentName;
108     }
109
110     /**
111      * Returns the flow execution key argument name, used to request that an
112      * executing conversation resumes.
113      */

114     public String JavaDoc getFlowExecutionKeyArgumentName() {
115         return flowExecutionKeyArgumentName;
116     }
117
118     /**
119      * Sets the flow execution key argument name, used to request that an
120      * executing conversation resumes.
121      */

122     public void setFlowExecutionKeyArgumentName(String JavaDoc flowExecutionKeyArgumentName) {
123         this.flowExecutionKeyArgumentName = flowExecutionKeyArgumentName;
124     }
125
126     /**
127      * Returns the event id argument name, used to signal what user action
128      * happened within a paused flow execution.
129      */

130     public String JavaDoc getEventIdArgumentName() {
131         return eventIdArgumentName;
132     }
133
134     /**
135      * Sets the event id argument name, used to signal what user action happened
136      * within a paused flow execution.
137      */

138     public void setEventIdArgumentName(String JavaDoc eventIdArgumentName) {
139         this.eventIdArgumentName = eventIdArgumentName;
140     }
141
142     /**
143      * Returns the <i>default</i> flowId argument value. If no flow id argument
144      * is provided, the default acts as a fallback. Defaults to
145      * <code>null</code>.
146      */

147     public String JavaDoc getDefaultFlowId() {
148         return defaultFlowId;
149     }
150
151     /**
152      * Sets the default flowId argument value.
153      * <p>
154      * This value will be used if no flowId argument value can be extracted from
155      * the request by the {@link #extractFlowId(ExternalContext)} operation.
156      */

157     public void setDefaultFlowId(String JavaDoc defaultFlowId) {
158         this.defaultFlowId = defaultFlowId;
159     }
160
161     // data and behavior for response issuance
162

163     /**
164      * The string-encoded id of the flow execution will be exposed to the view
165      * in a model attribute with this name ("flowExecutionKey").
166      */

167     private static final String JavaDoc FLOW_EXECUTION_KEY_ATTRIBUTE = "flowExecutionKey";
168
169     /**
170      * The flow execution context itself will be exposed to the view in a model
171      * attribute with this name ("flowExecutionContext").
172      */

173     private static final String JavaDoc FLOW_EXECUTION_CONTEXT_ATTRIBUTE = "flowExecutionContext";
174
175     /**
176      * The default URL encoding scheme: UTF-8.
177      */

178     private static final String JavaDoc DEFAULT_URL_ENCODING_SCHEME = "UTF-8";
179
180     /**
181      * Model attribute that identifies the flow execution participated in,
182      * defaults to {@link #FLOW_EXECUTION_KEY_ATTRIBUTE}.
183      */

184     private String JavaDoc flowExecutionKeyAttributeName = FLOW_EXECUTION_KEY_ATTRIBUTE;
185
186     /**
187      * Model attribute that provides state about the flow execution participated
188      * in, defaults to {@link #FLOW_EXECUTION_CONTEXT_ATTRIBUTE}.
189      */

190     private String JavaDoc flowExecutionContextAttributeName = FLOW_EXECUTION_CONTEXT_ATTRIBUTE;
191
192     /**
193      * The url encoding scheme to be used to encode URLs built by this argument
194      * handler. Defaults to {@link #DEFAULT_URL_ENCODING_SCHEME}.
195      */

196     private String JavaDoc urlEncodingScheme = DEFAULT_URL_ENCODING_SCHEME;
197
198     /**
199      * A flag indicating whether to interpret a redirect URL that starts with a
200      * slash ("/") as relative to the current ServletContext, i.e. as relative
201      * to the web application root, as opposed to absolute. Default is true.
202      */

203     private boolean redirectContextRelative = true;
204
205     /**
206      * Returns the flow execution key attribute name, used as a model attribute
207      * for identifying the executing flow being participated in.
208      */

209     public String JavaDoc getFlowExecutionKeyAttributeName() {
210         return flowExecutionKeyAttributeName;
211     }
212
213     /**
214      * Sets the flow execution key attribute name, used as a model attribute for
215      * identifying the current state of the executing flow being participated in
216      * (typically used by view templates during rendering).
217      */

218     public void setFlowExecutionKeyAttributeName(String JavaDoc flowExecutionKeyAttributeName) {
219         this.flowExecutionKeyAttributeName = flowExecutionKeyAttributeName;
220     }
221
222     /**
223      * Returns the flow execution context attribute name.
224      */

225     public String JavaDoc getFlowExecutionContextAttributeName() {
226         return flowExecutionContextAttributeName;
227     }
228
229     /**
230      * Sets the flow execution context attribute name.
231      */

232     public void setFlowExecutionContextAttributeName(String JavaDoc flowExecutionContextAttributeName) {
233         this.flowExecutionContextAttributeName = flowExecutionContextAttributeName;
234     }
235
236     /**
237      * Returns the url encoding scheme to be used to encode URLs built by this
238      * argument handler. Defaults to "UTF-8".
239      */

240     public String JavaDoc getUrlEncodingScheme() {
241         return urlEncodingScheme;
242     }
243
244     /**
245      * Set the url encoding scheme to be used to encode URLs built by this
246      * argument handler. Defaults to "UTF-8".
247      */

248     public void setUrlEncodingScheme(String JavaDoc urlEncodingScheme) {
249         this.urlEncodingScheme = urlEncodingScheme;
250     }
251
252     /**
253      * Set whether to interpret a given redirect URL that starts with a slash
254      * ("/") as relative to the current ServletContext, i.e. as relative to the
255      * web application root.
256      * <p>
257      * Default is "true": A redirect URL that starts with a slash will be
258      * interpreted as relative to the web application root, i.e. the context
259      * path will be prepended to the URL.
260      */

261     public void setRedirectContextRelative(boolean redirectContextRelative) {
262         this.redirectContextRelative = redirectContextRelative;
263     }
264
265     /**
266      * Return whether to interpret a given redirect URL that starts with a slash
267      * ("/") as relative to the current ServletContext, i.e. as relative to the
268      * web application root.
269      */

270     public boolean isRedirectContextRelative() {
271         return redirectContextRelative;
272     }
273
274     public abstract boolean isFlowIdPresent(ExternalContext context);
275
276     public abstract String JavaDoc extractFlowId(ExternalContext context) throws FlowExecutorArgumentExtractionException;
277
278     public abstract boolean isFlowExecutionKeyPresent(ExternalContext context);
279
280     public abstract String JavaDoc extractFlowExecutionKey(ExternalContext context)
281             throws FlowExecutorArgumentExtractionException;
282
283     public abstract boolean isEventIdPresent(ExternalContext context);
284
285     public abstract String JavaDoc extractEventId(ExternalContext context) throws FlowExecutorArgumentExtractionException;
286
287     public void exposeFlowExecutionContext(String JavaDoc flowExecutionKey, FlowExecutionContext context, Map JavaDoc model) {
288         if (flowExecutionKey != null) {
289             model.put(getFlowExecutionKeyAttributeName(), flowExecutionKey);
290         }
291         model.put(getFlowExecutionContextAttributeName(), context);
292     }
293
294     public abstract String JavaDoc createFlowDefinitionUrl(FlowDefinitionRedirect flowDefinitionRedirect,
295             ExternalContext context);
296
297     public abstract String JavaDoc createFlowExecutionUrl(String JavaDoc flowExecutionKey, FlowExecutionContext flowExecution,
298             ExternalContext context);
299
300     public abstract String JavaDoc createExternalUrl(ExternalRedirect redirect, String JavaDoc flowExecutionKey, ExternalContext context);
301
302     // helpers for use in subclasses
303

304     /**
305      * Apply the configured default flow id to given extracted flow id.
306      * @param extractedFlowId the extracted flow id, could be null if non was
307      * available in the external context
308      * @return the extracted flow id if not empty, the default flow id otherwise
309      * (which could still be null if not set)
310      * @see #getDefaultFlowId()
311      */

312     protected String JavaDoc applyDefaultFlowId(String JavaDoc extractedFlowId) {
313         return StringUtils.hasText(extractedFlowId) ? extractedFlowId : getDefaultFlowId();
314     }
315
316     /**
317      * URL-encode the given input object with the configured encoding scheme.
318      * @param value the unencoded value
319      * @return the encoded output String
320      * @see #getUrlEncodingScheme()
321      */

322     protected String JavaDoc encodeValue(Object JavaDoc value) {
323         return value != null ? urlEncode(value.toString()) : "";
324     }
325
326     /**
327      * Make given redirect URL context relative if necessary. If the URL starts
328      * with a slash ("/") it will be made relative to the current
329      * ServletContext, i.e. relative to the web application root.
330      * @param url the original URL
331      * @param context the external context
332      * @return the processed URL
333      * @see #isRedirectContextRelative()
334      */

335     protected String JavaDoc makeRedirectUrlContextRelativeIfNecessary(String JavaDoc url, ExternalContext context) {
336         StringBuffer JavaDoc res = new StringBuffer JavaDoc();
337         if (url.startsWith("/") && isRedirectContextRelative()) {
338             res.append(context.getContextPath());
339         }
340         res.append(url);
341         return res.toString();
342     }
343
344     // internal helpers
345

346     /**
347      * URL-encode the given input String with the configured encoding scheme.
348      * <p>
349      * Default implementation uses <code>URLEncoder.encode(input, enc)</code>
350      * on JDK 1.4+, falling back to <code>URLEncoder.encode(input)</code>
351      * (which uses the platform default encoding) on JDK 1.3.
352      * @param input the unencoded input String
353      * @return the encoded output String
354      */

355     private String JavaDoc urlEncode(String JavaDoc input) {
356         if (JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_14) {
357             return URLEncoder.encode(input);
358         }
359         try {
360             return URLEncoder.encode(input, getUrlEncodingScheme());
361         }
362         catch (UnsupportedEncodingException JavaDoc e) {
363             throw new IllegalArgumentException JavaDoc("Cannot encode URL " + input);
364         }
365     }
366 }
Popular Tags