Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
ViewHandler |
|
| 1.5;1.5 |
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 java.io.IOException; | |
22 | import java.io.UnsupportedEncodingException; | |
23 | import java.util.Collections; | |
24 | import java.util.List; | |
25 | import java.util.Locale; | |
26 | import java.util.Map; | |
27 | import java.util.Set; | |
28 | ||
29 | import javax.faces.FacesException; | |
30 | import javax.faces.component.UIViewRoot; | |
31 | import javax.faces.context.ExternalContext; | |
32 | import javax.faces.context.FacesContext; | |
33 | import javax.faces.view.ViewDeclarationLanguage; | |
34 | ||
35 | import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam; | |
36 | ||
37 | /** | |
38 | * A ViewHandler manages the component-tree-creation and component-tree-rendering parts of a request lifecycle (ie | |
39 | * "create view", "restore view" and "render response"). | |
40 | * <p> | |
41 | * A ViewHandler is responsible for generating the component tree when a new view is requested; see method "createView". | |
42 | * <p> | |
43 | * When the user performs a "postback", ie activates a UICommand component within a view, then the ViewHandler is | |
44 | * responsible for recreating a view tree identical to the one used previously to render that view; see method | |
45 | * "restoreView". | |
46 | * <p> | |
47 | * And the ViewHandler is also responsible for rendering the final output to be sent to the user by invoking the | |
48 | * rendering methods on components; see method "renderView". | |
49 | * <p> | |
50 | * This class also isolates callers from the underlying request/response system. In particular, this class does not | |
51 | * explicitly depend upon the javax.servlet apis. This allows JSF to be used on servers that do not implement the | |
52 | * servlet API (for example, plain CGI). | |
53 | * <p> | |
54 | * Examples: | |
55 | * <ul> | |
56 | * <li>A JSP ViewHandler exists for using "jsp" pages as the presentation technology. This class then works together | |
57 | * with a taghandler class and a jsp servlet class to implement the methods on this abstract class definition. | |
58 | * <li>A Facelets ViewHandler instead uses an xml file to define the components and non-component data that make up a | |
59 | * specific view. | |
60 | * </ul> | |
61 | * Of course there is no reason why the "template" needs to be a textual file. A view could be generated based on data | |
62 | * in a database, or many other mechanisms. | |
63 | * <p> | |
64 | * This class is expected to be invoked via the concrete implementation of {@link javax.faces.lifecycle.Lifecycle}. | |
65 | * <p> | |
66 | * For the official specification for this class, see <a | |
67 | * href="http://java.sun.com/javaee/javaserverfaces/1.2/docs/api/index.html">JSF Specification</a>. | |
68 | */ | |
69 | 1052 | public abstract class ViewHandler |
70 | { | |
71 | public static final String CHARACTER_ENCODING_KEY = "javax.faces.request.charset"; | |
72 | public static final String DEFAULT_FACELETS_SUFFIX = ".xhtml"; | |
73 | public static final String DEFAULT_SUFFIX = ".xhtml .view.xml .jsp"; | |
74 | ||
75 | /** | |
76 | * Indicate the default suffixes, separated by spaces to derive the default file URI | |
77 | * used by JSF to create views and render pages. | |
78 | */ | |
79 | @JSFWebConfigParam(defaultValue=".xhtml .view.xml .jsp", since="1.1", group="viewhandler") | |
80 | public static final String DEFAULT_SUFFIX_PARAM_NAME = "javax.faces.DEFAULT_SUFFIX"; | |
81 | ||
82 | /** | |
83 | * The default extension used to handle facelets pages. | |
84 | */ | |
85 | @JSFWebConfigParam(defaultValue=".xhtml", since="2.0", group="viewhandler") | |
86 | public static final String FACELETS_SUFFIX_PARAM_NAME = "javax.faces.FACELETS_SUFFIX"; | |
87 | ||
88 | /** | |
89 | * Set of extensions handled by facelets, separated by ';'. | |
90 | */ | |
91 | @JSFWebConfigParam(since="2.0", group="viewhandler") | |
92 | public static final String FACELETS_VIEW_MAPPINGS_PARAM_NAME = "javax.faces.FACELETS_VIEW_MAPPINGS"; | |
93 | // TODO: Notify EG on that last constant. Using the Facelets' param as well for backward compatiblity is | |
94 | // silly. If an application uses Facelets then they'll be using facelets.jar. Once they chose to | |
95 | // remove that JAR, they ought to be aware that some changes could be needed, like fixing their | |
96 | // context-param. -= Simon Lessard =- | |
97 | ||
98 | @JSFWebConfigParam(since="2.2") | |
99 | public static final java.lang.String DISABLE_FACELET_JSF_VIEWHANDLER_PARAM_NAME = | |
100 | "DISABLE_FACELET_JSF_VIEWHANDLER"; | |
101 | ||
102 | /** | |
103 | * Define the default buffer size value passed to ExternalContext.setResponseBufferResponse() and in a | |
104 | * servlet environment to HttpServletResponse.setBufferSize(). | |
105 | */ | |
106 | @JSFWebConfigParam(since = "2.0", alias = "facelets.BUFFER_SIZE", classType = "java.lang.Integer", | |
107 | tags = "performance", defaultValue="1024", | |
108 | desc = "Define the default buffer size value passed to ExternalContext.setResponseBufferResponse() and in " | |
109 | + "a servlet environment to HttpServletResponse.setBufferSize()") | |
110 | public static final java.lang.String FACELETS_BUFFER_SIZE_PARAM_NAME = "javax.faces.FACELETS_BUFFER_SIZE"; | |
111 | ||
112 | /** | |
113 | * Set of class names, separated by ';', implementing TagDecorator interface, used to transform | |
114 | * a view definition in a facelet abstract syntax tree, that is used later to generate a component tree. | |
115 | */ | |
116 | @JSFWebConfigParam(since = "2.0", alias = "facelets.DECORATORS") | |
117 | public static final java.lang.String FACELETS_DECORATORS_PARAM_NAME = "javax.faces.FACELETS_DECORATORS"; | |
118 | ||
119 | /** | |
120 | * Set of .taglib.xml files, separated by ';' that should be loaded by facelet engine. | |
121 | */ | |
122 | @JSFWebConfigParam(since = "2.0", | |
123 | desc = "Set of .taglib.xml files, separated by ';' that should be loaded by facelet engine.", | |
124 | alias = "facelets.LIBRARIES") | |
125 | public static final java.lang.String FACELETS_LIBRARIES_PARAM_NAME = "javax.faces.FACELETS_LIBRARIES"; | |
126 | ||
127 | /** | |
128 | * Define the period used to refresh the facelet abstract syntax tree from the view definition file. | |
129 | * | |
130 | * <p>By default is infinite (no active).</p> | |
131 | */ | |
132 | @JSFWebConfigParam(since = "2.0", defaultValue = "-1", alias = "facelets.REFRESH_PERIOD", | |
133 | classType = "java.lang.Long", tags = "performance") | |
134 | public static final java.lang.String FACELETS_REFRESH_PERIOD_PARAM_NAME = "javax.faces.FACELETS_REFRESH_PERIOD"; | |
135 | ||
136 | /** | |
137 | * Skip comments found on a facelet file. | |
138 | */ | |
139 | @JSFWebConfigParam(since = "2.0", alias = "facelets.SKIP_COMMENTS") | |
140 | public static final java.lang.String FACELETS_SKIP_COMMENTS_PARAM_NAME = "javax.faces.FACELETS_SKIP_COMMENTS"; | |
141 | ||
142 | /** | |
143 | * @since JSF 1.2 | |
144 | */ | |
145 | public String calculateCharacterEncoding(FacesContext context) | |
146 | { | |
147 | 8 | String encoding = null; |
148 | 8 | ExternalContext externalContext = context.getExternalContext(); |
149 | 8 | String contentType = externalContext.getRequestHeaderMap().get("Content-Type"); |
150 | 8 | int indexOf = contentType == null ? -1 : contentType.indexOf("charset"); |
151 | 8 | if (indexOf != -1) |
152 | { | |
153 | 2 | String tempEnc = contentType.substring(indexOf); // charset=UTF-8 |
154 | 2 | encoding = tempEnc.substring(tempEnc.indexOf("=") + 1); // UTF-8 |
155 | 2 | if (encoding.length() == 0) |
156 | { | |
157 | 0 | encoding = null; |
158 | } | |
159 | } | |
160 | 8 | if (encoding == null) |
161 | { | |
162 | 6 | boolean sessionAvailable = externalContext.getSession(false) != null; |
163 | 6 | if (sessionAvailable) |
164 | { | |
165 | 4 | Object sessionParam = externalContext.getSessionMap().get(CHARACTER_ENCODING_KEY); |
166 | 4 | if (sessionParam != null) |
167 | { | |
168 | 2 | encoding = sessionParam.toString(); |
169 | } | |
170 | } | |
171 | } | |
172 | ||
173 | 8 | return encoding; |
174 | } | |
175 | ||
176 | /** | |
177 | * Return the Locale object that should be used when rendering this view to the current user. | |
178 | * <p> | |
179 | * Some request protocols allow an application user to specify what locale they prefer the response to be in. For | |
180 | * example, HTTP requests can specify the "accept-language" header. | |
181 | * <p> | |
182 | * Method {@link javax.faces.application.Application#getSupportedLocales()} defines what locales this JSF | |
183 | * application is capable of supporting. | |
184 | * <p> | |
185 | * This method should match such sources of data up and return the Locale object that is the best choice for | |
186 | * rendering the current application to the current user. | |
187 | */ | |
188 | public abstract Locale calculateLocale(FacesContext context); | |
189 | ||
190 | /** | |
191 | * Return the id of an available render-kit that should be used to map the JSF components into user presentation. | |
192 | * <p> | |
193 | * The render-kit selected (eg html, xhtml, pdf, xul, ...) may depend upon the user, properties associated with the | |
194 | * request, etc. | |
195 | */ | |
196 | public abstract String calculateRenderKitId(FacesContext context); | |
197 | ||
198 | /** | |
199 | * Build a root node for a component tree. | |
200 | * <p> | |
201 | * When a request is received, this method is called if restoreView returns null, ie this is not a "postback". In | |
202 | * this case, a root node is created and then renderView is invoked. It is the responsibility of the renderView | |
203 | * method to build the full component tree (ie populate the UIViewRoot with descendant nodes). | |
204 | * <p> | |
205 | * This method is also invoked when navigation occurs from one view to another, where the viewId passed is the id of | |
206 | * the new view to be displayed. Again it is the responsibility of renderView to then populate the viewroot with | |
207 | * descendants. | |
208 | * <p> | |
209 | * The locale and renderKit settings are inherited from the current UIViewRoot that is configured before this method | |
210 | * is called. That means of course that they do NOT get set for GET requests, including navigation that has the | |
211 | * redirect flag set. | |
212 | */ | |
213 | public abstract UIViewRoot createView(FacesContext context, String viewId); | |
214 | ||
215 | /** | |
216 | * @param context | |
217 | * @param input | |
218 | * @return | |
219 | * | |
220 | * @since 2.0 | |
221 | */ | |
222 | public String deriveViewId(FacesContext context, String input) | |
223 | { | |
224 | //The default implementation of this method simply returns rawViewId unchanged. | |
225 | 0 | return input; |
226 | } | |
227 | ||
228 | /** | |
229 | * | |
230 | * @param context | |
231 | * @param rawViewId | |
232 | * @return | |
233 | * @since 2.1 | |
234 | */ | |
235 | public String deriveLogicalViewId(FacesContext context, String rawViewId) | |
236 | { | |
237 | 0 | return rawViewId; |
238 | } | |
239 | ||
240 | /** | |
241 | * Returns a URL, suitable for encoding and rendering, that (if activated) will cause the JSF | |
242 | * request processing lifecycle for the specified viewId to be executed | |
243 | */ | |
244 | public abstract String getActionURL(FacesContext context, String viewId); | |
245 | ||
246 | /** | |
247 | * Return a JSF action URL derived from the viewId argument that is suitable to be used as | |
248 | * the target of a link in a JSF response. Compiliant implementations must implement this method | |
249 | * as specified in section JSF.7.5.2. The default implementation simply calls through to | |
250 | * getActionURL(javax.faces.context.FacesContext, java.lang.String), passing the arguments context and viewId. | |
251 | * | |
252 | * @param context | |
253 | * @param viewId | |
254 | * @param parameters | |
255 | * @param includeViewParams | |
256 | * @return | |
257 | * | |
258 | * @since 2.0 | |
259 | */ | |
260 | public String getBookmarkableURL(FacesContext context, String viewId, Map<String, List<String>> parameters, | |
261 | boolean includeViewParams) | |
262 | { | |
263 | 0 | return getActionURL(context, viewId); |
264 | } | |
265 | ||
266 | /** | |
267 | * Return the ViewDeclarationLanguage instance used for this ViewHandler instance. | |
268 | * <P> | |
269 | * The default implementation of this method returns null. | |
270 | * | |
271 | * @param context | |
272 | * @param viewId | |
273 | * @return | |
274 | * | |
275 | * @since 2.0 | |
276 | */ | |
277 | public ViewDeclarationLanguage getViewDeclarationLanguage(FacesContext context, String viewId) | |
278 | { | |
279 | // TODO: In some places like RestoreViewExecutor, we are calling deriveViewId | |
280 | // TODO: after call restoreViewSupport.calculateViewId | |
281 | // Maybe this method should be called from here, because it is supposed that | |
282 | // calculateViewId "calculates the view id!" | |
283 | ||
284 | // here we return null to support pre jsf 2.0 ViewHandlers (e.g. com.sun.facelets.FaceletViewHandler), | |
285 | // because they don't provide any ViewDeclarationLanguage, | |
286 | // but in the default implementation (ViewHandlerImpl) we return vdlFactory.getViewDeclarationLanguage(viewId) | |
287 | 0 | return null; |
288 | } | |
289 | ||
290 | /** | |
291 | * Return a JSF action URL derived from the viewId argument that is suitable to be used by | |
292 | * the NavigationHandler to issue a redirect request to the URL using a NonFaces request. | |
293 | * Compiliant implementations must implement this method as specified in section JSF.7.5.2. | |
294 | * The default implementation simply calls through to | |
295 | * getActionURL(javax.faces.context.FacesContext, java.lang.String), passing the arguments context and viewId. | |
296 | * | |
297 | * @param context | |
298 | * @param viewId | |
299 | * @param parameters | |
300 | * @param includeViewParams | |
301 | * @return | |
302 | * | |
303 | * @since 2.0 | |
304 | */ | |
305 | public String getRedirectURL(FacesContext context, String viewId, Map<String, List<String>> parameters, | |
306 | boolean includeViewParams) | |
307 | { | |
308 | 0 | return getActionURL(context, viewId); |
309 | } | |
310 | ||
311 | /** | |
312 | * Returns a URL, suitable for encoding and rendering, that (if activated) | |
313 | * will retrieve the specified web application resource. | |
314 | */ | |
315 | public abstract String getResourceURL(FacesContext context, String path); | |
316 | ||
317 | /** | |
318 | * Initialize the view for the request processing lifecycle. | |
319 | * <P> | |
320 | * This method must be called at the beginning of the Restore View Phase of the Request | |
321 | * Processing Lifecycle. It is responsible for performing any per-request initialization | |
322 | * necessary to the operation of the lifycecle. | |
323 | * <P> | |
324 | * The default implementation must perform the following actions. If | |
325 | * ExternalContext.getRequestCharacterEncoding() returns null, call | |
326 | * calculateCharacterEncoding(javax.faces.context.FacesContext) and pass the result, | |
327 | * if non-null, into the ExternalContext.setRequestCharacterEncoding(java.lang.String) method. | |
328 | * If ExternalContext.getRequestCharacterEncoding() returns non-null take no action. | |
329 | * | |
330 | * @since JSF 1.2 | |
331 | */ | |
332 | public void initView(FacesContext context) throws FacesException | |
333 | { | |
334 | 4 | String encoding = this.calculateCharacterEncoding(context); |
335 | 4 | if (encoding != null) |
336 | { | |
337 | try | |
338 | { | |
339 | 4 | context.getExternalContext().setRequestCharacterEncoding(encoding); |
340 | } | |
341 | 2 | catch (UnsupportedEncodingException uee) |
342 | { | |
343 | 2 | throw new FacesException(uee); |
344 | 2 | } |
345 | } | |
346 | 2 | } |
347 | ||
348 | /** | |
349 | * Perform whatever actions are required to render the response view to the | |
350 | * response object associated with the current FacesContext. | |
351 | * <P> | |
352 | * Otherwise, the default implementation must obtain a reference to the | |
353 | * ViewDeclarationLanguage for the viewId of the argument viewToRender and call its | |
354 | * ViewDeclarationLanguage.renderView(javax.faces.context.FacesContext, javax.faces.component.UIViewRoot) | |
355 | * method, returning the result and not swallowing any exceptions thrown by that method. | |
356 | */ | |
357 | public abstract void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException, FacesException; | |
358 | ||
359 | /** | |
360 | * Perform whatever actions are required to restore the view associated with the | |
361 | * specified FacesContext and viewId. It may delegate to the restoreView of the | |
362 | * associated StateManager to do the actual work of restoring the view. If there | |
363 | * is no available state for the specified viewId, return null. | |
364 | * <P> | |
365 | * Otherwise, the default implementation must obtain a reference to the | |
366 | * ViewDeclarationLanguage for this viewId and call its | |
367 | * ViewDeclarationLanguage.restoreView(javax.faces.context.FacesContext, java.lang.String) | |
368 | * method, returning the result and not swallowing any exceptions thrown by that method. | |
369 | */ | |
370 | public abstract UIViewRoot restoreView(FacesContext context, String viewId); | |
371 | ||
372 | /** | |
373 | * Take any appropriate action to either immediately write out the current state information | |
374 | * (by calling StateManager.writeState(javax.faces.context.FacesContext, java.lang.Object), | |
375 | * or noting where state information should later be written. | |
376 | * <P> | |
377 | * This method must do nothing if the current request is an Ajax request. When responding | |
378 | * to Ajax requests, the state is obtained by calling StateManager.getViewState(javax.faces.context.FacesContext) | |
379 | * and then written into the Ajax response during | |
380 | * final encoding (UIViewRoot.encodeEnd(javax.faces.context.FacesContext). | |
381 | */ | |
382 | public abstract void writeState(FacesContext context) throws IOException; | |
383 | ||
384 | /** | |
385 | * @since 2.2 | |
386 | * @param urlPattern | |
387 | */ | |
388 | public void addProtectedView(String urlPattern) | |
389 | { | |
390 | 0 | } |
391 | ||
392 | /** | |
393 | * @since 2.2 | |
394 | * @param urlPattern | |
395 | */ | |
396 | public boolean removeProtectedView(String urlPattern) | |
397 | { | |
398 | 0 | return false; |
399 | } | |
400 | ||
401 | /** | |
402 | * @since 2.2 | |
403 | * @return | |
404 | */ | |
405 | public Set<String> getProtectedViewsUnmodifiable() | |
406 | { | |
407 | 0 | Set<String> set = Collections.emptySet(); |
408 | 0 | return Collections.unmodifiableSet(set); |
409 | } | |
410 | } |