/*
* $Id: CopyFormToContext.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.struts.action.ActionForm;
import org.apache.struts.chain.commands.ActionCommandBase;
import org.apache.struts.chain.contexts.ActionContext;
import org.apache.struts.chain.contexts.ActionContextBase;
import org.apache.struts.config.ActionConfig;
/**
* <p>Subclass this command and configure it as part of a per-forward chain to
* perform any necessary pre-population or other preparation for a form before
* control is dispatched to the view layer.</p>
*
* @version $Id: CopyFormToContext.java 471754 2006-11-06 14:55:09Z husted $
*/
public class CopyFormToContext extends ActionCommandBase {
// ------------------------------------------------------ Instance Variables
/**
* <p>The name of a form bean as configured in a struts-config.xml file
* for this module. </p>
*
* <p> Either actionPath or both this and scope are required configuration
* properties.</p>
*/
private String formName = null;
/**
* <p>The name of a scope, such as "request" or "session" in which the
* form to be prepared will be placed for reference by the view and other
* parts of Struts.</p>
*
* <p>Either <code>actionPath</code> or both this and
* <code>formName</code> are required configuration properties.</p>
*/
private String scope = null;
/**
* <p>The path of an <code><action></code> mapping as configured in
* a <code>struts-config.xml</code> file for this module. This action
* will be looked up, and its <code>name</code> and <code>scope</code>
* values will be used as if those values were configured directly in this
* instance's <code>formName</code> and <code>scope</code>
* properties.</p>
*
* <p>Either <code>this</code> or both <code>scope</code> and
* <code>formName</code> are required configuration properties.</p>
*/
private String actionPath = null;
/**
* The context key under which the form which was looked up will be
* stored. Defaults to "actionForm" but may be overridden in cases where
* the "request" ActionForm must be preserved.
*/
private String toKey = ActionContextBase.ACTION_FORM_KEY;
// ------------------------------------------------------ Properties
/**
* <p>Return ActionPath property.</p>
*
* @return ActionPath property
*/
public String getActionPath() {
return this.actionPath;
}
/**
* <p>Set ActionPath property.</p>
*
* @param actionPath New valuefor ActionPath
*/
public void setActionPath(String actionPath) {
this.actionPath = actionPath;
}
/**
* <p>Return FormName property.</p>
*
* @return FormName property
*/
public String getFormName() {
return this.formName;
}
/**
* <p>Set FormName property.</p>
*
* @param formName New valuefor FormName
*/
public void setFormName(String formName) {
this.formName = formName;
}
/**
* <p>Return Scope property.</p>
*
* @return Scope property
*/
public String getScope() {
return this.scope;
}
/**
* <p>Set Scope property.</p>
*
* @param scope New valuefor Scope
*/
public void setScope(String scope) {
this.scope = scope;
}
/**
* <p>Return ToKey property.</p>
*
* @return ToKey property
*/
public String getToKey() {
return this.toKey;
}
/**
* <p>Set ToKey property.</p>
*
* @param toKey New valuefor FormName
*/
public void setToKey(String toKey) {
this.toKey = toKey;
}
// ------------------------------------------------------
/**
* <p>Look up an ActionForm instance based on the configured properties of
* this command and copy it into the <code>Context</code>. After this
* command successfully executes, an ActionForm instance will exist in the
* specified scope and will be available, for example for backing fields
* in an HTML form. It will also be in the <code>ActionContext</code>
* available for another command to do prepopulation of values or other
* preparation.</p>
*
* @param actionContext Our ActionContext
* @return TRUE if processing should halt
* @throws Exception on any error
*/
public boolean execute(ActionContext actionContext)
throws Exception {
ActionForm form = findOrCreateForm(actionContext);
if (isEmpty(getToKey())) {
throw new IllegalStateException("Property 'toKey' must be defined.");
}
actionContext.put(getToKey(), form);
return false;
}
/**
* <p>Based on the properties of this command and the given
* <code>ActionContext</code>, find or create an ActionForm instance for
* preparation.</p>
*
* @param context ActionContextBase class that we are processing
* @return ActionForm instance
* @throws IllegalArgumentException On ActionConfig not found
* @throws IllegalStateException On undefined scope and formbean
* @throws IllegalAccessException On failed instantiation
* @throws InstantiationException If ActionContext is not subsclass of
* ActionContextBase
*/
protected ActionForm findOrCreateForm(ActionContext context)
throws IllegalAccessException, InstantiationException {
String effectiveFormName;
String effectiveScope;
if (!(isEmpty(this.getActionPath()))) {
ActionConfig actionConfig =
context.getModuleConfig().findActionConfig(this.getActionPath());
if (actionConfig == null) {
throw new IllegalArgumentException(
"No ActionConfig found for path " + this.getActionPath());
}
effectiveFormName = actionConfig.getName();
effectiveScope = actionConfig.getScope();
} else {
effectiveFormName = this.getFormName();
effectiveScope = this.getScope();
}
if (isEmpty(effectiveScope) || isEmpty(effectiveFormName)) {
throw new IllegalStateException("Both scope [" + effectiveScope
+ "] and formName [" + effectiveFormName + "] must be defined.");
}
return findOrCreateForm(context, effectiveFormName, effectiveScope);
}
/**
* <p>Actually find or create an instance of ActionForm configured under
* the form-bean-name <code>effectiveFormName</code>, looking in in the
* <code>ActionContext's</code> scope as identified by
* <code>effectiveScope</code>. If a form is created, it will also be
* stored in that scope.</p>
*
* <p><b>NOTE:</b> This specific method depends on the instance of
* <code>ActionContext</code> which is passed being a subclass of
* <code>ActionContextBase</code>, which implements the utility method
* <code>findOrCreateActionForm</code>. </p>
*
* @param ctx The ActionContext we are processing
* @param effectiveFormName the target form name
* @param effectiveScope The target scope
* @return ActionForm instnace, storing in scope if created
* @throws InstantiationException If ActionContext is not subsclass of
* ActionContextBase
* @throws InstantiationException If object cannot be created
* @throws IllegalArgumentException On form not found in/ scope
* @throws IllegalAccessException On failed instantiation
* @throws IllegalStateException If ActionContext is not a subclass of
* ActionBase
*/
protected ActionForm findOrCreateForm(ActionContext ctx,
String effectiveFormName, String effectiveScope)
throws IllegalAccessException, InstantiationException {
ActionContextBase context;
try {
context = (ActionContextBase) ctx;
} catch (ClassCastException e) {
throw new IllegalStateException("ActionContext [" + ctx + "]"
+ " must be subclass of ActionContextBase");
}
ActionForm form =
context.findOrCreateActionForm(effectiveFormName, effectiveScope);
if (form == null) {
throw new IllegalArgumentException("No form found under scope ["
+ effectiveScope + "] and formName [" + effectiveFormName + "]");
}
return form;
}
/**
* <p>Convenience method to test for an empty string.</p>
*
* @param test String to test
* @return TRUE if test is null or zero-length
*/
private boolean isEmpty(String test) {
return (test == null) || (test.trim().length() == 0);
}
}