/* * $Id: WrappingLookupCommand.java 471754 2006-11-06 14:55:09Z husted $ * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.struts.chain.commands.generic; import org.apache.commons.beanutils.ConstructorUtils; import org.apache.commons.chain.Catalog; import org.apache.commons.chain.CatalogFactory; import org.apache.commons.chain.Command; import org.apache.commons.chain.Context; import org.apache.commons.chain.Filter; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.struts.chain.commands.util.ClassUtils; import java.lang.reflect.InvocationTargetException; /** * <p>Variant on chain LookupCommand which can optionally wrap the context it * passes to the looked up command in an alternative class.</p> */ public class WrappingLookupCommand implements Filter { /** * Provide Commons Logging instance for this class. */ private static final Log LOG = LogFactory.getLog(WrappingLookupCommand.class); // ------------------------------------------------------ Instance Variables /** * <p>Field for property.</p> */ private String catalogName = null; /** * <p>Field for property.</p> */ private String name = null; /** * <p>Field for property.</p> */ private String nameKey = null; /** * <p>Field for property.</p> */ private String wrapperClassName = null; /** * <p>Field for property.</p> */ private boolean optional = false; /** * <p>Zero-argument constructor.</p> */ public WrappingLookupCommand() { catalogName = null; name = null; nameKey = null; optional = false; } /** * <p>Return CatalogName property. </p> * * @return Value of CatalogName property. */ public String getCatalogName() { return catalogName; } /** * <p>Set CatalogName property.</p> * * @param catalogName New value for CatalogName */ public void setCatalogName(String catalogName) { this.catalogName = catalogName; } /** * <p>Retrieve Name property.</p> * * @return Value of Name property */ public String getName() { return name; } /** * <p>Set Name property.</p> * * @param name New value for Name */ public void setName(String name) { this.name = name; } /** * <p>Return NameKey property.</p> * * @return Value of NameKey property. */ public String getNameKey() { return nameKey; } /** * <p>Set NameKey property.</p> * * @param nameKey New value for NameKey */ public void setNameKey(String nameKey) { this.nameKey = nameKey; } /** * <p>Test Optional property.</p> * * @return TRUE if Optional is TRUE. */ public boolean isOptional() { return optional; } /** * <p>Set Optional property.</p> * * @param optional New value for Optional */ public void setOptional(boolean optional) { this.optional = optional; } /** * <p>Return the WrapperClass property.</p> * * @return The WrapperClass property */ public String getWrapperClassName() { return wrapperClassName; } /** * <p>Set WrappClassName property. </p> * * @param wrapperClassName The name of a WrapperClass */ public void setWrapperClassName(String wrapperClassName) { this.wrapperClassName = wrapperClassName; } /** * <p>Invoke the Command for a Context, returning TRUE if processing * should halt.</p> * * @param context Our ActionContext * @return TRUE if processing should halt * @throws Exception On any error */ public boolean execute(Context context) throws Exception { if (LOG.isTraceEnabled()) { LOG.trace("execute [" + this + "]"); } Command command = getCommand(context); if (command != null) { return command.execute(getContext(context)); } else { return false; } } /** * <p>Process the Exception for any Command that is a filter.</p> * * @param context Our ActionContext * @param exception The Exception thrown by another Comamnd in a Chain * @return TRUE if there is a Filter to process */ public boolean postprocess(Context context, Exception exception) { Command command = getCommand(context); if ((command != null) && (command instanceof Filter)) { try { return ((Filter) command).postprocess(getContext(context), exception); } catch (NoSuchMethodException ex) { LOG.error("Error wrapping context in postprocess", ex); } catch (IllegalAccessException ex) { LOG.error("Error wrapping context in postprocess", ex); } catch (InvocationTargetException ex) { LOG.error("Error wrapping context in postprocess", ex); } catch (InstantiationException ex) { LOG.error("Error wrapping context in postprocess", ex); } catch (ClassNotFoundException ex) { LOG.error("Error wrapping context in postprocess", ex); } } return false; } /** * <p>Return the Command to process for this Context.</p> * * @param context The Context we are processing * @return The Command to process for this Context */ protected Command getCommand(Context context) { CatalogFactory catalogFactory = CatalogFactory.getInstance(); String catalogName = getCatalogName(); Catalog catalog; if (catalogName == null) { catalog = catalogFactory.getCatalog(); catalogName = "{default}"; // for debugging purposes } else { catalog = catalogFactory.getCatalog(catalogName); } if (catalog == null) { throw new IllegalArgumentException("Cannot find catalog '" + catalogName + "'"); } Command command; String name = getName(); if (name == null) { name = (String) context.get(getNameKey()); } if (name != null) { if (LOG.isDebugEnabled()) { LOG.debug("Lookup command " + name + " in catalog " + catalogName); } command = catalog.getCommand(name); if (LOG.isDebugEnabled()) { LOG.debug("Found command " + command + ";" + " optional: " + isOptional()); } if ((command == null) && !isOptional()) { throw new IllegalArgumentException("Cannot find command " + "'" + name + "' in catalog '" + catalogName + "'"); } else { return command; } } else { throw new IllegalArgumentException("No command name"); } } /** * <p>If the wrapperClassName property is not null, return a Context of * the type specified by wrapperClassName, instantiated using a single-arg * constructor which takes the context passed as an argument to this * method.</p> * * <p>This method throws an exception if the wrapperClass cannot be found, * or if there are any errors instantiating the wrapping context.</p> * * @param context Context we are processing * @return Context wrapper * @throws ClassNotFoundException On failed instantiation * @throws InstantiationException On failed instantiation * @throws InvocationTargetException On failed instantiation * @throws IllegalAccessException On failed instantiation * @throws NoSuchMethodException On failed instantiation */ protected Context getContext(Context context) throws ClassNotFoundException, InstantiationException, InvocationTargetException, IllegalAccessException, NoSuchMethodException { if (wrapperClassName == null) { if (LOG.isDebugEnabled()) { LOG.debug("No defined wrapper class; " + "returning original context."); } return context; } if (LOG.isDebugEnabled()) { LOG.debug("Looking for wrapper class: " + wrapperClassName); } Class wrapperClass = ClassUtils.getApplicationClass(wrapperClassName); if (LOG.isDebugEnabled()) { LOG.debug("Instantiating wrapper class"); } return (Context) ConstructorUtils.invokeConstructor(wrapperClass, new Object[] { context }); } }