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