1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.lifecycle;
20
21 import java.io.BufferedReader;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.InputStreamReader;
25 import java.io.OutputStream;
26 import java.util.HashMap;
27 import java.util.Map;
28 import javax.faces.FacesException;
29 import javax.faces.application.Resource;
30 import javax.faces.context.ExternalContext;
31 import javax.faces.context.FacesContext;
32 import javax.faces.lifecycle.ClientWindow;
33 import javax.faces.render.ResponseStateManager;
34 import javax.servlet.http.Cookie;
35 import javax.servlet.http.HttpServletResponse;
36
37
38
39
40
41 public class CODIClientSideWindow extends ClientWindow
42 {
43
44
45
46
47
48
49
50
51
52
53 private static final String AUTOMATED_ENTRY_POINT_PARAMETER_KEY = "automatedEntryPoint";
54
55 private static final long serialVersionUID = 5293942986187078113L;
56
57 private static final String WINDOW_ID_COOKIE_PREFIX = "jfwid-";
58 private static final String CODI_REQUEST_TOKEN = "mfRid";
59
60 private static final String UNINITIALIZED_WINDOW_ID_VALUE = "uninitializedWindowId";
61 private static final String WINDOW_ID_REPLACE_PATTERN = "$$windowIdValue$$";
62 private static final String NOSCRIPT_URL_REPLACE_PATTERN = "$$noscriptUrl$$";
63 private static final String NOSCRIPT_PARAMETER = "mfDirect";
64
65 private final ClientConfig clientConfig;
66
67 private final WindowContextConfig windowContextConfig;
68
69 private final TokenGenerator clientWindowTokenGenerator;
70
71 private String windowId;
72
73 private String unparsedWindowHandlerHtml = null;
74
75 private Map<String,String> queryParamsMap;
76
77
78
79
80
81
82
83 protected CODIClientSideWindow(TokenGenerator clientWindowTokenGenerator,
84 WindowContextConfig windowContextConfig,
85 ClientConfig clientConfig)
86 {
87 this.windowContextConfig = windowContextConfig;
88 this.clientConfig = clientConfig;
89 this.clientWindowTokenGenerator = clientWindowTokenGenerator;
90 }
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119 public void decode(FacesContext facesContext)
120 {
121 if (facesContext.isPostback())
122 {
123
124 if (getId() == null)
125 {
126 setId(calculateWindowIdFromPost(facesContext));
127 }
128 }
129
130 if (!isClientSideWindowHandlerRequest(facesContext))
131 {
132 return;
133 }
134
135 ExternalContext externalContext = facesContext.getExternalContext();
136
137 if (isNoscriptRequest(externalContext))
138 {
139
140 clientConfig.setJavaScriptEnabled(false);
141 return;
142 }
143
144 String windowId = getWindowIdFromCookie(externalContext);
145 if (windowId == null)
146 {
147
148 sendWindowHandlerHtml(facesContext, null);
149 facesContext.responseComplete();
150 }
151 else
152 {
153 if (AUTOMATED_ENTRY_POINT_PARAMETER_KEY.equals(windowId) ||
154 (!windowContextConfig.isUnknownWindowIdsAllowed()
155 ))
156 {
157
158
159
160 windowId = createWindowId(facesContext);
161
162
163 sendWindowHandlerHtml(facesContext, windowId);
164 facesContext.responseComplete();
165 }
166 else
167 {
168
169
170
171 setId(windowId);
172 }
173 }
174 }
175
176 public String calculateWindowIdFromPost(FacesContext context)
177 {
178
179
180 String windowId = context.getExternalContext().getRequestParameterMap().get(
181 ResponseStateManager.CLIENT_WINDOW_PARAM);
182 if (windowId != null)
183 {
184 return windowId;
185 }
186 return null;
187 }
188
189 private boolean isClientSideWindowHandlerRequest(FacesContext facesContext)
190 {
191
192
193 return !facesContext.isPostback() && clientConfig.isClientSideWindowHandlerRequest(facesContext);
194 }
195
196 private boolean isNoscriptRequest(ExternalContext externalContext)
197 {
198 String noscript = externalContext.getRequestParameterMap().get(NOSCRIPT_PARAMETER);
199
200 return (noscript != null && "true".equals(noscript));
201 }
202
203 private void sendWindowHandlerHtml(FacesContext facesContext, String windowId)
204 {
205 HttpServletResponse httpResponse = (HttpServletResponse) facesContext.getExternalContext().getResponse();
206
207 try
208 {
209 httpResponse.setStatus(HttpServletResponse.SC_OK);
210 httpResponse.setContentType("text/html");
211
212 if (unparsedWindowHandlerHtml == null)
213 {
214 Resource resource = facesContext.getApplication().getResourceHandler().createResource(
215 "windowhandler.html", "org.apache.myfaces.windowId");
216
217 unparsedWindowHandlerHtml = convertStreamToString(resource.getInputStream());
218 }
219
220 String windowHandlerHtml = unparsedWindowHandlerHtml;
221
222 if (windowId == null)
223 {
224 windowId = UNINITIALIZED_WINDOW_ID_VALUE;
225 }
226
227
228 windowHandlerHtml = windowHandlerHtml.replace(WINDOW_ID_REPLACE_PATTERN, windowId);
229
230
231 windowHandlerHtml = windowHandlerHtml.replace(
232 NOSCRIPT_URL_REPLACE_PATTERN, getNoscriptUrl(facesContext.getExternalContext()));
233
234 OutputStream os = httpResponse.getOutputStream();
235 try
236 {
237 os.write(windowHandlerHtml.getBytes());
238 }
239 finally
240 {
241 os.close();
242 }
243 }
244 catch (IOException ioe)
245 {
246 throw new FacesException(ioe);
247 }
248 }
249
250 private static String convertStreamToString(InputStream is)
251 {
252 StringBuilder sb = new StringBuilder();
253 try
254 {
255 BufferedReader reader = new BufferedReader(new InputStreamReader(is));
256 String line = null;
257 while ((line = reader.readLine()) != null)
258 {
259 sb.append(line + "\n");
260 }
261 }
262 catch (IOException e)
263 {
264 throw new FacesException(e);
265 }
266 finally
267 {
268 if (is != null)
269 {
270 try
271 {
272 is.close();
273 }
274 catch (IOException e)
275 {
276
277 }
278 }
279 }
280 return sb.toString();
281 }
282
283 private String getNoscriptUrl(ExternalContext externalContext)
284 {
285 String url = externalContext.getRequestPathInfo();
286 if (url == null)
287 {
288 url = "";
289 }
290
291
292 int lastSlash = url.lastIndexOf('/');
293 if (lastSlash != -1)
294 {
295 url = url.substring(lastSlash + 1);
296 }
297
298
299 url = addParameters(externalContext, url, true, true, true);
300
301
302 if (url.contains("?"))
303 {
304 url = url + "&";
305 }
306 else
307 {
308 url = url + "?";
309 }
310 url = url + NOSCRIPT_PARAMETER + "=true";
311
312
313
314
315 url = url.replace("\"", "");
316 url = url.replace("\'", "");
317
318 return url;
319 }
320
321
322
323
324
325
326
327
328
329
330 public static String addParameters(ExternalContext externalContext, String url,
331 boolean addRequestParameter, boolean addPageParameter, boolean encodeValues)
332 {
333 StringBuilder finalUrl = new StringBuilder(url);
334 boolean existingParameters = url.contains("?");
335 boolean urlContainsWindowId = url.contains(ResponseStateManager.CLIENT_WINDOW_URL_PARAM + "=");
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378 return finalUrl.toString();
379 }
380
381 protected String createWindowId(FacesContext context)
382 {
383 String windowId = clientWindowTokenGenerator._getNextToken();
384 setId(windowId);
385 return windowId;
386 }
387
388 private String getWindowIdFromCookie(ExternalContext externalContext)
389 {
390 String cookieName = WINDOW_ID_COOKIE_PREFIX + getRequestToken(externalContext);
391 Cookie cookie = (Cookie) externalContext.getRequestCookieMap().get(cookieName);
392
393 if (cookie != null)
394 {
395
396
397
398 cookie.setMaxAge(0);
399
400 return cookie.getValue();
401 }
402
403 return null;
404 }
405
406 private String getRequestToken(ExternalContext externalContext)
407 {
408 String requestToken = externalContext.getRequestParameterMap().get(CODI_REQUEST_TOKEN);
409 if (requestToken != null)
410 {
411 return requestToken;
412 }
413
414 return "";
415 }
416
417 @Override
418 public String getId()
419 {
420 return windowId;
421 }
422
423 public void setId(String id)
424 {
425 windowId = id;
426 queryParamsMap = null;
427 }
428
429 @Override
430 public Map<String, String> getQueryURLParameters(FacesContext context)
431 {
432 if (queryParamsMap == null)
433 {
434 String id = context.getExternalContext().getClientWindow().getId();
435 if (id != null)
436 {
437 queryParamsMap = new HashMap<String, String>(2,1);
438 queryParamsMap.put(ResponseStateManager.CLIENT_WINDOW_URL_PARAM, id);
439 }
440 }
441 return queryParamsMap;
442 }
443 }