1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.struts.chain.commands.generic;
19
20 import org.apache.commons.beanutils.ConstructorUtils;
21 import org.apache.commons.chain.Catalog;
22 import org.apache.commons.chain.CatalogFactory;
23 import org.apache.commons.chain.Command;
24 import org.apache.commons.chain.Context;
25 import org.apache.commons.chain.Filter;
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.struts.chain.commands.util.ClassUtils;
29
30 import java.lang.reflect.InvocationTargetException;
31
32 /***
33 * <p>Variant on chain LookupCommand which can optionally wrap the context it
34 * passes to the looked up command in an alternative class.</p>
35 */
36 public class WrappingLookupCommand implements Filter {
37 /***
38 * Provide Commons Logging instance for this class.
39 */
40 private static final Log LOG =
41 LogFactory.getLog(WrappingLookupCommand.class);
42
43
44
45 /***
46 * <p>Field for property.</p>
47 */
48 private String catalogName = null;
49
50 /***
51 * <p>Field for property.</p>
52 */
53 private String name = null;
54
55 /***
56 * <p>Field for property.</p>
57 */
58 private String nameKey = null;
59
60 /***
61 * <p>Field for property.</p>
62 */
63 private String wrapperClassName = null;
64
65 /***
66 * <p>Field for property.</p>
67 */
68 private boolean optional = false;
69
70 /***
71 * <p>Zero-argument constructor.</p>
72 */
73 public WrappingLookupCommand() {
74 catalogName = null;
75 name = null;
76 nameKey = null;
77 optional = false;
78 }
79
80 /***
81 * <p>Return CatalogName property. </p>
82 *
83 * @return Value of CatalogName property.
84 */
85 public String getCatalogName() {
86 return catalogName;
87 }
88
89 /***
90 * <p>Set CatalogName property.</p>
91 *
92 * @param catalogName New value for CatalogName
93 */
94 public void setCatalogName(String catalogName) {
95 this.catalogName = catalogName;
96 }
97
98 /***
99 * <p>Retrieve Name property.</p>
100 *
101 * @return Value of Name property
102 */
103 public String getName() {
104 return name;
105 }
106
107 /***
108 * <p>Set Name property.</p>
109 *
110 * @param name New value for Name
111 */
112 public void setName(String name) {
113 this.name = name;
114 }
115
116 /***
117 * <p>Return NameKey property.</p>
118 *
119 * @return Value of NameKey property.
120 */
121 public String getNameKey() {
122 return nameKey;
123 }
124
125 /***
126 * <p>Set NameKey property.</p>
127 *
128 * @param nameKey New value for NameKey
129 */
130 public void setNameKey(String nameKey) {
131 this.nameKey = nameKey;
132 }
133
134 /***
135 * <p>Test Optional property.</p>
136 *
137 * @return TRUE if Optional is TRUE.
138 */
139 public boolean isOptional() {
140 return optional;
141 }
142
143 /***
144 * <p>Set Optional property.</p>
145 *
146 * @param optional New value for Optional
147 */
148 public void setOptional(boolean optional) {
149 this.optional = optional;
150 }
151
152 /***
153 * <p>Return the WrapperClass property.</p>
154 *
155 * @return The WrapperClass property
156 */
157 public String getWrapperClassName() {
158 return wrapperClassName;
159 }
160
161 /***
162 * <p>Set WrappClassName property. </p>
163 *
164 * @param wrapperClassName The name of a WrapperClass
165 */
166 public void setWrapperClassName(String wrapperClassName) {
167 this.wrapperClassName = wrapperClassName;
168 }
169
170 /***
171 * <p>Invoke the Command for a Context, returning TRUE if processing
172 * should halt.</p>
173 *
174 * @param context Our ActionContext
175 * @return TRUE if processing should halt
176 * @throws Exception On any error
177 */
178 public boolean execute(Context context)
179 throws Exception {
180 if (LOG.isTraceEnabled()) {
181 LOG.trace("execute [" + this + "]");
182 }
183
184 Command command = getCommand(context);
185
186 if (command != null) {
187 return command.execute(getContext(context));
188 } else {
189 return false;
190 }
191 }
192
193 /***
194 * <p>Process the Exception for any Command that is a filter.</p>
195 *
196 * @param context Our ActionContext
197 * @param exception The Exception thrown by another Comamnd in a Chain
198 * @return TRUE if there is a Filter to process
199 */
200 public boolean postprocess(Context context, Exception exception) {
201 Command command = getCommand(context);
202
203 if ((command != null) && (command instanceof Filter)) {
204 try {
205 return ((Filter) command).postprocess(getContext(context),
206 exception);
207 } catch (NoSuchMethodException ex) {
208 LOG.error("Error wrapping context in postprocess", ex);
209 } catch (IllegalAccessException ex) {
210 LOG.error("Error wrapping context in postprocess", ex);
211 } catch (InvocationTargetException ex) {
212 LOG.error("Error wrapping context in postprocess", ex);
213 } catch (InstantiationException ex) {
214 LOG.error("Error wrapping context in postprocess", ex);
215 } catch (ClassNotFoundException ex) {
216 LOG.error("Error wrapping context in postprocess", ex);
217 }
218 }
219
220 return false;
221 }
222
223 /***
224 * <p>Return the Command to process for this Context.</p>
225 *
226 * @param context The Context we are processing
227 * @return The Command to process for this Context
228 */
229 protected Command getCommand(Context context) {
230 CatalogFactory catalogFactory = CatalogFactory.getInstance();
231 String catalogName = getCatalogName();
232 Catalog catalog;
233
234 if (catalogName == null) {
235 catalog = catalogFactory.getCatalog();
236 catalogName = "{default}";
237 } else {
238 catalog = catalogFactory.getCatalog(catalogName);
239 }
240
241 if (catalog == null) {
242 throw new IllegalArgumentException("Cannot find catalog '"
243 + catalogName + "'");
244 }
245
246 Command command;
247 String name = getName();
248
249 if (name == null) {
250 name = (String) context.get(getNameKey());
251 }
252
253 if (name != null) {
254 if (LOG.isDebugEnabled()) {
255 LOG.debug("Lookup command " + name + " in catalog "
256 + catalogName);
257 }
258
259 command = catalog.getCommand(name);
260
261 if (LOG.isDebugEnabled()) {
262 LOG.debug("Found command " + command + ";" + " optional: "
263 + isOptional());
264 }
265
266 if ((command == null) && !isOptional()) {
267 throw new IllegalArgumentException("Cannot find command " + "'"
268 + name + "' in catalog '" + catalogName + "'");
269 } else {
270 return command;
271 }
272 } else {
273 throw new IllegalArgumentException("No command name");
274 }
275 }
276
277 /***
278 * <p>If the wrapperClassName property is not null, return a Context of
279 * the type specified by wrapperClassName, instantiated using a single-arg
280 * constructor which takes the context passed as an argument to this
281 * method.</p>
282 *
283 * <p>This method throws an exception if the wrapperClass cannot be found,
284 * or if there are any errors instantiating the wrapping context.</p>
285 *
286 * @param context Context we are processing
287 * @return Context wrapper
288 * @throws ClassNotFoundException On failed instantiation
289 * @throws InstantiationException On failed instantiation
290 * @throws InvocationTargetException On failed instantiation
291 * @throws IllegalAccessException On failed instantiation
292 * @throws NoSuchMethodException On failed instantiation
293 */
294 protected Context getContext(Context context)
295 throws ClassNotFoundException, InstantiationException,
296 InvocationTargetException, IllegalAccessException,
297 NoSuchMethodException {
298 if (wrapperClassName == null) {
299 if (LOG.isDebugEnabled()) {
300 LOG.debug("No defined wrapper class; "
301 + "returning original context.");
302 }
303
304 return context;
305 }
306
307 if (LOG.isDebugEnabled()) {
308 LOG.debug("Looking for wrapper class: " + wrapperClassName);
309 }
310
311 Class wrapperClass = ClassUtils.getApplicationClass(wrapperClassName);
312
313 if (LOG.isDebugEnabled()) {
314 LOG.debug("Instantiating wrapper class");
315 }
316
317 return (Context) ConstructorUtils.invokeConstructor(wrapperClass,
318 new Object[] { context });
319 }
320 }