1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.shared_orchestra.renderkit.html;
20
21 import org.apache.myfaces.shared_orchestra.config.MyfacesConfig;
22 import org.apache.myfaces.shared_orchestra.renderkit.RendererUtils;
23 import org.apache.myfaces.shared_orchestra.renderkit.JSFAttr;
24 import org.apache.myfaces.shared_orchestra.renderkit.html.util.FormInfo;
25
26 import javax.faces.FacesException;
27 import javax.faces.application.ViewHandler;
28 import javax.faces.component.UIComponent;
29 import javax.faces.component.UIForm;
30 import javax.faces.component.html.HtmlForm;
31 import javax.faces.context.FacesContext;
32 import javax.faces.context.ResponseWriter;
33 import java.io.IOException;
34 import java.util.HashSet;
35 import java.util.Map;
36 import java.util.Set;
37
38
39
40
41
42
43
44 public class HtmlFormRendererBase
45 extends HtmlRenderer {
46
47
48 private static final String HIDDEN_SUBMIT_INPUT_SUFFIX = "_SUBMIT";
49 private static final String HIDDEN_SUBMIT_INPUT_VALUE = "1";
50
51 private static final String HIDDEN_COMMAND_INPUTS_SET_ATTR
52 = UIForm.class.getName() + ".org.apache.myfaces.HIDDEN_COMMAND_INPUTS_SET";
53
54 private static final String VALIDATE_CONTEXT_PARAM = "org.apache.myfaces.VALIDATE";
55 private static final String SCROLL_HIDDEN_INPUT = "org.apache.myfaces.SCROLL_HIDDEN_INPUT";
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 private static final String FORM_CLIENT_ID_ATTR = "com.sun.faces.FORM_CLIENT_ID_ATTR";
75
76
77 public void encodeBegin(FacesContext facesContext, UIComponent component)
78 throws IOException {
79 org.apache.myfaces.shared_orchestra.renderkit.RendererUtils.checkParamValidity(facesContext, component, UIForm.class);
80
81
82
83 facesContext.getExternalContext().getRequestMap().put(FORM_CLIENT_ID_ATTR,
84 component.getClientId(facesContext));
85
86 if ("true".equals(facesContext.getExternalContext().getInitParameter(VALIDATE_CONTEXT_PARAM))) {
87 FormInfo info = RendererUtils.findNestingForm(component, facesContext);
88
89 if (info != null && info.getForm() != null) {
90 throw new FacesException("You should never nest HTML-forms. " +
91 "This leads to unpredictable behaviour in all major browsers. " +
92 "You can use multiple forms on a page, but they may not be nested!" +
93 "If you need to disable this check (on your own risk!) set the param " +
94 "org.apache.myfaces.VALIDATE in your web.xml context parameters to false");
95 }
96 }
97
98 UIForm htmlForm = (UIForm) component;
99
100 ResponseWriter writer = facesContext.getResponseWriter();
101 String clientId = htmlForm.getClientId(facesContext);
102 String actionURL = getActionUrl(facesContext, htmlForm);
103 String method = getMethod(facesContext, htmlForm);
104 String acceptCharset = getAcceptCharset(facesContext, htmlForm);
105
106 writer.startElement(HTML.FORM_ELEM, htmlForm);
107 writer.writeAttribute(HTML.ID_ATTR, clientId, null);
108 writer.writeAttribute(HTML.NAME_ATTR, clientId, null);
109 writer.writeAttribute(HTML.METHOD_ATTR, method, null);
110 if((acceptCharset != null) && (acceptCharset.compareTo("")!=0)) writer.writeAttribute(HTML.ACCEPT_CHARSET_ATTR, acceptCharset, null);
111 writer.writeURIAttribute(HTML.ACTION_ATTR,
112 facesContext.getExternalContext().encodeActionURL(actionURL),
113 null);
114
115 HtmlRendererUtils.renderHTMLAttributes(writer, htmlForm, HTML.FORM_PASSTHROUGH_ATTRIBUTES);
116
117 writer.write("");
118
119
120
121
122 beforeFormElementsStart(facesContext, component);
123 afterFormElementsStart(facesContext, component);
124 }
125
126 protected String getActionUrl(FacesContext facesContext, UIForm form) {
127 return getActionUrl(facesContext);
128 }
129
130 protected String getMethod(FacesContext facesContext, UIForm form) {
131 return "post";
132 }
133
134 protected String getAcceptCharset(FacesContext facesContext, UIForm form ) {
135 return (String)form.getAttributes().get( JSFAttr.ACCEPTCHARSET_ATTR );
136 }
137
138 public void encodeEnd(FacesContext facesContext, UIComponent component)
139 throws IOException {
140 ResponseWriter writer = facesContext.getResponseWriter();
141
142 beforeFormElementsEnd(facesContext, component);
143
144
145 writer.startElement(HTML.INPUT_ELEM, component);
146 writer.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_HIDDEN, null);
147 writer.writeAttribute(HTML.NAME_ATTR, component.getClientId(facesContext) +
148 HIDDEN_SUBMIT_INPUT_SUFFIX, null);
149 writer.writeAttribute(HTML.VALUE_ATTR, HIDDEN_SUBMIT_INPUT_VALUE, null);
150 writer.endElement(HTML.INPUT_ELEM);
151
152 renderScrollHiddenInputIfNecessary(component, facesContext, writer);
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167 Set set = (Set) facesContext.getExternalContext().getRequestMap().get(
168 getHiddenCommandInputsSetName(facesContext, component));
169 if (set != null && !set.isEmpty()) {
170 HtmlRendererUtils.renderHiddenCommandFormParams(writer, set);
171
172 String target;
173 if (component instanceof HtmlForm) {
174 target = ((HtmlForm) component).getTarget();
175 }
176 else {
177 target = (String) component.getAttributes().get(HTML.TARGET_ATTR);
178 }
179 HtmlRendererUtils.renderClearHiddenCommandFormParamsFunction(writer,
180 component.getClientId(facesContext),
181 set,
182 target);
183 }
184
185
186
187
188 ViewHandler viewHandler = facesContext.getApplication().getViewHandler();
189 viewHandler.writeState(facesContext);
190
191 afterFormElementsEnd(facesContext, component);
192 writer.endElement(HTML.FORM_ELEM);
193 }
194
195 private static String getHiddenCommandInputsSetName(FacesContext facesContext, UIComponent form) {
196 StringBuffer buf = new StringBuffer();
197 buf.append(HIDDEN_COMMAND_INPUTS_SET_ATTR);
198 buf.append("_");
199 buf.append(form.getClientId(facesContext));
200 return buf.toString();
201 }
202
203 private static String getScrollHiddenInputName(FacesContext facesContext, UIComponent form) {
204 StringBuffer buf = new StringBuffer();
205 buf.append(SCROLL_HIDDEN_INPUT);
206 buf.append("_");
207 buf.append(form.getClientId(facesContext));
208 return buf.toString();
209 }
210
211
212 public void decode(FacesContext facesContext, UIComponent component) {
213 org.apache.myfaces.shared_orchestra.renderkit.RendererUtils.checkParamValidity(facesContext, component, UIForm.class);
214
215
216
217
218
219
220
221
222 UIForm htmlForm = (UIForm) component;
223
224 Map paramMap = facesContext.getExternalContext().getRequestParameterMap();
225 String submittedValue = (String) paramMap.get(component.getClientId(facesContext) +
226 HIDDEN_SUBMIT_INPUT_SUFFIX);
227 if (submittedValue != null && submittedValue.equals(HIDDEN_SUBMIT_INPUT_VALUE)) {
228 htmlForm.setSubmitted(true);
229 }
230 else {
231 htmlForm.setSubmitted(false);
232 }
233 }
234
235
236 public static void addHiddenCommandParameter(FacesContext facesContext, UIComponent form, String paramName) {
237 Set set = (Set) facesContext.getExternalContext().getRequestMap().get(getHiddenCommandInputsSetName(facesContext, form));
238 if (set == null) {
239 set = new HashSet();
240 facesContext.getExternalContext().getRequestMap().put(getHiddenCommandInputsSetName(facesContext, form), set);
241 }
242 set.add(paramName);
243 }
244
245 public static void renderScrollHiddenInputIfNecessary(UIComponent form, FacesContext facesContext, ResponseWriter writer)
246 throws IOException {
247 if (form == null) {
248 return;
249 }
250
251 if (facesContext.getExternalContext().getRequestMap().get(getScrollHiddenInputName(facesContext, form)) == null)
252 {
253 if (MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isAutoScroll()) {
254 HtmlRendererUtils.renderAutoScrollHiddenInput(facesContext, writer);
255 }
256 facesContext.getExternalContext().getRequestMap().put(getScrollHiddenInputName(facesContext, form), Boolean.TRUE);
257 }
258 }
259
260
261
262
263
264 protected void beforeFormElementsStart(FacesContext facesContext, UIComponent component)
265 throws IOException {
266 }
267
268
269
270
271
272 protected void afterFormElementsStart(FacesContext facesContext, UIComponent component)
273 throws IOException {
274 }
275
276
277
278
279
280 protected void beforeFormElementsEnd(FacesContext facesContext, UIComponent component)
281 throws IOException {
282 }
283
284
285
286
287
288 protected void afterFormElementsEnd(FacesContext facesContext, UIComponent component)
289 throws IOException {
290 }
291 }