Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
ViewHandler |
|
| 0.0;0 |
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.FacesException; | |
22 | import javax.faces.context.ExternalContext; | |
23 | ||
24 | import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam; | |
25 | ||
26 | import java.io.UnsupportedEncodingException; | |
27 | import java.util.Locale; | |
28 | ||
29 | /** | |
30 | * A ViewHandler manages the component-tree-creation and component-tree-rendering parts | |
31 | * of a request lifecycle (ie "create view", "restore view" and "render response"). | |
32 | * <p> | |
33 | * A ViewHandler is responsible for generating the component tree when a new view is | |
34 | * requested; see method "createView". | |
35 | * <p> | |
36 | * When the user performs a "postback", ie activates a UICommand component within a view, | |
37 | * then the ViewHandler is responsible for recreating a view tree identical to the one | |
38 | * used previously to render that view; see method "restoreView". | |
39 | * <p> | |
40 | * And the ViewHandler is also responsible for rendering the final output to be sent to the | |
41 | * user by invoking the rendering methods on components; see method "renderView". | |
42 | * <p> | |
43 | * This class also isolates callers from the underlying request/response system. In particular, | |
44 | * this class does not explicitly depend upon the javax.servlet apis. This allows JSF to be | |
45 | * used on servers that do not implement the servlet API (for example, plain CGI). | |
46 | * <p> | |
47 | * Examples: | |
48 | * <ul> | |
49 | * <li>A JSP ViewHandler exists for using "jsp" pages as the presentation technology. | |
50 | * This class then works together with a taghandler class and a jsp servlet class to | |
51 | * implement the methods on this abstract class definition. | |
52 | * <li>A Facelets ViewHandler instead uses an xml file to define the components and | |
53 | * non-component data that make up a specific view. | |
54 | * </ul> | |
55 | * Of course there is no reason why the "template" needs to be a textual file. A view could | |
56 | * be generated based on data in a database, or many other mechanisms. | |
57 | * <p> | |
58 | * This class is expected to be invoked via the concrete implementation of | |
59 | * {@link javax.faces.lifecycle.Lifecycle}. | |
60 | * <p> | |
61 | * For the official specification for this class, see | |
62 | * <a href="http://java.sun.com/javaee/javaserverfaces/1.2/docs/api/index.html">JSF Specification</a>. | |
63 | * | |
64 | * @author Manfred Geiler (latest modification by $Author: lu4242 $) | |
65 | * @version $Revision: 833810 $ $Date: 2009-11-07 21:40:01 -0500 (Sat, 07 Nov 2009) $ | |
66 | */ | |
67 | 0 | public abstract class ViewHandler |
68 | { | |
69 | public static final String CHARACTER_ENCODING_KEY = "javax.faces.request.charset"; | |
70 | ||
71 | /** | |
72 | * Indicate the default suffix to derive the file URI if extension mapping is used. | |
73 | */ | |
74 | @JSFWebConfigParam(defaultValue=".jsp", since="1.1") | |
75 | public static final String DEFAULT_SUFFIX_PARAM_NAME = "javax.faces.DEFAULT_SUFFIX"; | |
76 | public static final String DEFAULT_SUFFIX = ".jsp"; | |
77 | ||
78 | /** | |
79 | * @since JSF 1.2 | |
80 | */ | |
81 | public String calculateCharacterEncoding(javax.faces.context.FacesContext context) | |
82 | { | |
83 | 0 | String _encoding = null; |
84 | 0 | ExternalContext externalContext = context.getExternalContext(); |
85 | 0 | String _contentType = (String) externalContext.getRequestHeaderMap().get("Content-Type"); |
86 | 0 | int _indexOf = _contentType == null ? -1 :_contentType.indexOf("charset"); |
87 | 0 | if(_indexOf != -1) |
88 | { | |
89 | 0 | String _tempEnc =_contentType.substring(_indexOf); //charset=UTF-8 |
90 | 0 | _encoding = _tempEnc.substring(_tempEnc.indexOf("=")+1); //UTF-8 |
91 | 0 | if (_encoding.length() == 0) |
92 | { | |
93 | 0 | _encoding = null; |
94 | } | |
95 | } | |
96 | 0 | if (_encoding == null) |
97 | { | |
98 | 0 | boolean _sessionAvailable = externalContext.getSession(false) != null; |
99 | 0 | if(_sessionAvailable) |
100 | { | |
101 | 0 | Object _sessionParam = externalContext.getSessionMap().get(CHARACTER_ENCODING_KEY); |
102 | 0 | if (_sessionParam != null) |
103 | { | |
104 | 0 | _encoding = _sessionParam.toString(); |
105 | } | |
106 | } | |
107 | } | |
108 | ||
109 | 0 | return _encoding; |
110 | } | |
111 | ||
112 | /** | |
113 | * Return the Locale object that should be used when rendering this view to the | |
114 | * current user. | |
115 | * <p> | |
116 | * Some request protocols allow an application user to specify what locale they prefer | |
117 | * the response to be in. For example, HTTP requests can specify the "accept-language" | |
118 | * header. | |
119 | * <p> | |
120 | * Method {@link javax.faces.application.Application#getSupportedLocales()} defines | |
121 | * what locales this JSF application is capable of supporting. | |
122 | * <p> | |
123 | * This method should match such sources of data up and return the Locale object that | |
124 | * is the best choice for rendering the current application to the current user. | |
125 | */ | |
126 | public abstract Locale calculateLocale(javax.faces.context.FacesContext context); | |
127 | ||
128 | /** | |
129 | * Return the id of an available render-kit that should be used to map the JSF | |
130 | * components into user presentation. | |
131 | * <p> | |
132 | * The render-kit selected (eg html, xhtml, pdf, xul, ...) may depend upon the user, | |
133 | * properties associated with the request, etc. | |
134 | */ | |
135 | public abstract String calculateRenderKitId(javax.faces.context.FacesContext context); | |
136 | ||
137 | /** | |
138 | * Build a root node for a component tree. | |
139 | * <p> | |
140 | * When a request is received, this method is called if restoreView returns null, | |
141 | * ie this is not a "postback". In this case, a root node is created and then renderView | |
142 | * is invoked. It is the responsibility of the renderView method to build the full | |
143 | * component tree (ie populate the UIViewRoot with descendant nodes). | |
144 | * <p> | |
145 | * This method is also invoked when navigation occurs from one view to another, where | |
146 | * the viewId passed is the id of the new view to be displayed. Again it is the responsibility | |
147 | * of renderView to then populate the viewroot with descendants. | |
148 | * <p> | |
149 | * The locale and renderKit settings are inherited from the current UIViewRoot that is | |
150 | * configured before this method is called. That means of course that they do NOT | |
151 | * get set for GET requests, including navigation that has the redirect flag set. | |
152 | */ | |
153 | public abstract javax.faces.component.UIViewRoot createView(javax.faces.context.FacesContext context, | |
154 | String viewId); | |
155 | ||
156 | /** | |
157 | * Return a URL that a remote system can invoke in order to access the specified view. | |
158 | * <p> | |
159 | * Note that the URL a user enters and the viewId which is invoked can be | |
160 | * different. The simplest difference is a change in suffix (eg url "foo.jsf" | |
161 | * references view "foo.jsp"). | |
162 | */ | |
163 | public abstract String getActionURL(javax.faces.context.FacesContext context, | |
164 | String viewId); | |
165 | ||
166 | /** | |
167 | * Return a URL that a remote system can invoke in order to access the specified resource. | |
168 | * <p> | |
169 | * When path starts with a slash, it is relative to the webapp root. Otherwise it is | |
170 | * relative to the value returned by getActionURL. | |
171 | */ | |
172 | public abstract String getResourceURL(javax.faces.context.FacesContext context, | |
173 | String path); | |
174 | ||
175 | /** | |
176 | * Method must be called by the JSF impl at the beginning of Phase <i>Restore View</i> of the JSF | |
177 | * lifecycle. | |
178 | * | |
179 | * @since JSF 1.2 | |
180 | */ | |
181 | public void initView(javax.faces.context.FacesContext context) throws FacesException | |
182 | { | |
183 | 0 | String _encoding = this.calculateCharacterEncoding(context); |
184 | 0 | if(_encoding != null) |
185 | { | |
186 | try | |
187 | { | |
188 | 0 | context.getExternalContext().setRequestCharacterEncoding(_encoding); |
189 | } | |
190 | 0 | catch(UnsupportedEncodingException uee) |
191 | { | |
192 | 0 | throw new FacesException(uee); |
193 | 0 | } |
194 | } | |
195 | 0 | } |
196 | ||
197 | /** | |
198 | * Combine the output of all the components in the viewToRender with data from the | |
199 | * original view template (if any) and write the result to context.externalContext.response. | |
200 | * <p> | |
201 | * Component output is generated by invoking the encodeBegin, encodeChildren (optional) | |
202 | * and encodeEnd methods on relevant components in the specified view. How this is | |
203 | * interleaved with the non-component content of the view template (if any) is left | |
204 | * to the ViewHandler implementation. | |
205 | * <p> | |
206 | * The actual type of the Response object depends upon the concrete implementation of | |
207 | * this class. It will almost certainly be an OutputStream of some sort, but may be | |
208 | * specific to the particular request/response system in use. | |
209 | * <p> | |
210 | * If the view cannot be rendered (eg due to an error in a component) then a FacesException | |
211 | * is thrown. | |
212 | * <p> | |
213 | * Note that if a "postback" has occurred but no navigation to a different view, then | |
214 | * the viewToRender will be fully populated with components already. However on direct | |
215 | * access to a new view, or when navigation has occurred, the viewToRender will just | |
216 | * contain an empty UIViewRoot object that must be populated with components from | |
217 | * the "view template". | |
218 | */ | |
219 | public abstract void renderView(javax.faces.context.FacesContext context, | |
220 | javax.faces.component.UIViewRoot viewToRender) | |
221 | throws java.io.IOException, | |
222 | FacesException; | |
223 | ||
224 | /** | |
225 | * Handle a "postback" request by recreating the component tree that was most recently | |
226 | * presented to the user for the specified view. | |
227 | * <p> | |
228 | * When the user performs a "postback" of a view that has previously been created, ie | |
229 | * is updating the state of an existing view tree, then the view handler must recreate | |
230 | * a view tree identical to the one used previously to render that view to the user, | |
231 | * so that the data received from the user can be compared to the old state and the | |
232 | * correct "changes" detected (well, actually only those components that respond to | |
233 | * input are actually needed before the render phase). | |
234 | * <p> | |
235 | * The components in this tree will then be given the opportunity to examine new input | |
236 | * data provided by the user, and react in the appropriate manner for that component, | |
237 | * as specified for the JSF lifecycle. | |
238 | * <p> | |
239 | * Much of the work required by this method <i>must</i> be delegated to an instance | |
240 | * of StateManager. | |
241 | * <p> | |
242 | * If there is no record of the current user having been sent the specified view | |
243 | * (ie no saved state information available), then NULL should be returned. | |
244 | * <p> | |
245 | * Note that input data provided by the user may also be used to determine exactly | |
246 | * how to restore this view. In the case of "client side state", information | |
247 | * about the components to be restored will be available here. Even for | |
248 | * "server side state", user input may include an indicator that is used to | |
249 | * select among a number of different saved states available for this viewId and | |
250 | * this user. | |
251 | * <p> | |
252 | * Note that data received from users is inherently untrustworthy; care should be | |
253 | * taken to validate this information appropriately. | |
254 | * <p> | |
255 | * See writeState for more details. | |
256 | */ | |
257 | public abstract javax.faces.component.UIViewRoot restoreView(javax.faces.context.FacesContext context, | |
258 | String viewId); | |
259 | ||
260 | /** | |
261 | * Write sufficient information to context.externalContext.response in order to | |
262 | * be able to restore this view if the user performs a "postback" using that | |
263 | * rendered response. | |
264 | * <p> | |
265 | * For "client side state saving", sufficient information about the view | |
266 | * state should be written to allow a "restore view" operation to succeed | |
267 | * later. This does not necessarily mean storing <i>all</i> data about the | |
268 | * current view; only data that cannot be recreated from the "template" for | |
269 | * this view needs to be saved. | |
270 | * <p> | |
271 | * For "server side state saving", this method may write out nothing. Alternately | |
272 | * it may write out a "state identifier" to identify which of multiple saved | |
273 | * user states for a particular view should be selected (or just verify that the | |
274 | * saved state does indeed correspond to the expected one). | |
275 | */ | |
276 | public abstract void writeState(javax.faces.context.FacesContext context) | |
277 | throws java.io.IOException; | |
278 | } |