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.HashSet;
23 import java.util.Iterator;
24 import java.util.Set;
25 import java.util.logging.Level;
26 import java.util.logging.Logger;
27
28 import javax.faces.FactoryFinder;
29 import javax.faces.application.StateManager;
30 import javax.faces.component.NamingContainer;
31 import javax.faces.component.UIComponent;
32 import javax.faces.component.UIViewRoot;
33 import javax.faces.context.ExternalContext;
34 import javax.faces.context.FacesContext;
35 import javax.faces.render.RenderKit;
36 import javax.faces.render.RenderKitFactory;
37 import javax.faces.render.ResponseStateManager;
38 import javax.faces.view.StateManagementStrategy;
39 import javax.faces.view.ViewDeclarationLanguage;
40
41 import org.apache.myfaces.renderkit.StateCacheUtils;
42
43 public class StateManagerImpl extends StateManager
44 {
45 private static final Logger log = Logger.getLogger(StateManagerImpl.class.getName());
46
47 private static final String SERIALIZED_VIEW_REQUEST_ATTR =
48 StateManagerImpl.class.getName() + ".SERIALIZED_VIEW";
49
50 private static final String IS_SAVING_STATE = "javax.faces.IS_SAVING_STATE";
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 uiViewRoot = tsm.restoreTreeStructure(stateArray[0]);
147
148 if (uiViewRoot != null)
149 {
150 facesContext.setViewRoot (uiViewRoot);
151 uiViewRoot.processRestoreState(facesContext, stateArray[1]);
152 }
153 }
154 }
155 if (log.isLoggable(Level.FINEST))
156 {
157 log.finest("Exiting restoreView - " + viewId);
158 }
159
160 return uiViewRoot;
161 }
162
163
164
165
166
167 @Override
168 public Object saveView(FacesContext facesContext)
169 {
170 Object serializedView = null;
171 UIViewRoot uiViewRoot = facesContext.getViewRoot();
172 ResponseStateManager responseStateManager = facesContext.getRenderKit().getResponseStateManager();
173
174 String viewId = uiViewRoot.getViewId();
175 ViewDeclarationLanguage vdl = facesContext.getApplication().
176 getViewHandler().getViewDeclarationLanguage(facesContext,viewId);
177
178 try
179 {
180 facesContext.getAttributes().put(IS_SAVING_STATE, Boolean.TRUE);
181 if (vdl != null)
182 {
183 StateManagementStrategy sms = vdl.getStateManagementStrategy(facesContext, viewId);
184
185 if (sms != null)
186 {
187 if (log.isLoggable(Level.FINEST))
188 {
189 log.finest("Calling saveView of StateManagementStrategy: " + sms.getClass().getName());
190 }
191
192 serializedView = sms.saveView(facesContext);
193
194
195
196 if (StateCacheUtils.isMyFacesResponseStateManager(responseStateManager))
197 {
198 StateCacheUtils.getMyFacesResponseStateManager(responseStateManager).
199 saveState(facesContext, serializedView);
200 }
201
202 return serializedView;
203 }
204 }
205
206
207
208
209
210 if (uiViewRoot.isTransient())
211 {
212 return null;
213 }
214
215 if (log.isLoggable(Level.FINEST))
216 {
217 log.finest("Entering saveSerializedView");
218 }
219
220 checkForDuplicateIds(facesContext, facesContext.getViewRoot(), new HashSet<String>());
221
222 if (log.isLoggable(Level.FINEST))
223 {
224 log.finest("Processing saveSerializedView - Checked for duplicate Ids");
225 }
226
227 ExternalContext externalContext = facesContext.getExternalContext();
228
229
230 serializedView = facesContext.getAttributes()
231 .get(SERIALIZED_VIEW_REQUEST_ATTR);
232 if (serializedView == null)
233 {
234 if (log.isLoggable(Level.FINEST))
235 {
236 log.finest("Processing saveSerializedView - create new serialized view");
237 }
238
239
240 Object treeStruct = getTreeStructureToSave(facesContext);
241 Object compStates = getComponentStateToSave(facesContext);
242 serializedView = new Object[] {treeStruct, compStates};
243 facesContext.getAttributes().put(SERIALIZED_VIEW_REQUEST_ATTR,
244 serializedView);
245
246 if (log.isLoggable(Level.FINEST))
247 {
248 log.finest("Processing saveSerializedView - new serialized view created");
249 }
250 }
251
252
253
254 if (StateCacheUtils.isMyFacesResponseStateManager(responseStateManager))
255 {
256 StateCacheUtils.getMyFacesResponseStateManager(responseStateManager).
257 saveState(facesContext, serializedView);
258 }
259
260 if (log.isLoggable(Level.FINEST))
261 {
262 log.finest("Exiting saveView");
263 }
264 }
265 finally
266 {
267 facesContext.getAttributes().remove(IS_SAVING_STATE);
268 }
269
270 return serializedView;
271 }
272
273 private static void checkForDuplicateIds(FacesContext context,
274 UIComponent component,
275 Set<String> ids)
276 {
277 String id = component.getId();
278 if (id != null && !ids.add(id))
279 {
280 throw new IllegalStateException("Client-id : " + id +
281 " is duplicated in the faces tree. Component : " +
282 component.getClientId(context)+", path: " +
283 getPathToComponent(component));
284 }
285
286 if (component instanceof NamingContainer)
287 {
288 ids = new HashSet<String>();
289 }
290
291 int facetCount = component.getFacetCount();
292 if (facetCount > 0)
293 {
294 for (UIComponent facet : component.getFacets().values())
295 {
296 checkForDuplicateIds (context, facet, ids);
297 }
298 }
299 for (int i = 0, childCount = component.getChildCount(); i < childCount; i++)
300 {
301 UIComponent child = component.getChildren().get(i);
302 checkForDuplicateIds (context, child, ids);
303 }
304 }
305
306 private static String getPathToComponent(UIComponent component)
307 {
308 StringBuffer buf = new StringBuffer();
309
310 if(component == null)
311 {
312 buf.append("{Component-Path : ");
313 buf.append("[null]}");
314 return buf.toString();
315 }
316
317 getPathToComponent(component,buf);
318
319 buf.insert(0,"{Component-Path : ");
320 buf.append("}");
321
322 return buf.toString();
323 }
324
325 private static void getPathToComponent(UIComponent component, StringBuffer buf)
326 {
327 if(component == null)
328 {
329 return;
330 }
331
332 StringBuffer intBuf = new StringBuffer();
333
334 intBuf.append("[Class: ");
335 intBuf.append(component.getClass().getName());
336 if(component instanceof UIViewRoot)
337 {
338 intBuf.append(",ViewId: ");
339 intBuf.append(((UIViewRoot) component).getViewId());
340 }
341 else
342 {
343 intBuf.append(",Id: ");
344 intBuf.append(component.getId());
345 }
346 intBuf.append("]");
347
348 buf.insert(0,intBuf.toString());
349
350 getPathToComponent(component.getParent(),buf);
351 }
352
353 @Override
354 public void writeState(FacesContext facesContext,
355 Object state) throws IOException
356 {
357 if (log.isLoggable(Level.FINEST))
358 {
359 log.finest("Entering writeState");
360 }
361
362
363
364 RenderKit renderKit = facesContext.getRenderKit();
365 ResponseStateManager responseStateManager = renderKit.getResponseStateManager();
366
367 responseStateManager.writeState(facesContext, state);
368
369 if (log.isLoggable(Level.FINEST))
370 {
371 log.finest("Exiting writeState");
372 }
373
374 }
375
376
377
378 protected RenderKitFactory getRenderKitFactory()
379 {
380 if (_renderKitFactory == null)
381 {
382 _renderKitFactory = (RenderKitFactory)FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
383 }
384 return _renderKitFactory;
385 }
386
387 }