1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.struts.chain.contexts;
19
20 import org.apache.commons.chain.Context;
21 import org.apache.commons.chain.impl.ContextBase;
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.apache.struts.action.Action;
25 import org.apache.struts.action.ActionForm;
26 import org.apache.struts.action.ActionMessages;
27 import org.apache.struts.chain.Constants;
28 import org.apache.struts.config.ActionConfig;
29 import org.apache.struts.config.FormBeanConfig;
30 import org.apache.struts.config.ForwardConfig;
31 import org.apache.struts.config.ModuleConfig;
32 import org.apache.struts.util.MessageResources;
33 import org.apache.struts.util.TokenProcessor;
34
35 import java.util.Locale;
36 import java.util.Map;
37
38 /***
39 * <p> Provide an abstract but semi-complete implementation of ActionContext
40 * to serve as the base for concrete implementations. </p> <p> The abstract
41 * methods to implement are the accessors for the named states,
42 * <code>getApplicationScope</code>, <code>getRequestScope</code>, and
43 * <code>getSessionScope</code>. </p>
44 */
45 public abstract class ActionContextBase extends ContextWrapper
46 implements ActionContext {
47 /***
48 * @see Constants.ACTION_KEY
49 */
50 public static final String ACTION_KEY = Constants.ACTION_KEY;
51
52 /***
53 * @see
54 */
55 public static final String ACTION_CONFIG_KEY = Constants.ACTION_CONFIG_KEY;
56
57 /***
58 * @see Constants.ACTION_FORM_KEY
59 */
60 public static final String ACTION_FORM_KEY = Constants.ACTION_FORM_KEY;
61
62 /***
63 * @see Constants.FORWARD_CONFIG_KEY
64 */
65 public static final String FORWARD_CONFIG_KEY =
66 Constants.FORWARD_CONFIG_KEY;
67
68 /***
69 * @see Constants.MODULE_CONFIG_KEY
70 */
71 public static final String MODULE_CONFIG_KEY = Constants.MODULE_CONFIG_KEY;
72
73 /***
74 * @see Constants.EXCEPTION_KEY
75 */
76 public static final String EXCEPTION_KEY = Constants.EXCEPTION_KEY;
77
78 /***
79 * <p> Provide the default context attribute under which to store the
80 * ActionMessage cache for errors. </p>
81 */
82 public static final String ERROR_ACTION_MESSAGES_KEY = "errors";
83
84 /***
85 * <p> Provide the default context attribute under which to store the
86 * ActionMessage cache. </p>
87 */
88 public static final String MESSAGE_ACTION_MESSAGES_KEY = "messages";
89
90 /***
91 * @see Constants.MESSAGE_RESOURCES_KEY
92 */
93 public static final String MESSAGE_RESOURCES_KEY =
94 Constants.MESSAGE_RESOURCES_KEY;
95
96 /***
97 * @see Constants.INCLUDE_KEY
98 */
99 public static final String INCLUDE_KEY = Constants.INCLUDE_KEY;
100
101 /***
102 * @see Constants.LOCALE_KEY
103 */
104 public static final String LOCALE_KEY = Constants.LOCALE_KEY;
105
106 /***
107 * @see Constants.CANCEL_KEY
108 */
109 public static final String CANCEL_KEY = Constants.CANCEL_KEY;
110
111 /***
112 * @see Constants.VALID_KEY
113 */
114 public static final String VALID_KEY = Constants.VALID_KEY;
115
116 /***
117 * Provide the default context attribute under which to store the
118 * transaction token key.
119 */
120 public static final String TRANSACTION_TOKEN_KEY = "TRANSACTION_TOKEN_KEY";
121
122 /***
123 * Provide the default context attribute under which to store the token
124 * key.
125 */
126 public static final String TOKEN_KEY = "TOKEN_KEY";
127
128 /***
129 * Store the TokenProcessor instance for this Context.
130 */
131 protected TokenProcessor token = null;
132
133 /***
134 * Store the Log instance for this Context.
135 */
136 private Log logger = null;
137
138 /***
139 * Instantiate ActionContextBase, wrapping the given Context.
140 *
141 * @param context Context to wrap
142 */
143 public ActionContextBase(Context context) {
144 super(context);
145 token = TokenProcessor.getInstance();
146 logger = LogFactory.getLog(this.getClass());
147 }
148
149 /***
150 * Instantiate ActionContextBase, wrapping a default ContextBase
151 * instance.
152 */
153 public ActionContextBase() {
154 this(new ContextBase());
155 }
156
157
158
159
160 public void release() {
161 this.token = null;
162 }
163
164 public abstract Map getApplicationScope();
165
166 public abstract Map getRequestScope();
167
168 public abstract Map getSessionScope();
169
170 public Map getScope(String scopeName) {
171 if (REQUEST_SCOPE.equals(scopeName)) {
172 return this.getRequestScope();
173 }
174
175 if (SESSION_SCOPE.equals(scopeName)) {
176 return this.getSessionScope();
177 }
178
179 if (APPLICATION_SCOPE.equals(scopeName)) {
180 return this.getApplicationScope();
181 }
182
183 throw new IllegalArgumentException("Invalid scope: " + scopeName);
184 }
185
186
187
188
189 public void setAction(Action action) {
190 this.put(ACTION_KEY, action);
191 }
192
193 public Action getAction() {
194 return (Action) this.get(ACTION_KEY);
195 }
196
197 public void setActionForm(ActionForm form) {
198 this.put(ACTION_FORM_KEY, form);
199 }
200
201 public ActionForm getActionForm() {
202 return (ActionForm) this.get(ACTION_FORM_KEY);
203 }
204
205 public void setActionConfig(ActionConfig config) {
206 this.put(ACTION_CONFIG_KEY, config);
207 }
208
209 public ActionConfig getActionConfig() {
210 return (ActionConfig) this.get(ACTION_CONFIG_KEY);
211 }
212
213 public void setForwardConfig(ForwardConfig forward) {
214 this.put(FORWARD_CONFIG_KEY, forward);
215 }
216
217 public ForwardConfig getForwardConfig() {
218 return (ForwardConfig) this.get(FORWARD_CONFIG_KEY);
219 }
220
221 public void setInclude(String include) {
222 this.put(INCLUDE_KEY, include);
223 }
224
225 public String getInclude() {
226 return (String) this.get(INCLUDE_KEY);
227 }
228
229 public Boolean getFormValid() {
230 return (Boolean) this.get(VALID_KEY);
231 }
232
233 public void setFormValid(Boolean valid) {
234 this.put(VALID_KEY, valid);
235 }
236
237 public ModuleConfig getModuleConfig() {
238 return (ModuleConfig) this.get(MODULE_CONFIG_KEY);
239 }
240
241 public void setModuleConfig(ModuleConfig config) {
242 this.put(MODULE_CONFIG_KEY, config);
243 }
244
245 public Exception getException() {
246 return (Exception) this.get(EXCEPTION_KEY);
247 }
248
249 public void setException(Exception e) {
250 this.put(EXCEPTION_KEY, e);
251 }
252
253
254
255
256 public void addMessages(ActionMessages messages) {
257 this.addActionMessages(MESSAGE_ACTION_MESSAGES_KEY, messages);
258 }
259
260 public void addErrors(ActionMessages errors) {
261 this.addActionMessages(ERROR_ACTION_MESSAGES_KEY, errors);
262 }
263
264 public ActionMessages getErrors() {
265 return (ActionMessages) this.get(ERROR_ACTION_MESSAGES_KEY);
266 }
267
268 public ActionMessages getMessages() {
269 return (ActionMessages) this.get(MESSAGE_ACTION_MESSAGES_KEY);
270 }
271
272 public void saveErrors(ActionMessages errors) {
273 this.saveActionMessages(ERROR_ACTION_MESSAGES_KEY, errors);
274 }
275
276 public void saveMessages(ActionMessages messages) {
277 this.saveActionMessages(MESSAGE_ACTION_MESSAGES_KEY, messages);
278 }
279
280
281
282 /***
283 * <p> Add the given messages to a cache stored in this Context, under
284 * key. </p>
285 *
286 * @param key The attribute name for the message cache
287 * @param messages The ActionMessages to add
288 */
289 public void addActionMessages(String key, ActionMessages messages) {
290 if (messages == null) {
291
292 return;
293 }
294
295
296 ActionMessages requestMessages = (ActionMessages) this.get(key);
297
298 if (requestMessages == null) {
299 requestMessages = new ActionMessages();
300 }
301
302
303 requestMessages.add(messages);
304
305
306 this.remove(key);
307
308
309 this.saveActionMessages(key, requestMessages);
310 }
311
312
313
314 /***
315 * <p> Save the given ActionMessages into the request scope under the
316 * given key, clearing the attribute if the messages are empty or null.
317 * </p>
318 *
319 * @param key The attribute name for the message cache
320 * @param messages The ActionMessages to add
321 */
322 public void saveActionMessages(String key, ActionMessages messages) {
323 this.saveActionMessages(REQUEST_SCOPE, key, messages);
324 }
325
326 /***
327 * <p>Save the given <code>messages</code> into the map identified by the
328 * given <code>scopeId</code> under the given <code>key</code>.</p>
329 *
330 * @param scopeId
331 * @param key
332 * @param messages
333 */
334 public void saveActionMessages(String scopeId, String key,
335 ActionMessages messages) {
336 Map scope = getScope(scopeId);
337
338 if ((messages == null) || messages.isEmpty()) {
339 scope.remove(key);
340
341 return;
342 }
343
344 scope.put(key, messages);
345 }
346
347
348
349
350 /***
351 * <p> Adapt a legacy form of SaveMessages to the ActionContext API by
352 * storing the ActoinMessages under the default scope.
353 *
354 * @param scope The scope for the internal cache
355 * @param messages ActionMesssages to cache
356 */
357 public void saveMessages(String scope, ActionMessages messages) {
358 this.saveMessages(messages);
359 }
360
361
362
363
364
365
366
367
368
369 public void saveToken() {
370 String token = this.generateToken();
371
372 this.put(TRANSACTION_TOKEN_KEY, token);
373 }
374
375 public String generateToken() {
376 return token.generateToken(getTokenGeneratorId());
377 }
378
379
380
381
382
383
384 protected String getTokenGeneratorId() {
385 return "";
386 }
387
388 public boolean isTokenValid() {
389 return this.isTokenValid(false);
390 }
391
392 public boolean isTokenValid(boolean reset) {
393
394
395 String saved = (String) this.get(TRANSACTION_TOKEN_KEY);
396
397 if (saved == null) {
398 return false;
399 }
400
401 if (reset) {
402 this.resetToken();
403 }
404
405
406 String token = (String) this.get(TOKEN_KEY);
407
408 if (token == null) {
409 return false;
410 }
411
412 return saved.equals(token);
413 }
414
415 public void resetToken() {
416 this.remove(TRANSACTION_TOKEN_KEY);
417 }
418
419
420
421
422 public Boolean getCancelled() {
423 return (Boolean) this.get(CANCEL_KEY);
424 }
425
426 public void setCancelled(Boolean cancelled) {
427 this.put(CANCEL_KEY, cancelled);
428 }
429
430
431
432
433 public void setMessageResources(MessageResources messageResources) {
434 this.put(MESSAGE_RESOURCES_KEY, messageResources);
435 }
436
437 public MessageResources getMessageResources() {
438 return (MessageResources) this.get(MESSAGE_RESOURCES_KEY);
439 }
440
441 public MessageResources getMessageResources(String key) {
442 return (MessageResources) this.get(key);
443 }
444
445
446
447
448 public void setLocale(Locale locale) {
449 this.put(LOCALE_KEY, locale);
450 }
451
452 public Locale getLocale() {
453 return (Locale) this.get(LOCALE_KEY);
454 }
455
456
457
458
459
460
461 /***
462 * <p> Provide the currently configured commons-logging <code>Log</code>
463 * instance. </p>
464 *
465 * @return Log instance for this context
466 */
467 public Log getLogger() {
468 return this.logger;
469 }
470
471 /***
472 * <p> Set the commons-logging <code>Log</code> instance which should be
473 * used to LOG messages. This is initialized at instantiation time but may
474 * be overridden. Be advised not to set the value to null, as
475 * <code>ActionContextBase</code> uses the logger for some of its own
476 * operations. </p>
477 */
478 public void setLogger(Log logger) {
479 this.logger = logger;
480 }
481
482 /***
483 * <p> Using this <code>ActionContext</code>'s default
484 * <code>ModuleConfig</code>, return an existing <code>ActionForm</code>
485 * in the specified scope, or create a new one and add it to the specified
486 * scope. </p>
487 *
488 * @param formName The name attribute of our ActionForm
489 * @param scopeName The scope identier (request, session)
490 * @return The ActionForm for this request
491 * @throws IllegalAccessException If object cannot be created
492 * @throws InstantiationException If object cannot be created
493 * @see this.findOrCreateActionForm(String, String, ModuleConfig)
494 */
495 public ActionForm findOrCreateActionForm(String formName, String scopeName)
496 throws IllegalAccessException, InstantiationException {
497 return this.findOrCreateActionForm(formName, scopeName,
498 this.getModuleConfig());
499 }
500
501 /***
502 * <p> In the context of the given <code>ModuleConfig</code> and this
503 * <code>ActionContext</code>, look for an existing
504 * <code>ActionForm</code> in the specified scope. If one is found, return
505 * it; otherwise, create a new instance, add it to that scope, and then
506 * return it. </p>
507 *
508 * @param formName The name attribute of our ActionForm
509 * @param scopeName The scope identier (request, session)
510 * @return The ActionForm for this request
511 * @throws IllegalAccessException If object cannot be created
512 * @throws InstantiationException If object cannot be created
513 * @throws IllegalArgumentException If form config is missing from module
514 * or scopeName is invalid
515 */
516 public ActionForm findOrCreateActionForm(String formName, String scopeName,
517 ModuleConfig moduleConfig)
518 throws IllegalAccessException, InstantiationException {
519 Map scope = this.getScope(scopeName);
520
521 ActionForm instance;
522 FormBeanConfig formBeanConfig =
523 moduleConfig.findFormBeanConfig(formName);
524
525 if (formBeanConfig == null) {
526 throw new IllegalArgumentException("No form config found under "
527 + formName + " in module " + moduleConfig.getPrefix());
528 }
529
530 instance = (ActionForm) scope.get(formName);
531
532
533 if (instance != null) {
534 getLogger().trace("Found an instance in scope " + scopeName
535 + "; test for reusability");
536
537 if (formBeanConfig.canReuse(instance)) {
538 return instance;
539 }
540 }
541
542 ActionForm form = formBeanConfig.createActionForm(this);
543
544
545 scope.put(formName, form);
546
547 return form;
548 }
549 }