1 /*
2 * Copyright (c) 2002-2006 by OpenSymphony
3 * All rights reserved.
4 */
5 package com.opensymphony.xwork2.interceptor;
6
7 import com.opensymphony.xwork2.ActionContext;
8 import com.opensymphony.xwork2.ActionInvocation;
9 import com.opensymphony.xwork2.ObjectFactory;
10 import com.opensymphony.xwork2.XWorkException;
11 import com.opensymphony.xwork2.config.entities.ActionConfig;
12 import com.opensymphony.xwork2.inject.Inject;
13
14 import java.lang.reflect.Method;
15 import java.util.Map;
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<String, Object> 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 @Override
100 public String intercept(ActionInvocation invocation) throws Exception {
101 Object action = invocation.getAction();
102
103 if (action instanceof ScopedModelDriven) {
104 ScopedModelDriven modelDriven = (ScopedModelDriven) action;
105 if (modelDriven.getModel() == null) {
106 ActionContext ctx = ActionContext.getContext();
107 ActionConfig config = invocation.getProxy().getConfig();
108
109 String cName = className;
110 if (cName == null) {
111 try {
112 Method method = action.getClass().getMethod(GET_MODEL, new Class[0]);
113 Class cls = method.getReturnType();
114 cName = cls.getName();
115 } catch (NoSuchMethodException e) {
116 throw new XWorkException("The " + GET_MODEL + "() is not defined in action " + action.getClass() + "", config);
117 }
118 }
119 String modelName = name;
120 if (modelName == null) {
121 modelName = cName;
122 }
123 Object model = resolveModel(objectFactory, ctx, cName, scope, modelName);
124 modelDriven.setModel(model);
125 modelDriven.setScopeKey(modelName);
126 }
127 }
128 return invocation.invoke();
129 }
130
131 /**
132 * @param className the className to set
133 */
134 public void setClassName(String className) {
135 this.className = className;
136 }
137
138 /**
139 * @param name the name to set
140 */
141 public void setName(String name) {
142 this.name = name;
143 }
144
145 /**
146 * @param scope the scope to set
147 */
148 public void setScope(String scope) {
149 this.scope = scope;
150 }
151 }