org.apache.struts.config.ActionConfig Maven / Gradle / Ivy
/*
* $Id$
*
* 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.config;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.struts.util.RequestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A JavaBean representing the configuration information of an
* <action>
element from a Struts module configuration
* file.
*
* @version $Rev$ $Date$
* @since Struts 1.1
*/
public class ActionConfig extends BaseConfig {
private static final long serialVersionUID = -7821814205678644815L;
/**
* The {@code Log} instance for this class.
*/
private transient final Logger log =
LoggerFactory.getLogger(ActionConfig.class);
// ----------------------------------------------------- Instance Variables
/**
* The set of exception handling configurations for this action, if
* any, keyed by the type
property.
*/
protected HashMap exceptions = new HashMap<>();
/**
* The set of local forward configurations for this action, if any,
* keyed by the name
property.
*/
protected HashMap forwards = new HashMap<>();
// ------------------------------------------------------------- Properties
/**
* The module configuration with which we are associated.
*/
protected ModuleConfig moduleConfig = null;
/**
* The request-scope or session-scope attribute name under which our
* form bean is accessed, if it is different from the form bean's
* specified name
.
*/
protected String attribute = null;
/**
* The internal identification of this action mapping. Identifications are
* not inheritable and must be unique within a module.
*
* @since Struts 1.3.6
*/
protected String actionId = null;
/**
* The path of the ActionConfig that this object should inherit
* properties from.
*/
protected String inherit = null;
/**
* Indicates whether the "cancellable " property has been set or not.
*/
private boolean cancellableSet = false;
/**
* Can this Action be cancelled? [false]
By default, when an
* Action is cancelled, validation is bypassed and the Action should not
* execute the business operation. If a request tries to cancel an Action
* when cancellable is not set, a "InvalidCancelException" is thrown.
*
*/
protected boolean cancellable = false;
/**
* Have the inheritance values for this class been applied?
*/
protected boolean extensionProcessed = false;
/**
* Context-relative path of the web application resource that will
* process this request via RequestDispatcher.forward(), instead of
* instantiating and calling the Action
class specified by
* "type". Exactly one of forward
, include
, or
* type
must be specified.
*/
protected String forward = null;
/**
* Context-relative path of the web application resource that will
* process this request via RequestDispatcher.include(), instead of
* instantiating and calling the Action
class specified by
* "type". Exactly one of forward
, include
, or
* type
must be specified.
*/
protected String include = null;
/**
* Context-relative path of the input form to which control should be
* returned if a validation error is encountered. Required if "name" is
* specified and the input bean returns validation errors.
*/
protected String input = null;
/**
* Fully qualified Java class name of the MultipartRequestHandler
* implementation class used to process multi-part request data for this
* Action.
*/
protected String multipartClass = null;
/**
* Name of the form bean, if any, associated with this Action.
*/
protected String name = null;
/**
* General purpose configuration parameter that can be used to pass
* extra information to the Action instance selected by this Action.
* Struts does not itself use this value in any way.
*/
protected String parameter = null;
/**
* Context-relative path of the submitted request, starting with a
* slash ("/") character, and omitting any filename extension if extension
* mapping is being used.
*/
protected String path = null;
/**
* Prefix used to match request parameter names to form bean property
* names, if any.
*/
protected String prefix = null;
/**
* Comma-delimited list of security role names allowed to request this
* Action.
*/
protected String roles = null;
/**
* The set of security role names used to authorize access to this
* Action, as an array for faster access.
*/
protected String[] roleNames = new String[0];
/**
* Identifier of the scope ("request" or "session") within which our
* form bean is accessed, if any.
*/
protected String scope = "session";
/**
* Should this action be instantiated once per module (singleton)
* or once per request (prototype)?
*/
private boolean singleton = true;
/**
* Identifies conditions for automatic form reset.
*/
protected String reset = PopulateEvent.ALL;
private String[] resetNames = { PopulateEvent.ALL };
/**
* Identifies conditions for automatic form population with values
* from HTTP request.
*/
protected String populate = PopulateEvent.ALL;
private String[] populateNames = { PopulateEvent.ALL };
/**
* Suffix used to match request parameter names to form bean property
* names, if any.
*/
protected String suffix = null;
/**
* Fully qualified Java class name of the Action
class to
* be used to process requests for this mapping if the
* forward
and include
properties are not set.
* Exactly one of forward
, include
, or
* type
must be specified.
*/
protected String type = null;
/**
*
Indicates Action be configured as the default one for this module,
* when true.
*/
protected boolean unknown = false;
/**
* Indicates whether the "validate" property has been set or not.
*/
private boolean validateSet = false;
/**
*
Should the validate()
method of the form bean
* associated with this action be called?
*/
protected boolean validate = true;
/**
*
The name of a commons-chain
command which should be
* executed as part of the processing of this action.
*
* @since Struts 1.3.0
*/
protected String command = null;
/**
*
The name of a commons-chain
catalog in which
* command
should be sought. If a command
is
* defined and this property is undefined, the "default" catalog will be
* used. This is likely to be infrequently used after a future release of
* commons-chain
supports a one-string expression of a
* catalog/chain combination.
*
* @since Struts 1.3.0
*/
protected String catalog = null;
/**
* The name of the {@link org.apache.struts.dispatcher.Dispatcher} implementation
* that will dispatch to the end point of this action.
*
* @since Struts 1.4
*/
protected String dispatcher;
// 2014/07/02 - security problem patch.
// Author: NTT DATA Corporation
/**
* Accepted page value for multi-page validation.
* If two or more page values are accepted, then acceptPage is set minimum of them.
* If multi-page validation is not use, acceptPage is not set. Then multi-page validation is disabled.
* @since Struts 1.4.1
*/
protected Integer acceptPage = null;
/**
*
The internal name of this action mapping. If an action has a name, it may be used
* as a shortcut in a URI. For example, an action with an identification of "editPerson"
* may be internally forwarded as "editPerson?id=1" which will then resolve to the
* real URI path at execution time.
*
* @return the actionId
* @since Struts 1.3.6
*/
public String getActionId() {
return this.actionId;
}
/**
* The internal name of this action mapping. The name is not inheritable,
* may not contain a forward slash, and must be unique within a module.
*
* @param actionId the action identifier
* @since Struts 1.3.6
* @throws IllegalStateException if the configuration is frozen
* @throws IllegalArgumentException if the identifier contains a forward slash
*/
public void setActionId(String actionId) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
if ((actionId != null) && (actionId.indexOf("/") > -1)) {
throw new IllegalArgumentException("actionId '" + actionId + "' may not contain a forward slash");
}
this.actionId = actionId;
}
/**
* The module configuration with which we are associated.
*/
public ModuleConfig getModuleConfig() {
return (this.moduleConfig);
}
/**
*
The module configuration with which we are associated.
*/
public void setModuleConfig(ModuleConfig moduleConfig) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
this.moduleConfig = moduleConfig;
}
/**
*
Returns the request-scope or session-scope attribute name under
* which our form bean is accessed, if it is different from the form
* bean's specified name
.
*
* @return attribute name under which our form bean is accessed.
*/
public String getAttribute() {
if (this.attribute == null) {
return (this.name);
} else {
return (this.attribute);
}
}
/**
*
Set the request-scope or session-scope attribute name under which
* our form bean is accessed, if it is different from the form bean's
* specified name
.
*
* @param attribute the request-scope or session-scope attribute name
* under which our form bean is access.
*/
public void setAttribute(String attribute) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
this.attribute = attribute;
}
/**
*
Accessor for cancellable property
*
* @return True if Action can be cancelled
*/
public boolean getCancellable() {
return (this.cancellable);
}
/**
* Mutator for for cancellable property
*
* @param cancellable
*/
public void setCancellable(boolean cancellable) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
this.cancellable = cancellable;
this.cancellableSet = true;
}
/**
* Returns the path
or actionId
of the
* ActionConfig
that this object should inherit properties
* from.
*
* @return the path or action id of the action mapping that this object
* should inherit properties from.
*/
public String getExtends() {
return (this.inherit);
}
/**
* Set the path
or actionId
of the
* ActionConfig
that this object should inherit properties
* from.
*
* @param inherit the path or action id of the action mapping that this
* object should inherit properties from.
*/
public void setExtends(String inherit) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
this.inherit = inherit;
}
public boolean isExtensionProcessed() {
return extensionProcessed;
}
/**
* Returns context-relative path of the web application resource that
* will process this request.
*
* @return context-relative path of the web application resource that will
* process this request.
*/
public String getForward() {
return (this.forward);
}
/**
*
Set the context-relative path of the web application resource that
* will process this request. Exactly one of forward
,
* include
, or type
must be specified.
*
* @param forward context-relative path of the web application resource
* that will process this request.
*/
public void setForward(String forward) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
this.forward = forward;
}
/**
*
Context-relative path of the web application resource that will
* process this request.
*
* @return Context-relative path of the web application resource that will
* process this request.
*/
public String getInclude() {
return (this.include);
}
/**
*
Set context-relative path of the web application resource that will
* process this request. Exactly one of forward
,
* include
, or type
must be specified.
*
* @param include context-relative path of the web application resource
* that will process this request.
*/
public void setInclude(String include) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
this.include = include;
}
/**
*
Get the context-relative path of the input form to which control
* should be returned if a validation error is encountered.
*
* @return context-relative path of the input form to which control should
* be returned if a validation error is encountered.
*/
public String getInput() {
return (this.input);
}
/**
*
Set the context-relative path of the input form to which control
* should be returned if a validation error is encountered. Required if
* "name" is specified and the input bean returns validation errors.
*
* @param input context-relative path of the input form to which control
* should be returned if a validation error is encountered.
*/
public void setInput(String input) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
this.input = input;
}
/**
*
Return the fully qualified Java class name of the
* MultipartRequestHandler
implementation class used to
* process multi-part request data for this Action.
*/
public String getMultipartClass() {
return (this.multipartClass);
}
/**
*
Set the fully qualified Java class name of the
* MultipartRequestHandler
implementation class used to
* process multi-part request data for this Action.
*
* @param multipartClass fully qualified class name of the
* MultipartRequestHandler
* implementation class.
*/
public void setMultipartClass(String multipartClass) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
this.multipartClass = multipartClass;
}
/**
*
Return name of the form bean, if any, associated with this Action.
*/
public String getName() {
return (this.name);
}
/**
* @param name name of the form bean associated with this Action.
*/
public void setName(String name) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
this.name = name;
}
/**
*
Return general purpose configuration parameter that can be used to
* pass extra information to the Action instance selected by this Action.
* Struts does not itself use this value in any way.
*/
public String getParameter() {
return (this.parameter);
}
/**
*
General purpose configuration parameter that can be used to pass
* extra information to the Action instance selected by this Action.
* Struts does not itself use this value in any way.
*
* @param parameter General purpose configuration parameter.
*/
public void setParameter(String parameter) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
this.parameter = parameter;
}
/**
*
Return context-relative path of the submitted request, starting
* with a slash ("/") character, and omitting any filename extension if
* extension mapping is being used.
*/
public String getPath() {
return (this.path);
}
/**
*
Set context-relative path of the submitted request, starting with a
* slash ("/") character, and omitting any filename extension if extension
* mapping is being used.
*
* @param path context-relative path of the submitted request.
*/
public void setPath(String path) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
this.path = path;
}
/**
*
Retruns prefix used to match request parameter names to form bean
* property names, if any.
*/
public String getPrefix() {
return (this.prefix);
}
/**
* @param prefix Prefix used to match request parameter names to form bean
* property names, if any.
*/
public void setPrefix(String prefix) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
this.prefix = prefix;
}
public String getRoles() {
return (this.roles);
}
public void setRoles(String roles) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
this.roles = roles;
if (roles == null) {
roleNames = new String[0];
return;
}
ArrayList list = new ArrayList<>();
while (true) {
int comma = roles.indexOf(',');
if (comma < 0) {
break;
}
list.add(roles.substring(0, comma).trim());
roles = roles.substring(comma + 1);
}
roles = roles.trim();
if (roles.length() > 0) {
list.add(roles);
}
roleNames = list.toArray(new String[list.size()]);
}
/**
* Get array of security role names used to authorize access to this
* Action.
*/
public String[] getRoleNames() {
return (this.roleNames);
}
/**
*
Get the scope ("request" or "session") within which our form bean
* is accessed, if any.
*/
public String getScope() {
return (this.scope);
}
/**
* @param scope scope ("request" or "session") within which our form bean
* is accessed, if any.
*/
public void setScope(String scope) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
this.scope = scope;
}
/**
*
Gets the comma-delimiated list of events that specify when this
* action should be reset.
*
* @since Struts 1.4
* @see #getResetNames()
* @see #setReset(String)
*/
public final String getReset() {
return (this.reset);
}
/**
* Gets the array of events names that specify when this
* action should be reset.
*
* @since Struts 1.4
* @see #getReset()
* @see PopulateEvent
*/
public final String[] getResetNames() {
return (this.resetNames);
}
/**
* @param reset the comma-delimited list of reset events
*
* @since Struts 1.4
* @see #getReset()
* @see #getResetNames()
*/
public final void setReset(String reset) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
this.reset = reset;
this.resetNames = reset.split(",");
}
/**
* Gets the comma-delimiated list of events that specify when this
* action should be populated.
*
* @since Struts 1.4
* @see #getPopulateNames()
* @see #setPopulate(String)
*/
public final String getPopulate() {
return (this.populate);
}
/**
* Gets the array of events names that specify when this
* action should be populated.
*
* @since Struts 1.4
* @see #getPopulate()
* @see PopulateEvent
*/
public final String[] getPopulateNames() {
return (this.populateNames);
}
/**
* @param populate the comma-delimited list of populate events
*
* @since Struts 1.4
* @see #getPopulate()
* @see #getPopulateNames()
*/
public final void setPopulate(String populate) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
this.populate = populate;
this.populateNames = populate.split(",");
}
/**
* Determines whether this action is a singleton (one per module)
* or a prototype (one per request). Actions are defaulted to
* singletons unless otherwise specified.
*
* @return true
for singleton; otherwise prototype
* @see #setSingleton(boolean)
* @since Struts 1.4
*/
public final boolean isSingleton() {
return this.singleton;
}
/**
* Stores whether this action is a singleton.
*
* @param singleton true
for singleton; otherwise prototype
* @see #isSingleton()
* @since Struts 1.4
*/
public final void setSingleton(boolean singleton) {
this.singleton = singleton;
}
/**
* Return suffix used to match request parameter names to form bean
* property names, if any.
*/
public String getSuffix() {
return (this.suffix);
}
/**
* @param suffix Suffix used to match request parameter names to form bean
* property names, if any.
*/
public void setSuffix(String suffix) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
this.suffix = suffix;
}
public String getType() {
return (this.type);
}
public void setType(String type) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
this.type = type;
}
/**
* Determine whether Action is configured as the default one for this
* module.
*/
public boolean getUnknown() {
return (this.unknown);
}
/**
* @param unknown Indicates Action is configured as the default one for
* this module, when true.
*/
public void setUnknown(boolean unknown) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
this.unknown = unknown;
}
public boolean getValidate() {
return (this.validate);
}
public void setValidate(boolean validate) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
this.validate = validate;
this.validateSet = true;
}
/**
* Get the name of a commons-chain
command which should
* be executed as part of the processing of this action.
*
* @return name of a commons-chain
command which should be
* executed as part of the processing of this action.
* @since Struts 1.3.0
*/
public String getCommand() {
return (this.command);
}
/**
* Get the name of a commons-chain
catalog in which a
* specified command should be sought. This is likely to be infrequently
* used after a future release of commons-chain
supports a
* one-string expression of a catalog/chain combination.
*
* @return name of a commons-chain
catalog in which a
* specified command should be sought.
* @since Struts 1.3.0
*/
public String getCatalog() {
return (this.catalog);
}
/**
* Set the name of a commons-chain
command which should
* be executed as part of the processing of this action.
*
* @param command name of a commons-chain
command which
* should be executed as part of the processing of this
* action.
* @since Struts 1.3.0
*/
public void setCommand(String command) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
this.command = command;
}
/**
* Set the name of a commons-chain
catalog in which a
* specified command should be sought. This is likely to be infrequently
* used after a future release of commons-chain
supports a
* one-string expression of a catalog/chain combination.
*
* @param catalog name of a commons-chain
catalog in which a
* specified command should be sought.
* @since Struts 1.3.0
*/
public void setCatalog(String catalog) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
this.catalog = catalog;
}
/**
* Retrieves the fully-qualified class name of the
* {@link org.apache.struts.dispatcher.Dispatcher} implementation that will
* dispatch to the this action.
*
* @return the dispatcher class name or null
* @see #setDispatcher(String)
* @since Struts 1.4
*/
public final String getDispatcher() {
return dispatcher;
}
/**
* Stores the fully-qualified class name of the
* {@link org.apache.struts.dispatcher.Dispatcher} implementation that will
* dispatch to the this action.
*
* @param dispatcher the dispatcher class name
* @throws IllegalStateException if the configuration is frozen
* @see #getDispatcher()
* @since Struts 1.4
*/
public final void setDispatcher(String dispatcher) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
this.dispatcher = dispatcher;
}
// 2014/07/02 - security problem patch.
// Author: NTT DATA Corporation
/**
* Returns accepted page value for multi-page validation.
*
* @return Accepted page value for multi-page validation
* @since Struts 1.4.1
*/
public Integer getAcceptPage() {
return acceptPage;
}
/**
* Set accepted page value for multi-page validation.
*
* @param acceptPage Accepted page value for multi-page validation
* @since Struts 1.4.1
*/
public void setAcceptPage(Integer acceptPage) {
this.acceptPage = acceptPage;
}
// ------------------------------------------------------ Protected Methods
/**
* Traces the hierarchy of this object to check if any of the ancestors
* is extending this instance.
*
* @param moduleConfig The configuration for the module being configured.
* @return true if circular inheritance was detected.
*/
protected boolean checkCircularInheritance(ModuleConfig moduleConfig) {
String ancestor = getExtends();
while (ancestor != null) {
// check if we have the same path or id as an ancestor
if (getPath().equals(ancestor) || ancestor.equals(getActionId())) {
return true;
}
// get our ancestor's config
ActionConfig baseConfig = moduleConfig.findActionConfig(ancestor);
if (baseConfig == null) {
baseConfig = moduleConfig.findActionConfigId(ancestor);
}
if (baseConfig != null) {
ancestor = baseConfig.getExtends();
} else {
ancestor = null;
}
}
return false;
}
/**
* Compare the exception handlers of this action with that of the given
* and copy those that are not present.
*
* @param baseConfig The action config to copy handlers from.
* @see #inheritFrom(ActionConfig)
*/
protected void inheritExceptionHandlers(ActionConfig baseConfig)
throws ClassNotFoundException, IllegalAccessException,
InstantiationException, InvocationTargetException {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
// Inherit exception handler configs
ExceptionConfig[] baseHandlers = baseConfig.findExceptionConfigs();
for (int i = 0; i < baseHandlers.length; i++) {
ExceptionConfig baseHandler = baseHandlers[i];
// Do we have this handler?
ExceptionConfig copy =
this.findExceptionConfig(baseHandler.getType());
if (copy == null) {
// We don't have this, so let's copy it
copy =
(ExceptionConfig) RequestUtils.applicationInstance(baseHandler.getClass()
.getName());
BeanUtils.copyProperties(copy, baseHandler);
this.addExceptionConfig(copy);
copy.setProperties(baseHandler.copyProperties());
} else {
// process any extension that this config might have
copy.processExtends(getModuleConfig(), this);
}
}
}
/**
* Compare the forwards of this action with that of the given and copy
* those that are not present.
*
* @param baseConfig The action config to copy forwards from.
* @see #inheritFrom(ActionConfig)
*/
protected void inheritForwards(ActionConfig baseConfig)
throws ClassNotFoundException, IllegalAccessException,
InstantiationException, InvocationTargetException {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
// Inherit forward configs
ForwardConfig[] baseForwards = baseConfig.findForwardConfigs();
for (ForwardConfig baseForward : baseForwards) {
// Do we have this forward?
ForwardConfig copy = this.findForwardConfig(baseForward.getName());
if (copy == null) {
// We don't have this, so let's copy it
copy =
(ForwardConfig) RequestUtils.applicationInstance(baseForward.getClass()
.getName());
BeanUtils.copyProperties(copy, baseForward);
this.addForwardConfig(copy);
copy.setProperties(baseForward.copyProperties());
} else {
// process any extension for this forward
copy.processExtends(getModuleConfig(), this);
}
}
}
// --------------------------------------------------------- Public Methods
/**
* Add a new ExceptionConfig
instance to the set
* associated with this action.
*
* @param config The new configuration instance to be added
* @throws IllegalStateException if this module configuration has been
* frozen
*/
public void addExceptionConfig(ExceptionConfig config) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
exceptions.put(config.getType(), config);
}
/**
* Add a new ForwardConfig
instance to the set of global
* forwards associated with this action.
*
* @param config The new configuration instance to be added
* @throws IllegalStateException if this module configuration has been
* frozen
*/
public void addForwardConfig(ForwardConfig config) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
forwards.put(config.getName(), config);
}
/**
* Return the exception configuration for the specified type, if any;
* otherwise return null
.
*
* @param type Exception class name to find a configuration for
*/
public ExceptionConfig findExceptionConfig(String type) {
return (exceptions.get(type));
}
/**
* Return the exception configurations for this action. If there are
* none, a zero-length array is returned.
*/
public ExceptionConfig[] findExceptionConfigs() {
ExceptionConfig[] results = new ExceptionConfig[exceptions.size()];
return (exceptions.values().toArray(results));
}
/**
* Find and return the ExceptionConfig
instance defining
* how Exceptions
of the specified type should be handled.
* This is performed by checking local and then global configurations for
* the specified exception's class, and then looking up the superclass
* chain (again checking local and then global configurations). If no
* handler configuration can be found, return null
.
*
* Introduced in ActionMapping
in Struts 1.1, but pushed
* up to ActionConfig
in Struts 1.2.0.
*
* @param type Exception class for which to find a handler
* @since Struts 1.2.0
*/
public ExceptionConfig findException(Class> type) {
// Check through the entire superclass hierarchy as needed
ExceptionConfig config;
while (true) {
// Check for a locally defined handler
String name = type.getName();
log.debug("findException: look locally for {}", name);
config = findExceptionConfig(name);
if (config != null) {
return (config);
}
// Check for a globally defined handler
log.debug("findException: look globally for {}", name);
config = getModuleConfig().findExceptionConfig(name);
if (config != null) {
return (config);
}
// Loop again for our superclass (if any)
type = type.getSuperclass();
if (type == null) {
break;
}
}
return (null); // No handler has been configured
}
/**
* Return the forward configuration for the specified key, if any;
* otherwise return null
.
*
* @param name Name of the forward configuration to return
*/
public ForwardConfig findForwardConfig(String name) {
return (forwards.get(name));
}
/**
* Return all forward configurations for this module. If there are
* none, a zero-length array is returned.
*/
public ForwardConfig[] findForwardConfigs() {
ForwardConfig[] results = new ForwardConfig[forwards.size()];
return (forwards.values().toArray(results));
}
/**
* Freeze the configuration of this action.
*/
public void freeze() {
super.freeze();
ExceptionConfig[] econfigs = findExceptionConfigs();
for (int i = 0; i < econfigs.length; i++) {
econfigs[i].freeze();
}
ForwardConfig[] fconfigs = findForwardConfigs();
for (int i = 0; i < fconfigs.length; i++) {
fconfigs[i].freeze();
}
}
/**
* Inherit values that have not been overridden from the provided
* config object. Subclasses overriding this method should verify that
* the given parameter is of a class that contains a property it is trying
* to inherit:
*
*
* if (config instanceof MyCustomConfig) {
* MyCustomConfig myConfig =
* (MyCustomConfig) config;
*
* if (getMyCustomProp() == null) {
* setMyCustomProp(myConfig.getMyCustomProp());
* }
* }
*
*
* If the given config
is extending another object, those
* extensions should be resolved before it's used as a parameter to this
* method.
*
* @param config The object that this instance will be inheriting its
* values from.
* @see #processExtends(ModuleConfig)
*/
public void inheritFrom(ActionConfig config)
throws ClassNotFoundException, IllegalAccessException,
InstantiationException, InvocationTargetException {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
// Inherit values that have not been overridden
if (getAttribute() == null) {
setAttribute(config.getAttribute());
}
if (!cancellableSet) {
setCancellable(config.getCancellable());
}
if (getCatalog() == null) {
setCatalog(config.getCatalog());
}
if (getCommand() == null) {
setCommand(config.getCommand());
}
if (getForward() == null) {
setForward(config.getForward());
}
if (getInclude() == null) {
setInclude(config.getInclude());
}
if (getInput() == null) {
setInput(config.getInput());
}
if (getMultipartClass() == null) {
setMultipartClass(config.getMultipartClass());
}
if (getName() == null) {
setName(config.getName());
}
if (getParameter() == null) {
setParameter(config.getParameter());
}
if (getPath() == null) {
setPath(config.getPath());
}
if (getPrefix() == null) {
setPrefix(config.getPrefix());
}
if (getRoles() == null) {
setRoles(config.getRoles());
}
if (getScope().equals("session")) {
setScope(config.getScope());
}
if (getSuffix() == null) {
setSuffix(config.getSuffix());
}
if (getType() == null) {
setType(config.getType());
}
if (!getUnknown()) {
setUnknown(config.getUnknown());
}
if (!validateSet) {
setValidate(config.getValidate());
}
// 2014/07/02 - security problem patch.
// Author: NTT DATA Corporation
if (getAcceptPage() == null) {
setAcceptPage(config.getAcceptPage());
}
inheritExceptionHandlers(config);
inheritForwards(config);
inheritProperties(config);
}
/**
* Inherit configuration information from the ActionConfig that this
* instance is extending. This method verifies that any action config
* object that it inherits from has also had its processExtends() method
* called.
*
* @param moduleConfig The {@link ModuleConfig} that this bean is from.
* @see #inheritFrom(ActionConfig)
*/
public void processExtends(ModuleConfig moduleConfig)
throws ClassNotFoundException, IllegalAccessException,
InstantiationException, InvocationTargetException {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
String ancestor = getExtends();
if ((!extensionProcessed) && (ancestor != null)) {
ActionConfig baseConfig =
moduleConfig.findActionConfig(ancestor);
if (baseConfig == null) {
baseConfig = moduleConfig.findActionConfigId(ancestor);
}
if (baseConfig == null) {
throw new NullPointerException("Unable to find "
+ "action for '" + ancestor + "' to extend.");
}
// Check against circular inheritance and make sure the base
// config's own extends has been processed already
if (checkCircularInheritance(moduleConfig)) {
throw new IllegalArgumentException(
"Circular inheritance detected for action " + getPath());
}
// Make sure the ancestor's own extension has been processed.
if (!baseConfig.isExtensionProcessed()) {
baseConfig.processExtends(moduleConfig);
}
// Copy values from the base config
inheritFrom(baseConfig);
}
extensionProcessed = true;
}
/**
* Remove the specified exception configuration instance.
*
* @param config ExceptionConfig instance to be removed
* @throws IllegalStateException if this module configuration has been
* frozen
*/
public void removeExceptionConfig(ExceptionConfig config) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
exceptions.remove(config.getType());
}
/**
* Remove the specified forward configuration instance.
*
* @param config ForwardConfig instance to be removed
* @throws IllegalStateException if this module configuration has been
* frozen
*/
public void removeForwardConfig(ForwardConfig config) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
forwards.remove(config.getName());
}
/**
* Return a String representation of this object.
*/
public String toString() {
StringBuilder sb = new StringBuilder("ActionConfig[");
sb.append("cancellable=");
sb.append(cancellable);
sb.append(",path=");
sb.append(path);
sb.append(",validate=");
sb.append(validate);
if (actionId != null) {
sb.append(",actionId=");
sb.append(actionId);
}
if (attribute != null) {
sb.append(",attribute=");
sb.append(attribute);
}
if (catalog != null) {
sb.append(",catalog=");
sb.append(catalog);
}
if (command != null) {
sb.append(",command=");
sb.append(command);
}
if (dispatcher != null) {
sb.append(",dispatcher=");
sb.append(dispatcher);
}
if (forward != null) {
sb.append(",forward=");
sb.append(forward);
}
if (include != null) {
sb.append(",include=");
sb.append(include);
}
if (inherit != null) {
sb.append(",extends=");
sb.append(inherit);
}
if (input != null) {
sb.append(",input=");
sb.append(input);
}
if (multipartClass != null) {
sb.append(",multipartClass=");
sb.append(multipartClass);
}
if (name != null) {
sb.append(",name=");
sb.append(name);
}
if (parameter != null) {
sb.append(",parameter=");
sb.append(parameter);
}
if (prefix != null) {
sb.append(",prefix=");
sb.append(prefix);
}
if (roles != null) {
sb.append(",roles=");
sb.append(roles);
}
if (scope != null) {
sb.append(",scope=");
sb.append(scope);
}
if (reset != null) {
sb.append(",reset=");
sb.append(reset);
}
if (populate != null) {
sb.append(",populate=");
sb.append(populate);
}
sb.append(",singleton=");
sb.append(singleton);
if (suffix != null) {
sb.append(",suffix=");
sb.append(suffix);
}
if (type != null) {
sb.append(",type=");
sb.append(type);
}
// 2014/07/02 - security problem patch.
// Author: NTT DATA Corporation
if (acceptPage != null) {
sb.append(",acceptPage=");
sb.append(acceptPage);
}
sb.append("]");
return (sb.toString());
}
}