/*
* Copyright (c) 1998-2011 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.jsf.application;
import java.io.*;
import java.util.*;
import javax.faces.*;
import javax.faces.application.*;
import javax.faces.component.*;
import javax.faces.context.*;
import javax.faces.render.*;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.*;
import javax.servlet.jsp.jstl.core.*;
import com.caucho.jsf.context.*;
import com.caucho.util.*;
public class JspViewHandler extends ViewHandler
{
private static final L10N L = new L10N(JspViewHandler.class);
@Override
public Locale calculateLocale(FacesContext context)
{
if (context == null)
throw new NullPointerException();
ExternalContext extContext = context.getExternalContext();
Locale locale;
ArrayList<Locale> supportedLocales = new ArrayList<Locale>();
Iterator<Locale> iter = context.getApplication().getSupportedLocales();
while (iter != null && iter.hasNext())
supportedLocales.add(iter.next());
iter = extContext.getRequestLocales();
while (iter.hasNext()) {
locale = iter.next();
for (int i = 0; i < supportedLocales.size(); i++) {
Locale supLocale = supportedLocales.get(i);
if (supLocale.equals(locale))
return supLocale;
else if ("".equals(supLocale.getCountry())
&& locale.getLanguage().equals(supLocale.getLanguage()))
return supLocale;
}
}
locale = context.getApplication().getDefaultLocale();
if (locale != null)
return locale;
return Locale.getDefault();
}
@Override
public String calculateCharacterEncoding(FacesContext context)
{
if (context == null)
throw new NullPointerException();
ExternalContext extContext = context.getExternalContext();
HttpServletRequest req = (HttpServletRequest) extContext.getRequest();
String contentType = req.getHeader("Content-Type");
if (contentType != null) {
int p = contentType.indexOf("charset=");
if (p > 0) {
int q = contentType.indexOf(';', p + 9);
String charset;
if (q > 0)
charset = contentType.substring(p + 8, q).trim();
else
charset = contentType.substring(p + 8).trim();
return charset;
}
}
if (extContext.getSession(false) != null) {
Map<String,Object> sessionMap = extContext.getSessionMap();
Object value = sessionMap.get(CHARACTER_ENCODING_KEY);
if (value != null)
return value.toString();
}
return "utf-8";
}
@Override
public String calculateRenderKitId(FacesContext context)
{
if (context == null)
throw new NullPointerException();
ExternalContext extContext = context.getExternalContext();
Map requestMap = extContext.getRequestMap();
String id;
id = (String) requestMap.get(ResponseStateManager.RENDER_KIT_ID_PARAM);
if (id != null)
return id;
Application app = context.getApplication();
id = app.getDefaultRenderKitId();
if (id != null)
return id;
return RenderKitFactory.HTML_BASIC_RENDER_KIT;
}
public UIViewRoot createView(FacesContext context,
String viewId)
{
if (context == null)
throw new NullPointerException();
if (viewId != null) {
viewId = convertViewId(context, viewId);
ExternalContext extContext = context.getExternalContext();
String servletPath = extContext.getRequestServletPath();
if (viewId.equals(servletPath)
|| (servletPath == null
&& viewId.equals(extContext.getRequestPathInfo()))) {
try {
extContext.redirect(extContext.getRequestContextPath());
}
catch (IOException e) {
throw new FacesException(e);
}
context.renderResponse();
context.responseComplete();
return null;
}
}
UIViewRoot viewRoot = (UIViewRoot) context.getApplication()
.createComponent(UIViewRoot.COMPONENT_TYPE);
viewRoot.setViewId(viewId);
UIViewRoot oldView = context.getViewRoot();
String renderKitId = null;
if (oldView != null)
renderKitId = oldView.getRenderKitId();
if (renderKitId == null)
renderKitId = calculateRenderKitId(context);
viewRoot.setRenderKitId(renderKitId);
Locale locale = null;
if (oldView != null)
locale = oldView.getLocale();
if (locale == null)
locale = calculateLocale(context);
viewRoot.setLocale(locale);
return viewRoot;
}
public static String createViewId(FacesContext context)
{
ExternalContext extContext = context.getExternalContext();
Map requestMap = extContext.getRequestMap();
boolean isInclude
= requestMap.containsKey(RequestDispatcher.INCLUDE_REQUEST_URI);
String pathInfo;
if (isInclude)
pathInfo = (String) requestMap.get(RequestDispatcher.INCLUDE_PATH_INFO);
else
pathInfo = extContext.getRequestPathInfo();
if (pathInfo != null)
return pathInfo;
String servletPath = extContext.getRequestServletPath();
String path;
int dot;
if (servletPath != null
&& (dot = servletPath.lastIndexOf('.')) > 0
&& servletPath.lastIndexOf('/') < dot) {
String suffix
= extContext.getInitParameter(ViewHandler.DEFAULT_SUFFIX_PARAM_NAME);
if (suffix == null)
suffix = ViewHandler.DEFAULT_SUFFIX;
// /test/foo.jsp
return servletPath.substring(0, dot) + suffix;
}
throw new FacesException(L.l("no view-id found"));
}
static String convertViewId(FacesContext context, String viewId)
{
ExternalContext extContext = context.getExternalContext();
Map requestMap = extContext.getRequestMap();
boolean isInclude
= requestMap.containsKey(RequestDispatcher.INCLUDE_REQUEST_URI);
String pathInfo;
if (isInclude)
pathInfo = (String) requestMap.get(RequestDispatcher.INCLUDE_PATH_INFO);
else
pathInfo = extContext.getRequestPathInfo();
if (pathInfo != null)
return viewId;
int dot;
if ((dot = viewId.lastIndexOf('.')) > 0
&& viewId.lastIndexOf('/') < dot) {
String suffix
= extContext.getInitParameter(ViewHandler.DEFAULT_SUFFIX_PARAM_NAME);
if (suffix == null)
suffix = ViewHandler.DEFAULT_SUFFIX;
return viewId.substring(0, dot) + suffix;
}
else
return viewId;
}
public String getActionURL(FacesContext context,
String viewId)
{
if (context == null || viewId == null)
throw new NullPointerException();
if (! viewId.startsWith("/"))
throw new IllegalArgumentException();
ExternalContext extContext = context.getExternalContext();
HttpServletRequest request
= (HttpServletRequest) extContext.getRequest();
final String contextPath = request.getContextPath();
final String servletPath = request.getServletPath();
final String pathInfo = request.getPathInfo();
if (pathInfo == null) /*suffix mapping*/ {
final int lastDot = viewId.lastIndexOf('.');
final int suffixDot = servletPath.lastIndexOf('.');
return contextPath +
(lastDot == -1 || suffixDot == -1
? viewId
: viewId.substring(0, lastDot) +
servletPath.substring(suffixDot));
}
else /*prefix mapping*/ {
return contextPath + servletPath + viewId;
}
}
public String getResourceURL(FacesContext context,
String path)
{
if (path.startsWith("/")) {
ExternalContext extContext = context.getExternalContext();
HttpServletRequest request
= (HttpServletRequest) extContext.getRequest();
return request.getContextPath() + path;
}
else
return path;
}
public void renderView(FacesContext context,
UIViewRoot viewToRender)
throws IOException, FacesException
{
if (! viewToRender.isRendered())
return;
String viewId;
viewId = viewToRender.getViewId();
ExternalContext extContext = context.getExternalContext();
HttpServletResponse response
= (javax.servlet.http.HttpServletResponse) extContext.getResponse();
HttpServletRequest request
= (javax.servlet.http.HttpServletRequest) extContext.getRequest();
Config.set(request, Config.FMT_LOCALE, viewToRender);
response.setContentType("text/html");
RenderKitFactory renderKitFactory
= (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
String renderKitId = viewToRender.getRenderKitId();
if (renderKitId == null)
renderKitId = RenderKitFactory.HTML_BASIC_RENDER_KIT;
RenderKit renderKit = renderKitFactory.getRenderKit(context, renderKitId);
String encoding = request.getCharacterEncoding();
ResponseWriter oldOut = context.getResponseWriter();
ResponseWriter out;
JspResponseWrapper resWrapper = new JspResponseWrapper();
resWrapper.init(response);
extContext.setResponse(resWrapper);
extContext.dispatch(viewId);
String tail = resWrapper.completeJsf();
extContext.setResponse(response);
out = renderKit.createResponseWriter(response.getWriter(),
null,
encoding);
context.setResponseWriter(out);
//context.getApplication().getViewHandler().writeState(context);
// XXX: save view
out.startDocument();
viewToRender.encodeAll(context);
if (tail != null)
out.write(tail);
out.endDocument();
if (oldOut != null)
context.setResponseWriter(oldOut);
}
@Override
public UIViewRoot restoreView(FacesContext context,
String viewId)
throws FacesException
{
if (context == null)
throw new NullPointerException();
if (viewId != null)
viewId = convertViewId(context, viewId);
else
viewId = createViewId(context);
String renderKitId = calculateRenderKitId(context);
StateManager stateManager = context.getApplication().getStateManager();
return stateManager.restoreView(context, viewId, renderKitId);
}
@Override
public void writeState(FacesContext context)
throws IOException
{
UIViewRoot viewRoot = context.getViewRoot();
if (viewRoot != null) {
StateManager stateManager = context.getApplication().getStateManager();
Object state = stateManager.saveView(context);
stateManager.writeState(context, state);
}
}
public String toString()
{
return "JspViewHandler[]";
}
}