KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > myfaces > renderkit > html > HtmlLinkRendererBase


1 /*
2  * Copyright 2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.myfaces.renderkit.html;
17
18 import org.apache.myfaces.config.MyfacesConfig;
19 import org.apache.myfaces.renderkit.JSFAttr;
20 import org.apache.myfaces.renderkit.RendererUtils;
21 import org.apache.myfaces.renderkit.html.util.DummyFormResponseWriter;
22 import org.apache.myfaces.renderkit.html.util.DummyFormUtils;
23 import org.apache.myfaces.renderkit.html.util.JavascriptUtils;
24
25 import javax.faces.application.StateManager;
26 import javax.faces.application.ViewHandler;
27 import javax.faces.component.*;
28 import javax.faces.component.html.HtmlCommandLink;
29 import javax.faces.context.FacesContext;
30 import javax.faces.context.ResponseWriter;
31 import javax.faces.event.ActionEvent;
32 import java.io.IOException JavaDoc;
33 import java.io.UnsupportedEncodingException JavaDoc;
34 import java.net.URLEncoder JavaDoc;
35 import java.util.Iterator JavaDoc;
36
37 /**
38  * @author Manfred Geiler (latest modification by $Author: svieujot $)
39  * @version $Revision: 1.19 $ $Date: 2005/03/16 16:40:59 $
40  * $Log: HtmlLinkRendererBase.java,v $
41  * Revision 1.19 2005/03/16 16:40:59 svieujot
42  * Call form.onsubmit in HtmlCommandLink (otherwise bypassed by calling directly form.submit.
43  *
44  * Revision 1.18 2004/10/13 11:51:01 matze
45  * renamed packages to org.apache
46  *
47  * Revision 1.17 2004/09/08 15:23:12 manolito
48  * Autoscroll feature
49  *
50  * Revision 1.16 2004/09/08 09:32:03 manolito
51  * MyfacesConfig moved to config package
52  *
53  * Revision 1.15 2004/07/18 21:25:30 o_rossmueller
54  * fix #991234: use hidden field name in link url
55  *
56  * Revision 1.14 2004/07/01 22:00:56 mwessendorf
57  * ASF switch
58  *
59  * Revision 1.13 2004/06/16 23:50:08 o_rossmueller
60  * force separate end tag
61  *
62  * Revision 1.12 2004/06/08 01:34:44 o_rossmueller
63  * render link value if available as required by JSF 1.1 renderkitdocs
64  *
65  * Revision 1.11 2004/06/03 12:57:03 o_rossmueller
66  * modified link renderer to use one hidden field for all links according to 1.1 renderkit docs
67  * added onclick=clear_XXX to button
68  *
69  * Revision 1.10 2004/05/18 14:31:39 manolito
70  * user role support completely moved to components source tree
71  *
72  * Revision 1.9 2004/05/18 12:02:29 manolito
73  * getActionURL and getResourceURL must not call encodeActionURL or encodeResourceURL
74  *
75  * Revision 1.8 2004/05/12 01:50:47 o_rossmueller
76  * fix #951896: add state params once is enough ;-)
77  *
78  * Revision 1.7 2004/05/12 01:41:32 o_rossmueller
79  * fix #951896: added state params to link URLs for ALLOW_JAVASCRIPT=false
80  *
81  * Revision 1.6 2004/05/04 06:36:21 manolito
82  * Bugfix #947302
83  *
84  * Revision 1.5 2004/04/29 19:34:38 o_rossmueller
85  * javascript for 'target' attribute handling
86  *
87  * Revision 1.4 2004/04/27 10:32:24 manolito
88  * clear hidden inputs javascript function
89  *
90  * Revision 1.3 2004/04/05 11:14:05 manolito
91  * removed isVisibleOnUserRole
92  *
93  * Revision 1.2 2004/03/31 14:50:34 manolito
94  * bug fix
95  *
96  * Revision 1.1 2004/03/31 11:58:44 manolito
97  * custom component refactoring
98  *
99  */

