1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.myfaces.custom.ajax.api;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.apache.myfaces.component.html.ext.UIComponentPerspective;
25 import org.apache.myfaces.custom.ajax.util.AjaxRendererUtils;
26 import org.apache.myfaces.custom.inputAjax.HtmlCommandButtonAjax;
27 import org.apache.myfaces.custom.util.URIComponentUtils;
28 import org.apache.myfaces.shared_tomahawk.component.ExecuteOnCallback;
29 import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
30 import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlResponseWriterImpl;
31 import org.apache.myfaces.shared_tomahawk.renderkit.html.util.FormInfo;
32
33 import javax.faces.application.StateManager;
34 import javax.faces.component.UIComponent;
35 import javax.faces.component.UIViewRoot;
36 import javax.faces.context.FacesContext;
37 import javax.faces.event.PhaseEvent;
38 import javax.faces.event.PhaseId;
39 import javax.faces.event.PhaseListener;
40 import javax.servlet.ServletRequest;
41 import javax.servlet.ServletResponse;
42 import java.io.IOException;
43 import java.io.PrintWriter;
44 import java.util.Iterator;
45 import java.util.List;
46 import java.util.Map;
47 import java.util.Set;
48
49
50
51
52
53
54
55
56 public class AjaxDecodePhaseListener
57 implements PhaseListener
58 {
59 private static Log log = LogFactory.getLog(AjaxDecodePhaseListener.class);
60
61
62
63
64
65
66
67 public PhaseId getPhaseId()
68 {
69 return PhaseId.APPLY_REQUEST_VALUES;
70 }
71
72 public void beforePhase(PhaseEvent event)
73 {
74 log.debug("In AjaxDecodePhaseListener beforePhase");
75 FacesContext context = event.getFacesContext();
76 Map externalRequestMap = context.getExternalContext().getRequestParameterMap();
77
78 if (externalRequestMap.containsKey("affectedAjaxComponent"))
79 {
80 UIViewRoot root = context.getViewRoot();
81 String affectedAjaxComponent = (String) context.getExternalContext()
82 .getRequestParameterMap().get("affectedAjaxComponent");
83 UIComponent ajaxComponent = root.findComponent(affectedAjaxComponent);
84
85 if (ajaxComponent instanceof UIComponentPerspective)
86 {
87 UIComponentPerspective componentPerspective = (UIComponentPerspective) ajaxComponent;
88 ajaxComponent = (UIComponent) componentPerspective.executeOn(context, new ExecuteOnCallback()
89 {
90 public Object execute(FacesContext facesContext, UIComponent ajaxComponent)
91 {
92 handleAjaxRequest(ajaxComponent, facesContext);
93
94 return ajaxComponent;
95 }
96 });
97 }
98 else
99 {
100 handleAjaxRequest(ajaxComponent, context);
101 }
102
103 StateManager stateManager = context.getApplication().getStateManager();
104 if (!stateManager.isSavingStateInClient(context))
105 {
106 stateManager.saveSerializedView(context);
107 }
108 context.responseComplete();
109 }
110 }
111
112
113 private void handleAjaxRequest(UIComponent ajaxComponent, FacesContext facesContext)
114 {
115 String updateOnly = (String) facesContext.getExternalContext().getRequestParameterMap().get("updateOnly");
116 if(updateOnly == null) {
117
118 decodeAjax(ajaxComponent, facesContext);
119 facesContext.getViewRoot().processApplication(facesContext);
120 }
121
122 encodeAjax(ajaxComponent, facesContext);
123 }
124
125 private void decodeAjax(UIComponent ajaxComponent, FacesContext context)
126 {
127
128 String affectedAjaxComponent = (String) context.getExternalContext()
129 .getRequestParameterMap().get("affectedAjaxComponent");
130 if (ajaxComponent == null)
131 {
132 String msg = "Component with id [" + affectedAjaxComponent + "] not found in view tree.";
133 log.error(msg);
134 throw new ComponentNotFoundException(msg);
135 }
136 log.debug("affectedAjaxComponent: " + ajaxComponent + " - " + ajaxComponent.getId());
137
138
139 if (ajaxComponent instanceof HtmlCommandButtonAjax)
140 {
141
142
143
144 FormInfo fi = RendererUtils.findNestingForm(ajaxComponent, context);
145 UIComponent form = fi.getForm();
146
147 if (form != null)
148 {
149 form.processDecodes(context);
150
151 form.processValidators(context);
152
153
154 form.processUpdates(context);
155
156
157 }
158 }
159 else if (ajaxComponent instanceof AjaxComponent)
160 {
161 try
162 {
163
164 ((AjaxComponent) ajaxComponent).decodeAjax(context);
165 }
166 catch (Exception e)
167 {
168 log.error("Exception while decoding ajax-request", e);
169 }
170 }
171 else
172 {
173 log.error("Found component is no ajaxComponent : " + RendererUtils.getPathToComponent(ajaxComponent));
174 }
175 }
176
177
178 private void encodeAjax(UIComponent component, FacesContext context)
179 {
180 ServletResponse response =
181 (ServletResponse) context.getExternalContext().getResponse();
182 ServletRequest request =
183 (ServletRequest) context.getExternalContext().getRequest();
184 UIViewRoot viewRoot = context.getViewRoot();
185 Map requestMap = context.getExternalContext().getRequestParameterMap();
186
187 String charset = (String) requestMap.get("charset");
188
189
190
191
192
193
194
195
196
197
198 response.setLocale(viewRoot.getLocale());
199
200
201 if(component instanceof DeprecatedAjaxComponent)
202 {
203 try
204 {
205 String contentType = getContentType("text/xml", charset);
206 response.setContentType(contentType);
207
208 StringBuffer buff = new StringBuffer();
209 buff.append("<?xml version=\"1.0\"?>\n");
210 buff.append("<response>\n");
211
212 PrintWriter out = response.getWriter();
213 out.print(buff);
214
215
216 context.setResponseWriter(new HtmlResponseWriterImpl(out,
217 contentType,
218 request.getCharacterEncoding()));
219
220 if (component instanceof HtmlCommandButtonAjax)
221 {
222 buff = new StringBuffer();
223 buff.append("<triggerComponent id=\"");
224 buff.append(component.getClientId(context));
225 buff.append("\" />\n");
226 out.print(buff);
227
228
229
230
231 FormInfo fi = RendererUtils.findNestingForm(component, context);
232 UIComponent form = fi.getForm();
233
234 if (form != null)
235 {
236
237 encodeChildren(form, context, requestMap);
238 }
239 }
240 else if (component instanceof AjaxComponent)
241 {
242
243
244 ((AjaxComponent) component).encodeAjax(context);
245 } else {
246
247 AjaxRendererUtils.encodeAjax(context, component);
248 }
249
250 out.print("</response>");
251 out.flush();
252 }
253 catch (IOException e)
254 {
255 log.error("Exception while rendering ajax-response", e);
256 }
257 }
258 else if (component instanceof AjaxComponent)
259 {
260 try
261 {
262 if (context.getResponseWriter() == null)
263 {
264 String contentType = getContentType("text/html", charset);
265 response.setContentType(contentType);
266 PrintWriter writer = response.getWriter();
267 context.setResponseWriter(new HtmlResponseWriterImpl(writer,
268 contentType, response.getCharacterEncoding()));
269 }
270
271 ((AjaxComponent) component).encodeAjax(context);
272 }
273 catch (IOException e)
274 {
275 log.error("Exception while rendering ajax-response", e);
276 }
277 }
278
279 }
280
281 private String getContentType(String contentType, String charset)
282 {
283 if (charset == null || charset.trim().length() == 0)
284 return contentType;
285 else
286 return contentType + ";charset=" + charset;
287 }
288
289 private void encodeChildren(UIComponent form, FacesContext context, Map requestMap)
290 throws IOException
291 {
292 List formChildren = form.getChildren();
293 for (int i = 0; i < formChildren.size(); i++)
294 {
295 UIComponent uiComponent = (UIComponent) formChildren.get(i);
296
297
298 if (requestMap.containsKey(uiComponent.getClientId(context)))
299 {
300
301 AjaxRendererUtils.encodeAjax(context, uiComponent);
302 }
303
304 encodeChildren(uiComponent, context, requestMap);
305 }
306 }
307
308
309
310
311
312 public static String mapToString(Map map)
313 {
314 Set entries = map.entrySet();
315 Iterator iter = entries.iterator();
316 StringBuffer buff = new StringBuffer();
317 while (iter.hasNext())
318 {
319 Map.Entry entry = (Map.Entry) iter.next();
320 buff.append("[" + entry.getKey() + "," + entry.getValue() + "]\n");
321 }
322 return buff.toString();
323 }
324
325 public static Object getValueForComponent(FacesContext context, UIComponent component)
326 {
327 String possibleClientId = component.getClientId(context);
328
329 if (!context.getExternalContext().getRequestParameterMap().containsKey(possibleClientId))
330 {
331 possibleClientId = (String) context.getExternalContext()
332 .getRequestParameterMap().get("affectedAjaxComponent");
333
334 log.debug("affectedAjaxComponent: " + possibleClientId);
335 UIViewRoot root = context.getViewRoot();
336 UIComponent ajaxComponent = root.findComponent(possibleClientId);
337 if (ajaxComponent instanceof UIComponentPerspective)
338 {
339 UIComponentPerspective componentPerspective = (UIComponentPerspective) ajaxComponent;
340
341 ajaxComponent = (UIComponent)componentPerspective.executeOn(context, new ExecuteOnCallback()
342 {
343 public Object execute(FacesContext facesContext, UIComponent uiComponent)
344 {
345 return uiComponent;
346 }
347 });
348 }
349
350 if (ajaxComponent != component)
351 {
352 log.error("No value found for this component : " + possibleClientId);
353 return null;
354 }
355 }
356
357 Object encodedValue = context.getExternalContext().getRequestParameterMap().get(possibleClientId);
358
359 if (encodedValue instanceof String)
360 {
361 return URIComponentUtils.decodeURIComponent((String) encodedValue);
362 }
363 else return encodedValue;
364 }
365
366 public void afterPhase(PhaseEvent event)
367 {
368
369 }
370
371
372 }