1 /*
2 * Copyright (c) 2002-2006 by OpenSymphony
3 * All rights reserved.
4 */
5 package com.opensymphony.xwork2.interceptor;
6
7 import java.lang.reflect.Method;
8 import java.util.Map;
9
10 import com.opensymphony.xwork2.ActionContext;
11 import com.opensymphony.xwork2.ActionInvocation;
12 import com.opensymphony.xwork2.ObjectFactory;
13 import com.opensymphony.xwork2.XWorkException;
14 import com.opensymphony.xwork2.config.entities.ActionConfig;
15 import com.opensymphony.xwork2.inject.Inject;
16
17 /**
18 * <!-- START SNIPPET: description -->
19 *
20 * An interceptor that enables scoped model-driven actions.
21 *
22 * <p/>This interceptor only activates on actions that implement the {@link ScopedModelDriven} interface. If
23 * detected, it will retrieve the model class from the configured scope, then provide it to the Action.
24 *
25 * <!-- END SNIPPET: description -->
26 *
27 * <p/> <u>Interceptor parameters:</u>
28 *
29 * <!-- START SNIPPET: parameters -->
30 *
31 * <ul>
32 *
33 * <li>className - The model class name. Defaults to the class name of the object returned by the getModel() method.</li>
34 *
35 * <li>name - The key to use when storing or retrieving the instance in a scope. Defaults to the model
36 * class name.</li>
37 *
38 * <li>scope - The scope to store and retrieve the model. Defaults to 'request' but can also be 'session'.</li>
39 * </ul>
40 *
41 * <!-- END SNIPPET: parameters -->
42 *
43 * <p/> <u>Extending the interceptor:</u>
44 *
45 * <p/>
46 *
47 * <!-- START SNIPPET: extending -->
48 *
49 * There are no known extension points for this interceptor.
50 *
51 * <!-- END SNIPPET: extending -->
52 *
53 * <p/> <u>Example code:</u>
54 *
55 * <pre>
56 * <!-- START SNIPPET: example -->
57 *
58 * <-- Basic usage -->
59 * <interceptor name="scopedModelDriven" class="com.opensymphony.interceptor.ScopedModelDrivenInterceptor" />
60 *
61 * <-- Using all available parameters -->
62 * <interceptor name="gangsterForm" class="com.opensymphony.interceptor.ScopedModelDrivenInterceptor">
63 * <param name="scope">session</param>
64 * <param name="name">gangsterForm</param>
65 * <param name="className">com.opensymphony.example.GangsterForm</param>
66 * </interceptor>
67 *
68 * <!-- END SNIPPET: example -->
69 * </pre>
70 */
71 public class ScopedModelDrivenInterceptor extends AbstractInterceptor {
72
73 private static final String GET_MODEL = "getModel";
74 private String scope;
75 private String name;
76 private String className;
77 private ObjectFactory objectFactory;
78
79 @Inject
80 public void setObjectFactory(ObjectFactory factory) {
81 this.objectFactory = factory;
82 }
83
84 protected Object resolveModel(ObjectFactory factory, ActionContext actionContext, String modelClassName, String modelScope, String modelName) throws Exception {
85 Object model = null;
86 Map scopeMap = actionContext.getContextMap();
87 if ("session".equals(modelScope)) {
88 scopeMap = actionContext.getSession();
89 }
90
91 model = scopeMap.get(modelName);
92 if (model == null) {
93 model = factory.buildBean(modelClassName, null);
94 scopeMap.put(modelName, model);
95 }
96 return model;
97 }
98
99 public String intercept(ActionInvocation invocation) throws Exception {
100 Object action = invocation.getAction();
101
102 if (action instanceof ScopedModelDriven) {
103 ScopedModelDriven modelDriven = (ScopedModelDriven) action;
104 if (modelDriven.getModel() == null) {
105 ActionContext ctx = ActionContext.getContext();
106 ActionConfig config = invocation.getProxy().getConfig();
107
108 String cName = className;
109 if (cName == null) {
110 try {
111 Method method = action.getClass().getMethod(GET_MODEL, new Class[0]);
112 Class cls = method.getReturnType();
113 cName = cls.getName();
114 } catch (NoSuchMethodException e) {
115 throw new XWorkException("The " + GET_MODEL + "() is not defined in action " + action.getClass() + "", config);
116 }
117 }
118 String modelName = name;
119 if (modelName == null) {
120 modelName = cName;
121 }
122 Object model = resolveModel(objectFactory, ctx, cName, scope, modelName);
123 modelDriven.setModel(model);
124 modelDriven.setScopeKey(modelName);
125 }
126 }
127 return invocation.invoke();
128 }
129
130 /**
131 * @param className the className to set
132 */
133 public void setClassName(String className) {
134 this.className = className;
135 }
136
137 /**
138 * @param name the name to set
139 */
140 public void setName(String name) {
141 this.name = name;
142 }
143
144 /**
145 * @param scope the scope to set
146 */
147 public void setScope(String scope) {
148 this.scope = scope;
149 }
150 }