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