1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
package org.seasar.teeda.core.application; |
17 | |
|
18 | |
import java.io.IOException; |
19 | |
import java.util.Iterator; |
20 | |
import java.util.List; |
21 | |
import java.util.Locale; |
22 | |
|
23 | |
import javax.faces.FacesException; |
24 | |
import javax.faces.application.Application; |
25 | |
import javax.faces.application.StateManager; |
26 | |
import javax.faces.application.ViewHandler; |
27 | |
import javax.faces.component.UIViewRoot; |
28 | |
import javax.faces.context.ExternalContext; |
29 | |
import javax.faces.context.FacesContext; |
30 | |
import javax.faces.internal.FacesConfigOptions; |
31 | |
import javax.faces.internal.RenderPreparableUtil; |
32 | |
import javax.faces.render.RenderKitFactory; |
33 | |
import javax.portlet.PortletURL; |
34 | |
import javax.portlet.RenderResponse; |
35 | |
import javax.servlet.ServletRequest; |
36 | |
import javax.servlet.ServletResponse; |
37 | |
import javax.servlet.http.HttpServletResponse; |
38 | |
import javax.servlet.http.HttpSession; |
39 | |
import javax.servlet.jsp.jstl.core.Config; |
40 | |
|
41 | |
import org.seasar.framework.util.AssertionUtil; |
42 | |
import org.seasar.framework.util.StringUtil; |
43 | |
import org.seasar.teeda.core.JsfConstants; |
44 | |
import org.seasar.teeda.core.config.webapp.element.ServletMappingElement; |
45 | |
import org.seasar.teeda.core.config.webapp.element.WebappConfig; |
46 | |
import org.seasar.teeda.core.portlet.FacesPortlet; |
47 | |
import org.seasar.teeda.core.util.PortletUtil; |
48 | |
import org.seasar.teeda.core.util.ServletExternalContextUtil; |
49 | |
import org.seasar.teeda.core.util.StateManagerUtil; |
50 | |
import org.seasar.teeda.core.util.WebappConfigUtil; |
51 | |
|
52 | |
|
53 | |
|
54 | |
|
55 | |
|
56 | |
public class ViewHandlerImpl extends ViewHandler { |
57 | |
|
58 | 31 | public ViewHandlerImpl() { |
59 | 31 | } |
60 | |
|
61 | |
public Locale calculateLocale(FacesContext context) { |
62 | 3 | AssertionUtil.assertNotNull("context", context); |
63 | 2 | Locale supportedLocale = getLocaleFromSupportedLocales(context); |
64 | 2 | if (supportedLocale != null) { |
65 | 1 | return supportedLocale; |
66 | |
} |
67 | 1 | Locale defaultLocale = getLocaleFromDefaultLocale(context); |
68 | 1 | if (defaultLocale != null) { |
69 | 1 | return defaultLocale; |
70 | |
} |
71 | 0 | return Locale.getDefault(); |
72 | |
} |
73 | |
|
74 | |
protected Locale getLocaleFromSupportedLocales(FacesContext context) { |
75 | 4 | Application app = context.getApplication(); |
76 | 4 | for (Iterator locales = context.getExternalContext() |
77 | 6 | .getRequestLocales(); locales.hasNext();) { |
78 | 4 | Locale locale = (Locale) locales.next(); |
79 | 4 | for (Iterator supportedLocales = app.getSupportedLocales(); supportedLocales |
80 | 5 | .hasNext();) { |
81 | 3 | Locale supportedLocale = (Locale) supportedLocales.next(); |
82 | 3 | if (isMatchLocale(locale, supportedLocale)) { |
83 | 2 | return supportedLocale; |
84 | |
} |
85 | |
} |
86 | |
} |
87 | 2 | return null; |
88 | |
} |
89 | |
|
90 | |
protected Locale getLocaleFromDefaultLocale(FacesContext context) { |
91 | 3 | Locale defaultLocale = context.getApplication().getDefaultLocale(); |
92 | 3 | for (Iterator locales = context.getExternalContext() |
93 | 4 | .getRequestLocales(); locales.hasNext();) { |
94 | 3 | Locale reqLocale = (Locale) locales.next(); |
95 | 3 | if (isMatchLocale(reqLocale, defaultLocale)) { |
96 | 2 | return defaultLocale; |
97 | |
} |
98 | |
} |
99 | 1 | return null; |
100 | |
} |
101 | |
|
102 | |
protected boolean isMatchLocale(Locale reqLocale, Locale jsfLocale) { |
103 | 11 | if (reqLocale == null && jsfLocale == null) { |
104 | 1 | return true; |
105 | 10 | } else if (reqLocale == null || jsfLocale == null) { |
106 | 1 | return false; |
107 | |
} |
108 | 9 | if (reqLocale.equals(jsfLocale)) { |
109 | 5 | return true; |
110 | |
} |
111 | 4 | return reqLocale.getLanguage().equals(jsfLocale.getLanguage()) |
112 | |
&& StringUtil.isEmpty(jsfLocale.getCountry()); |
113 | |
} |
114 | |
|
115 | |
public String calculateRenderKitId(FacesContext context) { |
116 | 5 | AssertionUtil.assertNotNull("context", context); |
117 | 4 | String renderKitId = context.getApplication().getDefaultRenderKitId(); |
118 | 4 | if (renderKitId == null) { |
119 | 2 | renderKitId = RenderKitFactory.HTML_BASIC_RENDER_KIT; |
120 | |
} |
121 | 4 | return renderKitId; |
122 | |
} |
123 | |
|
124 | |
public UIViewRoot createView(FacesContext context, String viewId) { |
125 | 3 | AssertionUtil.assertNotNull("context", context); |
126 | 2 | Locale locale = null; |
127 | 2 | String renderKitId = null; |
128 | 2 | UIViewRoot viewRoot = context.getViewRoot(); |
129 | 2 | if (viewRoot != null) { |
130 | 1 | locale = viewRoot.getLocale(); |
131 | 1 | renderKitId = viewRoot.getRenderKitId(); |
132 | |
} else { |
133 | 1 | locale = calculateLocale(context); |
134 | 1 | renderKitId = calculateRenderKitId(context); |
135 | |
} |
136 | 2 | viewRoot = (UIViewRoot) context.getApplication().createComponent( |
137 | |
UIViewRoot.COMPONENT_TYPE); |
138 | 2 | viewRoot.setViewId(viewId); |
139 | 2 | viewRoot.setLocale(locale); |
140 | 2 | viewRoot.setRenderKitId(renderKitId); |
141 | 2 | return viewRoot; |
142 | |
} |
143 | |
|
144 | |
public String getActionURL(FacesContext context, String viewId) { |
145 | 4 | AssertionUtil.assertNotNull("context", context); |
146 | 3 | AssertionUtil.assertNotNull("viewId", viewId); |
147 | |
|
148 | |
|
149 | 2 | if (PortletUtil.isRender(context)) { |
150 | 0 | RenderResponse response = (RenderResponse) context |
151 | |
.getExternalContext().getResponse(); |
152 | 0 | PortletURL url = response.createActionURL(); |
153 | 0 | url.setParameter(FacesPortlet.VIEW_ID, viewId); |
154 | 0 | return url.toString(); |
155 | |
} |
156 | |
|
157 | 2 | String path = getViewIdPath(context, viewId); |
158 | 2 | if (path != null && path.startsWith("/")) { |
159 | 2 | return context.getExternalContext().getRequestContextPath() + path; |
160 | |
} else { |
161 | 0 | return path; |
162 | |
} |
163 | |
} |
164 | |
|
165 | |
public String getResourceURL(FacesContext context, String path) { |
166 | 4 | AssertionUtil.assertNotNull("context", context); |
167 | 3 | AssertionUtil.assertNotNull("path", path); |
168 | 2 | if (path.startsWith("/")) { |
169 | 1 | return context.getExternalContext().getRequestContextPath() + path; |
170 | |
} else { |
171 | 1 | return path; |
172 | |
} |
173 | |
} |
174 | |
|
175 | |
public void renderView(FacesContext context, UIViewRoot viewRoot) |
176 | |
throws IOException, FacesException { |
177 | 0 | AssertionUtil.assertNotNull("context", context); |
178 | 0 | AssertionUtil.assertNotNull("viewRoot", viewRoot); |
179 | 0 | RenderPreparableUtil.encodeBeforeForComponent(context, viewRoot); |
180 | |
|
181 | 0 | ExternalContext externalContext = context.getExternalContext(); |
182 | |
|
183 | |
|
184 | 0 | ensureResponseLocaleSet(externalContext, viewRoot); |
185 | 0 | ensureRequestLocaleSet(externalContext, viewRoot); |
186 | |
try { |
187 | 0 | String viewId = convertViewIdIfNeed(context); |
188 | 0 | context.getViewRoot().setViewId(viewId); |
189 | 0 | externalContext.dispatch(viewId); |
190 | |
} finally { |
191 | |
|
192 | 0 | if (!PortletUtil.isPortlet(context)) { |
193 | 0 | storeResponseCharacterEncoding(externalContext); |
194 | |
} |
195 | |
} |
196 | 0 | } |
197 | |
|
198 | |
|
199 | |
public UIViewRoot restoreView(FacesContext context, String viewId) { |
200 | 1 | AssertionUtil.assertNotNull("context", context); |
201 | 1 | Application app = context.getApplication(); |
202 | 1 | String renderKitId = calculateRenderKitId(context); |
203 | 1 | StateManager stateManager = app.getStateManager(); |
204 | 1 | return stateManager.restoreView(context, viewId, renderKitId); |
205 | |
} |
206 | |
|
207 | |
public void writeState(FacesContext context) throws IOException { |
208 | 1 | AssertionUtil.assertNotNull("context", context); |
209 | 1 | if (StateManagerUtil.isSavingStateInClient(context)) { |
210 | 0 | context.getResponseWriter().writeText(JsfConstants.STATE_MARKER, |
211 | |
null); |
212 | |
} |
213 | 1 | } |
214 | |
|
215 | |
protected String getViewIdPath(FacesContext context, String viewId) { |
216 | 6 | if (!viewId.startsWith("/")) { |
217 | 0 | throw new IllegalArgumentException(); |
218 | |
} |
219 | |
|
220 | |
|
221 | 6 | if (PortletUtil.isPortlet(context)) { |
222 | 0 | return viewId; |
223 | |
} |
224 | |
|
225 | 6 | WebappConfig webappConfig = getWebappConfig(context); |
226 | 6 | String urlPattern = getUrlPattern(webappConfig, context); |
227 | 6 | if (urlPattern != null) { |
228 | 4 | if (urlPattern.startsWith("*.")) { |
229 | 2 | urlPattern = urlPattern.substring(1, urlPattern.length()); |
230 | 2 | if (viewId.endsWith(urlPattern)) { |
231 | 0 | return viewId; |
232 | |
} else { |
233 | 2 | int index = viewId.lastIndexOf("."); |
234 | 2 | if (index >= 0) { |
235 | 1 | return viewId.substring(0, index) + urlPattern; |
236 | |
} else { |
237 | 1 | return viewId + urlPattern; |
238 | |
} |
239 | |
} |
240 | |
} else { |
241 | 2 | if (urlPattern.endsWith("/*")) { |
242 | 0 | urlPattern = urlPattern.substring(0, |
243 | |
urlPattern.length() - 2); |
244 | |
} |
245 | 2 | return urlPattern + viewId; |
246 | |
} |
247 | |
} else { |
248 | 2 | return viewId; |
249 | |
} |
250 | |
} |
251 | |
|
252 | |
protected String getUrlPattern(WebappConfig webappConfig, |
253 | |
FacesContext context) { |
254 | 8 | String servletPath = context.getExternalContext() |
255 | |
.getRequestServletPath(); |
256 | 8 | String pathInfo = context.getExternalContext().getRequestPathInfo(); |
257 | 8 | List servletMappings = webappConfig.getServletMappingElements(); |
258 | 8 | for (Iterator itr = servletMappings.iterator(); itr.hasNext();) { |
259 | 7 | ServletMappingElement servletMapping = (ServletMappingElement) itr |
260 | |
.next(); |
261 | 7 | String urlPattern = servletMapping.getUrlPattern(); |
262 | 7 | if ((isExtensionMapping(urlPattern) && pathInfo == null) |
263 | |
|| (!isExtensionMapping(urlPattern) && pathInfo != null)) { |
264 | 5 | if (isExtensionMapping(urlPattern)) { |
265 | 2 | String extension = urlPattern.substring(1, urlPattern |
266 | |
.length()); |
267 | 2 | if (servletPath.endsWith(extension) |
268 | |
|| servletPath.equals(urlPattern)) { |
269 | 2 | return urlPattern; |
270 | |
} |
271 | |
} else { |
272 | 3 | urlPattern = urlPattern.substring(0, |
273 | |
urlPattern.length() - 2); |
274 | 3 | if (servletPath.equals(urlPattern)) { |
275 | 3 | return urlPattern; |
276 | |
} |
277 | |
} |
278 | |
} |
279 | |
} |
280 | 3 | return null; |
281 | |
} |
282 | |
|
283 | |
protected String convertViewIdIfNeed(FacesContext context) { |
284 | 0 | WebappConfig webappConfig = getWebappConfig(context); |
285 | 0 | ExternalContext externalContext = context.getExternalContext(); |
286 | 0 | String viewId = context.getViewRoot().getViewId(); |
287 | |
|
288 | 0 | if (PortletUtil.isPortlet(context)) { |
289 | 0 | return viewId; |
290 | |
} |
291 | 0 | String urlPattern = getUrlPattern(webappConfig, context); |
292 | 0 | if (urlPattern != null && isExtensionMapping(urlPattern)) { |
293 | 0 | String defaultSuffix = externalContext |
294 | |
.getInitParameter(ViewHandler.DEFAULT_SUFFIX_PARAM_NAME); |
295 | 0 | String suffix = defaultSuffix != null ? defaultSuffix |
296 | |
: ViewHandler.DEFAULT_SUFFIX; |
297 | 0 | if (!viewId.endsWith(suffix)) { |
298 | 0 | int dot = viewId.lastIndexOf('.'); |
299 | 0 | if (dot == -1) { |
300 | 0 | viewId = viewId + suffix; |
301 | |
} else { |
302 | 0 | viewId = viewId.substring(0, dot) + suffix; |
303 | |
} |
304 | |
} |
305 | |
} |
306 | 0 | return viewId; |
307 | |
} |
308 | |
|
309 | |
protected WebappConfig getWebappConfig(FacesContext context) { |
310 | 6 | return WebappConfigUtil.getWebappConfig(context); |
311 | |
} |
312 | |
|
313 | |
protected void ensureResponseLocaleSet(ExternalContext externalContext, |
314 | |
UIViewRoot viewRoot) { |
315 | 0 | if (externalContext.getResponse() instanceof ServletResponse) { |
316 | 0 | ServletResponse res = (ServletResponse) externalContext |
317 | |
.getResponse(); |
318 | 0 | res.setLocale(viewRoot.getLocale()); |
319 | |
} |
320 | 0 | } |
321 | |
|
322 | |
protected void ensureRequestLocaleSet(ExternalContext externalContext, |
323 | |
UIViewRoot viewRoot) { |
324 | |
|
325 | 0 | if (externalContext.getRequest() instanceof ServletRequest) { |
326 | 0 | Config.set((ServletRequest) externalContext.getRequest(), |
327 | |
Config.FMT_LOCALE, viewRoot.getLocale()); |
328 | |
} |
329 | 0 | } |
330 | |
|
331 | |
protected void storeResponseCharacterEncoding( |
332 | |
ExternalContext externalContext) { |
333 | |
|
334 | 0 | final String pathInfo = externalContext.getRequestPathInfo(); |
335 | 0 | if (!pathInfo.endsWith(FacesConfigOptions.getDefaultSuffix())) { |
336 | 0 | return; |
337 | |
} |
338 | 0 | if (externalContext.getResponse() instanceof ServletResponse) { |
339 | 0 | ServletResponse res = (ServletResponse) externalContext |
340 | |
.getResponse(); |
341 | 0 | if (!ServletExternalContextUtil.isHttpServletResponse(res)) { |
342 | 0 | return; |
343 | |
} |
344 | 0 | HttpServletResponse httpRes = ServletExternalContextUtil |
345 | |
.getResponse(externalContext); |
346 | 0 | HttpSession session = (HttpSession) externalContext |
347 | |
.getSession(false); |
348 | 0 | if (session != null) { |
349 | 0 | final String enc = httpRes.getCharacterEncoding(); |
350 | 0 | session.setAttribute(ViewHandler.CHARACTER_ENCODING_KEY, enc); |
351 | |
} |
352 | |
} |
353 | 0 | } |
354 | |
|
355 | |
private static boolean isExtensionMapping(String urlPattern) { |
356 | 17 | return (urlPattern != null) && (urlPattern.startsWith("*.")); |
357 | |
} |
358 | |
} |