1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.application.jsp;
20
21 import org.apache.commons.collections.map.AbstractReferenceMap;
22 import org.apache.commons.collections.map.ReferenceMap;
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25 import org.apache.myfaces.application.MyfacesStateManager;
26 import org.apache.myfaces.application.TreeStructureManager;
27 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
28 import org.apache.myfaces.renderkit.MyfacesResponseStateManager;
29 import org.apache.myfaces.shared_impl.renderkit.RendererUtils;
30 import org.apache.myfaces.shared_impl.util.MyFacesObjectInputStream;
31
32 import javax.faces.FacesException;
33 import javax.faces.FactoryFinder;
34 import javax.faces.component.NamingContainer;
35 import javax.faces.component.UIComponent;
36 import javax.faces.component.UIViewRoot;
37 import javax.faces.context.ExternalContext;
38 import javax.faces.context.FacesContext;
39 import javax.faces.render.RenderKit;
40 import javax.faces.render.RenderKitFactory;
41 import javax.faces.render.ResponseStateManager;
42 import java.io.*;
43 import java.lang.reflect.Method;
44 import java.security.AccessController;
45 import java.security.PrivilegedActionException;
46 import java.security.PrivilegedExceptionAction;
47 import java.util.*;
48 import java.util.zip.GZIPInputStream;
49 import java.util.zip.GZIPOutputStream;
50
51
52
53
54
55
56
57
58
59 public class JspStateManagerImpl
60 extends MyfacesStateManager
61 {
62 private static final Log log = LogFactory.getLog(JspStateManagerImpl.class);
63 private static final String SERIALIZED_VIEW_SESSION_ATTR
64 = JspStateManagerImpl.class.getName() + ".SERIALIZED_VIEW";
65 private static final String SERIALIZED_VIEW_REQUEST_ATTR
66 = JspStateManagerImpl.class.getName() + ".SERIALIZED_VIEW";
67 private static final String RESTORED_SERIALIZED_VIEW_REQUEST_ATTR
68 = JspStateManagerImpl.class.getName() + ".RESTORED_SERIALIZED_VIEW";
69
70
71
72
73
74 @JSFWebConfigParam(defaultValue="20",since="1.1")
75 private static final String NUMBER_OF_VIEWS_IN_SESSION_PARAM = "org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION";
76
77
78
79
80 private static final int DEFAULT_NUMBER_OF_VIEWS_IN_SESSION = 20;
81
82
83
84
85
86
87 @JSFWebConfigParam(defaultValue="true",since="1.1")
88 private static final String SERIALIZE_STATE_IN_SESSION_PARAM = "org.apache.myfaces.SERIALIZE_STATE_IN_SESSION";
89
90
91
92
93
94
95 @JSFWebConfigParam(defaultValue="true",since="1.1")
96 private static final String COMPRESS_SERVER_STATE_PARAM = "org.apache.myfaces.COMPRESS_STATE_IN_SESSION";
97
98
99
100
101 private static final boolean DEFAULT_COMPRESS_SERVER_STATE_PARAM = true;
102
103
104
105
106 private static final boolean DEFAULT_SERIALIZE_STATE_IN_SESSION = true;
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131 @JSFWebConfigParam(defaultValue="off", expectedValues="off, no, hard-soft, soft, soft-weak, weak", since="1.2.5")
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 private RenderKitFactory _renderKitFactory = null;
155
156 public JspStateManagerImpl()
157 {
158 if (log.isTraceEnabled()) log.trace("New JspStateManagerImpl instance created");
159 }
160
161 protected Object getComponentStateToSave(FacesContext facesContext)
162 {
163 if (log.isTraceEnabled()) log.trace("Entering getComponentStateToSave");
164
165 UIViewRoot viewRoot = facesContext.getViewRoot();
166 if (viewRoot.isTransient())
167 {
168 return null;
169 }
170
171 Object serializedComponentStates = viewRoot.processSaveState(facesContext);
172
173 if (log.isTraceEnabled()) log.trace("Exiting getComponentStateToSave");
174 return serializedComponentStates;
175 }
176
177
178
179
180
181
182
183 protected Object getTreeStructureToSave(FacesContext facesContext)
184 {
185 if (log.isTraceEnabled()) log.trace("Entering getTreeStructureToSave");
186 UIViewRoot viewRoot = facesContext.getViewRoot();
187 if (viewRoot.isTransient())
188 {
189 return null;
190 }
191 TreeStructureManager tsm = new TreeStructureManager();
192 Object retVal = tsm.buildTreeStructureToSave(viewRoot);
193 if (log.isTraceEnabled()) log.trace("Exiting getTreeStructureToSave");
194 return retVal;
195 }
196
197
198
199
200
201
202
203 protected void restoreComponentState(FacesContext facesContext,
204 UIViewRoot uiViewRoot,
205 String renderKitId)
206 {
207 if (log.isTraceEnabled()) log.trace("Entering restoreComponentState");
208
209
210
211
212
213 RenderKit renderKit = getRenderKitFactory().getRenderKit(facesContext, renderKitId);
214 ResponseStateManager responseStateManager = renderKit.getResponseStateManager();
215
216 Object serializedComponentStates;
217 if (isSavingStateInClient(facesContext))
218 {
219 if (isLegacyResponseStateManager(responseStateManager))
220 {
221 serializedComponentStates = responseStateManager.getComponentStateToRestore(facesContext);
222 }
223 else
224 {
225 serializedComponentStates = responseStateManager.getState(facesContext, uiViewRoot.getViewId());
226 }
227 if (serializedComponentStates == null)
228 {
229 log.error("No serialized component state found in client request!");
230
231 uiViewRoot.setViewId(null);
232 return;
233 }
234 }
235 else
236 {
237 Integer serverStateId = getServerStateId((Object[]) responseStateManager.getState(facesContext, uiViewRoot.getViewId()));
238
239 Object[] stateObj = (Object[])( (serverStateId == null)? null : getSerializedViewFromServletSession(facesContext, uiViewRoot.getViewId(), serverStateId) );
240 if (stateObj == null)
241 {
242 log.error("No serialized view found in server session!");
243
244 uiViewRoot.setViewId(null);
245 return;
246 }
247 SerializedView serializedView = new SerializedView(stateObj[0], stateObj[1]);
248 serializedComponentStates = serializedView.getState();
249 if (serializedComponentStates == null)
250 {
251 log.error("No serialized component state found in server session!");
252 return;
253 }
254 }
255
256 if (uiViewRoot.getRenderKitId() == null)
257 {
258
259 uiViewRoot.setRenderKitId(renderKitId);
260 }
261
262
263 uiViewRoot.processRestoreState(facesContext, serializedComponentStates);
264
265 if (log.isTraceEnabled()) log.trace("Exiting restoreComponentState");
266 }
267
268 protected Integer getServerStateId(Object[] state)
269 {
270 if (state != null)
271 {
272 Object serverStateId = state[JSF_SEQUENCE_INDEX];
273 if (serverStateId != null)
274 {
275 return Integer.valueOf((String) serverStateId, Character.MAX_RADIX);
276 }
277 }
278 return null;
279 }
280
281
282
283
284 protected UIViewRoot restoreTreeStructure(FacesContext facesContext,
285 String viewId,
286 String renderKitId)
287 {
288 if (log.isTraceEnabled()) log.trace("Entering restoreTreeStructure");
289
290 RenderKit rk = getRenderKitFactory().getRenderKit(facesContext, renderKitId);
291 ResponseStateManager responseStateManager = rk.getResponseStateManager();
292
293 UIViewRoot uiViewRoot;
294 if (isSavingStateInClient(facesContext))
295 {
296
297 Object treeStructure = responseStateManager.getTreeStructureToRestore(facesContext, viewId);
298 if (treeStructure == null)
299 {
300 if (log.isDebugEnabled()) log.debug("Exiting restoreTreeStructure - No tree structure state found in client request");
301 return null;
302 }
303
304 TreeStructureManager tsm = new TreeStructureManager();
305 uiViewRoot = tsm.restoreTreeStructure(treeStructure);
306 if (log.isTraceEnabled()) log.trace("Tree structure restored from client request");
307 }
308 else
309 {
310
311 Integer serverStateId = getServerStateId((Object[]) responseStateManager.getState(facesContext, viewId));
312
313 Object[] stateObj = (Object[])( (serverStateId == null)? null : getSerializedViewFromServletSession(facesContext, viewId, serverStateId) );
314 if (stateObj == null)
315 {
316 if (log.isDebugEnabled()) log.debug("Exiting restoreTreeStructure - No serialized view found in server session!");
317 return null;
318 }
319
320 SerializedView serializedView = new SerializedView(stateObj[0], stateObj[1]);
321 Object treeStructure = serializedView.getStructure();
322 if (treeStructure == null)
323 {
324 if (log.isDebugEnabled()) log.debug("Exiting restoreTreeStructure - No tree structure state found in server session, former UIViewRoot must have been transient");
325 return null;
326 }
327
328 TreeStructureManager tsm = new TreeStructureManager();
329 uiViewRoot = tsm.restoreTreeStructure(serializedView.getStructure());
330 if (log.isTraceEnabled()) log.trace("Tree structure restored from server session");
331 }
332
333 if (log.isTraceEnabled()) log.trace("Exiting restoreTreeStructure");
334 return uiViewRoot;
335 }
336
337 public UIViewRoot restoreView(FacesContext facesContext, String viewId, String renderKitId)
338 {
339 if (log.isTraceEnabled()) log.trace("Entering restoreView - viewId: "+viewId+" ; renderKitId: "+renderKitId);
340
341 RenderKit renderKit = getRenderKitFactory().getRenderKit(facesContext, renderKitId);
342 ResponseStateManager responseStateManager = renderKit.getResponseStateManager();
343
344 Object state;
345 if (isSavingStateInClient(facesContext))
346 {
347 if (log.isTraceEnabled()) log.trace("Restoring view from client");
348
349 state = responseStateManager.getState(facesContext, viewId);
350 }
351 else
352 {
353 if (log.isTraceEnabled()) log.trace("Restoring view from session");
354
355 Integer serverStateId = getServerStateId((Object[]) responseStateManager.getState(facesContext, viewId));
356
357 state = (serverStateId == null) ? null : getSerializedViewFromServletSession(facesContext, viewId, serverStateId);
358 }
359
360 UIViewRoot uiViewRoot = null;
361
362 if (state != null) {
363 Object[] stateArray = (Object[])state;
364 TreeStructureManager tsm = new TreeStructureManager();
365 uiViewRoot = tsm.restoreTreeStructure(stateArray[0]);
366
367 if (uiViewRoot != null) {
368 uiViewRoot.processRestoreState(facesContext, stateArray[1]);
369 }
370 }
371
372 if (log.isTraceEnabled()) log.trace("Exiting restoreView - "+viewId);
373
374 return uiViewRoot;
375 }
376
377 public SerializedView saveSerializedView(FacesContext facesContext) throws IllegalStateException
378 {
379 if (log.isTraceEnabled()) log.trace("Entering saveSerializedView");
380
381 checkForDuplicateIds(facesContext, facesContext.getViewRoot(), new HashSet<String>());
382
383 if (log.isTraceEnabled()) log.trace("Processing saveSerializedView - Checked for duplicate Ids");
384
385 ExternalContext externalContext = facesContext.getExternalContext();
386
387
388 Object serializedView = externalContext.getRequestMap()
389 .get(SERIALIZED_VIEW_REQUEST_ATTR);
390 if (serializedView == null)
391 {
392 if (log.isTraceEnabled()) log.trace("Processing saveSerializedView - create new serialized view");
393
394
395 Object treeStruct = getTreeStructureToSave(facesContext);
396 Object compStates = getComponentStateToSave(facesContext);
397 serializedView = new Object[] {treeStruct, compStates};
398 externalContext.getRequestMap().put(SERIALIZED_VIEW_REQUEST_ATTR,
399 serializedView);
400
401 if (log.isTraceEnabled()) log.trace("Processing saveSerializedView - new serialized view created");
402 }
403
404 Object[] serializedViewArray = (Object[]) serializedView;
405
406 if (!isSavingStateInClient(facesContext))
407 {
408 if (log.isTraceEnabled()) log.trace("Processing saveSerializedView - server-side state saving - save state");
409
410 saveSerializedViewInServletSession(facesContext, serializedView);
411
412 if (log.isTraceEnabled()) log.trace("Exiting saveSerializedView - server-side state saving - saved state");
413 return new SerializedView(serializedViewArray[0], new Object[0]);
414 }
415
416 if (log.isTraceEnabled()) log.trace("Exiting saveSerializedView - client-side state saving");
417
418 return new SerializedView(serializedViewArray[0], serializedViewArray[1]);
419 }
420
421 private static void checkForDuplicateIds(FacesContext context,
422 UIComponent component,
423 Set<String> ids)
424 {
425 String id = component.getId();
426 if (id != null && !ids.add(id))
427 {
428 throw new IllegalStateException("Client-id : "+id +
429 " is duplicated in the faces tree. Component : "+component.getClientId(context)+", path: "+
430 getPathToComponent(component));
431 }
432 if (component instanceof NamingContainer)
433 {
434 ids = new HashSet<String>();
435 }
436 Iterator it = component.getFacetsAndChildren();
437 while (it.hasNext())
438 {
439 UIComponent kid = (UIComponent) it.next();
440 checkForDuplicateIds(context, kid, ids);
441 }
442 }
443
444 private static String getPathToComponent(UIComponent component)
445 {
446 StringBuffer buf = new StringBuffer();
447
448 if(component == null)
449 {
450 buf.append("{Component-Path : ");
451 buf.append("[null]}");
452 return buf.toString();
453 }
454
455 getPathToComponent(component,buf);
456
457 buf.insert(0,"{Component-Path : ");
458 buf.append("}");
459
460 return buf.toString();
461 }
462
463 private static void getPathToComponent(UIComponent component, StringBuffer buf)
464 {
465 if(component == null)
466 return;
467
468 StringBuffer intBuf = new StringBuffer();
469
470 intBuf.append("[Class: ");
471 intBuf.append(component.getClass().getName());
472 if(component instanceof UIViewRoot)
473 {
474 intBuf.append(",ViewId: ");
475 intBuf.append(((UIViewRoot) component).getViewId());
476 }
477 else
478 {
479 intBuf.append(",Id: ");
480 intBuf.append(component.getId());
481 }
482 intBuf.append("]");
483
484 buf.insert(0,intBuf.toString());
485
486 if(component!=null)
487 {
488 getPathToComponent(component.getParent(),buf);
489 }
490 }
491
492 public void writeState(FacesContext facesContext,
493 SerializedView serializedView) throws IOException
494 {
495 if (log.isTraceEnabled()) log.trace("Entering writeState");
496
497 UIViewRoot uiViewRoot = facesContext.getViewRoot();
498
499 RenderKit renderKit = getRenderKitFactory().getRenderKit(facesContext, uiViewRoot.getRenderKitId());
500 ResponseStateManager responseStateManager = renderKit.getResponseStateManager();
501
502 if (isLegacyResponseStateManager(responseStateManager))
503 {
504 responseStateManager.writeState(facesContext, serializedView);
505 }
506 else if (!isSavingStateInClient(facesContext))
507 {
508 Object[] state = new Object[2];
509 state[JSF_SEQUENCE_INDEX] = Integer.toString(getNextViewSequence(facesContext), Character.MAX_RADIX);
510 responseStateManager.writeState(facesContext, state);
511 }
512 else
513 {
514 Object[] state = new Object[2];
515 state[0] = serializedView.getStructure();
516 state[1] = serializedView.getState();
517 responseStateManager.writeState(facesContext, state);
518 }
519
520 if (log.isTraceEnabled()) log.trace("Exiting writeState");
521
522 }
523
524
525
526
527
528
529
530 public void writeStateAsUrlParams(FacesContext facesContext,
531 SerializedView serializedView) throws IOException
532 {
533 if (log.isTraceEnabled()) log.trace("Entering writeStateAsUrlParams");
534
535 if (isSavingStateInClient(facesContext))
536 {
537 if (log.isTraceEnabled()) log.trace("Processing writeStateAsUrlParams - client-side state saving writing state");
538
539 UIViewRoot uiViewRoot = facesContext.getViewRoot();
540
541 RenderKit renderKit = getRenderKitFactory().getRenderKit(facesContext, uiViewRoot.getRenderKitId());
542 ResponseStateManager responseStateManager = renderKit.getResponseStateManager();
543 if (responseStateManager instanceof MyfacesResponseStateManager)
544 {
545 ((MyfacesResponseStateManager)responseStateManager).writeStateAsUrlParams(facesContext,
546 serializedView);
547 }
548 else
549 {
550 log.error("ResponseStateManager of render kit " + uiViewRoot.getRenderKitId() + " is no MyfacesResponseStateManager and does not support saving state in url parameters.");
551 }
552 }
553
554 if (log.isTraceEnabled()) log.trace("Exiting writeStateAsUrlParams");
555 }
556
557
558
559 protected RenderKitFactory getRenderKitFactory()
560 {
561 if (_renderKitFactory == null)
562 {
563 _renderKitFactory = (RenderKitFactory)FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
564 }
565 return _renderKitFactory;
566 }
567
568 protected void saveSerializedViewInServletSession(FacesContext context,
569 Object serializedView)
570 {
571 Map<String, Object> sessionMap = context.getExternalContext().getSessionMap();
572 SerializedViewCollection viewCollection = (SerializedViewCollection) sessionMap
573 .get(SERIALIZED_VIEW_SESSION_ATTR);
574 if (viewCollection == null)
575 {
576 viewCollection = new SerializedViewCollection();
577 sessionMap.put(SERIALIZED_VIEW_SESSION_ATTR, viewCollection);
578 }
579 viewCollection.add(context, serializeView(context, serializedView));
580
581 sessionMap.put(SERIALIZED_VIEW_SESSION_ATTR, viewCollection);
582 }
583
584 protected Object getSerializedViewFromServletSession(FacesContext context, String viewId, Integer sequence)
585 {
586 ExternalContext externalContext = context.getExternalContext();
587 Map<String, Object> requestMap = externalContext.getRequestMap();
588 Object serializedView = null;
589 if (requestMap.containsKey(RESTORED_SERIALIZED_VIEW_REQUEST_ATTR))
590 {
591 serializedView = requestMap.get(RESTORED_SERIALIZED_VIEW_REQUEST_ATTR);
592 }
593 else
594 {
595 SerializedViewCollection viewCollection = (SerializedViewCollection) externalContext
596 .getSessionMap().get(SERIALIZED_VIEW_SESSION_ATTR);
597 if (viewCollection != null)
598 {
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614 if (sequence != null)
615 {
616 Object state = viewCollection.get(sequence, viewId);
617 if (state != null)
618 {
619 serializedView = deserializeView(state);
620 }
621 }
622 }
623 requestMap.put(RESTORED_SERIALIZED_VIEW_REQUEST_ATTR, serializedView);
624 nextViewSequence(context);
625 }
626 return serializedView;
627 }
628
629 protected int getNextViewSequence(FacesContext context)
630 {
631 ExternalContext externalContext = context.getExternalContext();
632
633 if (!externalContext.getRequestMap().containsKey(RendererUtils.SEQUENCE_PARAM))
634 {
635 nextViewSequence(context);
636 }
637
638 Integer sequence = (Integer) externalContext.getRequestMap().get(RendererUtils.SEQUENCE_PARAM);
639 return sequence.intValue();
640 }
641
642 protected void nextViewSequence(FacesContext facescontext)
643 {
644 ExternalContext externalContext = facescontext.getExternalContext();
645 Object sessionObj = externalContext.getSession(true);
646 synchronized(sessionObj)
647
648 {
649 Map<String, Object> map = externalContext.getSessionMap();
650 Integer sequence = (Integer) map.get(RendererUtils.SEQUENCE_PARAM);
651 if(sequence == null || sequence.intValue() == Integer.MAX_VALUE)
652 {
653 sequence = Integer.valueOf(1);
654 }
655 else
656 {
657 sequence = Integer.valueOf(sequence.intValue() + 1);
658 }
659 map.put(RendererUtils.SEQUENCE_PARAM, sequence);
660 externalContext.getRequestMap().put(RendererUtils.SEQUENCE_PARAM, sequence);
661 }
662 }
663
664 protected Object serializeView(FacesContext context, Object serializedView)
665 {
666 if (log.isTraceEnabled()) log.trace("Entering serializeView");
667
668 if(isSerializeStateInSession(context))
669 {
670 if (log.isTraceEnabled()) log.trace("Processing serializeView - serialize state in session");
671
672 ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
673 try
674 {
675 OutputStream os = baos;
676 if(isCompressStateInSession(context))
677 {
678 if (log.isTraceEnabled()) log.trace("Processing serializeView - serialize compressed");
679
680 os.write(COMPRESSED_FLAG);
681 os = new GZIPOutputStream(os, 1024);
682 }
683 else
684 {
685 if (log.isTraceEnabled()) log.trace("Processing serializeView - serialize uncompressed");
686
687 os.write(UNCOMPRESSED_FLAG);
688 }
689
690 Object[] stateArray = (Object[]) serializedView;
691
692 ObjectOutputStream out = new ObjectOutputStream(os);
693 out.writeObject(stateArray[0]);
694 out.writeObject(stateArray[1]);
695 out.close();
696 baos.close();
697
698 if (log.isTraceEnabled()) log.trace("Exiting serializeView - serialized. Bytes : "+baos.size());
699 return baos.toByteArray();
700 }
701 catch (IOException e)
702 {
703 log.error("Exiting serializeView - Could not serialize state: " + e.getMessage(), e);
704 return null;
705 }
706 }
707
708
709 if (log.isTraceEnabled())
710 log.trace("Exiting serializeView - do not serialize state in session.");
711
712 return serializedView;
713
714 }
715
716
717
718
719
720
721
722 protected boolean isSerializeStateInSession(FacesContext context)
723 {
724 String value = context.getExternalContext().getInitParameter(
725 SERIALIZE_STATE_IN_SESSION_PARAM);
726 boolean serialize = DEFAULT_SERIALIZE_STATE_IN_SESSION;
727 if (value != null)
728 {
729 serialize = Boolean.valueOf(value);
730 }
731 return serialize;
732 }
733
734
735
736
737
738
739
740 protected boolean isCompressStateInSession(FacesContext context)
741 {
742 String value = context.getExternalContext().getInitParameter(
743 COMPRESS_SERVER_STATE_PARAM);
744 boolean compress = DEFAULT_COMPRESS_SERVER_STATE_PARAM;
745 if (value != null)
746 {
747 compress = Boolean.valueOf(value);
748 }
749 return compress;
750 }
751
752 protected Object deserializeView(Object state)
753 {
754 if (log.isTraceEnabled()) log.trace("Entering deserializeView");
755
756 if(state instanceof byte[])
757 {
758 if (log.isTraceEnabled()) log.trace("Processing deserializeView - deserializing serialized state. Bytes : "+((byte[]) state).length);
759
760 try
761 {
762 ByteArrayInputStream bais = new ByteArrayInputStream((byte[]) state);
763 InputStream is = bais;
764 if(is.read() == COMPRESSED_FLAG)
765 {
766 is = new GZIPInputStream(is);
767 }
768 ObjectInputStream ois = null;
769 try
770 {
771 final ObjectInputStream in = new MyFacesObjectInputStream(is);
772 ois = in;
773 Object object = null;
774 if (System.getSecurityManager() != null)
775 {
776 object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object []>()
777 {
778 public Object[] run() throws PrivilegedActionException, IOException, ClassNotFoundException
779 {
780 return new Object[] {in.readObject(), in.readObject()};
781 }
782 });
783 }
784 else
785 {
786 object = new Object[] {in.readObject(), in.readObject()};
787 }
788 return object;
789 }
790 finally
791 {
792 if (ois != null)
793 {
794 ois.close();
795 ois = null;
796 }
797 }
798 }
799 catch (PrivilegedActionException e)
800 {
801 log.error("Exiting deserializeView - Could not deserialize state: " + e.getMessage(), e);
802 return null;
803 }
804 catch (IOException e)
805 {
806 log.error("Exiting deserializeView - Could not deserialize state: " + e.getMessage(), e);
807 return null;
808 }
809 catch (ClassNotFoundException e)
810 {
811 log.error("Exiting deserializeView - Could not deserialize state: " + e.getMessage(), e);
812 return null;
813 }
814 }
815 else if (state instanceof Object[])
816 {
817 if (log.isTraceEnabled()) log.trace("Exiting deserializeView - state not serialized.");
818
819 return state;
820 }
821 else if(state == null)
822 {
823 log.error("Exiting deserializeView - this method should not be called with a null-state.");
824 return null;
825 }
826 else
827 {
828 log.error("Exiting deserializeView - this method should not be called with a state of type : "+state.getClass());
829 return null;
830 }
831 }
832
833 private boolean isLegacyResponseStateManager(ResponseStateManager instance) {
834
835 Method[] methods = instance.getClass().getMethods();
836 for (Method m : methods)
837 {
838 if (m.getName().equals("getState") &&
839 Arrays.equals(m.getParameterTypes(),new Class[] {FacesContext.class, String.class}))
840 {
841 return false;
842 }
843 }
844
845 return true;
846 }
847
848 protected static class SerializedViewCollection implements Serializable
849 {
850 private static final long serialVersionUID = -3734849062185115847L;
851
852 private final List<Object> _keys = new ArrayList<Object>(DEFAULT_NUMBER_OF_VIEWS_IN_SESSION);
853 private final Map<Object, Object> _serializedViews = new HashMap<Object, Object>();
854
855
856
857 private transient Map<Object, Object> _oldSerializedViews = null;
858
859 public synchronized void add(FacesContext context, Object state)
860 {
861 Object key = new SerializedViewKey(context);
862 _serializedViews.put(key, state);
863
864 while (_keys.remove(key));
865 _keys.add(key);
866
867 int views = getNumberOfViewsInSession(context);
868 while (_keys.size() > views)
869 {
870 key = _keys.remove(0);
871 Object oldView = _serializedViews.remove(key);
872 if (oldView != null &&
873 !CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF.equals(getCacheOldViewsInSessionMode(context)))
874 {
875 getOldSerializedViewsMap().put(key, oldView);
876 }
877 }
878 }
879
880
881
882
883
884
885
886 protected int getNumberOfViewsInSession(FacesContext context)
887 {
888 String value = context.getExternalContext().getInitParameter(
889 NUMBER_OF_VIEWS_IN_SESSION_PARAM);
890 int views = DEFAULT_NUMBER_OF_VIEWS_IN_SESSION;
891 if (value != null)
892 {
893 try
894 {
895 views = Integer.parseInt(value);
896 if (views <= 0)
897 {
898 log.error("Configured value for " + NUMBER_OF_VIEWS_IN_SESSION_PARAM
899 + " is not valid, must be an value > 0, using default value ("
900 + DEFAULT_NUMBER_OF_VIEWS_IN_SESSION);
901 views = DEFAULT_NUMBER_OF_VIEWS_IN_SESSION;
902 }
903 }
904 catch (Throwable e)
905 {
906 log.error("Error determining the value for " + NUMBER_OF_VIEWS_IN_SESSION_PARAM
907 + ", expected an integer value > 0, using default value ("
908 + DEFAULT_NUMBER_OF_VIEWS_IN_SESSION + "): " + e.getMessage(), e);
909 }
910 }
911 return views;
912 }
913
914
915
916
917 protected Map<Object, Object> getOldSerializedViewsMap()
918 {
919 FacesContext context = FacesContext.getCurrentInstance();
920 if (_oldSerializedViews == null && context != null)
921 {
922 String cacheMode = getCacheOldViewsInSessionMode(context);
923 if (CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK.equals(cacheMode))
924 {
925 _oldSerializedViews = new ReferenceMap(AbstractReferenceMap.WEAK, AbstractReferenceMap.WEAK, true);
926 }
927 else if (CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT_WEAK.equals(cacheMode))
928 {
929 _oldSerializedViews = new ReferenceMap(AbstractReferenceMap.SOFT, AbstractReferenceMap.WEAK, true);
930 }
931 else if (CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT.equals(cacheMode))
932 {
933 _oldSerializedViews = new ReferenceMap(AbstractReferenceMap.SOFT, AbstractReferenceMap.SOFT, true);
934 }
935 else if (CACHE_OLD_VIEWS_IN_SESSION_MODE_HARD_SOFT.equals(cacheMode))
936 {
937 _oldSerializedViews = new ReferenceMap(AbstractReferenceMap.HARD, AbstractReferenceMap.SOFT);
938 }
939 }
940 return _oldSerializedViews;
941 }
942
943
944
945
946
947
948
949
950
951 protected String getCacheOldViewsInSessionMode(FacesContext context) {
952 String value = context.getExternalContext().getInitParameter(
953 CACHE_OLD_VIEWS_IN_SESSION_MODE);
954 if (value == null)
955 {
956 return CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF;
957 }
958 else if (value.equalsIgnoreCase(CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT))
959 {
960 return CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT;
961 }
962 else if (value.equalsIgnoreCase(CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT_WEAK))
963 {
964 return CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT_WEAK;
965 }
966 else if (value.equalsIgnoreCase(CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK))
967 {
968 return CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK;
969 }
970 else if (value.equalsIgnoreCase(CACHE_OLD_VIEWS_IN_SESSION_MODE_HARD_SOFT))
971 {
972 return CACHE_OLD_VIEWS_IN_SESSION_MODE_HARD_SOFT;
973 }
974 else
975 {
976 return CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF;
977 }
978 }
979
980 public Object get(Integer sequence, String viewId)
981 {
982 Object key = new SerializedViewKey(viewId, sequence);
983 Object value = _serializedViews.get(key);
984 if (value == null)
985 {
986 Map<Object,Object> oldSerializedViewMap = getOldSerializedViewsMap();
987 if (oldSerializedViewMap != null)
988 {
989 value = oldSerializedViewMap.get(key);
990 }
991 }
992 return value;
993 }
994 }
995
996 protected static class SerializedViewKey implements Serializable
997 {
998 private static final long serialVersionUID = -1170697124386063642L;
999
1000 private final String _viewId;
1001 private final Integer _sequenceId;
1002
1003 public SerializedViewKey(String viewId, Integer sequence)
1004 {
1005 _sequenceId = sequence;
1006 _viewId = viewId;
1007 }
1008
1009 public SerializedViewKey(FacesContext context)
1010 {
1011 _sequenceId = RendererUtils.getViewSequence(context);
1012 _viewId = context.getViewRoot().getViewId();
1013 }
1014
1015 @Override
1016 public int hashCode()
1017 {
1018 final int PRIME = 31;
1019 int result = 1;
1020 result = PRIME * result + ((_sequenceId == null) ? 0 : _sequenceId.hashCode());
1021 result = PRIME * result + ((_viewId == null) ? 0 : _viewId.hashCode());
1022 return result;
1023 }
1024
1025 @Override
1026 public boolean equals(Object obj)
1027 {
1028 if (this == obj)
1029 return true;
1030 if (obj == null)
1031 return false;
1032 if (getClass() != obj.getClass())
1033 return false;
1034 final SerializedViewKey other = (SerializedViewKey) obj;
1035 if (_sequenceId == null)
1036 {
1037 if (other._sequenceId != null)
1038 return false;
1039 }
1040 else if (!_sequenceId.equals(other._sequenceId))
1041 return false;
1042 if (_viewId == null)
1043 {
1044 if (other._viewId != null)
1045 return false;
1046 }
1047 else if (!_viewId.equals(other._viewId))
1048 return false;
1049 return true;
1050 }
1051
1052 }
1053 }