View Javadoc
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 }