1 /* 2 * $Id$ 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; 22 23 import java.util.Map; 24 25 import org.apache.struts.Globals; 26 import org.apache.struts.action.ActionForm; 27 import org.apache.struts.chain.contexts.ActionContext; 28 import org.apache.struts.config.ActionConfig; 29 import org.slf4j.Logger; 30 import org.slf4j.LoggerFactory; 31 32 /** 33 * <p>Populate the form bean (if any) for this request.</p> 34 * 35 * @version $Rev$ $Date: 2005-11-12 13:01:44 -0500 (Sat, 12 Nov 2005) 36 * $ 37 */ 38 public abstract class AbstractPopulateActionForm extends ActionCommandBase { 39 40 /** 41 * The {@code Log} instance for this class. 42 */ 43 private final Logger log = 44 LoggerFactory.getLogger(AbstractPopulateActionForm.class); 45 46 // ---------------------------------------------------------- Public Methods 47 48 /** 49 * <p>Populate the form bean (if any) for this request.</p> 50 * 51 * @param actionCtx The <code>Context</code> for the current request 52 * @return <code>false</code> so that processing continues 53 * @throws Exception On an unexpected error 54 */ 55 @Override 56 protected boolean execute_(ActionContext actionCtx) 57 throws Exception { 58 59 ActionConfig actionConfig = actionCtx.getActionConfig(); 60 ActionForm actionForm = actionCtx.getActionForm(); 61 62 // First determine if the request was cancelled 63 handleCancel(actionCtx, actionConfig, actionForm); 64 65 // Is there a form bean for this request? 66 if (actionForm == null) { 67 return (false); 68 } 69 70 // Reset the form bean only if configured so 71 if (isReset(actionCtx, actionConfig)) { 72 log.debug("Reseting form bean '{}'", actionConfig.getName()); 73 reset(actionCtx, actionConfig, actionForm); 74 } 75 76 // Populate the form bean only if configured so 77 if (isPopulate(actionCtx, actionConfig)) { 78 log.debug("Populating form bean '{}'", actionConfig.getName()); 79 populate(actionCtx, actionConfig, actionForm); 80 } 81 82 return CONTINUE_PROCESSING; 83 } 84 85 // ------------------------------------------------------- Protected Methods 86 87 /** 88 * Determines whether an action form should be reset 89 * 90 * @param context the ActionContext we are processing 91 * @param actionConfig action config for current request 92 * 93 * @return true if action form should be reset 94 * 95 * @since Struts 1.4 96 */ 97 protected abstract boolean isReset(ActionContext context, 98 ActionConfig actionConfig); 99 100 /** 101 * Determines whether an action form should be populated. 102 * 103 * @param context the ActionContext we are processing 104 * @param actionConfig action config for current request 105 * @return true if action form should be populated 106 * @since Struts 1.4 107 */ 108 protected abstract boolean isPopulate(ActionContext context, 109 ActionConfig actionConfig); 110 111 /** 112 * <p>Call the <code>reset()</code> method on the specified form 113 * bean.</p> 114 * 115 * @param context The context for this request 116 * @param actionConfig The actionConfig for this request 117 * @param actionForm The form bean for this request 118 */ 119 protected abstract void reset(ActionContext context, 120 ActionConfig actionConfig, ActionForm actionForm); 121 122 /** 123 * <p> Populate the given <code>ActionForm</code> with request parameter 124 * values, taking into account any prefix/suffix values configured on the 125 * given <code>ActionConfig</code>. </p> 126 * 127 * @param context The ActionContext we are processing 128 * @param actionConfig The ActionConfig we are processing 129 * @param actionForm The ActionForm we are processing 130 * @throws Exception On an unexpected error 131 */ 132 protected abstract void populate(ActionContext context, 133 ActionConfig actionConfig, ActionForm actionForm) 134 throws Exception; 135 136 // original implementation casting context to WebContext is not safe 137 // when the input value is an ActionContext. 138 139 /** 140 * <p>For a given request parameter name, trim off any prefix and/or 141 * suffix which are defined in <code>actionConfig</code> and return what 142 * remains. If either prefix or suffix is defined, then return null for 143 * <code>name</code> values which do not begin or end accordingly.</p> 144 * 145 * @param actionConfig The ActionConfig we are processing 146 * @param name The request parameter name to proceess 147 * @return The request parameter name trimmed of any suffix or prefix 148 */ 149 protected String trimParameterName(ActionConfig actionConfig, String name) { 150 String stripped = name; 151 String prefix = actionConfig.getPrefix(); 152 String suffix = actionConfig.getSuffix(); 153 154 if (prefix != null) { 155 if (!stripped.startsWith(prefix)) { 156 return null; 157 } 158 159 stripped = stripped.substring(prefix.length()); 160 } 161 162 if (suffix != null) { 163 if (!stripped.endsWith(suffix)) { 164 return null; 165 } 166 167 stripped = 168 stripped.substring(0, stripped.length() - suffix.length()); 169 } 170 171 return stripped; 172 } 173 174 /** 175 * <p>Take into account whether the request includes any defined value for 176 * the global "cancel" parameter.</p> <p> An issue was raised (but I don't 177 * think a Bugzilla ticket created) about the security implications of 178 * using a well-known cancel property which skips form validation, as you 179 * may not write your actions to deal with the cancellation case. </p> 180 * 181 * @param context The ActionContext we are processing 182 * @param actionConfig The ActionConfig we are processing 183 * @param actionForm The ActionForm we are processing 184 * @throws Exception On an unexpected error 185 * @see Globals#CANCEL_PROPERTY 186 * @see Globals#CANCEL_PROPERTY_X 187 */ 188 protected void handleCancel(ActionContext context, 189 ActionConfig actionConfig, ActionForm actionForm) 190 throws Exception { 191 Map<String, String[]> paramValues = context.getParameterMap(); 192 193 // Set the cancellation attribute if appropriate 194 if ((paramValues.get(Globals.CANCEL_PROPERTY) != null) 195 || (paramValues.get(Globals.CANCEL_PROPERTY_X) != null)) { 196 context.setCancelled(Boolean.TRUE); 197 } else { 198 context.setCancelled(Boolean.FALSE); 199 } 200 } 201 }