1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.struts.faces.renderer;
18
19
20 import java.io.IOException;
21 import java.util.Iterator;
22
23 import javax.faces.component.NamingContainer;
24 import javax.faces.component.UICommand;
25 import javax.faces.component.UIComponent;
26 import javax.faces.component.UIForm;
27 import javax.faces.component.UIParameter;
28 import javax.faces.context.FacesContext;
29 import javax.faces.context.ResponseWriter;
30 import javax.faces.event.ActionEvent;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.apache.struts.Globals;
35 import org.apache.struts.config.ActionConfig;
36 import org.apache.struts.config.ModuleConfig;
37
38
39 /***
40 * <p><code>Renderer</code> implementation for the <code>commandLink</code>
41 * tag from the <em>Struts-Faces Integration Library</em>.</p>
42 *
43 * @version $Rev: 421138 $ $Date: 2006-07-11 22:41:40 -0700 (Tue, 11 Jul 2006) $
44 */
45
46 public class CommandLinkRenderer extends AbstractRenderer {
47
48
49
50
51
52 /***
53 * <p>Token for private names.</p>
54 */
55 private static final String TOKEN =
56 "org_apache_struts_faces_renderer_CommandLinkRenderer";
57
58
59 /***
60 * <p>The <code>Log</code> instance for this class.</p>
61 */
62 private static Log log = LogFactory.getLog(CommandLinkRenderer.class);
63
64
65
66
67
68 /***
69 * <p>Perform setup processing that will be required for decoding the
70 * incoming request.</p>
71 *
72 * @param context FacesContext for the request we are processing
73 * @param component UIComponent to be processed
74 *
75 * @exception NullPointerException if <code>context</code>
76 * or <code>component</code> is null
77 */
78 public void decode(FacesContext context, UIComponent component) {
79
80
81 if ((context == null) || (component == null)) {
82 throw new NullPointerException();
83 }
84
85
86 if (!component.isRendered() || isDisabled(component) ||
87 isReadOnly(component)) {
88 return;
89 }
90
91
92 UIForm form = null;
93 UIComponent parent = component.getParent();
94 while (parent != null) {
95 if (parent instanceof UIForm) {
96 form = (UIForm) parent;
97 break;
98 }
99 parent = parent.getParent();
100 }
101 if (form == null) {
102 log.warn("CommandLinkComponent not nested inside UIForm, ignored");
103 return;
104 }
105
106
107 String paramId = TOKEN;
108 String value = (String)
109 context.getExternalContext().getRequestParameterMap().get(paramId);
110 if ((value == null) || !value.equals(component.getClientId(context))) {
111 if (log.isTraceEnabled()) {
112 log.trace("decode(" + component.getId() + ") --> not active");
113 }
114 return;
115 }
116
117
118 if (log.isTraceEnabled()) {
119 log.trace("decode(" + component.getId() + ") --> queueEvent()");
120 }
121 component.queueEvent(new ActionEvent(component));
122
123 }
124
125
126 private static String passThrough[] =
127 { "accesskey", "charset", "dir", "hreflang", "lang", "onblur",
128
129 "onkeypress", "onkeyup", "onmousedown", "onmousemove",
130 "onmouseout", "onmouseover", "onmouseup", "rel", "rev",
131 "style", "tabindex", "target", "title", "type" };
132
133
134 /***
135 * <p>Render the beginning of a hyperlink to submit this form.</p>
136 *
137 * @param context FacesContext for the request we are processing
138 * @param component UIComponent to be rendered
139 * @param writer ResponseWriter we are rendering to
140 *
141 * @exception IOException if an input/output error occurs while rendering
142 * @exception NullPointerException if <code>context</code>
143 * or <code>component</code> is null
144 */
145 public void renderStart(FacesContext context, UIComponent component,
146 ResponseWriter writer)
147 throws IOException {
148
149
150 if (!component.isRendered() || isDisabled(component) ||
151 isReadOnly(component)) {
152 return;
153 }
154
155
156 UIForm form = null;
157 UIComponent parent = component.getParent();
158 while (parent != null) {
159 if (parent instanceof UIForm) {
160 form = (UIForm) parent;
161 break;
162 }
163 parent = parent.getParent();
164 }
165 if (form == null) {
166 log.warn("CommandLinkComponent not nested inside UIForm, ignored");
167 return;
168 }
169 String formClientId = form.getClientId(context);
170
171
172
173 String key = formClientId + NamingContainer.SEPARATOR_CHAR + TOKEN;
174 if (context.getExternalContext().getRequestMap().get(key) == null) {
175 writer.startElement("input", null);
176 writer.writeAttribute("name", TOKEN, null);
177 writer.writeAttribute("type", "hidden", null);
178 writer.writeAttribute("value", "", null);
179 writer.endElement("input");
180 context.getExternalContext().getRequestMap().put
181 (key, Boolean.TRUE);
182 }
183
184
185
186 writer.startElement("a", component);
187
188 }
189
190
191 /***
192 * <p>Render the attributes of a hyperlink to submit this form.</p>
193 *
194 * @param context FacesContext for the request we are processing
195 * @param component UIComponent to be rendered
196 * @param writer ResponseWriter we are rendering to
197 *
198 * @exception IOException if an input/output error occurs while rendering
199 * @exception NullPointerException if <code>context</code>
200 * or <code>component</code> is null
201 */
202 public void renderAttributes(FacesContext context, UIComponent component,
203 ResponseWriter writer)
204 throws IOException {
205
206
207 if (!component.isRendered() || isDisabled(component) ||
208 isReadOnly(component)) {
209 return;
210 }
211
212
213 UIForm form = null;
214 UIComponent parent = component.getParent();
215 while (parent != null) {
216 if (parent instanceof UIForm) {
217 form = (UIForm) parent;
218 break;
219 }
220 parent = parent.getParent();
221 }
222 if (form == null) {
223 log.warn("CommandLinkComponent not nested inside UIForm, ignored");
224 return;
225 }
226 String formClientId = form.getClientId(context);
227
228
229 if (component.getId() != null) {
230 writer.writeAttribute("id", component.getClientId(context), "id");
231 }
232 writer.writeAttribute("href", "#", null);
233 String styleClass = (String)
234 component.getAttributes().get("styleClass");
235 if (styleClass != null) {
236 writer.writeAttribute("class", styleClass, "styleClass");
237 }
238 renderPassThrough(context, component, writer, passThrough);
239
240
241 StringBuffer sb = new StringBuffer();
242 sb.append("document.forms['");
243 sb.append(formClientId);
244 sb.append("']['");
245 sb.append(TOKEN);
246 sb.append("'].value='");
247 sb.append(component.getClientId(context));
248 sb.append("';");
249 Iterator kids = component.getChildren().iterator();
250 while (kids.hasNext()) {
251 UIComponent kid = (UIComponent) kids.next();
252 if (!(kid instanceof UIParameter)) {
253 continue;
254 }
255 sb.append("document.forms['");
256 sb.append(formClientId);
257 sb.append("']['");
258 sb.append((String) kid.getAttributes().get("name"));
259 sb.append("'].value='");
260 sb.append((String) kid.getAttributes().get("value"));
261 sb.append("';");
262 }
263 sb.append("document.forms['");
264 sb.append(formClientId);
265 sb.append("'].submit(); return false;");
266 writer.writeAttribute("onclick", sb.toString(), null);
267
268
269 Object value = component.getAttributes().get("value");
270 if (value != null) {
271 if (value instanceof String) {
272 writer.write((String) value);
273 } else {
274 writer.write(value.toString());
275 }
276 }
277
278 }
279
280
281 /***
282 * <p>Render the end of a hyperlink to submit this form.</p>
283 *
284 * @param context FacesContext for the request we are processing
285 * @param component UIComponent to be rendered
286 * @param writer ResponseWriter we are rendering to
287 *
288 * @exception IOException if an input/output error occurs while rendering
289 * @exception NullPointerException if <code>context</code>
290 * or <code>component</code> is null
291 */
292 public void renderEnd(FacesContext context, UIComponent component,
293 ResponseWriter writer)
294 throws IOException {
295
296
297 if (!component.isRendered() || isDisabled(component) ||
298 isReadOnly(component)) {
299 return;
300 }
301
302
303 writer.endElement("a");
304
305 }
306
307
308 }