View Javadoc

1   /*
2    * $Id: Form.java 766376 2009-04-18 18:48:47Z musachy $
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  
22  package org.apache.struts2.components;
23  
24  import com.opensymphony.xwork2.ObjectFactory;
25  import com.opensymphony.xwork2.config.Configuration;
26  import com.opensymphony.xwork2.config.RuntimeConfiguration;
27  import com.opensymphony.xwork2.config.entities.ActionConfig;
28  import com.opensymphony.xwork2.config.entities.InterceptorMapping;
29  import com.opensymphony.xwork2.inject.Inject;
30  import com.opensymphony.xwork2.interceptor.MethodFilterInterceptorUtil;
31  import com.opensymphony.xwork2.util.ValueStack;
32  import com.opensymphony.xwork2.validator.ActionValidatorManager;
33  import com.opensymphony.xwork2.validator.FieldValidator;
34  import com.opensymphony.xwork2.validator.ValidationInterceptor;
35  import com.opensymphony.xwork2.validator.Validator;
36  import org.apache.struts2.StrutsConstants;
37  import org.apache.struts2.views.annotations.StrutsTag;
38  import org.apache.struts2.views.annotations.StrutsTagAttribute;
39  import org.apache.commons.lang.xwork.StringUtils;
40  
41  import javax.servlet.http.HttpServletRequest;
42  import javax.servlet.http.HttpServletResponse;
43  import java.util.*;
44  import java.util.Set;
45  
46  /***
47   * <!-- START SNIPPET: javadoc -->
48   * <p/>
49   * Renders HTML an input form.<p/>
50   * <p/>
51   * The remote form allows the form to be submitted without the page being refreshed. The results from the form
52   * can be inserted into any HTML element on the page.<p/>
53   * <p/>
54   * NOTE:<p/>
55   * The order / logic in determining the posting url of the generated HTML form is as follows:-
56   * <ol>
57   * <li>
58   * If the action attribute is not specified, then the current request will be used to
59   * determine the posting url
60   * </li>
61   * <li>
62   * If the action is given, Struts will try to obtain an ActionConfig. This will be
63   * successfull if the action attribute is a valid action alias defined struts.xml.
64   * </li>
65   * <li>
66   * If the action is given and is not an action alias defined in struts.xml, Struts
67   * will used the action attribute as if it is the posting url, separting the namespace
68   * from it and using UrlHelper to generate the final url.
69   * </li>
70   * </ol>
71   * <p/>
72   * <!-- END SNIPPET: javadoc -->
73   * <p/>
74   * <p/> <b>Examples</b>
75   * <p/>
76   * <pre>
77   * <!-- START SNIPPET: example -->
78   * <p/>
79   * &lt;s:form ... /&gt;
80   * <p/>
81   * <!-- END SNIPPET: example -->
82   * </pre>
83   *
84   */
85  @StrutsTag(
86      name="form",
87      tldTagClass="org.apache.struts2.views.jsp.ui.FormTag",
88      description="Renders an input form",
89      allowDynamicAttributes=true)
90  public class Form extends ClosingUIBean {
91      public static final String OPEN_TEMPLATE = "form";
92      public static final String TEMPLATE = "form-close";
93  
94      private int sequence = 0;
95  
96      protected String onsubmit;
97      protected String onreset;
98      protected String action;
99      protected String target;
100     protected String enctype;
101     protected String method;
102     protected String namespace;
103     protected String validate;
104     protected String portletMode;
105     protected String windowState;
106     protected String acceptcharset;
107     protected String focusElement;
108 
109     protected Configuration configuration;
110     protected ObjectFactory objectFactory;
111     protected UrlRenderer urlRenderer;
112     protected ActionValidatorManager actionValidatorManager;
113 
114     public Form(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
115         super(stack, request, response);
116     }
117 
118     protected boolean evaluateNameValue() {
119         return false;
120     }
121 
122     public String getDefaultOpenTemplate() {
123         return OPEN_TEMPLATE;
124     }
125 
126     protected String getDefaultTemplate() {
127         return TEMPLATE;
128     }
129 
130     @Inject
131     public void setConfiguration(Configuration configuration) {
132         this.configuration = configuration;
133     }
134 
135     @Inject
136     public void setObjectFactory(ObjectFactory objectFactory) {
137         this.objectFactory = objectFactory;
138     }
139 
140     @Inject
141     public void setUrlRenderer(UrlRenderer urlRenderer) {
142     	this.urlRenderer = urlRenderer;
143     }
144 
145     @Inject
146     public void setActionValidatorManager(ActionValidatorManager mgr) {
147         this.actionValidatorManager = mgr;
148     }
149 
150 
151     /*
152     * Revised for Portlet actionURL as form action, and add wwAction as hidden
153     * field. Refer to template.simple/form.vm
154     */
155     protected void evaluateExtraParams() {
156         super.evaluateExtraParams();
157         if (validate != null) {
158             addParameter("validate", findValue(validate, Boolean.class));
159         }
160 
161         if (name == null) {
162             //make the name the same as the id
163             String id = (String) getParameters().get("id");
164              if (StringUtils.isNotEmpty(id)) {
165                 addParameter("name", id);
166              }
167         }
168 
169         if (onsubmit != null) {
170             addParameter("onsubmit", findString(onsubmit));
171         }
172 
173         if (onreset != null) {
174             addParameter("onreset", findString(onreset));
175         }
176 
177         if (target != null) {
178             addParameter("target", findString(target));
179         }
180 
181         if (enctype != null) {
182             addParameter("enctype", findString(enctype));
183         }
184 
185         if (method != null) {
186             addParameter("method", findString(method));
187         }
188 
189         if (acceptcharset != null) {
190             addParameter("acceptcharset", findString(acceptcharset));
191         }
192 
193         // keep a collection of the tag names for anything special the templates might want to do (such as pure client
194         // side validation)
195         if (!parameters.containsKey("tagNames")) {
196             // we have this if check so we don't do this twice (on open and close of the template)
197             addParameter("tagNames", new ArrayList());
198         }
199 
200         if (focusElement != null) {
201             addParameter("focusElement", findString(focusElement));
202         }
203     }
204 
205     /***
206      * Form component determine the its HTML element id as follows:-
207      * <ol>
208      *    <li>if an 'id' attribute is specified.</li>
209      *    <li>if an 'action' attribute is specified, it will be used as the id.</li>
210      * </ol>
211      */
212     protected void populateComponentHtmlId(Form form) {
213         if (id != null) {
214             addParameter("id", escape(id));
215         }
216 
217         // if no id given, it will be tried to generate it from the action attribute
218         // by the urlRenderer implementation
219         urlRenderer.renderFormUrl(this);
220     }
221 
222     /***
223      * Evaluate client side JavaScript Enablement.
224      * @param actionName the actioName to check for
225      * @param namespace the namespace to check for
226      * @param actionMethod the method to ckeck for
227      */
228     protected void evaluateClientSideJsEnablement(String actionName, String namespace, String actionMethod) {
229 
230         // Only evaluate if Client-Side js is to be enable when validate=true
231         Boolean validate = (Boolean) getParameters().get("validate");
232         if (validate != null && validate) {
233 
234             addParameter("performValidation", Boolean.FALSE);
235 
236             RuntimeConfiguration runtimeConfiguration = configuration.getRuntimeConfiguration();
237             ActionConfig actionConfig = runtimeConfiguration.getActionConfig(namespace, actionName);
238 
239             if (actionConfig != null) {
240                 List<InterceptorMapping> interceptors = actionConfig.getInterceptors();
241                 for (InterceptorMapping interceptorMapping : interceptors) {
242                     if (ValidationInterceptor.class.isInstance(interceptorMapping.getInterceptor())) {
243                         ValidationInterceptor validationInterceptor = (ValidationInterceptor) interceptorMapping.getInterceptor();
244 
245                         Set excludeMethods = validationInterceptor.getExcludeMethodsSet();
246                         Set includeMethods = validationInterceptor.getIncludeMethodsSet();
247 
248                         if (MethodFilterInterceptorUtil.applyMethod(excludeMethods, includeMethods, actionMethod)) {
249                             addParameter("performValidation", Boolean.TRUE);
250                         }
251                         return;
252                     }
253                 }
254             }
255         }
256     }
257 
258     public List getValidators(String name) {
259         Class actionClass = (Class) getParameters().get("actionClass");
260         if (actionClass == null) {
261             return Collections.EMPTY_LIST;
262         }
263 
264         List<Validator> all = actionValidatorManager.getValidators(actionClass, (String) getParameters().get("actionName"));
265         List<Validator> validators = new ArrayList<Validator>();
266         for (Validator validator : all) {
267             if (validator instanceof FieldValidator) {
268                 FieldValidator fieldValidator = (FieldValidator) validator;
269                 if (fieldValidator.getFieldName().equals(name)) {
270                     validators.add(fieldValidator);
271                 }
272             }
273         }
274 
275         return validators;
276     }
277 
278     /***
279      * Get a incrementing sequence unique to this <code>Form</code> component.
280      * It is used by <code>Form</code> component's child that might need a
281      * sequence to make them unique.
282      *
283      * @return int
284      */
285     protected int getSequence() {
286         return sequence++;
287     }
288 
289     @StrutsTagAttribute(description="HTML onsubmit attribute")
290     public void setOnsubmit(String onsubmit) {
291         this.onsubmit = onsubmit;
292     }
293 
294     @StrutsTagAttribute(description="HTML onreset attribute")
295     public void setOnreset(String onreset) {
296         this.onreset = onreset;
297     }
298 
299     @StrutsTagAttribute(description="Set action name to submit to, without .action suffix", defaultValue="current action")
300     public void setAction(String action) {
301         this.action = action;
302     }
303 
304     @StrutsTagAttribute(description="HTML form target attribute")
305     public void setTarget(String target) {
306         this.target = target;
307     }
308 
309     @StrutsTagAttribute(description="HTML form enctype attribute")
310     public void setEnctype(String enctype) {
311         this.enctype = enctype;
312     }
313 
314     @StrutsTagAttribute(description="HTML form method attribute")
315     public void setMethod(String method) {
316         this.method = method;
317     }
318 
319     @StrutsTagAttribute(description="Namespace for action to submit to", defaultValue="current namespace")
320     public void setNamespace(String namespace) {
321         this.namespace = namespace;
322     }
323 
324     @StrutsTagAttribute(description="Whether client side/remote validation should be performed. Only" +
325                 " useful with theme xhtml/ajax", type="Boolean", defaultValue="false")
326     public void setValidate(String validate) {
327         this.validate = validate;
328     }
329 
330     @StrutsTagAttribute(description="The portlet mode to display after the form submit")
331     public void setPortletMode(String portletMode) {
332         this.portletMode = portletMode;
333     }
334 
335     @StrutsTagAttribute(description="The window state to display after the form submit")
336     public void setWindowState(String windowState) {
337         this.windowState = windowState;
338     }
339 
340     @StrutsTagAttribute(description="The accepted charsets for this form. The values may be comma or blank delimited.")
341     public void setAcceptcharset(String acceptcharset) {
342         this.acceptcharset = acceptcharset;
343     }
344 
345     @StrutsTagAttribute(description="Id of element that will receive the focus when page loads.")
346     public void setFocusElement(String focusElement) {
347         this.focusElement = focusElement;
348     }
349 }