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