1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.application;
20
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.HashSet;
24 import java.util.List;
25 import java.util.Set;
26 import java.util.logging.Level;
27 import java.util.logging.Logger;
28
29 import javax.faces.FactoryFinder;
30 import javax.faces.application.StateManager;
31 import javax.faces.component.NamingContainer;
32 import javax.faces.component.UIComponent;
33 import javax.faces.component.UIComponentBase;
34 import javax.faces.component.UIViewRoot;
35 import javax.faces.context.FacesContext;
36 import javax.faces.render.RenderKit;
37 import javax.faces.render.RenderKitFactory;
38 import javax.faces.render.ResponseStateManager;
39 import javax.faces.view.StateManagementStrategy;
40 import javax.faces.view.ViewDeclarationLanguage;
41
42 import org.apache.myfaces.application.viewstate.StateCacheUtils;
43 import org.apache.myfaces.context.RequestViewContext;
44
45 public class StateManagerImpl extends StateManager
46 {
47 private static final Logger log = Logger.getLogger(StateManagerImpl.class.getName());
48
49 private static final String SERIALIZED_VIEW_REQUEST_ATTR =
50 StateManagerImpl.class.getName() + ".SERIALIZED_VIEW";
51
52 private RenderKitFactory _renderKitFactory = null;
53
54 public StateManagerImpl()
55 {
56 }
57
58 @Override
59 protected Object getComponentStateToSave(FacesContext facesContext)
60 {
61 if (log.isLoggable(Level.FINEST))
62 {
63 log.finest("Entering getComponentStateToSave");
64 }
65
66 UIViewRoot viewRoot = facesContext.getViewRoot();
67 if (viewRoot.isTransient())
68 {
69 return null;
70 }
71
72 Object serializedComponentStates = viewRoot.processSaveState(facesContext);
73
74 if (log.isLoggable(Level.FINEST))
75 {
76 log.finest("Exiting getComponentStateToSave");
77 }
78 return serializedComponentStates;
79 }
80
81
82
83
84
85
86
87 @Override
88 protected Object getTreeStructureToSave(FacesContext facesContext)
89 {
90 if (log.isLoggable(Level.FINEST))
91 {
92 log.finest("Entering getTreeStructureToSave");
93 }
94 UIViewRoot viewRoot = facesContext.getViewRoot();
95 if (viewRoot.isTransient())
96 {
97 return null;
98 }
99 TreeStructureManager tsm = new TreeStructureManager();
100 Object retVal = tsm.buildTreeStructureToSave(viewRoot);
101 if (log.isLoggable(Level.FINEST))
102 {
103 log.finest("Exiting getTreeStructureToSave");
104 }
105 return retVal;
106 }
107
108 @Override
109 public UIViewRoot restoreView(FacesContext facesContext, String viewId, String renderKitId)
110 {
111 if (log.isLoggable(Level.FINEST))
112 {
113 log.finest("Entering restoreView - viewId: " + viewId + " ; renderKitId: " + renderKitId);
114 }
115
116 UIViewRoot uiViewRoot = null;
117
118 ViewDeclarationLanguage vdl = facesContext.getApplication().
119 getViewHandler().getViewDeclarationLanguage(facesContext,viewId);
120 StateManagementStrategy sms = null;
121 if (vdl != null)
122 {
123 sms = vdl.getStateManagementStrategy(facesContext, viewId);
124 }
125
126 if (sms != null)
127 {
128 if (log.isLoggable(Level.FINEST))
129 {
130 log.finest("Redirect to StateManagementStrategy: " + sms.getClass().getName());
131 }
132
133 uiViewRoot = sms.restoreView(facesContext, viewId, renderKitId);
134 }
135 else
136 {
137 RenderKit renderKit = getRenderKitFactory().getRenderKit(facesContext, renderKitId);
138 ResponseStateManager responseStateManager = renderKit.getResponseStateManager();
139
140 Object state = responseStateManager.getState(facesContext, viewId);
141
142 if (state != null)
143 {
144 Object[] stateArray = (Object[])state;
145 TreeStructureManager tsm = new TreeStructureManager();
146
147 uiViewRoot = tsm.restoreTreeStructure(((Object[])stateArray[0])[0]);
148
149 if (uiViewRoot != null)
150 {
151 facesContext.setViewRoot (uiViewRoot);
152 uiViewRoot.processRestoreState(facesContext, stateArray[1]);
153
154 RequestViewContext.getCurrentInstance(facesContext).refreshRequestViewContext(
155 facesContext, uiViewRoot);
156
157
158
159
160
161 Object rlc = ((Object[])stateArray[0])[1];
162 if (rlc != null)
163 {
164 facesContext.setResourceLibraryContracts((List) UIComponentBase.
165 restoreAttachedState(facesContext, rlc));
166 }
167 }
168 }
169 }
170 if (log.isLoggable(Level.FINEST))
171 {
172 log.finest("Exiting restoreView - " + viewId);
173 }
174
175 return uiViewRoot;
176 }
177
178
179
180
181
182 @Override
183 public Object saveView(FacesContext facesContext)
184 {
185 UIViewRoot uiViewRoot = facesContext.getViewRoot();
186
187 if (uiViewRoot.isTransient())
188 {
189 return null;
190 }
191
192 Object serializedView = null;
193 ResponseStateManager responseStateManager = facesContext.getRenderKit().getResponseStateManager();
194
195 String viewId = uiViewRoot.getViewId();
196 ViewDeclarationLanguage vdl = facesContext.getApplication().
197 getViewHandler().getViewDeclarationLanguage(facesContext,viewId);
198
199 try
200 {
201 facesContext.getAttributes().put(StateManager.IS_SAVING_STATE, Boolean.TRUE);
202 if (vdl != null)
203 {
204 StateManagementStrategy sms = vdl.getStateManagementStrategy(facesContext, viewId);
205
206 if (sms != null)
207 {
208 if (log.isLoggable(Level.FINEST))
209 {
210 log.finest("Calling saveView of StateManagementStrategy: " + sms.getClass().getName());
211 }
212
213 serializedView = sms.saveView(facesContext);
214
215
216
217 if (StateCacheUtils.isMyFacesResponseStateManager(responseStateManager))
218 {
219 StateCacheUtils.getMyFacesResponseStateManager(responseStateManager).
220 saveState(facesContext, serializedView);
221 }
222
223 return serializedView;
224 }
225 }
226
227
228
229
230
231 if (uiViewRoot.isTransient())
232 {
233 return null;
234 }
235
236 if (log.isLoggable(Level.FINEST))
237 {
238 log.finest("Entering saveSerializedView");
239 }
240
241 checkForDuplicateIds(facesContext, facesContext.getViewRoot(), new HashSet<String>());
242
243 if (log.isLoggable(Level.FINEST))
244 {
245 log.finest("Processing saveSerializedView - Checked for duplicate Ids");
246 }
247
248
249 serializedView = facesContext.getAttributes().get(SERIALIZED_VIEW_REQUEST_ATTR);
250 if (serializedView == null)
251 {
252 if (log.isLoggable(Level.FINEST))
253 {
254 log.finest("Processing saveSerializedView - create new serialized view");
255 }
256
257
258 Object treeStruct = getTreeStructureToSave(facesContext);
259 Object compStates = getComponentStateToSave(facesContext);
260 Object rlcStates = !facesContext.getResourceLibraryContracts().isEmpty() ?
261 UIComponentBase.saveAttachedState(facesContext,
262 new ArrayList<String>(facesContext.getResourceLibraryContracts())) : null;
263 serializedView = new Object[] {
264 new Object[]{treeStruct, rlcStates} ,
265 compStates};
266 facesContext.getAttributes().put(SERIALIZED_VIEW_REQUEST_ATTR,
267 serializedView);
268
269 if (log.isLoggable(Level.FINEST))
270 {
271 log.finest("Processing saveSerializedView - new serialized view created");
272 }
273 }
274
275
276
277 if (StateCacheUtils.isMyFacesResponseStateManager(responseStateManager))
278 {
279 StateCacheUtils.getMyFacesResponseStateManager(responseStateManager).
280 saveState(facesContext, serializedView);
281 }
282
283 if (log.isLoggable(Level.FINEST))
284 {
285 log.finest("Exiting saveView");
286 }
287 }
288 finally
289 {
290 facesContext.getAttributes().remove(StateManager.IS_SAVING_STATE);
291 }
292
293 return serializedView;
294 }
295
296 private static void checkForDuplicateIds(FacesContext context,
297 UIComponent component,
298 Set<String> ids)
299 {
300 String id = component.getId();
301 if (id != null && !ids.add(id))
302 {
303 throw new IllegalStateException("Client-id : " + id +
304 " is duplicated in the faces tree. Component : " +
305 component.getClientId(context)+", path: " +
306 getPathToComponent(component));
307 }
308
309 if (component instanceof NamingContainer)
310 {
311 ids = new HashSet<String>();
312 }
313
314 int facetCount = component.getFacetCount();
315 if (facetCount > 0)
316 {
317 for (UIComponent facet : component.getFacets().values())
318 {
319 checkForDuplicateIds (context, facet, ids);
320 }
321 }
322 for (int i = 0, childCount = component.getChildCount(); i < childCount; i++)
323 {
324 UIComponent child = component.getChildren().get(i);
325 checkForDuplicateIds (context, child, ids);
326 }
327 }
328
329 private static String getPathToComponent(UIComponent component)
330 {
331 StringBuffer buf = new StringBuffer();
332
333 if(component == null)
334 {
335 buf.append("{Component-Path : ");
336 buf.append("[null]}");
337 return buf.toString();
338 }
339
340 getPathToComponent(component,buf);
341
342 buf.insert(0,"{Component-Path : ");
343 buf.append("}");
344
345 return buf.toString();
346 }
347
348 private static void getPathToComponent(UIComponent component, StringBuffer buf)
349 {
350 if(component == null)
351 {
352 return;
353 }
354
355 StringBuffer intBuf = new StringBuffer();
356
357 intBuf.append("[Class: ");
358 intBuf.append(component.getClass().getName());
359 if(component instanceof UIViewRoot)
360 {
361 intBuf.append(",ViewId: ");
362 intBuf.append(((UIViewRoot) component).getViewId());
363 }
364 else
365 {
366 intBuf.append(",Id: ");
367 intBuf.append(component.getId());
368 }
369 intBuf.append("]");
370
371 buf.insert(0,intBuf.toString());
372
373 getPathToComponent(component.getParent(),buf);
374 }
375
376 @Override
377 public void writeState(FacesContext facesContext,
378 Object state) throws IOException
379 {
380 if (log.isLoggable(Level.FINEST))
381 {
382 log.finest("Entering writeState");
383 }
384
385
386
387 RenderKit renderKit = facesContext.getRenderKit();
388 ResponseStateManager responseStateManager = renderKit.getResponseStateManager();
389
390 responseStateManager.writeState(facesContext, state);
391
392 if (log.isLoggable(Level.FINEST))
393 {
394 log.finest("Exiting writeState");
395 }
396
397 }
398
399
400
401 protected RenderKitFactory getRenderKitFactory()
402 {
403 if (_renderKitFactory == null)
404 {
405 _renderKitFactory = (RenderKitFactory)FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
406 }
407 return _renderKitFactory;
408 }
409
410 }