1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.renderkit.html;
20
21 import java.io.IOException;
22 import java.util.logging.Level;
23 import java.util.logging.Logger;
24
25 import javax.faces.context.ExternalContext;
26 import javax.faces.context.FacesContext;
27 import javax.faces.context.ResponseWriter;
28 import javax.faces.render.RenderKitFactory;
29 import javax.faces.render.ResponseStateManager;
30
31 import org.apache.myfaces.application.StateCache;
32 import org.apache.myfaces.application.StateCacheFactory;
33 import org.apache.myfaces.application.viewstate.StateCacheFactoryImpl;
34 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
35 import org.apache.myfaces.renderkit.MyfacesResponseStateManager;
36 import org.apache.myfaces.shared.config.MyfacesConfig;
37 import org.apache.myfaces.shared.renderkit.html.HTML;
38 import org.apache.myfaces.shared.renderkit.html.HtmlRendererUtils;
39 import org.apache.myfaces.shared.renderkit.html.util.JavascriptUtils;
40 import org.apache.myfaces.shared.util.StateUtils;
41 import org.apache.myfaces.shared.util.WebConfigParamUtils;
42
43
44
45
46
47 public class HtmlResponseStateManager extends MyfacesResponseStateManager
48 {
49
50 private static final Logger log = Logger.getLogger(HtmlResponseStateManager.class.getName());
51
52
53 private static final int STATE_PARAM = 0;
54 private static final int VIEWID_PARAM = 1;
55
56 public static final String STANDARD_STATE_SAVING_PARAM = "javax.faces.ViewState";
57
58
59
60
61
62
63
64
65
66
67
68 @JSFWebConfigParam(since="2.0.6", expectedValues="true, false", defaultValue="true", group="state")
69 public static final String INIT_PARAM_HANDLE_STATE_CACHING_MECHANICS
70 = "org.apache.myfaces.HANDLE_STATE_CACHING_MECHANICS";
71
72
73
74
75 @JSFWebConfigParam(since="2.2.8, 2.1.18, 2.0.24", expectedValues="true, false",
76 defaultValue="true", group="state")
77 public static final String INIT_PARAM_AUTOCOMPLETE_OFF_VIEW_STATE =
78 "org.apache.myfaces.AUTOCOMPLETE_OFF_VIEW_STATE";
79
80 private Boolean _handleStateCachingMechanics;
81
82 private StateCacheFactory _stateCacheFactory;
83
84 private Boolean _autoCompleteOffViewState;
85
86 public HtmlResponseStateManager()
87 {
88 _stateCacheFactory = new StateCacheFactoryImpl();
89 _autoCompleteOffViewState = null;
90 }
91
92 protected boolean isHandlingStateCachingMechanics(FacesContext facesContext)
93 {
94 if (_handleStateCachingMechanics == null)
95 {
96 _handleStateCachingMechanics
97 = WebConfigParamUtils.getBooleanInitParameter(facesContext.getExternalContext(),
98 INIT_PARAM_HANDLE_STATE_CACHING_MECHANICS, true);
99 }
100 return _handleStateCachingMechanics.booleanValue();
101 }
102
103 public void writeState(FacesContext facesContext, Object state) throws IOException
104 {
105 ResponseWriter responseWriter = facesContext.getResponseWriter();
106
107 Object savedStateObject = null;
108
109 if (isHandlingStateCachingMechanics(facesContext))
110 {
111
112 savedStateObject = getStateCache(facesContext).encodeSerializedState(facesContext, state);
113 }
114 else
115 {
116 Object token = null;
117 Object[] savedState = new Object[2];
118 token = state;
119
120 if (log.isLoggable(Level.FINEST))
121 {
122 log.finest("Writing state in client");
123 }
124
125
126 if (token != null)
127 {
128 savedState[STATE_PARAM] = token;
129 }
130 else
131 {
132 if (log.isLoggable(Level.FINEST))
133 {
134 log.finest("No component states to be saved in client response!");
135 }
136 }
137
138 savedState[VIEWID_PARAM] = facesContext.getViewRoot().getViewId();
139
140 if (log.isLoggable(Level.FINEST))
141 {
142 log.finest("Writing view state and renderKit fields");
143 }
144
145 savedStateObject = savedState;
146 }
147
148
149 writeViewStateField(facesContext, responseWriter, savedStateObject);
150
151
152 writeRenderKitIdField(facesContext, responseWriter);
153 }
154
155 @Override
156 public void saveState(FacesContext facesContext, Object state)
157 {
158 if (isHandlingStateCachingMechanics(facesContext))
159 {
160 getStateCache(facesContext).saveSerializedView(facesContext, state);
161 }
162 else
163 {
164
165 }
166 }
167
168 private void writeViewStateField(FacesContext facesContext, ResponseWriter responseWriter, Object savedState)
169 throws IOException
170 {
171 String serializedState = StateUtils.construct(savedState, facesContext.getExternalContext());
172 ExternalContext extContext = facesContext.getExternalContext();
173 MyfacesConfig myfacesConfig = MyfacesConfig.getCurrentInstance(extContext);
174
175
176 if (JavascriptUtils.isJavascriptAllowed(extContext) && myfacesConfig.isViewStateJavascript())
177 {
178 HtmlRendererUtils.renderViewStateJavascript(facesContext, STANDARD_STATE_SAVING_PARAM, serializedState);
179 }
180 else
181 {
182 responseWriter.startElement(HTML.INPUT_ELEM, null);
183 responseWriter.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_HIDDEN, null);
184 responseWriter.writeAttribute(HTML.NAME_ATTR, STANDARD_STATE_SAVING_PARAM, null);
185 if (myfacesConfig.isRenderViewStateId())
186 {
187 responseWriter.writeAttribute(HTML.ID_ATTR, STANDARD_STATE_SAVING_PARAM, null);
188 }
189 responseWriter.writeAttribute(HTML.VALUE_ATTR, serializedState, null);
190 if (this.isAutocompleteOffViewState(facesContext))
191 {
192 responseWriter.writeAttribute(HTML.AUTOCOMPLETE_ATTR, "off", null);
193 }
194 responseWriter.endElement(HTML.INPUT_ELEM);
195 }
196 }
197
198 private void writeRenderKitIdField(FacesContext facesContext, ResponseWriter responseWriter) throws IOException
199 {
200
201 String defaultRenderKitId = facesContext.getApplication().getDefaultRenderKitId();
202 if (defaultRenderKitId != null && !RenderKitFactory.HTML_BASIC_RENDER_KIT.equals(defaultRenderKitId))
203 {
204 responseWriter.startElement(HTML.INPUT_ELEM, null);
205 responseWriter.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_HIDDEN, null);
206 responseWriter.writeAttribute(HTML.NAME_ATTR, ResponseStateManager.RENDER_KIT_ID_PARAM, null);
207 responseWriter.writeAttribute(HTML.VALUE_ATTR, defaultRenderKitId, null);
208 responseWriter.endElement(HTML.INPUT_ELEM);
209 }
210 }
211
212 @Override
213 public Object getState(FacesContext facesContext, String viewId)
214 {
215 Object savedState = getSavedState(facesContext);
216 if (savedState == null)
217 {
218 return null;
219 }
220
221 if (isHandlingStateCachingMechanics(facesContext))
222 {
223 return getStateCache(facesContext).restoreSerializedView(facesContext, viewId, savedState);
224 }
225 else
226 {
227 return ((Object[])savedState)[STATE_PARAM];
228 }
229 }
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268 private Object getSavedState(FacesContext facesContext)
269 {
270 Object encodedState =
271 facesContext.getExternalContext().getRequestParameterMap().get(STANDARD_STATE_SAVING_PARAM);
272 if(encodedState==null || (((String) encodedState).length() == 0))
273 {
274 return null;
275 }
276
277 Object savedStateObject = StateUtils.reconstruct((String)encodedState, facesContext.getExternalContext());
278
279 if (isHandlingStateCachingMechanics(facesContext))
280 {
281 return savedStateObject;
282 }
283 else
284 {
285 Object[] savedState = (Object[]) savedStateObject;
286
287 if (savedState == null)
288 {
289 if (log.isLoggable(Level.FINEST))
290 {
291 log.finest("No saved state");
292 }
293 return null;
294 }
295
296 String restoredViewId = (String)savedState[VIEWID_PARAM];
297
298 if (restoredViewId == null)
299 {
300
301 if (log.isLoggable(Level.FINEST))
302 {
303 log.finest("No saved state or state of a different viewId: " + restoredViewId);
304 }
305
306 return null;
307 }
308
309 return savedState;
310 }
311 }
312
313
314
315
316
317
318 @Override
319 public boolean isPostback(FacesContext context)
320 {
321 return context.getExternalContext().getRequestParameterMap().containsKey(ResponseStateManager.VIEW_STATE_PARAM);
322 }
323
324 @Override
325 public String getViewState(FacesContext facesContext, Object baseState)
326 {
327 if (baseState == null)
328 {
329 return null;
330 }
331
332 Object state = null;
333 if (isHandlingStateCachingMechanics(facesContext))
334 {
335 state = getStateCache(facesContext).saveSerializedView(facesContext, baseState);
336 }
337 else
338 {
339
340 Object[] savedState = new Object[2];
341
342 if (state != null)
343 {
344 savedState[STATE_PARAM] = baseState;
345 }
346
347 savedState[VIEWID_PARAM] = facesContext.getViewRoot().getViewId();
348
349 state = savedState;
350 }
351 return StateUtils.construct(state, facesContext.getExternalContext());
352 }
353
354 @Override
355 public boolean isWriteStateAfterRenderViewRequired(FacesContext facesContext)
356 {
357 return getStateCache(facesContext).isWriteStateAfterRenderViewRequired(facesContext);
358 }
359
360 protected StateCache getStateCache(FacesContext facesContext)
361 {
362 return _stateCacheFactory.getStateCache(facesContext);
363 }
364
365 private boolean isAutocompleteOffViewState(FacesContext facesContext)
366 {
367 if (_autoCompleteOffViewState == null)
368 {
369 _autoCompleteOffViewState = WebConfigParamUtils.getBooleanInitParameter(facesContext.getExternalContext(),
370 INIT_PARAM_AUTOCOMPLETE_OFF_VIEW_STATE, true);
371 }
372 return _autoCompleteOffViewState;
373 }
374 }