1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package javax.faces.application;
20
21 import javax.faces.context.FacesContext;
22
23 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
24
25 import java.io.IOException;
26
27
28 /**
29 * Responsible for storing sufficient information about a component tree so that an identical tree
30 * can later be recreated.
31 * <p>
32 * It is up to the concrete implementation to decide whether to use information from the "view template"
33 * that was used to first create the view, or whether to store sufficient information to enable the
34 * view to be restored without any reference to the original template. However as JSF components have
35 * mutable fields that can be set by code, and affected by user input, at least some state does need
36 * to be kept in order to recreate a previously-existing component tree.
37 * <p>
38 * There are two different options defined by the specification: "client" and "server" state.
39 * <p>
40 * When "client" state is configured, all state information required to create the tree is embedded within
41 * the data rendered to the client. Note that because data received from a remote client must always be
42 * treated as "tainted", care must be taken when using such data. Some StateManager implementations may
43 * use encryption to ensure that clients cannot modify the data, and that the data received on postback
44 * is therefore trustworthy.
45 * <p>
46 * When "server" state is configured, the data is saved somewhere "on the back end", and (at most) a
47 * token is embedded in the data rendered to the user.
48 * <p>
49 * This class is usually invoked by a concrete implementation of ViewHandler.
50 * <p>
51 * Note that class ViewHandler isolates JSF components from the details of the request format. This class
52 * isolates JSF components from the details of the response format. Because request and response are usually
53 * tightly coupled, the StateManager and ViewHandler implementations are also usually fairly tightly coupled
54 * (ie the ViewHandler/StateManager implementations come as pairs).
55 * <p>
56 * See also the <a href="http://java.sun.com/javaee/javaserverfaces/1.2/docs/api/index.html">JSF Specification</a>
57 *
58 * @author Manfred Geiler (latest modification by $Author: lu4242 $)
59 * @author Stan Silvert
60 * @version $Revision: 833810 $ $Date: 2009-11-07 21:40:01 -0500 (Sat, 07 Nov 2009) $
61 */
62 public abstract class StateManager
63 {
64 /**
65 * Define the state method to be used. There are two different options defined by the
66 * specification: "client" and "server" state.
67 * <p>
68 * When "client" state is configured, all state information required to create the tree is embedded within
69 * the data rendered to the client. Note that because data received from a remote client must always be
70 * treated as "tainted", care must be taken when using such data. Some StateManager implementations may
71 * use encryption to ensure that clients cannot modify the data, and that the data received on postback
72 * is therefore trustworthy.
73 * </p>
74 * <p>
75 * When "server" state is configured, the data is saved somewhere "on the back end", and (at most) a
76 * token is embedded in the data rendered to the user.
77 * </p>
78 */
79 @JSFWebConfigParam(defaultValue="server", expectedValues="server,client", since="1.1")
80 public static final String STATE_SAVING_METHOD_PARAM_NAME = "javax.faces.STATE_SAVING_METHOD";
81 public static final String STATE_SAVING_METHOD_CLIENT = "client";
82 public static final String STATE_SAVING_METHOD_SERVER = "server";
83 private Boolean _savingStateInClient = null;
84
85 /**
86 * Invokes getTreeStructureToSave and getComponentStateToSave, then return an object that wraps the two
87 * resulting objects. This object can then be passed to method writeState.
88 * <p>
89 * Deprecated; use saveView instead.
90 *
91 * @deprecated
92 */
93 public StateManager.SerializedView saveSerializedView(javax.faces.context.FacesContext context) {
94 return null;
95 }
96
97 /**
98 * Returns an object that is sufficient to recreate the component tree that is the viewroot of
99 * the specified context.
100 * <p>
101 * The return value is suitable for passing to method writeState.
102 *
103 * @since 1.2
104 */
105 public Object saveView(FacesContext context) {
106 StateManager.SerializedView serializedView = saveSerializedView(context);
107 if (serializedView == null) return null;
108
109 Object[] structureAndState = new Object[2];
110 structureAndState[0] = serializedView.getStructure();
111 structureAndState[1] = serializedView.getState();
112
113 return structureAndState;
114 }
115
116 /**
117 * Return data that is sufficient to recreate the component tree that is the viewroot of the specified
118 * context, but without restoring the state in the components.
119 * <p>
120 * Using this data, a tree of components which has the same "shape" as the original component
121 * tree can be recreated. However the component instances themselves will have only their default
122 * values, ie their member fields will not have been set to the original values.
123 * <p>
124 * Deprecated; use saveView instead.
125 *
126 * @deprecated
127 */
128 protected Object getTreeStructureToSave(javax.faces.context.FacesContext context) {
129 return null;
130 }
131
132 /**
133 * Return data that can be applied to a component tree created using the "getTreeStructureToSave"
134 * method.
135 * <p>
136 * Deprecated; use saveView instead.
137 *
138 * @deprecated
139 */
140 protected Object getComponentStateToSave(javax.faces.context.FacesContext context) {
141 return null;
142 }
143
144 /**
145 * Associate the provided state object with the current response being generated.
146 * <p>
147 * When client-side state is enabled, it is expected that method writes the data contained in the
148 * state parameter to the response somehow.
149 * <p>
150 * When server-side state is enabled, at most a "token" is expected to be written.
151 * <p>
152 * Deprecated; use writeState(FacesContext, Object) instead. This method was abstract
153 * in JSF1.1, but is now an empty non-abstract method so that old classes that implement
154 * this method continue to work, while new classes can just override the new writeState
155 * method rather than this one.
156 *
157 * @deprecated
158 */
159 public void writeState(javax.faces.context.FacesContext context,
160 StateManager.SerializedView state)
161 throws java.io.IOException {
162 // default impl does nothing as per JSF 1.2 javadoc
163 }
164
165 /**
166 * Associate the provided state object with the current response being generated.
167 * <p>
168 * When client-side state is enabled, it is expected that method writes the data contained in the
169 * state parameter to the response somehow.
170 * <p>
171 * When server-side state is enabled, at most a "token" is expected to be written.
172 * <p>
173 * This method should be overridden by subclasses. It is not abstract because a default
174 * implementation is provided that forwards to the old writeState method; this allows
175 * subclasses of StateManager written using the JSF1.1 API to continue to work.
176 * <p>
177 * @since 1.2
178 */
179 public void writeState(FacesContext context, Object state) throws IOException {
180 if (!(state instanceof Object[])) return;
181 Object[] structureAndState = (Object[])state;
182 if (structureAndState.length < 2) return;
183
184 writeState(context, new StateManager.SerializedView(structureAndState[0], structureAndState[1]));
185 }
186
187 public abstract javax.faces.component.UIViewRoot restoreView(javax.faces.context.FacesContext context,
188 String viewId,
189 String renderKitId);
190
191 /**
192 * @deprecated
193 */
194 protected javax.faces.component.UIViewRoot restoreTreeStructure(javax.faces.context.FacesContext context,
195 String viewId,
196 String renderKitId) {
197 return null;
198 }
199
200 /**
201 * @deprecated
202 */
203 protected void restoreComponentState(javax.faces.context.FacesContext context,
204 javax.faces.component.UIViewRoot viewRoot,
205 String renderKitId) {
206 // default impl does nothing as per JSF 1.2 javadoc
207 }
208
209 public boolean isSavingStateInClient(javax.faces.context.FacesContext context)
210 {
211 if(context == null) throw new NullPointerException("context");
212 if (_savingStateInClient != null) return _savingStateInClient.booleanValue();
213 String stateSavingMethod = context.getExternalContext().getInitParameter(STATE_SAVING_METHOD_PARAM_NAME);
214 if (stateSavingMethod == null)
215 {
216 _savingStateInClient = Boolean.FALSE; //Specs 10.1.3: default server saving
217 context.getExternalContext().log("No state saving method defined, assuming default server state saving");
218 }
219 else if (stateSavingMethod.equals(STATE_SAVING_METHOD_CLIENT))
220 {
221 _savingStateInClient = Boolean.TRUE;
222 }
223 else if (stateSavingMethod.equals(STATE_SAVING_METHOD_SERVER))
224 {
225 _savingStateInClient = Boolean.FALSE;
226 }
227 else
228 {
229 _savingStateInClient = Boolean.FALSE; //Specs 10.1.3: default server saving
230 context.getExternalContext().log("Illegal state saving method '" + stateSavingMethod + "', default server state saving will be used");
231 }
232 return _savingStateInClient.booleanValue();
233 }
234
235
236 /**
237 * @deprecated
238 */
239 public class SerializedView
240 {
241 private Object _structure;
242 private Object _state;
243
244 /**
245 * @deprecated
246 */
247 public SerializedView(Object structure, Object state)
248 {
249 _structure = structure;
250 _state = state;
251 }
252
253 /**
254 * @deprecated
255 */
256 public Object getStructure()
257 {
258 return _structure;
259 }
260
261 /**
262 * @deprecated
263 */
264 public Object getState()
265 {
266 return _state;
267 }
268 }
269 }