View Javadoc

1   /*
2    * $Id: WrappingLookupCommand.java 421119 2006-07-12 04:49:11Z wsmoak $
3    *
4    * Copyright 2005 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
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      // ------------------------------------------------------ Instance Variables
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}"; // for debugging purposes
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 }