100 public abstract class HtmlLinkRendererBase
101     extends HtmlRenderer
102 {
103
104     public static final String JavaDoc URL_STATE_MARKER = "JSF_URL_STATE_MARKER=DUMMY";
105     public static final int URL_STATE_MARKER_LEN = URL_STATE_MARKER.length();
106
107     //private static final Log log = LogFactory.getLog(HtmlLinkRenderer.class);
108

109     public boolean getRendersChildren()
110     {
111         // We must be able to render the children without a surrounding anchor
112
// if the Link is disabled
113
return true;
114     }
115
116     public void decode(FacesContext facesContext, UIComponent component)
117     {
118         super.decode(facesContext, component); //check for NP
119

120         if (component instanceof UICommand)
121         {
122             String JavaDoc clientId = component.getClientId(facesContext);
123             String JavaDoc reqValue = (String JavaDoc)facesContext.getExternalContext().getRequestParameterMap().get(HtmlRendererUtils.getHiddenCommandLinkFieldName(HtmlRendererUtils.getFormName(component, facesContext)));
124             if (reqValue != null && reqValue.equals(clientId))
125             {
126                 component.queueEvent(new ActionEvent(component));
127             }
128         }
129         else if (component instanceof UIOutput)
130         {
131             //do nothing
132
}
133         else
134         {
135             throw new IllegalArgumentException JavaDoc("Unsupported component class " + component.getClass().getName());
136         }
137     }
138
139
140     public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException JavaDoc
141     {
142         super.encodeBegin(facesContext, component); //check for NP
143

144         if (component instanceof UICommand)
145         {
146             renderCommandLinkStart(facesContext, component,
147                                    component.getClientId(facesContext),
148                                    ((UICommand)component).getValue(),
149                                    getStyle(facesContext, component),
150                                    getStyleClass(facesContext, component));
151         }
152         else if (component instanceof UIOutput)
153         {
154             renderOutputLinkStart(facesContext, (UIOutput)component);
155         }
156         else
157         {
158             throw new IllegalArgumentException JavaDoc("Unsupported component class " + component.getClass().getName());
159         }
160     }
161
162
163     /**
164      * Can be overwritten by derived classes to overrule the style to be used.
165      */

166     protected String JavaDoc getStyle(FacesContext facesContext, UIComponent link)
167     {
168         if (link instanceof HtmlCommandLink)
169         {
170             return ((HtmlCommandLink)link).getStyle();
171         }
172         else
173         {
174             return (String JavaDoc)link.getAttributes().get(HTML.STYLE_ATTR);
175         }
176     }
177
178     /**
179      * Can be overwritten by derived classes to overrule the style class to be used.
180      */

181     protected String JavaDoc getStyleClass(FacesContext facesContext, UIComponent link)
182     {
183         if (link instanceof HtmlCommandLink)
184         {
185             return ((HtmlCommandLink)link).getStyleClass();
186         }
187         else
188         {
189             return (String JavaDoc)link.getAttributes().get(HTML.STYLE_CLASS_ATTR);
190         }
191     }
192
193     public void encodeChildren(FacesContext facesContext, UIComponent component) throws IOException JavaDoc
194     {
195         RendererUtils.renderChildren(facesContext, component);
196     }
197
198     public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException JavaDoc
199     {
200         super.encodeEnd(facesContext, component); //check for NP
201
renderLinkEnd(facesContext, component);
202     }
203
204     protected void renderCommandLinkStart(FacesContext facesContext, UIComponent component,
205                                           String JavaDoc clientId,
206                                           Object JavaDoc value,
207                                           String JavaDoc style,
208                                           String JavaDoc styleClass)
209             throws IOException JavaDoc
210     {
211         ResponseWriter writer = facesContext.getResponseWriter();
212
213         if (JavascriptUtils.isJavascriptAllowed(facesContext.getExternalContext()))
214         {
215             renderJavaScriptAnchorStart(facesContext, writer, component, clientId);
216         }
217         else
218         {
219             renderNonJavaScriptAnchorStart(facesContext, writer, component, clientId);
220         }
221
222         writer.writeAttribute(HTML.ID_ATTR, clientId, null);
223         HtmlRendererUtils.renderHTMLAttributes(writer, component,
224                                                HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_STYLE);
225         HtmlRendererUtils.renderHTMLAttribute(writer, HTML.STYLE_ATTR, HTML.STYLE_ATTR,
226                                               style);
227         HtmlRendererUtils.renderHTMLAttribute(writer, HTML.STYLE_CLASS_ATTR, HTML.STYLE_CLASS_ATTR,
228                                               styleClass);
229
230         // render value as required by JSF 1.1 renderkitdocs
231
if(value != null)
232         {
233             writer.writeText(value.toString(), JSFAttr.VALUE_ATTR);
234         }
235     }
236
237     protected void renderJavaScriptAnchorStart(FacesContext facesContext,
238                                                ResponseWriter writer,
239                                                UIComponent component,
240                                                String JavaDoc clientId)
241         throws IOException JavaDoc
242     {
243         //Find form
244
UIComponent parent = component.getParent();
245         while (parent != null && !(parent instanceof UIForm))
246         {
247             parent = parent.getParent();
248         }
249
250         UIForm nestingForm = null;
251         String JavaDoc formName;
252         DummyFormResponseWriter dummyFormResponseWriter;
253         if (parent != null)
254         {
255             //link is nested inside a form
256
nestingForm = (UIForm)parent;
257             formName = nestingForm.getClientId(facesContext);
258             dummyFormResponseWriter = null;
259         }
260         else
261         {
262             //not nested in form, we must add a dummy form at the end of the document
263
formName = DummyFormUtils.DUMMY_FORM_NAME;
264             dummyFormResponseWriter = DummyFormUtils.getDummyFormResponseWriter(facesContext);
265             dummyFormResponseWriter.setWriteDummyForm(true);
266         }
267
268         StringBuffer JavaDoc onClick = new StringBuffer JavaDoc();
269
270         String JavaDoc commandOnclick;
271         if (component instanceof HtmlCommandLink)
272         {
273             commandOnclick = ((HtmlCommandLink)component).getOnclick();
274         }
275         else
276         {
277             commandOnclick = (String JavaDoc)component.getAttributes().get(HTML.ONCLICK_ATTR);
278         }
279         if (commandOnclick != null)
280         {
281             onClick.append(commandOnclick);
282             onClick.append(';');
283         }
284
285         //call the clear_<formName> method
286
onClick.append(HtmlRendererUtils.getClearHiddenCommandFormParamsFunctionName(formName)).append("();");
287
288         String JavaDoc jsForm = "document.forms['" + formName + "']";
289
290         if (MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isAutoScroll())
291         {
292             JavascriptUtils.appendAutoScrollAssignment(onClick, formName);
293         }
294
295         //add id parameter for decode
296
String JavaDoc hiddenFieldName = HtmlRendererUtils.getHiddenCommandLinkFieldName(formName);
297         onClick.append(jsForm);
298         onClick.append(".elements['").append(hiddenFieldName).append("']");
299         onClick.append(".value='").append(clientId).append("';");
300         if (nestingForm != null)
301         {
302             HtmlFormRendererBase.addHiddenCommandParameter(nestingForm, hiddenFieldName);
303         }
304         else
305         {
306             dummyFormResponseWriter.addDummyFormParameter(hiddenFieldName);
307         }
308
309         //add child parameters
310
for (Iterator JavaDoc it = component.getChildren().iterator(); it.hasNext(); )
311         {
312             UIComponent child = (UIComponent)it.next();
313             if (child instanceof UIParameter)
314             {
315                 String JavaDoc name = ((UIParameter)child).getName();
316                 Object JavaDoc value = ((UIParameter)child).getValue();
317
318                 renderLinkParameter(dummyFormResponseWriter, name, value, onClick, jsForm, nestingForm);
319             }
320         }
321
322         // target
323
String JavaDoc target = ((HtmlCommandLink)component).getTarget();
324         if (target != null && target.trim().length() > 0) {
325             onClick.append(jsForm);
326             onClick.append(".target='");
327             onClick.append(target);
328             onClick.append("';");
329         }
330         
331         // onSubmit
332
onClick.append("if("+jsForm+".onsubmit){"+jsForm+".onsubmit();}");
333         
334         //submit
335
onClick.append(jsForm);
336         onClick.append(".submit();return false;"); //return false, so that browser does not handle the click
337

338         writer.startElement(HTML.ANCHOR_ELEM, component);
339         writer.writeURIAttribute(HTML.HREF_ATTR, "#", null);
340         writer.writeAttribute(HTML.ONCLICK_ATTR, onClick.toString(), null);
341     }
342
343
344     protected void renderNonJavaScriptAnchorStart(FacesContext facesContext,
345                                                   ResponseWriter writer,
346                                                   UIComponent component,
347                                                   String JavaDoc clientId)
348         throws IOException JavaDoc
349     {
350         ViewHandler viewHandler = facesContext.getApplication().getViewHandler();
351         String JavaDoc viewId = facesContext.getViewRoot().getViewId();
352         String JavaDoc path = viewHandler.getActionURL(facesContext, viewId);
353
354         StringBuffer JavaDoc hrefBuf = new StringBuffer JavaDoc(path);
355
356         //add clientId parameter for decode
357

358         if (path.indexOf('?') == -1)
359         {
360             hrefBuf.append('?');
361         }
362         else
363         {
364             hrefBuf.append('&');
365         }
366         String JavaDoc hiddenFieldName = HtmlRendererUtils.getHiddenCommandLinkFieldName(HtmlRendererUtils.getFormName(component, facesContext));
367         hrefBuf.append(hiddenFieldName);
368         hrefBuf.append('=');
369         hrefBuf.append(clientId);
370
371         if (component.getChildCount() > 0)
372         {
373             addChildParametersToHref(component, hrefBuf,
374                                      false, //not the first url parameter
375
writer.getCharacterEncoding());
376         }
377
378         StateManager stateManager = facesContext.getApplication().getStateManager();
379         if (stateManager.isSavingStateInClient(facesContext))
380         {
381             hrefBuf.append("&");
382             hrefBuf.append(URL_STATE_MARKER);
383         }
384         String JavaDoc href = facesContext.getExternalContext().encodeActionURL(hrefBuf.toString());
385         writer.startElement(HTML.ANCHOR_ELEM, component);
386         writer.writeURIAttribute(HTML.HREF_ATTR,
387                                  facesContext.getExternalContext().encodeActionURL(href),
388                                  null);
389     }
390
391     private void addChildParametersToHref(UIComponent linkComponent,
392                                           StringBuffer JavaDoc hrefBuf,
393                                           boolean firstParameter,
394                                           String JavaDoc charEncoding)
395             throws IOException JavaDoc
396     {
397         for (Iterator JavaDoc it = linkComponent.getChildren().iterator(); it.hasNext(); )
398         {
399             UIComponent child = (UIComponent)it.next();
400             if (child instanceof UIParameter)
401             {
402                 String JavaDoc name = ((UIParameter)child).getName();
403                 Object JavaDoc value = ((UIParameter)child).getValue();
404
405                 addParameterToHref(name, value, hrefBuf, firstParameter, charEncoding);
406                 firstParameter = false;
407             }
408         }
409     }
410
411     protected void renderOutputLinkStart(FacesContext facesContext, UIOutput output)
412             throws IOException JavaDoc
413     {
414         ResponseWriter writer = facesContext.getResponseWriter();
415
416         //calculate href
417
String JavaDoc href = RendererUtils.getStringValue(facesContext, output);
418         if (output.getChildCount() > 0)
419         {
420             StringBuffer JavaDoc hrefBuf = new StringBuffer JavaDoc(href);
421             addChildParametersToHref(output, hrefBuf,
422                                      (href.indexOf('?') == -1), //first url parameter?
423
writer.getCharacterEncoding());
424             href = hrefBuf.toString();
425         }
426         href = facesContext.getExternalContext().encodeResourceURL(href); //TODO: or encodeActionURL ?
427

428         //write anchor
429
writer.startElement(HTML.ANCHOR_ELEM, output);
430         writer.writeAttribute(HTML.ID_ATTR, output.getClientId(facesContext), null);
431         writer.writeURIAttribute(HTML.HREF_ATTR, href, null);
432         HtmlRendererUtils.renderHTMLAttributes(writer, output, HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES);
433         writer.flush();
434     }
435
436     private void renderLinkParameter(DummyFormResponseWriter dummyFormResponseWriter,
437                                      String JavaDoc name,
438                                      Object JavaDoc value,
439                                      StringBuffer JavaDoc onClick,
440                                      String JavaDoc jsForm,
441                                      UIForm nestingForm)
442     {
443         if (name == null)
444         {
445             throw new IllegalArgumentException JavaDoc("Unnamed parameter value not allowed within command link.");
446         }
447         onClick.append(jsForm);
448         onClick.append(".elements['").append(name).append("']");
449         //UIParameter is no ValueHolder, so no conversion possible
450
String JavaDoc strParamValue = value != null ? value.toString() : ""; //TODO: Use Converter?
451
onClick.append(".value='").append(strParamValue).append("';");
452
453         if (nestingForm != null)
454         {
455             //renderHiddenParam(writer, name);
456
HtmlFormRendererBase.addHiddenCommandParameter(nestingForm, name);
457         }
458         else
459         {
460             dummyFormResponseWriter.addDummyFormParameter(name);
461         }
462     }
463
464     private static void addParameterToHref(String JavaDoc name, Object JavaDoc value, StringBuffer JavaDoc hrefBuf, boolean firstParameter, String JavaDoc charEncoding)
465             throws UnsupportedEncodingException JavaDoc
466     {
467         if (name == null)
468         {
469             throw new IllegalArgumentException JavaDoc("Unnamed parameter value not allowed within command link.");
470         }
471
472         hrefBuf.append(firstParameter ? '?' : '&');
473         hrefBuf.append(URLEncoder.encode(name, charEncoding));
474         hrefBuf.append('=');
475         if (value != null)
476         {
477             //UIParameter is no ConvertibleValueHolder, so no conversion possible
478
hrefBuf.append(URLEncoder.encode(value.toString(), charEncoding));
479         }
480     }
481
482
483     protected void renderLinkEnd(FacesContext facesContext, UIComponent component)
484             throws IOException JavaDoc
485     {
486         ResponseWriter writer = facesContext.getResponseWriter();
487         // force separate end tag
488
writer.writeText("", null);
489         writer.endElement(HTML.ANCHOR_ELEM);
490     }
491
492
493 }
494
Popular Tags