1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.shared.renderkit.html;
20
21 import java.io.IOException;
22 import java.util.HashSet;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Set;
26
27 import javax.faces.application.ViewHandler;
28 import javax.faces.component.UIComponent;
29 import javax.faces.component.UIForm;
30 import javax.faces.component.behavior.ClientBehavior;
31 import javax.faces.component.behavior.ClientBehaviorHolder;
32 import javax.faces.component.html.HtmlForm;
33 import javax.faces.context.FacesContext;
34 import javax.faces.context.ResponseWriter;
35
36 import org.apache.myfaces.shared.config.MyfacesConfig;
37 import org.apache.myfaces.shared.renderkit.JSFAttr;
38 import org.apache.myfaces.shared.renderkit.html.util.ResourceUtils;
39
40 public class HtmlFormRendererBase
41 extends HtmlRenderer
42 {
43
44 private static final String FORM_TARGET = HTML.FORM_ELEM;
45 private static final String HIDDEN_SUBMIT_INPUT_SUFFIX = "_SUBMIT";
46 private static final String HIDDEN_SUBMIT_INPUT_VALUE = "1";
47
48 private static final String HIDDEN_COMMAND_INPUTS_SET_ATTR
49 = UIForm.class.getName() + ".org.apache.myfaces.HIDDEN_COMMAND_INPUTS_SET";
50
51 private static final String SCROLL_HIDDEN_INPUT = "org.apache.myfaces.SCROLL_HIDDEN_INPUT";
52
53 public void encodeBegin(FacesContext facesContext, UIComponent component)
54 throws IOException
55 {
56 org.apache.myfaces.shared.renderkit.RendererUtils.checkParamValidity(facesContext, component, UIForm.class);
57
58 UIForm htmlForm = (UIForm)component;
59
60 ResponseWriter writer = facesContext.getResponseWriter();
61 String clientId = htmlForm.getClientId(facesContext);
62 String acceptCharset = getAcceptCharset(facesContext, htmlForm);
63 String actionURL = getActionUrl(facesContext, htmlForm);
64 String method = getMethod(facesContext, htmlForm);
65
66 Map<String, List<ClientBehavior>> behaviors = null;
67 if (component instanceof ClientBehaviorHolder)
68 {
69 behaviors = ((ClientBehaviorHolder) component).getClientBehaviors();
70 if (!behaviors.isEmpty())
71 {
72 ResourceUtils.renderDefaultJsfJsInlineIfNecessary(facesContext, writer);
73 }
74 }
75
76 writer.startElement(HTML.FORM_ELEM, htmlForm);
77 writer.writeAttribute(HTML.ID_ATTR, clientId, null);
78 writer.writeAttribute(HTML.NAME_ATTR, clientId, null);
79 writer.writeAttribute(HTML.METHOD_ATTR, method, null);
80 if (acceptCharset != null)
81 {
82 writer.writeAttribute(HTML.ACCEPT_CHARSET_ATTR, acceptCharset, null);
83 }
84 String encodedActionURL = facesContext.getExternalContext().encodeActionURL(actionURL);
85
86 writer.writeURIAttribute(HTML.ACTION_ATTR,
87 encodedActionURL,
88 null);
89
90 if (htmlForm instanceof ClientBehaviorHolder)
91 {
92 behaviors = ((ClientBehaviorHolder) htmlForm).getClientBehaviors();
93 if (behaviors.isEmpty() && isCommonPropertiesOptimizationEnabled(facesContext))
94 {
95 CommonPropertyUtils.renderEventProperties(writer,
96 CommonPropertyUtils.getCommonPropertiesMarked(htmlForm), htmlForm);
97 }
98 else
99 {
100 if (isCommonEventsOptimizationEnabled(facesContext))
101 {
102 CommonEventUtils.renderBehaviorizedEventHandlers(facesContext, writer,
103 CommonPropertyUtils.getCommonPropertiesMarked(htmlForm),
104 CommonEventUtils.getCommonEventsMarked(htmlForm), htmlForm, behaviors);
105 }
106 else
107 {
108 HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext, writer, htmlForm, behaviors);
109 }
110 }
111 if (isCommonPropertiesOptimizationEnabled(facesContext))
112 {
113 CommonPropertyUtils.renderCommonPassthroughPropertiesWithoutEvents(writer,
114 CommonPropertyUtils.getCommonPropertiesMarked(component), component);
115 HtmlRendererUtils.renderHTMLAttributes(writer, htmlForm, HTML.FORM_ATTRIBUTES);
116 }
117 else
118 {
119 HtmlRendererUtils.renderHTMLAttributes(writer, htmlForm,
120 HTML.FORM_PASSTHROUGH_ATTRIBUTES_WITHOUT_EVENTS);
121 }
122 }
123 else
124 {
125 if (isCommonPropertiesOptimizationEnabled(facesContext))
126 {
127 CommonPropertyUtils.renderCommonPassthroughProperties(writer,
128 CommonPropertyUtils.getCommonPropertiesMarked(component), component);
129 HtmlRendererUtils.renderHTMLAttributes(writer, htmlForm, HTML.FORM_ATTRIBUTES);
130 }
131 else
132 {
133 HtmlRendererUtils.renderHTMLAttributes(writer, htmlForm, HTML.FORM_PASSTHROUGH_ATTRIBUTES);
134 }
135 }
136
137 writer.write("");
138
139 String encodedPartialActionURL = facesContext.getExternalContext().encodePartialActionURL(actionURL);
140
141 if (encodedActionURL != null && encodedPartialActionURL != null
142 && (!encodedActionURL.equals(encodedPartialActionURL)))
143 {
144 HtmlRendererUtils.renderHiddenInputField(writer, "javax.faces.encodedURL", encodedPartialActionURL);
145 }
146
147
148
149
150 beforeFormElementsStart(facesContext, component);
151
152 MyfacesConfig config = MyfacesConfig.getCurrentInstance(facesContext.getExternalContext());
153 if (config.isRenderFormViewStateAtBegin())
154 {
155 renderViewStateAndHiddenFields(facesContext, component);
156 }
157
158 afterFormElementsStart(facesContext, component);
159 }
160
161 protected String getActionUrl(FacesContext facesContext, UIForm form)
162 {
163 return getActionUrl(facesContext);
164 }
165
166 protected String getMethod(FacesContext facesContext, UIForm form)
167 {
168 return "post";
169 }
170
171 protected String getAcceptCharset(FacesContext facesContext, UIForm form )
172 {
173 return (String)form.getAttributes().get( JSFAttr.ACCEPTCHARSET_ATTR );
174 }
175
176 public void encodeEnd(FacesContext facesContext, UIComponent component)
177 throws IOException
178 {
179 ResponseWriter writer = facesContext.getResponseWriter();
180
181 beforeFormElementsEnd(facesContext, component);
182
183
184 Set set = (Set) facesContext.getExternalContext().getRequestMap().get(
185 getHiddenCommandInputsSetName(facesContext, component));
186 if (set != null && !set.isEmpty())
187 {
188 HtmlRendererUtils.renderHiddenCommandFormParams(writer, set);
189
190 String target;
191 if (component instanceof HtmlForm)
192 {
193 target = ((HtmlForm)component).getTarget();
194 }
195 else
196 {
197 target = (String)component.getAttributes().get(HTML.TARGET_ATTR);
198 }
199 HtmlRendererUtils.renderClearHiddenCommandFormParamsFunction(writer,
200 component.getClientId(facesContext),
201 set,
202 target);
203 }
204
205 MyfacesConfig config = MyfacesConfig.getCurrentInstance(facesContext.getExternalContext());
206 if (!config.isRenderFormViewStateAtBegin())
207 {
208 renderViewStateAndHiddenFields(facesContext, component);
209 }
210
211 afterFormElementsEnd(facesContext, component);
212
213 writer.endElement(HTML.FORM_ELEM);
214 }
215
216 protected void renderViewStateAndHiddenFields(FacesContext facesContext, UIComponent component)
217 throws IOException
218 {
219 ResponseWriter writer = facesContext.getResponseWriter();
220
221
222 writer.startElement(HTML.INPUT_ELEM, null);
223 writer.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_HIDDEN, null);
224 writer.writeAttribute(HTML.NAME_ATTR, component.getClientId(facesContext) +
225 HIDDEN_SUBMIT_INPUT_SUFFIX, null);
226 writer.writeAttribute(HTML.VALUE_ATTR, HIDDEN_SUBMIT_INPUT_VALUE, null);
227 writer.endElement(HTML.INPUT_ELEM);
228
229 renderScrollHiddenInputIfNecessary(component, facesContext, writer);
230
231
232
233
234 ViewHandler viewHandler = facesContext.getApplication().getViewHandler();
235 viewHandler.writeState(facesContext);
236
237 List<UIComponent> componentResources = facesContext.getViewRoot().getComponentResources(facesContext,
238 FORM_TARGET);
239
240 for (int i = 0, size = componentResources.size(); i < size; i++)
241 {
242 UIComponent child = componentResources.get(i);
243 child.encodeAll (facesContext);
244 }
245 }
246
247 private static String getHiddenCommandInputsSetName(FacesContext facesContext, UIComponent form)
248 {
249 StringBuilder buf = new StringBuilder(HIDDEN_COMMAND_INPUTS_SET_ATTR.length()+20);
250 buf.append(HIDDEN_COMMAND_INPUTS_SET_ATTR);
251 buf.append("_");
252 buf.append(form.getClientId(facesContext));
253 return buf.toString();
254 }
255
256 private static String getScrollHiddenInputName(FacesContext facesContext, UIComponent form)
257 {
258 StringBuilder buf = new StringBuilder(SCROLL_HIDDEN_INPUT.length()+20);
259 buf.append(SCROLL_HIDDEN_INPUT);
260 buf.append("_");
261 buf.append(form.getClientId(facesContext));
262 return buf.toString();
263 }
264
265
266 public void decode(FacesContext facesContext, UIComponent component)
267 {
268 org.apache.myfaces.shared.renderkit.RendererUtils.checkParamValidity(facesContext, component, UIForm.class);
269
270
271
272
273
274
275
276
277 UIForm htmlForm = (UIForm)component;
278
279 Map paramMap = facesContext.getExternalContext().getRequestParameterMap();
280 String submittedValue = (String)paramMap.get(component.getClientId(facesContext) +
281 HIDDEN_SUBMIT_INPUT_SUFFIX);
282 if (submittedValue != null && submittedValue.equals(HIDDEN_SUBMIT_INPUT_VALUE))
283 {
284 htmlForm.setSubmitted(true);
285 }
286 else
287 {
288 htmlForm.setSubmitted(false);
289 }
290
291 HtmlRendererUtils.decodeClientBehaviors(facesContext, component);
292 }
293
294
295 public static void addHiddenCommandParameter(FacesContext facesContext, UIComponent form, String paramName)
296 {
297 Set set = (Set) facesContext.getExternalContext().getRequestMap().get(
298 getHiddenCommandInputsSetName(facesContext, form));
299 if (set == null)
300 {
301 set = new HashSet();
302 facesContext.getExternalContext().getRequestMap().put(
303 getHiddenCommandInputsSetName(facesContext, form), set);
304 }
305 set.add(paramName);
306 }
307
308 public static void renderScrollHiddenInputIfNecessary(
309 UIComponent form, FacesContext facesContext, ResponseWriter writer)
310 throws IOException
311 {
312 if (form == null)
313 {
314 return;
315 }
316
317 if (facesContext.getExternalContext().getRequestMap().get(
318 getScrollHiddenInputName(facesContext, form)) == null)
319 {
320 if (MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isAutoScroll())
321 {
322 HtmlRendererUtils.renderAutoScrollHiddenInput(facesContext, writer);
323 }
324 facesContext.getExternalContext().getRequestMap().put(getScrollHiddenInputName(
325 facesContext, form), Boolean.TRUE);
326 }
327 }
328
329
330
331
332
333 protected void beforeFormElementsStart(FacesContext facesContext, UIComponent component)
334 throws IOException
335 {
336
337 }
338
339
340
341
342
343 protected void afterFormElementsStart(FacesContext facesContext, UIComponent component)
344 throws IOException
345 {
346
347 }
348
349
350
351
352
353 protected void beforeFormElementsEnd(FacesContext facesContext, UIComponent component)
354 throws IOException
355 {
356
357 }
358
359
360
361
362
363 protected void afterFormElementsEnd(FacesContext facesContext, UIComponent component)
364 throws IOException
365 {
366
367 }
368 }