View Javadoc

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 org.apache.myfaces.renderkit.html;
20  
21  import org.apache.commons.logging.Log;
22  import org.apache.commons.logging.LogFactory;
23  import org.apache.myfaces.renderkit.MyfacesResponseStateManager;
24  import org.apache.myfaces.shared_impl.config.MyfacesConfig;
25  import org.apache.myfaces.shared_impl.renderkit.html.HTML;
26  import org.apache.myfaces.shared_impl.renderkit.html.HtmlRendererUtils;
27  import org.apache.myfaces.shared_impl.renderkit.html.util.JavascriptUtils;
28  import org.apache.myfaces.shared_impl.util.StateUtils;
29  
30  import javax.faces.application.StateManager;
31  import javax.faces.context.ExternalContext;
32  import javax.faces.context.FacesContext;
33  import javax.faces.context.ResponseWriter;
34  import javax.faces.render.RenderKitFactory;
35  import javax.faces.render.ResponseStateManager;
36  import java.io.IOException;
37  
38  /**
39   * @author Manfred Geiler (latest modification by $Author: lu4242 $)
40   * @version $Revision: 951800 $ $Date: 2010-06-05 21:07:42 -0500 (Sat, 05 Jun 2010) $
41   */
42  public class HtmlResponseStateManager
43      extends MyfacesResponseStateManager {
44      private static final Log log = LogFactory.getLog(HtmlResponseStateManager.class);
45  
46      private static final int TREE_PARAM = 0;
47      private static final int STATE_PARAM = 1;
48      private static final int VIEWID_PARAM = 2;
49  
50      public static final String STANDARD_STATE_SAVING_PARAM = "javax.faces.ViewState";
51  
52      public void writeState(FacesContext facescontext,
53                             StateManager.SerializedView serializedview) throws IOException {
54          ResponseWriter responseWriter = facescontext.getResponseWriter();
55  
56          Object[] savedState = new Object[3];
57  
58          if (facescontext.getApplication().getStateManager().isSavingStateInClient(facescontext)) {
59              if (log.isTraceEnabled()) log.trace("Writing state in client");
60              Object treeStruct = serializedview.getStructure();
61              Object compStates = serializedview.getState();
62  
63              if(treeStruct != null)
64              {
65                  savedState[TREE_PARAM]=treeStruct;
66              }
67              else {
68                  log.error("No tree structure to be saved in client response!");
69              }
70  
71              if (compStates != null) {
72                  savedState[STATE_PARAM] = compStates;
73              }
74              else {
75                  log.error("No component states to be saved in client response!");
76              }
77          }
78          else {
79              if (log.isTraceEnabled()) log.trace("Writing state in server");
80              // write viewSequence
81              Object treeStruct = serializedview.getStructure();
82              if (treeStruct != null) {
83                  if (treeStruct instanceof String) {
84                      savedState[TREE_PARAM] = treeStruct;
85                  }
86              }
87          }
88  
89          savedState[VIEWID_PARAM] = facescontext.getViewRoot().getViewId();
90  
91          if (log.isTraceEnabled()) log.trace("Writing view state and renderKit fields");
92  
93          // write the view state field
94          writeViewStateField(facescontext, responseWriter, savedState);
95  
96          // renderKitId field
97          writeRenderKitIdField(facescontext, responseWriter);
98      }
99  
100     private void writeViewStateField(FacesContext facesContext,
101                                        ResponseWriter responseWriter,
102                                        Object savedState) throws IOException
103     {
104         String serializedState = StateUtils.construct(savedState,
105                 facesContext.getExternalContext());
106         ExternalContext extContext = facesContext.getExternalContext();
107         MyfacesConfig myfacesConfig = MyfacesConfig.getCurrentInstance(extContext);
108         // Write Javascript viewstate if enabled and if javascript is allowed,
109         // otherwise write hidden input
110         if (JavascriptUtils.isJavascriptAllowed(extContext) && myfacesConfig.isViewStateJavascript()) {
111             HtmlRendererUtils.renderViewStateJavascript(facesContext, STANDARD_STATE_SAVING_PARAM, serializedState);
112         } else {
113             responseWriter.startElement(HTML.INPUT_ELEM, null);
114             responseWriter.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_HIDDEN, null);
115             responseWriter.writeAttribute(HTML.NAME_ATTR, STANDARD_STATE_SAVING_PARAM, null);
116             if (myfacesConfig.isRenderViewStateId()) {
117                 responseWriter.writeAttribute(HTML.ID_ATTR, STANDARD_STATE_SAVING_PARAM, null);
118             }
119             responseWriter.writeAttribute(HTML.VALUE_ATTR, serializedState, null);
120             responseWriter.endElement(HTML.INPUT_ELEM);
121         }
122     }
123 
124     private void writeRenderKitIdField(FacesContext facesContext,
125                                        ResponseWriter responseWriter) throws IOException {
126 
127         String defaultRenderKitId = facesContext.getApplication().getDefaultRenderKitId();
128         if (defaultRenderKitId != null && !RenderKitFactory.HTML_BASIC_RENDER_KIT.equals(defaultRenderKitId)) {
129             responseWriter.startElement(HTML.INPUT_ELEM, null);
130             responseWriter.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_HIDDEN, null);
131             responseWriter.writeAttribute(HTML.NAME_ATTR, ResponseStateManager.RENDER_KIT_ID_PARAM, null);
132             responseWriter.writeAttribute(HTML.VALUE_ATTR, defaultRenderKitId, null);
133             responseWriter.endElement(HTML.INPUT_ELEM);
134         }
135     }
136 
137     @Override
138     public Object getState(FacesContext facesContext, String viewId) {
139         Object[] savedState = getSavedState(facesContext);
140         if (savedState == null) {
141             return null;
142         }
143         
144         return new Object[] { savedState[TREE_PARAM], savedState[STATE_PARAM] };
145     }
146 
147     @Override
148     public Object getTreeStructureToRestore(FacesContext facesContext, String viewId) {
149         // Although this method won't be called anymore, 
150         // it has been kept for backward compatibility.
151         Object[] savedState = getSavedState(facesContext);
152         if (savedState == null) {
153             return null;
154         }
155 
156         return savedState[TREE_PARAM];
157     }
158 
159     @Override
160     public Object getComponentStateToRestore(FacesContext facesContext) {
161         // Although this method won't be called anymore, 
162         // it has been kept for backward compatibility.
163         Object[] savedState = getSavedState(facesContext);
164         if (savedState == null) {
165             return null;
166         }
167 
168         return savedState[STATE_PARAM];
169     }
170     
171     /**
172      * Reconstructs the state from the "javax.faces.ViewState" request parameter.
173      * 
174      * @param facesContext the current FacesContext
175      * 
176      * @return the reconstructed state, or <code>null</code> 
177      *          if there was no saved state
178      */
179     private Object[] getSavedState(FacesContext facesContext) {
180         Object encodedState = 
181             facesContext.getExternalContext().
182                 getRequestParameterMap().get(STANDARD_STATE_SAVING_PARAM);
183         if(encodedState==null || (((String) encodedState).length() == 0)) { 
184             return null;
185         }
186         
187         Object[] savedState = (Object[]) StateUtils.reconstruct(
188                 (String) encodedState, facesContext.getExternalContext());
189 
190         if (savedState == null)
191         {
192             if (log.isTraceEnabled()) {
193                 log.trace("No saved state");
194             }
195             return null;
196         }
197         
198         String restoredViewId = (String) savedState[VIEWID_PARAM];
199 
200         if (restoredViewId == null) {
201             // no saved state or state of different viewId
202             if (log.isTraceEnabled()) {
203                 log.trace("No saved state or state of a different viewId: " + restoredViewId);
204             }
205             
206             return null;
207         }
208         
209         return savedState;
210     }
211 
212 
213     /**
214      * Checks if the current request is a postback
215      * @since 1.2
216      */
217     @Override
218     public boolean isPostback(FacesContext context)
219     {
220         return context.getExternalContext()
221                 .getRequestParameterMap().containsKey(ResponseStateManager.VIEW_STATE_PARAM);
222     }
223 }
224 
225