001: /*
002: * Copyright 2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.myfaces.shared_impl.renderkit.html;
017:
018: import org.apache.myfaces.shared_impl.config.MyfacesConfig;
019: import org.apache.myfaces.shared_impl.renderkit.JSFAttr;
020:
021: import javax.faces.application.ViewHandler;
022: import javax.faces.component.UIComponent;
023: import javax.faces.component.UIForm;
024: import javax.faces.component.html.HtmlForm;
025: import javax.faces.context.FacesContext;
026: import javax.faces.context.ResponseWriter;
027: import java.io.IOException;
028: import java.util.HashSet;
029: import java.util.Map;
030: import java.util.Set;
031:
032: /**
033: * @author Manfred Geiler (latest modification by $Author: baranda $)
034: * @author Thomas Spiegl
035: * @author Anton Koinov
036: * @version $Revision: 544646 $ $Date: 2007-06-05 23:51:27 +0200 (Di, 05 Jun 2007) $
037: */
038: public class HtmlFormRendererBase extends HtmlRenderer {
039: //private static final Log log = LogFactory.getLog(HtmlFormRenderer.class);
040:
041: private static final String HIDDEN_SUBMIT_INPUT_SUFFIX = "_SUBMIT";
042: private static final String HIDDEN_SUBMIT_INPUT_VALUE = "1";
043:
044: private static final String HIDDEN_COMMAND_INPUTS_SET_ATTR = UIForm.class
045: .getName()
046: + ".org.apache.myfaces.HIDDEN_COMMAND_INPUTS_SET";
047:
048: private static final String SCROLL_HIDDEN_INPUT = "org.apache.myfaces.SCROLL_HIDDEN_INPUT";
049:
050: public void encodeBegin(FacesContext facesContext,
051: UIComponent component) throws IOException {
052: org.apache.myfaces.shared_impl.renderkit.RendererUtils
053: .checkParamValidity(facesContext, component,
054: UIForm.class);
055:
056: UIForm htmlForm = (UIForm) component;
057:
058: ResponseWriter writer = facesContext.getResponseWriter();
059: String clientId = htmlForm.getClientId(facesContext);
060: String acceptCharset = getAcceptCharset(htmlForm);
061: String actionURL = getActionUrl(facesContext);
062:
063: writer.startElement(HTML.FORM_ELEM, htmlForm);
064: writer.writeAttribute(HTML.ID_ATTR, clientId, null);
065: writer.writeAttribute(HTML.NAME_ATTR, clientId, null);
066: writer.writeAttribute(HTML.METHOD_ATTR, "post", null);
067: if (acceptCharset != null) {
068: writer.writeAttribute(HTML.ACCEPT_CHARSET_ATTR,
069: acceptCharset, null);
070: }
071: writer.writeURIAttribute(HTML.ACTION_ATTR, facesContext
072: .getExternalContext().encodeActionURL(actionURL), null);
073:
074: HtmlRendererUtils.renderHTMLAttributes(writer, htmlForm,
075: HTML.FORM_PASSTHROUGH_ATTRIBUTES);
076:
077: writer.write(""); // force start element tag to be closed
078:
079: // not needed in this version as nothing is written to the form tag, but
080: // included for backward compatibility to the 1.1.1 patch (JIRA MYFACES-1276)
081: // However, might be needed in the future
082: beforeFormElementsStart(facesContext, component);
083: afterFormElementsStart(facesContext, component);
084: }
085:
086: protected String getActionUrl(FacesContext facesContext, UIForm form) {
087: return getActionUrl(facesContext);
088: }
089:
090: protected String getMethod(FacesContext facesContext, UIForm form) {
091: return "post";
092: }
093:
094: protected String getAcceptCharset(FacesContext facesContext,
095: UIForm form) {
096: return (String) form.getAttributes().get(
097: JSFAttr.ACCEPTCHARSET_ATTR);
098: }
099:
100: public void encodeEnd(FacesContext facesContext,
101: UIComponent component) throws IOException {
102: ResponseWriter writer = facesContext.getResponseWriter();
103:
104: beforeFormElementsEnd(facesContext, component);
105:
106: //render hidden command inputs
107: Set set = (Set) component.getAttributes().get(
108: HIDDEN_COMMAND_INPUTS_SET_ATTR);
109: if (set != null && !set.isEmpty()) {
110: HtmlRendererUtils
111: .renderHiddenCommandFormParams(writer, set);
112:
113: String target;
114: if (component instanceof HtmlForm) {
115: target = ((HtmlForm) component).getTarget();
116: } else {
117: target = (String) component.getAttributes().get(
118: HTML.TARGET_ATTR);
119: }
120: HtmlRendererUtils
121: .renderClearHiddenCommandFormParamsFunction(writer,
122: component.getClientId(facesContext), set,
123: target);
124: }
125:
126: //write hidden input to determine "submitted" value on decode
127: writer.startElement(HTML.INPUT_ELEM, component);
128: writer.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_HIDDEN,
129: null);
130: writer.writeAttribute(HTML.NAME_ATTR, component
131: .getClientId(facesContext)
132: + HIDDEN_SUBMIT_INPUT_SUFFIX, null);
133: writer.writeAttribute(HTML.VALUE_ATTR,
134: HIDDEN_SUBMIT_INPUT_VALUE, null);
135: writer.endElement(HTML.INPUT_ELEM);
136:
137: renderScrollHiddenInputIfNecessary(component, facesContext,
138: writer);
139:
140: if (!facesContext.getApplication().getStateManager()
141: .isSavingStateInClient(facesContext)) {
142: writer.startElement(HTML.INPUT_ELEM, component);
143: writer.writeAttribute(HTML.TYPE_ATTR,
144: HTML.INPUT_TYPE_HIDDEN, null);
145: writer
146: .writeAttribute(
147: HTML.NAME_ATTR,
148: org.apache.myfaces.shared_impl.renderkit.RendererUtils.SEQUENCE_PARAM,
149: null);
150: writer
151: .writeAttribute(
152: org.apache.myfaces.shared_impl.renderkit.html.HTML.VALUE_ATTR,
153: org.apache.myfaces.shared_impl.renderkit.RendererUtils
154: .getViewSequence(facesContext),
155: null);
156: writer.endElement(HTML.INPUT_ELEM);
157: }
158:
159: //write state marker at the end of the form
160: //Todo: this breaks client-side enabled AJAX components again which are searching for the state
161: //we'll need to fix this
162: ViewHandler viewHandler = facesContext.getApplication()
163: .getViewHandler();
164: viewHandler.writeState(facesContext);
165:
166: afterFormElementsEnd(facesContext, component);
167: writer.endElement(HTML.FORM_ELEM);
168: }
169:
170: private static String getHiddenCommandInputsSetName(
171: FacesContext facesContext, UIComponent form) {
172: StringBuffer buf = new StringBuffer();
173: buf.append(HIDDEN_COMMAND_INPUTS_SET_ATTR);
174: buf.append("_");
175: buf.append(form.getClientId(facesContext));
176: return buf.toString();
177: }
178:
179: private static String getScrollHiddenInputName(
180: FacesContext facesContext, UIComponent form) {
181: StringBuffer buf = new StringBuffer();
182: buf.append(SCROLL_HIDDEN_INPUT);
183: buf.append("_");
184: buf.append(form.getClientId(facesContext));
185: return buf.toString();
186: }
187:
188: public void decode(FacesContext facesContext, UIComponent component) {
189: org.apache.myfaces.shared_impl.renderkit.RendererUtils
190: .checkParamValidity(facesContext, component,
191: UIForm.class);
192:
193: /*
194: if (HTMLUtil.isDisabled(component))
195: {
196: return;
197: }
198: */
199:
200: UIForm htmlForm = (UIForm) component;
201:
202: Map paramMap = facesContext.getExternalContext()
203: .getRequestParameterMap();
204: String submittedValue = (String) paramMap.get(component
205: .getClientId(facesContext)
206: + HIDDEN_SUBMIT_INPUT_SUFFIX);
207: if (submittedValue != null
208: && submittedValue.equals(HIDDEN_SUBMIT_INPUT_VALUE)) {
209: htmlForm.setSubmitted(true);
210: } else {
211: htmlForm.setSubmitted(false);
212: }
213: }
214:
215: public static void addHiddenCommandParameter(
216: FacesContext facesContext, UIComponent form,
217: String paramName) {
218: Set set = (Set) facesContext.getExternalContext()
219: .getRequestMap().get(
220: getHiddenCommandInputsSetName(facesContext,
221: form));
222: if (set == null) {
223: set = new HashSet();
224: facesContext.getExternalContext().getRequestMap().put(
225: getHiddenCommandInputsSetName(facesContext, form),
226: set);
227: }
228: set.add(paramName);
229: }
230:
231: public static void renderScrollHiddenInputIfNecessary(
232: UIComponent form, FacesContext facesContext,
233: ResponseWriter writer) throws IOException {
234: if (form == null) {
235: return;
236: }
237:
238: if (facesContext.getExternalContext().getRequestMap().get(
239: getScrollHiddenInputName(facesContext, form)) == null) {
240: if (MyfacesConfig.getCurrentInstance(
241: facesContext.getExternalContext()).isAutoScroll()) {
242: HtmlRendererUtils.renderAutoScrollHiddenInput(
243: facesContext, writer);
244: }
245: facesContext.getExternalContext().getRequestMap().put(
246: getScrollHiddenInputName(facesContext, form),
247: Boolean.TRUE);
248: }
249: }
250:
251: private String getAcceptCharset(UIComponent uiComponent) {
252: if (uiComponent instanceof HtmlForm) {
253: return ((HtmlForm) uiComponent).getAcceptcharset();
254: }
255: return (String) uiComponent.getAttributes().get(
256: JSFAttr.ACCEPTCHARSET_ATTR);
257: }
258:
259: /**
260: * Called before the state and any elements are added to the form tag in the
261: * encodeBegin method
262: */
263: protected void beforeFormElementsStart(FacesContext facesContext,
264: UIComponent component) throws IOException {
265: }
266:
267: /**
268: * Called after the state and any elements are added to the form tag in the
269: * encodeBegin method
270: */
271: protected void afterFormElementsStart(FacesContext facesContext,
272: UIComponent component) throws IOException {
273: }
274:
275: /**
276: * Called before the state and any elements are added to the form tag in the
277: * encodeEnd method
278: */
279: protected void beforeFormElementsEnd(FacesContext facesContext,
280: UIComponent component) throws IOException {
281: }
282:
283: /**
284: * Called after the state and any elements are added to the form tag in the
285: * encodeEnd method
286: */
287: protected void afterFormElementsEnd(FacesContext facesContext,
288: UIComponent component) throws IOException {
289: }
290: }
|