1 /* 2 * $Id: CopyFormToContext.java 471754 2006-11-06 14:55:09Z husted $ 3 * 4 * Licensed to the Apache Software Foundation (ASF) under one 5 * or more contributor license agreements. See the NOTICE file 6 * distributed with this work for additional information 7 * regarding copyright ownership. The ASF licenses this file 8 * to you under the Apache License, Version 2.0 (the 9 * "License"); you may not use this file except in compliance 10 * with the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, 15 * software distributed under the License is distributed on an 16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17 * KIND, either express or implied. See the License for the 18 * specific language governing permissions and limitations 19 * under the License. 20 */ 21 package org.apache.struts.chain.commands.generic; 22 23 import org.apache.struts.action.ActionForm; 24 import org.apache.struts.chain.commands.ActionCommandBase; 25 import org.apache.struts.chain.contexts.ActionContext; 26 import org.apache.struts.chain.contexts.ActionContextBase; 27 import org.apache.struts.config.ActionConfig; 28 29 /** 30 * <p>Subclass this command and configure it as part of a per-forward chain to 31 * perform any necessary pre-population or other preparation for a form before 32 * control is dispatched to the view layer.</p> 33 * 34 * @version $Id: CopyFormToContext.java 471754 2006-11-06 14:55:09Z husted $ 35 */ 36 public class CopyFormToContext extends ActionCommandBase { 37 // ------------------------------------------------------ Instance Variables 38 39 /** 40 * <p>The name of a form bean as configured in a struts-config.xml file 41 * for this module. </p> 42 * 43 * <p> Either actionPath or both this and scope are required configuration 44 * properties.</p> 45 */ 46 private String formName = null; 47 48 /** 49 * <p>The name of a scope, such as "request" or "session" in which the 50 * form to be prepared will be placed for reference by the view and other 51 * parts of Struts.</p> 52 * 53 * <p>Either <code>actionPath</code> or both this and 54 * <code>formName</code> are required configuration properties.</p> 55 */ 56 private String scope = null; 57 58 /** 59 * <p>The path of an <code><action></code> mapping as configured in 60 * a <code>struts-config.xml</code> file for this module. This action 61 * will be looked up, and its <code>name</code> and <code>scope</code> 62 * values will be used as if those values were configured directly in this 63 * instance's <code>formName</code> and <code>scope</code> 64 * properties.</p> 65 * 66 * <p>Either <code>this</code> or both <code>scope</code> and 67 * <code>formName</code> are required configuration properties.</p> 68 */ 69 private String actionPath = null; 70 71 /** 72 * The context key under which the form which was looked up will be 73 * stored. Defaults to "actionForm" but may be overridden in cases where 74 * the "request" ActionForm must be preserved. 75 */ 76 private String toKey = ActionContextBase.ACTION_FORM_KEY; 77 78 // ------------------------------------------------------ Properties 79 80 /** 81 * <p>Return ActionPath property.</p> 82 * 83 * @return ActionPath property 84 */ 85 public String getActionPath() { 86 return this.actionPath; 87 } 88 89 /** 90 * <p>Set ActionPath property.</p> 91 * 92 * @param actionPath New valuefor ActionPath 93 */ 94 public void setActionPath(String actionPath) { 95 this.actionPath = actionPath; 96 } 97 98 /** 99 * <p>Return FormName property.</p> 100 * 101 * @return FormName property 102 */ 103 public String getFormName() { 104 return this.formName; 105 } 106 107 /** 108 * <p>Set FormName property.</p> 109 * 110 * @param formName New valuefor FormName 111 */ 112 public void setFormName(String formName) { 113 this.formName = formName; 114 } 115 116 /** 117 * <p>Return Scope property.</p> 118 * 119 * @return Scope property 120 */ 121 public String getScope() { 122 return this.scope; 123 } 124 125 /** 126 * <p>Set Scope property.</p> 127 * 128 * @param scope New valuefor Scope 129 */ 130 public void setScope(String scope) { 131 this.scope = scope; 132 } 133 134 /** 135 * <p>Return ToKey property.</p> 136 * 137 * @return ToKey property 138 */ 139 public String getToKey() { 140 return this.toKey; 141 } 142 143 /** 144 * <p>Set ToKey property.</p> 145 * 146 * @param toKey New valuefor FormName 147 */ 148 public void setToKey(String toKey) { 149 this.toKey = toKey; 150 } 151 152 // ------------------------------------------------------ 153 154 /** 155 * <p>Look up an ActionForm instance based on the configured properties of 156 * this command and copy it into the <code>Context</code>. After this 157 * command successfully executes, an ActionForm instance will exist in the 158 * specified scope and will be available, for example for backing fields 159 * in an HTML form. It will also be in the <code>ActionContext</code> 160 * available for another command to do prepopulation of values or other 161 * preparation.</p> 162 * 163 * @param actionContext Our ActionContext 164 * @return TRUE if processing should halt 165 * @throws Exception on any error 166 */ 167 public boolean execute(ActionContext actionContext) 168 throws Exception { 169 ActionForm form = findOrCreateForm(actionContext); 170 171 if (isEmpty(getToKey())) { 172 throw new IllegalStateException("Property 'toKey' must be defined."); 173 } 174 175 actionContext.put(getToKey(), form); 176 177 return false; 178 } 179 180 /** 181 * <p>Based on the properties of this command and the given 182 * <code>ActionContext</code>, find or create an ActionForm instance for 183 * preparation.</p> 184 * 185 * @param context ActionContextBase class that we are processing 186 * @return ActionForm instance 187 * @throws IllegalArgumentException On ActionConfig not found 188 * @throws IllegalStateException On undefined scope and formbean 189 * @throws IllegalAccessException On failed instantiation 190 * @throws InstantiationException If ActionContext is not subsclass of 191 * ActionContextBase 192 */ 193 protected ActionForm findOrCreateForm(ActionContext context) 194 throws IllegalAccessException, InstantiationException { 195 String effectiveFormName; 196 String effectiveScope; 197 198 if (!(isEmpty(this.getActionPath()))) { 199 ActionConfig actionConfig = 200 context.getModuleConfig().findActionConfig(this.getActionPath()); 201 202 if (actionConfig == null) { 203 throw new IllegalArgumentException( 204 "No ActionConfig found for path " + this.getActionPath()); 205 } 206 207 effectiveFormName = actionConfig.getName(); 208 effectiveScope = actionConfig.getScope(); 209 } else { 210 effectiveFormName = this.getFormName(); 211 effectiveScope = this.getScope(); 212 } 213 214 if (isEmpty(effectiveScope) || isEmpty(effectiveFormName)) { 215 throw new IllegalStateException("Both scope [" + effectiveScope 216 + "] and formName [" + effectiveFormName + "] must be defined."); 217 } 218 219 return findOrCreateForm(context, effectiveFormName, effectiveScope); 220 } 221 222 /** 223 * <p>Actually find or create an instance of ActionForm configured under 224 * the form-bean-name <code>effectiveFormName</code>, looking in in the 225 * <code>ActionContext's</code> scope as identified by 226 * <code>effectiveScope</code>. If a form is created, it will also be 227 * stored in that scope.</p> 228 * 229 * <p><b>NOTE:</b> This specific method depends on the instance of 230 * <code>ActionContext</code> which is passed being a subclass of 231 * <code>ActionContextBase</code>, which implements the utility method 232 * <code>findOrCreateActionForm</code>. </p> 233 * 234 * @param ctx The ActionContext we are processing 235 * @param effectiveFormName the target form name 236 * @param effectiveScope The target scope 237 * @return ActionForm instnace, storing in scope if created 238 * @throws InstantiationException If ActionContext is not subsclass of 239 * ActionContextBase 240 * @throws InstantiationException If object cannot be created 241 * @throws IllegalArgumentException On form not found in/ scope 242 * @throws IllegalAccessException On failed instantiation 243 * @throws IllegalStateException If ActionContext is not a subclass of 244 * ActionBase 245 */ 246 protected ActionForm findOrCreateForm(ActionContext ctx, 247 String effectiveFormName, String effectiveScope) 248 throws IllegalAccessException, InstantiationException { 249 ActionContextBase context; 250 251 try { 252 context = (ActionContextBase) ctx; 253 } catch (ClassCastException e) { 254 throw new IllegalStateException("ActionContext [" + ctx + "]" 255 + " must be subclass of ActionContextBase"); 256 } 257 258 ActionForm form = 259 context.findOrCreateActionForm(effectiveFormName, effectiveScope); 260 261 if (form == null) { 262 throw new IllegalArgumentException("No form found under scope [" 263 + effectiveScope + "] and formName [" + effectiveFormName + "]"); 264 } 265 266 return form; 267 } 268 269 /** 270 * <p>Convenience method to test for an empty string.</p> 271 * 272 * @param test String to test 273 * @return TRUE if test is null or zero-length 274 */ 275 private boolean isEmpty(String test) { 276 return (test == null) || (test.trim().length() == 0); 277 } 278 }