001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License version 2
011: * as published by the Free Software Foundation.
012: *
013: * Resin Open Source is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
016: * of NON-INFRINGEMENT. See the GNU General Public License for more
017: * details.
018: *
019: * You should have received a copy of the GNU General Public License
020: * along with Resin Open Source; if not, write to the
021: *
022: * Free Software Foundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.jsf.application;
030:
031: import java.io.*;
032: import java.util.*;
033:
034: import javax.faces.*;
035: import javax.faces.application.*;
036: import javax.faces.component.*;
037: import javax.faces.context.*;
038: import javax.faces.render.*;
039:
040: import javax.servlet.http.*;
041: import javax.servlet.jsp.jstl.core.*;
042:
043: import com.caucho.jsf.context.*;
044: import com.caucho.util.*;
045:
046: public class JspViewHandler extends ViewHandler {
047: private static final L10N L = new L10N(JspViewHandler.class);
048:
049: @Override
050: public Locale calculateLocale(FacesContext context) {
051: if (context == null)
052: throw new NullPointerException();
053:
054: ExternalContext extContext = context.getExternalContext();
055:
056: Locale locale;
057:
058: ArrayList<Locale> supportedLocales = new ArrayList<Locale>();
059: Iterator<Locale> iter = context.getApplication()
060: .getSupportedLocales();
061:
062: while (iter != null && iter.hasNext())
063: supportedLocales.add(iter.next());
064:
065: iter = extContext.getRequestLocales();
066: while (iter.hasNext()) {
067: locale = iter.next();
068:
069: for (int i = 0; i < supportedLocales.size(); i++) {
070: Locale supLocale = supportedLocales.get(i);
071:
072: if (supLocale.equals(locale))
073: return supLocale;
074: else if ("".equals(supLocale.getCountry())
075: && locale.getLanguage().equals(
076: supLocale.getLanguage()))
077: return supLocale;
078: }
079: }
080:
081: locale = context.getApplication().getDefaultLocale();
082:
083: if (locale != null)
084: return locale;
085:
086: return Locale.getDefault();
087: }
088:
089: @Override
090: public String calculateCharacterEncoding(FacesContext context) {
091: if (context == null)
092: throw new NullPointerException();
093:
094: ExternalContext extContext = context.getExternalContext();
095:
096: HttpServletRequest req = (HttpServletRequest) extContext
097: .getRequest();
098:
099: String contentType = req.getHeader("Content-Type");
100:
101: if (contentType != null) {
102: int p = contentType.indexOf("charset=");
103:
104: if (p > 0) {
105: int q = contentType.indexOf(';', p + 1);
106:
107: String charset;
108:
109: if (q > 0)
110: charset = contentType.substring(p, q).trim();
111: else
112: charset = contentType.substring(p).trim();
113:
114: return charset;
115: }
116: }
117:
118: if (extContext.getSession(false) != null) {
119: Map<String, Object> sessionMap = extContext.getSessionMap();
120:
121: Object value = sessionMap.get(CHARACTER_ENCODING_KEY);
122:
123: if (value != null)
124: return value.toString();
125: }
126:
127: return "utf-8";
128: }
129:
130: @Override
131: public String calculateRenderKitId(FacesContext context) {
132: if (context == null)
133: throw new NullPointerException();
134:
135: ExternalContext extContext = context.getExternalContext();
136: Map requestMap = extContext.getRequestMap();
137:
138: String id;
139:
140: id = (String) requestMap
141: .get(ResponseStateManager.RENDER_KIT_ID_PARAM);
142:
143: if (id != null)
144: return id;
145:
146: Application app = context.getApplication();
147:
148: id = app.getDefaultRenderKitId();
149:
150: if (id != null)
151: return id;
152:
153: return RenderKitFactory.HTML_BASIC_RENDER_KIT;
154: }
155:
156: public UIViewRoot createView(FacesContext context, String viewId) {
157: if (context == null)
158: throw new NullPointerException();
159:
160: if (viewId != null)
161: viewId = convertViewId(context, viewId);
162: else
163: viewId = createViewId(context);
164:
165: ExternalContext extContext = context.getExternalContext();
166: String servletPath = extContext.getRequestServletPath();
167:
168: if (viewId == null
169: || viewId.equals(servletPath)
170: || (servletPath == null && viewId.equals(extContext
171: .getRequestPathInfo()))) {
172: try {
173: extContext.redirect(extContext.getRequestContextPath());
174: } catch (IOException e) {
175: throw new FacesException(e);
176: }
177:
178: context.renderResponse();
179: context.responseComplete();
180:
181: return null;
182: }
183:
184: UIViewRoot viewRoot = new UIViewRoot();
185:
186: viewRoot.setViewId(viewId);
187:
188: UIViewRoot oldView = context.getViewRoot();
189:
190: String renderKitId = null;
191:
192: if (oldView != null)
193: renderKitId = oldView.getRenderKitId();
194:
195: if (renderKitId == null)
196: renderKitId = calculateRenderKitId(context);
197:
198: viewRoot.setRenderKitId(renderKitId);
199:
200: Locale locale = null;
201:
202: if (oldView != null)
203: locale = oldView.getLocale();
204:
205: if (locale == null)
206: locale = calculateLocale(context);
207:
208: viewRoot.setLocale(locale);
209:
210: return viewRoot;
211: }
212:
213: public static String createViewId(FacesContext context) {
214: ExternalContext extContext = context.getExternalContext();
215:
216: Map requestMap = extContext.getRequestMap();
217:
218: boolean isInclude = requestMap
219: .containsKey("javax.servlet.include.request_uri");
220:
221: String pathInfo;
222:
223: if (isInclude)
224: pathInfo = (String) requestMap
225: .get("javax.servlet.include.path_info");
226: else
227: pathInfo = extContext.getRequestPathInfo();
228:
229: if (pathInfo != null)
230: return pathInfo;
231:
232: String servletPath = extContext.getRequestServletPath();
233:
234: String path;
235: int dot;
236:
237: if (servletPath != null
238: && (dot = servletPath.lastIndexOf('.')) > 0
239: && servletPath.lastIndexOf('/') < dot) {
240: String suffix = extContext
241: .getInitParameter(ViewHandler.DEFAULT_SUFFIX_PARAM_NAME);
242:
243: if (suffix == null)
244: suffix = ViewHandler.DEFAULT_SUFFIX;
245:
246: // /test/foo.jsp
247:
248: return servletPath.substring(0, dot) + suffix;
249: }
250:
251: throw new FacesException(L.l("no view-id found"));
252: }
253:
254: static String convertViewId(FacesContext context, String viewId) {
255: ExternalContext extContext = context.getExternalContext();
256:
257: Map requestMap = extContext.getRequestMap();
258:
259: boolean isInclude = requestMap
260: .containsKey("javax.servlet.include.request_uri");
261:
262: String pathInfo;
263:
264: if (isInclude)
265: pathInfo = (String) requestMap
266: .get("javax.servlet.include.path_info");
267: else
268: pathInfo = extContext.getRequestPathInfo();
269:
270: if (pathInfo != null)
271: return viewId;
272:
273: int dot;
274: if ((dot = viewId.lastIndexOf('.')) > 0
275: && viewId.lastIndexOf('/') < dot) {
276: String suffix = extContext
277: .getInitParameter(ViewHandler.DEFAULT_SUFFIX_PARAM_NAME);
278:
279: if (suffix == null)
280: suffix = ViewHandler.DEFAULT_SUFFIX;
281:
282: return viewId.substring(0, dot) + suffix;
283: } else
284: return viewId;
285: }
286:
287: public String getActionURL(FacesContext context, String viewId) {
288: if (context == null || viewId == null)
289: throw new NullPointerException();
290:
291: if (!viewId.startsWith("/"))
292: throw new IllegalArgumentException();
293:
294: ExternalContext extContext = context.getExternalContext();
295:
296: HttpServletRequest request = (HttpServletRequest) extContext
297: .getRequest();
298:
299: final String contextPath = request.getContextPath();
300:
301: final String servletPath = request.getServletPath();
302: final String pathInfo = request.getPathInfo();
303:
304: if (pathInfo == null) /*suffix mapping*/{
305: final int lastDot = viewId.lastIndexOf('.');
306:
307: return contextPath
308: + (lastDot == -1 ? viewId : viewId.substring(0,
309: lastDot)
310: + servletPath.substring(servletPath
311: .lastIndexOf('.')));
312: } else /*prefix mapping*/{
313:
314: return contextPath + servletPath + viewId;
315: }
316: }
317:
318: public String getResourceURL(FacesContext context, String path) {
319: if (path.startsWith("/")) {
320: ExternalContext extContext = context.getExternalContext();
321:
322: HttpServletRequest request = (HttpServletRequest) extContext
323: .getRequest();
324:
325: return request.getContextPath() + path;
326: } else
327: return path;
328: }
329:
330: public void renderView(FacesContext context, UIViewRoot viewToRender)
331: throws IOException, FacesException {
332: if (!viewToRender.isRendered())
333: return;
334:
335: String viewId;
336:
337: viewId = viewToRender.getViewId();
338:
339: ExternalContext extContext = context.getExternalContext();
340: HttpServletResponse response = (javax.servlet.http.HttpServletResponse) extContext
341: .getResponse();
342: HttpServletRequest request = (javax.servlet.http.HttpServletRequest) extContext
343: .getRequest();
344:
345: Config.set(request, Config.FMT_LOCALE, viewToRender);
346:
347: response.setContentType("text/html");
348:
349: RenderKitFactory renderKitFactory = (RenderKitFactory) FactoryFinder
350: .getFactory(FactoryFinder.RENDER_KIT_FACTORY);
351: String renderKitId = viewToRender.getRenderKitId();
352:
353: if (renderKitId == null)
354: renderKitId = RenderKitFactory.HTML_BASIC_RENDER_KIT;
355:
356: RenderKit renderKit = renderKitFactory.getRenderKit(context,
357: renderKitId);
358:
359: String encoding = request.getCharacterEncoding();
360:
361: ResponseWriter oldOut = context.getResponseWriter();
362:
363: ResponseWriter out;
364:
365: out = renderKit.createResponseWriter(response.getWriter(),
366: null, encoding);
367:
368: JspResponseWrapper resWrapper = new JspResponseWrapper();
369: resWrapper.init(response);
370: extContext.setResponse(resWrapper);
371:
372: extContext.dispatch(viewId);
373:
374: String tail = resWrapper.complete();
375:
376: extContext.setResponse(response);
377:
378: context.setResponseWriter(out);
379:
380: //context.getApplication().getViewHandler().writeState(context);
381:
382: // XXX: save view
383:
384: out.startDocument();
385:
386: viewToRender.encodeAll(context);
387:
388: if (tail != null)
389: out.write(tail);
390:
391: out.endDocument();
392:
393: context.setResponseWriter(oldOut);
394: }
395:
396: @Override
397: public UIViewRoot restoreView(FacesContext context, String viewId)
398: throws FacesException {
399: if (context == null)
400: throw new NullPointerException();
401:
402: if (viewId != null)
403: viewId = convertViewId(context, viewId);
404: else
405: viewId = createViewId(context);
406:
407: String renderKitId = calculateRenderKitId(context);
408: StateManager stateManager = context.getApplication()
409: .getStateManager();
410:
411: return stateManager.restoreView(context, viewId, renderKitId);
412: }
413:
414: @Override
415: public void writeState(FacesContext context) throws IOException {
416: UIViewRoot viewRoot = context.getViewRoot();
417:
418: if (viewRoot != null) {
419: StateManager stateManager = context.getApplication()
420: .getStateManager();
421:
422: Object state = stateManager.saveView(context);
423:
424: stateManager.writeState(context, state);
425: }
426: }
427:
428: public String toString() {
429: return "JspViewHandler[]";
430: }
431: }
|