1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.view.facelets;
20
21 import java.io.ByteArrayInputStream;
22 import java.io.ByteArrayOutputStream;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.ObjectInputStream;
26 import java.io.ObjectOutputStream;
27 import java.io.OutputStream;
28 import java.io.Serializable;
29 import java.security.AccessController;
30 import java.security.PrivilegedActionException;
31 import java.security.PrivilegedExceptionAction;
32 import java.util.ArrayList;
33 import java.util.HashMap;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.logging.Level;
37 import java.util.logging.Logger;
38 import java.util.zip.GZIPInputStream;
39 import java.util.zip.GZIPOutputStream;
40
41 import javax.faces.context.ExternalContext;
42 import javax.faces.context.FacesContext;
43
44 import org.apache.commons.collections.map.AbstractReferenceMap;
45 import org.apache.commons.collections.map.ReferenceMap;
46 import org.apache.myfaces.shared.renderkit.RendererUtils;
47 import org.apache.myfaces.shared.util.MyFacesObjectInputStream;
48
49
50
51
52
53
54
55
56
57
58
59 @Deprecated
60 class DefaultFaceletsStateManagementHelper
61 {
62
63 private static final Logger log = Logger.getLogger(DefaultFaceletsStateManagementHelper.class.getName());
64
65 private static final String SERIALIZED_VIEW_SESSION_ATTR=
66 DefaultFaceletsStateManagementHelper.class.getName() + ".SERIALIZED_VIEW";
67
68 public static final String SERIALIZED_VIEW_REQUEST_ATTR =
69 DefaultFaceletsStateManagementHelper.class.getName() + ".SERIALIZED_VIEW";
70
71 private static final String RESTORED_SERIALIZED_VIEW_REQUEST_ATTR =
72 DefaultFaceletsStateManagementHelper.class.getName() + ".RESTORED_SERIALIZED_VIEW";
73
74
75
76
77
78 private static final String NUMBER_OF_VIEWS_IN_SESSION_PARAM = "org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION";
79
80
81
82
83 private static final int DEFAULT_NUMBER_OF_VIEWS_IN_SESSION = 20;
84
85
86
87
88
89
90 private static final String SERIALIZE_STATE_IN_SESSION_PARAM = "org.apache.myfaces.SERIALIZE_STATE_IN_SESSION";
91
92
93
94
95
96
97 private static final String COMPRESS_SERVER_STATE_PARAM = "org.apache.myfaces.COMPRESS_STATE_IN_SESSION";
98
99
100
101
102 private static final boolean DEFAULT_COMPRESS_SERVER_STATE_PARAM = true;
103
104
105
106
107 private static final boolean DEFAULT_SERIALIZE_STATE_IN_SESSION = true;
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132 private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE = "org.apache.myfaces.CACHE_OLD_VIEWS_IN_SESSION_MODE";
133
134
135
136
137
138
139 private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE_HARD_SOFT = "hard-soft";
140
141 private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT = "soft";
142
143 private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT_WEAK = "soft-weak";
144
145 private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK = "weak";
146
147 private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF = "off";
148
149 private static final int UNCOMPRESSED_FLAG = 0;
150 private static final int COMPRESSED_FLAG = 1;
151
152 private static final int JSF_SEQUENCE_INDEX = 0;
153
154 protected Integer getServerStateId(Object[] state)
155 {
156 if (state != null)
157 {
158 Object serverStateId = state[JSF_SEQUENCE_INDEX];
159 if (serverStateId != null)
160 {
161 return Integer.valueOf((String) serverStateId, Character.MAX_RADIX);
162 }
163 }
164 return null;
165 }
166
167 protected void saveSerializedViewInServletSession(FacesContext context,
168 Object serializedView)
169 {
170 Map<String, Object> sessionMap = context.getExternalContext().getSessionMap();
171 SerializedViewCollection viewCollection = (SerializedViewCollection) sessionMap
172 .get(SERIALIZED_VIEW_SESSION_ATTR);
173 if (viewCollection == null)
174 {
175 viewCollection = new SerializedViewCollection();
176 sessionMap.put(SERIALIZED_VIEW_SESSION_ATTR, viewCollection);
177 }
178 viewCollection.add(context, serializeView(context, serializedView));
179
180 sessionMap.put(SERIALIZED_VIEW_SESSION_ATTR, viewCollection);
181 }
182
183 protected Object getSerializedViewFromServletSession(FacesContext context, String viewId, Integer sequence)
184 {
185 ExternalContext externalContext = context.getExternalContext();
186 Map<String, Object> requestMap = externalContext.getRequestMap();
187 Object serializedView = null;
188 if (requestMap.containsKey(RESTORED_SERIALIZED_VIEW_REQUEST_ATTR))
189 {
190 serializedView = requestMap.get(RESTORED_SERIALIZED_VIEW_REQUEST_ATTR);
191 }
192 else
193 {
194 SerializedViewCollection viewCollection = (SerializedViewCollection) externalContext
195 .getSessionMap().get(SERIALIZED_VIEW_SESSION_ATTR);
196 if (viewCollection != null)
197 {
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213 if (sequence != null)
214 {
215 Object state = viewCollection.get(sequence, viewId);
216 if (state != null)
217 {
218 serializedView = deserializeView(state);
219 }
220 }
221 }
222 requestMap.put(RESTORED_SERIALIZED_VIEW_REQUEST_ATTR, serializedView);
223 nextViewSequence(context);
224 }
225 return serializedView;
226 }
227
228 protected int getNextViewSequence(FacesContext context)
229 {
230 ExternalContext externalContext = context.getExternalContext();
231
232 if (!externalContext.getRequestMap().containsKey(RendererUtils.SEQUENCE_PARAM))
233 {
234 nextViewSequence(context);
235 }
236
237 Integer sequence = (Integer) externalContext.getRequestMap().get(RendererUtils.SEQUENCE_PARAM);
238 return sequence.intValue();
239 }
240
241 protected void nextViewSequence(FacesContext facescontext)
242 {
243 ExternalContext externalContext = facescontext.getExternalContext();
244 Object sessionObj = externalContext.getSession(true);
245 synchronized(sessionObj)
246
247 {
248 Map<String, Object> map = externalContext.getSessionMap();
249 Integer sequence = (Integer) map.get(RendererUtils.SEQUENCE_PARAM);
250 if(sequence == null || sequence.intValue() == Integer.MAX_VALUE)
251 {
252 sequence = Integer.valueOf(1);
253 }
254 else
255 {
256 sequence = Integer.valueOf(sequence.intValue() + 1);
257 }
258 map.put(RendererUtils.SEQUENCE_PARAM, sequence);
259 externalContext.getRequestMap().put(RendererUtils.SEQUENCE_PARAM, sequence);
260 }
261 }
262
263 protected Object serializeView(FacesContext context, Object serializedView)
264 {
265 if (log.isLoggable(Level.FINEST)) log.finest("Entering serializeView");
266
267 if(isSerializeStateInSession(context))
268 {
269 if (log.isLoggable(Level.FINEST)) log.finest("Processing serializeView - serialize state in session");
270
271 ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
272 try
273 {
274 OutputStream os = baos;
275 if(isCompressStateInSession(context))
276 {
277 if (log.isLoggable(Level.FINEST)) log.finest("Processing serializeView - serialize compressed");
278
279 os.write(COMPRESSED_FLAG);
280 os = new GZIPOutputStream(os, 1024);
281 }
282 else
283 {
284 if (log.isLoggable(Level.FINEST)) log.finest("Processing serializeView - serialize uncompressed");
285
286 os.write(UNCOMPRESSED_FLAG);
287 }
288
289 Object[] stateArray = (Object[]) serializedView;
290
291 ObjectOutputStream out = new ObjectOutputStream(os);
292 out.writeObject(stateArray[0]);
293 out.writeObject(stateArray[1]);
294 out.close();
295 baos.close();
296
297 if (log.isLoggable(Level.FINEST)) log.finest("Exiting serializeView - serialized. Bytes : "+baos.size());
298 return baos.toByteArray();
299 }
300 catch (IOException e)
301 {
302 log.log(Level.SEVERE, "Exiting serializeView - Could not serialize state: " + e.getMessage(), e);
303 return null;
304 }
305 }
306
307
308 if (log.isLoggable(Level.FINEST))
309 log.finest("Exiting serializeView - do not serialize state in session.");
310
311 return serializedView;
312
313 }
314
315
316
317
318
319
320
321 protected boolean isSerializeStateInSession(FacesContext context)
322 {
323 String value = context.getExternalContext().getInitParameter(
324 SERIALIZE_STATE_IN_SESSION_PARAM);
325 boolean serialize = DEFAULT_SERIALIZE_STATE_IN_SESSION;
326 if (value != null)
327 {
328 serialize = Boolean.valueOf(value);
329 }
330 return serialize;
331 }
332
333
334
335
336
337
338
339 protected boolean isCompressStateInSession(FacesContext context)
340 {
341 String value = context.getExternalContext().getInitParameter(
342 COMPRESS_SERVER_STATE_PARAM);
343 boolean compress = DEFAULT_COMPRESS_SERVER_STATE_PARAM;
344 if (value != null)
345 {
346 compress = Boolean.valueOf(value);
347 }
348 return compress;
349 }
350
351 protected Object deserializeView(Object state)
352 {
353 if (log.isLoggable(Level.FINEST)) log.finest("Entering deserializeView");
354
355 if(state instanceof byte[])
356 {
357 if (log.isLoggable(Level.FINEST)) log.finest("Processing deserializeView - deserializing serialized state. Bytes : "+((byte[]) state).length);
358
359 try
360 {
361 ByteArrayInputStream bais = new ByteArrayInputStream((byte[]) state);
362 InputStream is = bais;
363 if(is.read() == COMPRESSED_FLAG)
364 {
365 is = new GZIPInputStream(is);
366 }
367 ObjectInputStream ois = null;
368 try
369 {
370 final ObjectInputStream in = new MyFacesObjectInputStream(is);
371 ois = in;
372 Object object = null;
373 if (System.getSecurityManager() != null)
374 {
375 object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object []>()
376 {
377 public Object[] run() throws PrivilegedActionException, IOException, ClassNotFoundException
378 {
379 return new Object[] {in.readObject(), in.readObject()};
380 }
381 });
382 }
383 else
384 {
385 object = new Object[] {in.readObject(), in.readObject()};
386 }
387 return object;
388 }
389 finally
390 {
391 if (ois != null)
392 {
393 ois.close();
394 ois = null;
395 }
396 }
397 }
398 catch (PrivilegedActionException e)
399 {
400 log.log(Level.SEVERE, "Exiting deserializeView - Could not deserialize state: " + e.getMessage(), e);
401 return null;
402 }
403 catch (IOException e)
404 {
405 log.log(Level.SEVERE, "Exiting deserializeView - Could not deserialize state: " + e.getMessage(), e);
406 return null;
407 }
408 catch (ClassNotFoundException e)
409 {
410 log.log(Level.SEVERE, "Exiting deserializeView - Could not deserialize state: " + e.getMessage(), e);
411 return null;
412 }
413 }
414 else if (state instanceof Object[])
415 {
416 if (log.isLoggable(Level.FINEST)) log.finest("Exiting deserializeView - state not serialized.");
417
418 return state;
419 }
420 else if(state == null)
421 {
422 log.severe("Exiting deserializeView - this method should not be called with a null-state.");
423 return null;
424 }
425 else
426 {
427 log.severe("Exiting deserializeView - this method should not be called with a state of type : "+state.getClass());
428 return null;
429 }
430 }
431
432 protected static class SerializedViewCollection implements Serializable
433 {
434 private static final long serialVersionUID = -3734849062185115847L;
435
436 private final List<Object> _keys = new ArrayList<Object>(DEFAULT_NUMBER_OF_VIEWS_IN_SESSION);
437 private final Map<Object, Object> _serializedViews = new HashMap<Object, Object>();
438
439
440
441 private transient Map<Object, Object> _oldSerializedViews = null;
442
443 public synchronized void add(FacesContext context, Object state)
444 {
445 Object key = new SerializedViewKey(context);
446 _serializedViews.put(key, state);
447
448 while (_keys.remove(key));
449 _keys.add(key);
450
451 int views = getNumberOfViewsInSession(context);
452 while (_keys.size() > views)
453 {
454 key = _keys.remove(0);
455 Object oldView = _serializedViews.remove(key);
456 if (oldView != null &&
457 !CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF.equals(getCacheOldViewsInSessionMode(context)))
458 {
459 getOldSerializedViewsMap().put(key, oldView);
460 }
461 }
462 }
463
464
465
466
467
468
469
470 protected int getNumberOfViewsInSession(FacesContext context)
471 {
472 String value = context.getExternalContext().getInitParameter(
473 NUMBER_OF_VIEWS_IN_SESSION_PARAM);
474 int views = DEFAULT_NUMBER_OF_VIEWS_IN_SESSION;
475 if (value != null)
476 {
477 try
478 {
479 views = Integer.parseInt(value);
480 if (views <= 0)
481 {
482 log.severe("Configured value for " + NUMBER_OF_VIEWS_IN_SESSION_PARAM
483 + " is not valid, must be an value > 0, using default value ("
484 + DEFAULT_NUMBER_OF_VIEWS_IN_SESSION);
485 views = DEFAULT_NUMBER_OF_VIEWS_IN_SESSION;
486 }
487 }
488 catch (Throwable e)
489 {
490 log.log(Level.SEVERE, "Error determining the value for " + NUMBER_OF_VIEWS_IN_SESSION_PARAM
491 + ", expected an integer value > 0, using default value ("
492 + DEFAULT_NUMBER_OF_VIEWS_IN_SESSION + "): " + e.getMessage(), e);
493 }
494 }
495 return views;
496 }
497
498
499
500
501 @SuppressWarnings("unchecked")
502 protected Map<Object, Object> getOldSerializedViewsMap()
503 {
504 FacesContext context = FacesContext.getCurrentInstance();
505 if (_oldSerializedViews == null && context != null)
506 {
507 String cacheMode = getCacheOldViewsInSessionMode(context);
508 if (CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK.equals(cacheMode))
509 {
510 _oldSerializedViews = new ReferenceMap(AbstractReferenceMap.WEAK, AbstractReferenceMap.WEAK, true);
511 }
512 else if (CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT_WEAK.equals(cacheMode))
513 {
514 _oldSerializedViews = new ReferenceMap(AbstractReferenceMap.SOFT, AbstractReferenceMap.WEAK, true);
515 }
516 else if (CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT.equals(cacheMode))
517 {
518 _oldSerializedViews = new ReferenceMap(AbstractReferenceMap.SOFT, AbstractReferenceMap.SOFT, true);
519 }
520 else if (CACHE_OLD_VIEWS_IN_SESSION_MODE_HARD_SOFT.equals(cacheMode))
521 {
522 _oldSerializedViews = new ReferenceMap(AbstractReferenceMap.HARD, AbstractReferenceMap.SOFT);
523 }
524 }
525
526 return _oldSerializedViews;
527 }
528
529
530
531
532
533
534
535
536
537 protected String getCacheOldViewsInSessionMode(FacesContext context)
538 {
539 String value = context.getExternalContext().getInitParameter(
540 CACHE_OLD_VIEWS_IN_SESSION_MODE);
541 if (value == null)
542 {
543 return CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF;
544 }
545 else if (value.equalsIgnoreCase(CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT))
546 {
547 return CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT;
548 }
549 else if (value.equalsIgnoreCase(CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT_WEAK))
550 {
551 return CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT_WEAK;
552 }
553 else if (value.equalsIgnoreCase(CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK))
554 {
555 return CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK;
556 }
557 else if (value.equalsIgnoreCase(CACHE_OLD_VIEWS_IN_SESSION_MODE_HARD_SOFT))
558 {
559 return CACHE_OLD_VIEWS_IN_SESSION_MODE_HARD_SOFT;
560 }
561 else
562 {
563 return CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF;
564 }
565 }
566
567 public Object get(Integer sequence, String viewId)
568 {
569 Object key = new SerializedViewKey(viewId, sequence);
570 Object value = _serializedViews.get(key);
571 if (value == null)
572 {
573 Map<Object,Object> oldSerializedViewMap = getOldSerializedViewsMap();
574 if (oldSerializedViewMap != null)
575 {
576 value = oldSerializedViewMap.get(key);
577 }
578 }
579 return value;
580 }
581 }
582
583 protected static class SerializedViewKey implements Serializable
584 {
585 private static final long serialVersionUID = -1170697124386063642L;
586
587 private final String _viewId;
588 private final Integer _sequenceId;
589
590 public SerializedViewKey(String viewId, Integer sequence)
591 {
592 _sequenceId = sequence;
593 _viewId = viewId;
594 }
595
596 public SerializedViewKey(FacesContext context)
597 {
598 _sequenceId = RendererUtils.getViewSequence(context);
599 _viewId = context.getViewRoot().getViewId();
600 }
601
602 @Override
603 public int hashCode()
604 {
605 final int PRIME = 31;
606 int result = 1;
607 result = PRIME * result + ((_sequenceId == null) ? 0 : _sequenceId.hashCode());
608 result = PRIME * result + ((_viewId == null) ? 0 : _viewId.hashCode());
609 return result;
610 }
611
612 @Override
613 public boolean equals(Object obj)
614 {
615 if (this == obj)
616 return true;
617 if (obj == null)
618 return false;
619 if (getClass() != obj.getClass())
620 return false;
621 final SerializedViewKey other = (SerializedViewKey) obj;
622 if (_sequenceId == null)
623 {
624 if (other._sequenceId != null)
625 return false;
626 }
627 else if (!_sequenceId.equals(other._sequenceId))
628 return false;
629 if (_viewId == null)
630 {
631 if (other._viewId != null)
632 return false;
633 }
634 else if (!_viewId.equals(other._viewId))
635 return false;
636 return true;
637 }
638
639 }
640 }