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