/*
* Copyright 2013 OmniFaces.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.omnifaces.util;
import static javax.servlet.http.HttpServletResponse.SC_MOVED_PERMANENTLY;
import static org.omnifaces.util.Servlets.prepareRedirectURL;
import static org.omnifaces.util.Utils.encodeURL;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import javax.el.ELContext;
import javax.el.ValueExpression;
import javax.faces.application.Application;
import javax.faces.application.ProjectStage;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIViewParameter;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.Flash;
import javax.faces.event.PhaseId;
import javax.faces.view.ViewDeclarationLanguage;
import javax.faces.view.ViewMetadata;
import javax.faces.view.facelets.FaceletContext;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.omnifaces.component.ParamHolder;
/**
* <p>
* Collection of utility methods for the JSF API that are mainly shortcuts for obtaining stuff from the provided
* {@link FacesContext} argument. In effect, it 'flattens' the hierarchy of nested objects.
* <p>
* The difference with {@link Faces} is that no one method of {@link FacesLocal} obtains the {@link FacesContext} from
* the current thread by {@link FacesContext#getCurrentInstance()}. This job is up to the caller. This is more efficient
* in situations where multiple utility methods needs to be called at the same time. Invoking
* {@link FacesContext#getCurrentInstance()} is at its own an extremely cheap operation, however as it's to be obtained
* as a {@link ThreadLocal} variable, it's during the call still blocking all other running threads for some nanoseconds
* or so.
* <p>
* Note that methods which are <strong>directly</strong> available on {@link FacesContext} instance itself, such as
* {@link FacesContext#getExternalContext()}, {@link FacesContext#getViewRoot()},
* {@link FacesContext#isValidationFailed()}, etc are not delegated by the this utility class, because it would design
* technically not make any sense to delegate a single-depth method call like follows:
* <pre>
* ExternalContext externalContext = FacesLocal.getExternalContext(facesContext);
* </pre>
* <p>
* instead of just calling it directly like follows:
* <pre>
* ExternalContext externalContext = facesContext.getExternalContext();
* </pre>
*
* <h3>Usage</h3>
* <p>
* Some examples (for the full list, check the API documentation):
* <pre>
* FacesContext context = Faces.getContext();
* User user = FacesLocal.getSessionAttribute(context, "user");
* Item item = FacesLocal.evaluateExpressionGet(context, "#{item}");
* String cookieValue = FacesLocal.getRequestCookie(context, "cookieName");
* List<Locale> supportedLocales = FacesLocal.getSupportedLocales(context);
* FacesLocal.invalidateSession(context);
* FacesLocal.redirect(context, "login.xhtml");
* </pre>
*
* @author Arjan Tijms
* @author Bauke Scholtz
* @since 1.6
* @see Servlets
*/
public final class FacesLocal {
// Constants ------------------------------------------------------------------------------------------------------
private static final String DEFAULT_MIME_TYPE = "application/octet-stream";
private static final int DEFAULT_SENDFILE_BUFFER_SIZE = 10240;
private static final String SENDFILE_HEADER = "%s;filename=\"%2$s\"; filename*=UTF-8''%2$s";
private static final String ERROR_NO_VIEW = "There is no view.";
private static final String[] FACELET_CONTEXT_KEYS = {
FaceletContext.FACELET_CONTEXT_KEY, // Compiletime constant, may fail when compiled against EE6 and run on EE7.
"com.sun.faces.facelets.FACELET_CONTEXT", // JSF 2.0/2.1.
"javax.faces.FACELET_CONTEXT" // JSF 2.2.
};
// Constructors ---------------------------------------------------------------------------------------------------
private FacesLocal() {
// Hide constructor.
}
// JSF general ----------------------------------------------------------------------------------------------------
/**
* {@inheritDoc}
* @see Faces#getServerInfo()
*/
public static String getServerInfo(FacesContext context) {
return getServletContext(context).getServerInfo();
}
/**
* {@inheritDoc}
* @see Faces#isDevelopment()
*/
public static boolean isDevelopment(FacesContext context) {
return context.getApplication().getProjectStage() == ProjectStage.Development;
}
/**
* {@inheritDoc}
* @see Faces#getMapping()
*/
public static String getMapping(FacesContext context) {
ExternalContext externalContext = context.getExternalContext();
if (externalContext.getRequestPathInfo() == null) {
String path = externalContext.getRequestServletPath();
return path.substring(path.lastIndexOf('.'));
}
else {
return externalContext.getRequestServletPath();
}
}
/**
* {@inheritDoc}
* @see Faces#isPrefixMapping()
*/
public static boolean isPrefixMapping(FacesContext context) {
return Faces.isPrefixMapping(getMapping(context));
}
/**
* {@inheritDoc}
* @see Faces#evaluateExpressionGet(String)
*/
@SuppressWarnings("unchecked")
public static <T> T evaluateExpressionGet(FacesContext context, String expression) {
if (expression == null) {
return null;
}
return (T) context.getApplication().evaluateExpressionGet(context, expression, Object.class);
}
/**
* {@inheritDoc}
* @see Faces#evaluateExpressionSet(String, Object)
*/
public static void evaluateExpressionSet(FacesContext context, String expression, Object value) {
ELContext elContext = context.getELContext();
ValueExpression valueExpression = context.getApplication().getExpressionFactory()
.createValueExpression(elContext, expression, Object.class);
valueExpression.setValue(elContext, value);
}
/**
* {@inheritDoc}
* @see Faces#getContextAttribute(String)
*/
@SuppressWarnings("unchecked")
public static <T> T getContextAttribute(FacesContext context, String name) {
return (T) context.getAttributes().get(name);
}
/**
* {@inheritDoc}
* @see Faces#setContextAttribute(String, Object)
*/
public static void setContextAttribute(FacesContext context, String name, Object value) {
context.getAttributes().put(name, value);
}
// JSF views ------------------------------------------------------------------------------------------------------
/**
* {@inheritDoc}
* @see Faces#setViewRoot(String)
*/
public static void setViewRoot(FacesContext context, String viewId) {
context.setViewRoot(context.getApplication().getViewHandler().createView(context, viewId));
}
/**
* {@inheritDoc}
* @see Faces#getViewId()
*/
public static String getViewId(FacesContext context) {
UIViewRoot viewRoot = context.getViewRoot();
return (viewRoot != null) ? viewRoot.getViewId() : null;
}
/**
* {@inheritDoc}
* @see Faces#getViewDeclarationLanguage()
*/
public static ViewDeclarationLanguage getViewDeclarationLanguage(FacesContext context) {
return context.getApplication()
.getViewHandler()
.getViewDeclarationLanguage(context, context.getViewRoot().getViewId());
}
/**
* {@inheritDoc}
* @see Faces#normalizeViewId(String)
*/
public static String normalizeViewId(FacesContext context, String path) {
String mapping = getMapping(context);
if (Faces.isPrefixMapping(mapping)) {
if (path.startsWith(mapping)) {
return path.substring(mapping.length());
}
}
else if (path.endsWith(mapping)) {
return path.substring(0, path.lastIndexOf('.')) + Utils.coalesce(
getInitParameter(context, ViewHandler.FACELETS_SUFFIX_PARAM_NAME), ViewHandler.DEFAULT_FACELETS_SUFFIX);
}
return path;
}
/**
* {@inheritDoc}
* @see Faces#getViewParameters()
*/
public static Collection<UIViewParameter> getViewParameters(FacesContext context) {
UIViewRoot viewRoot = context.getViewRoot();
return (viewRoot != null) ? ViewMetadata.getViewParameters(viewRoot) : Collections.<UIViewParameter>emptyList();
}
/**
* {@inheritDoc}
* @see Faces#getViewParameterMap()
*/
public static Map<String, List<String>> getViewParameterMap(FacesContext context) {
Collection<UIViewParameter> viewParameters = getViewParameters(context);
if (viewParameters.isEmpty()) {
return Collections.<String, List<String>>emptyMap();
}
Map<String, List<String>> parameterMap = new HashMap<>();
for (UIViewParameter viewParameter : viewParameters) {
String value = viewParameter.getStringValue(context);
if (value != null) {
// <f:viewParam> doesn't support multiple values anyway, so having multiple <f:viewParam> on the
// same request parameter shouldn't end up in repeated parameters in action URL.
parameterMap.put(viewParameter.getName(), Collections.singletonList(value));
}
}
return parameterMap;
}
/**
* {@inheritDoc}
* @see Faces#getMetadataAttributes(String)
*/
public static Map<String, Object> getMetadataAttributes(FacesContext context, String viewId) {
ViewHandler viewHandler = context.getApplication().getViewHandler();
ViewDeclarationLanguage vdl = viewHandler.getViewDeclarationLanguage(context, viewId);
ViewMetadata metadata = vdl.getViewMetadata(context, viewId);
return (metadata != null)
? metadata.createMetadataView(context).getAttributes()
: Collections.<String, Object>emptyMap();
}
/**
* {@inheritDoc}
* @see Faces#getMetadataAttributes()
*/
public static Map<String, Object> getMetadataAttributes(FacesContext context) {
return context.getViewRoot().getAttributes();
}
/**
* {@inheritDoc}
* @see Faces#getMetadataAttribute(String, String)
*/
@SuppressWarnings("unchecked")
public static <T> T getMetadataAttribute(FacesContext context, String viewId, String name) {
return (T) getMetadataAttributes(context, viewId).get(name);
}
/**
* {@inheritDoc}
* @see Faces#getMetadataAttribute(String)
*/
@SuppressWarnings("unchecked")
public static <T> T getMetadataAttribute(FacesContext context, String name) {
return (T) getMetadataAttributes(context).get(name);
}
/**
* {@inheritDoc}
* @see Faces#getLocale()
*/
public static Locale getLocale(FacesContext context) {
Locale locale = null;
UIViewRoot viewRoot = context.getViewRoot();
// Prefer the locale set in the view.
if (viewRoot != null) {
locale = viewRoot.getLocale();
}
// Then the client preferred locale.
if (locale == null) {
Locale clientLocale = context.getExternalContext().getRequestLocale();
if (getSupportedLocales(context).contains(clientLocale)) {
locale = clientLocale;
}
}
// Then the JSF default locale.
if (locale == null) {
locale = context.getApplication().getDefaultLocale();
}
// Finally the system default locale.
if (locale == null) {
locale = Locale.getDefault();
}
return locale;
}
/**
* {@inheritDoc}
* @see Faces#getDefaultLocale()
*/
public static Locale getDefaultLocale(FacesContext context) {
return context.getApplication().getDefaultLocale();
}
/**
* {@inheritDoc}
* @see Faces#getSupportedLocales()
*/
public static List<Locale> getSupportedLocales(FacesContext context) {
Application application = context.getApplication();
List<Locale> supportedLocales = new ArrayList<>();
Locale defaultLocale = application.getDefaultLocale();
if (defaultLocale != null) {
supportedLocales.add(defaultLocale);
}
for (Iterator<Locale> iter = application.getSupportedLocales(); iter.hasNext();) {
Locale supportedLocale = iter.next();
if (!supportedLocale.equals(defaultLocale)) {
supportedLocales.add(supportedLocale);
}
}
return supportedLocales;
}
/**
* {@inheritDoc}
* @see Faces#setLocale(Locale)
*/
public static void setLocale(FacesContext context, Locale locale) {
UIViewRoot viewRoot = context.getViewRoot();
if (viewRoot == null) {
throw new IllegalStateException(ERROR_NO_VIEW);
}
viewRoot.setLocale(locale);
}
/**
* {@inheritDoc}
* @see Faces#getMessageBundle()
*/
public static ResourceBundle getMessageBundle(FacesContext context) {
String messageBundle = context.getApplication().getMessageBundle();
if (messageBundle == null) {
return null;
}
return ResourceBundle.getBundle(messageBundle, getLocale(context));
}
/**
* {@inheritDoc}
* @see Faces#getResourceBundle(String)
*/
public static ResourceBundle getResourceBundle(FacesContext context, String var) {
return context.getApplication().getResourceBundle(context, var);
}
/**
* {@inheritDoc}
* @see Faces#navigate(String)
*/
public static void navigate(FacesContext context, String outcome) {
context.getApplication().getNavigationHandler().handleNavigation(context, null, outcome);
}
/**
* {@inheritDoc}
* @see Faces#getBookmarkableURL(Map, boolean)
*/
public static String getBookmarkableURL
(FacesContext context, Map<String, List<String>> params, boolean includeViewParams)
{
String viewId = getViewId(context);
if (viewId == null) {
throw new IllegalStateException(ERROR_NO_VIEW);
}
return getBookmarkableURL(context, viewId, params, includeViewParams);
}
/**
* {@inheritDoc}
* @see Faces#getBookmarkableURL(String, Map, boolean)
*/
public static String getBookmarkableURL
(FacesContext context, String viewId, Map<String, List<String>> params, boolean includeViewParams)
{
return context.getApplication().getViewHandler().getBookmarkableURL(context, viewId, params, includeViewParams);
}
/**
* {@inheritDoc}
* @see Faces#getBookmarkableURL(Collection, boolean)
*/
public static String getBookmarkableURL
(FacesContext context, Collection<ParamHolder> params, boolean includeViewParams)
{
String viewId = getViewId(context);
if (viewId == null) {
throw new IllegalStateException(ERROR_NO_VIEW);
}
return getBookmarkableURL(context, viewId, params, includeViewParams);
}
/**
* {@inheritDoc}
* @see Faces#getBookmarkableURL(String, Collection, boolean)
*/
public static String getBookmarkableURL
(FacesContext context, String viewId, Collection<ParamHolder> params, boolean includeViewParams)
{
Map<String, List<String>> convertedParams = new HashMap<>();
for (ParamHolder param : params) {
Object value = param.getValue();
convertedParams.put(param.getName(), Collections.singletonList(value != null ? value.toString() : ""));
}
return getBookmarkableURL(context, viewId, convertedParams, includeViewParams);
}
// Facelets -------------------------------------------------------------------------------------------------------
/**
* {@inheritDoc}
* @see Faces#getFaceletContext()
*/
public static FaceletContext getFaceletContext(FacesContext context) {
Map<Object, Object> contextAttributes = context.getAttributes();
for (String key : FACELET_CONTEXT_KEYS) {
FaceletContext faceletContext = (FaceletContext) contextAttributes.get(key);
if (faceletContext != null) {
return faceletContext;
}
}
return null;
}
/**
* {@inheritDoc}
* @see Faces#getFaceletAttribute(String)
*/
@SuppressWarnings("unchecked")
public static <T> T getFaceletAttribute(FacesContext context, String name) {
return (T) getFaceletContext(context).getAttribute(name);
}
/**
* {@inheritDoc}
* @see Faces#setFaceletAttribute(String, Object)
*/
public static void setFaceletAttribute(FacesContext context, String name, Object value) {
getFaceletContext(context).setAttribute(name, value);
}
// HTTP request ---------------------------------------------------------------------------------------------------
/**
* {@inheritDoc}
* @see Faces#getRequest()
*/
public static HttpServletRequest getRequest(FacesContext context) {
return (HttpServletRequest) context.getExternalContext().getRequest();
}
/**
* {@inheritDoc}
* @see Faces#isAjaxRequest()
*/
public static boolean isAjaxRequest(FacesContext context) {
return context.getPartialViewContext().isAjaxRequest();
}
/**
* {@inheritDoc}
* @see Faces#getRequestParameterMap()
*/
public static Map<String, String> getRequestParameterMap(FacesContext context) {
return context.getExternalContext().getRequestParameterMap();
}
/**
* {@inheritDoc}
* @see Faces#getRequestParameter(String)
*/
public static String getRequestParameter(FacesContext context, String name) {
return getRequestParameterMap(context).get(name);
}
/**
* {@inheritDoc}
* @see Faces#getRequestParameterValuesMap()
*/
public static Map<String, String[]> getRequestParameterValuesMap(FacesContext context) {
return context.getExternalContext().getRequestParameterValuesMap();
}
/**
* {@inheritDoc}
* @see Faces#getRequestParameterValues(String)
*/
public static String[] getRequestParameterValues(FacesContext context, String name) {
return getRequestParameterValuesMap(context).get(name);
}
/**
* {@inheritDoc}
* @see Faces#getRequestHeaderMap()
*/
public static Map<String, String> getRequestHeaderMap(FacesContext context) {
return context.getExternalContext().getRequestHeaderMap();
}
/**
* {@inheritDoc}
* @see Faces#getRequestHeader(String)
*/
public static String getRequestHeader(FacesContext context, String name) {
return getRequestHeaderMap(context).get(name);
}
/**
* {@inheritDoc}
* @see Faces#getRequestHeaderValuesMap()
*/
public static Map<String, String[]> getRequestHeaderValuesMap(FacesContext context) {
return context.getExternalContext().getRequestHeaderValuesMap();
}
/**
* {@inheritDoc}
* @see Faces#getRequestHeaderValues(String)
*/
public static String[] getRequestHeaderValues(FacesContext context, String name) {
return getRequestHeaderValuesMap(context).get(name);
}
/**
* {@inheritDoc}
* @see Faces#getRequestContextPath()
*/
public static String getRequestContextPath(FacesContext context) {
return context.getExternalContext().getRequestContextPath();
}
/**
* {@inheritDoc}
* @see Faces#getRequestServletPath()
*/
public static String getRequestServletPath(FacesContext context) {
return context.getExternalContext().getRequestServletPath();
}
/**
* {@inheritDoc}
* @see Faces#getRequestPathInfo()
*/
public static String getRequestPathInfo(FacesContext context) {
return context.getExternalContext().getRequestPathInfo();
}
/**
* {@inheritDoc}
* @see Faces#getRequestHostname()
*/
public static String getRequestHostname(FacesContext context) {
return Servlets.getRequestHostname(getRequest(context));
}
/**
* {@inheritDoc}
* @see Faces#getRequestBaseURL()
*/
public static String getRequestBaseURL(FacesContext context) {
return Servlets.getRequestBaseURL(getRequest(context));
}
/**
* {@inheritDoc}
* @see Faces#getRequestDomainURL()
*/
public static String getRequestDomainURL(FacesContext context) {
return Servlets.getRequestDomainURL(getRequest(context));
}
/**
* {@inheritDoc}
* @see Faces#getRequestURL()
*/
public static String getRequestURL(FacesContext context) {
return getRequest(context).getRequestURL().toString();
}
/**
* {@inheritDoc}
* @see Faces#getRequestURI()
*/
public static String getRequestURI(FacesContext context) {
return getRequest(context).getRequestURI();
}
/**
* {@inheritDoc}
* @see Faces#getRequestQueryString()
*/
public static String getRequestQueryString(FacesContext context) {
return getRequest(context).getQueryString();
}
/**
* {@inheritDoc}
* @see Faces#getRequestQueryStringMap()
*/
public static Map<String, List<String>> getRequestQueryStringMap(FacesContext context) {
return Servlets.getRequestQueryStringMap(getRequest(context));
}
/**
* {@inheritDoc}
* @see Faces#getRequestURLWithQueryString()
*/
public static String getRequestURLWithQueryString(FacesContext context) {
return Servlets.getRequestURLWithQueryString(getRequest(context));
}
/**
* {@inheritDoc}
* @see Faces#getRequestURIWithQueryString()
*/
public static String getRequestURIWithQueryString(FacesContext context) {
return Servlets.getRequestURIWithQueryString(getRequest(context));
}
/**
* {@inheritDoc}
* @see Faces#getForwardRequestURI()
*/
public static String getForwardRequestURI(FacesContext context) {
return Servlets.getForwardRequestURI(getRequest(context));
}
/**
* {@inheritDoc}
* @see Faces#getForwardRequestQueryString()
*/
public static String getForwardRequestQueryString(FacesContext context) {
return Servlets.getForwardRequestQueryString(getRequest(context));
}
/**
* {@inheritDoc}
* @see Faces#getForwardRequestURIWithQueryString()
*/
public static String getForwardRequestURIWithQueryString(FacesContext context) {
return Servlets.getForwardRequestURIWithQueryString(getRequest(context));
}
/**
* {@inheritDoc}
* @see Faces#getRemoteAddr()
*/
public static String getRemoteAddr(FacesContext context) {
String forwardedFor = getRequestHeader(context, "X-Forwarded-For");
if (!Utils.isEmpty(forwardedFor)) {
return forwardedFor.split("\\s*,\\s*", 2)[0]; // It's a comma separated string: client,proxy1,proxy2,...
}
return getRequest(context).getRemoteAddr();
}
// HTTP response --------------------------------------------------------------------------------------------------
/**
* {@inheritDoc}
* @see Faces#getResponse()
*/
public static HttpServletResponse getResponse(FacesContext context) {
return (HttpServletResponse) context.getExternalContext().getResponse();
}
/**
* {@inheritDoc}
* @see Faces#getResponseBufferSize()
*/
public static int getResponseBufferSize(FacesContext context) {
return context.getExternalContext().getResponseBufferSize();
}
/**
* {@inheritDoc}
* @see Faces#getResponseCharacterEncoding()
*/
public static String getResponseCharacterEncoding(FacesContext context) {
return context.getExternalContext().getResponseCharacterEncoding();
}
/**
* {@inheritDoc}
* @see Faces#setResponseStatus(int)
*/
public static void setResponseStatus(FacesContext context, int status) {
context.getExternalContext().setResponseStatus(status);
}
/**
* {@inheritDoc}
* @see Faces#redirect(String, String...)
*/
public static void redirect(FacesContext context, String url, String... paramValues) throws IOException {
ExternalContext externalContext = context.getExternalContext();
externalContext.getFlash().setRedirect(true);
externalContext.redirect(prepareRedirectURL(getRequest(context), url, paramValues));
}
/**
* {@inheritDoc}
* @see Faces#redirectPermanent(String, String...)
*/
public static void redirectPermanent(FacesContext context, String url, String... paramValues) {
ExternalContext externalContext = context.getExternalContext();
externalContext.getFlash().setRedirect(true);
externalContext.setResponseStatus(SC_MOVED_PERMANENTLY);
externalContext.setResponseHeader("Location", prepareRedirectURL(getRequest(context), url, paramValues));
externalContext.setResponseHeader("Connection", "close");
context.responseComplete();
}
/**
* {@inheritDoc}
* @see Faces#responseSendError(int, String)
*/
public static void responseSendError(FacesContext context, int status, String message) throws IOException {
context.getExternalContext().responseSendError(status, message);
context.responseComplete();
// Below is a workaround for disappearing FacesContext in WildFly/Undertow. It disappears because Undertow
// immediately performs a forward to error page instead of waiting until servlet's service is finished. When
// the error page is a JSF page as well, then it implicitly invokes FacesServlet once again, which in turn
// creates another FacesContext which overrides the current FacesContext in the same thread! So, when the
// FacesContext which is created during the forward is released, it leaves the current FacesContext as null,
// causing NPE over all place which is relying on FacesContext#getCurrentInstance().
if (!Faces.hasContext()) {
Faces.setContext(context);
}
}
/**
* {@inheritDoc}
* @see Faces#addResponseHeader(String, String)
*/
public static void addResponseHeader(FacesContext context, String name, String value) {
context.getExternalContext().addResponseHeader(name, value);
}
/**
* {@inheritDoc}
* @see Faces#isResponseCommitted()
*/
public static boolean isResponseCommitted(FacesContext context) {
return context.getExternalContext().isResponseCommitted();
}
/**
* {@inheritDoc}
* @see Faces#responseReset()
*/
public static void responseReset(FacesContext context) {
context.getExternalContext().responseReset();
}
/**
* {@inheritDoc}
* @see Faces#isRenderResponse()
*/
public static boolean isRenderResponse(FacesContext context) {
return context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE;
}
// FORM based authentication --------------------------------------------------------------------------------------
/**
* {@inheritDoc}
* @see Faces#login(String, String)
*/
public static void login(FacesContext context, String username, String password) throws ServletException {
getRequest(context).login(username, password);
}
/**
* {@inheritDoc}
* @see Faces#authenticate()
*/
public static boolean authenticate(FacesContext context) throws ServletException, IOException {
return getRequest(context).authenticate(getResponse(context));
}
/**
* {@inheritDoc}
* @see Faces#logout()
*/
public static void logout(FacesContext context) throws ServletException {
getRequest(context).logout();
}
/**
* {@inheritDoc}
* @see Faces#getRemoteUser()
*/
public static String getRemoteUser(FacesContext context) {
return context.getExternalContext().getRemoteUser();
}
/**
* {@inheritDoc}
* @see Faces#isUserInRole(String)
*/
public static boolean isUserInRole(FacesContext context, String role) {
return context.getExternalContext().isUserInRole(role);
}
// HTTP cookies ---------------------------------------------------------------------------------------------------
/**
* {@inheritDoc}
* @see Faces#getRequestCookie(String)
*/
public static String getRequestCookie(FacesContext context, String name) {
Cookie cookie = (Cookie) context.getExternalContext().getRequestCookieMap().get(name);
return (cookie != null) ? Utils.decodeURL(cookie.getValue()) : null;
}
/**
* {@inheritDoc}
* @see Faces#addResponseCookie(String, String, int)
*/
public static void addResponseCookie(FacesContext context, String name, String value, int maxAge) {
addResponseCookie(context, name, value, getRequestHostname(context), null, maxAge);
}
/**
* {@inheritDoc}
* @see Faces#addResponseCookie(String, String, String, int)
*/
public static void addResponseCookie(FacesContext context, String name, String value, String path, int maxAge) {
addResponseCookie(context, name, value, getRequestHostname(context), path, maxAge);
}
/**
* {@inheritDoc}
* @see Faces#addResponseCookie(String, String, String, String, int)
*/
public static void addResponseCookie(FacesContext context, String name, String value, String domain, String path, int maxAge) {
if (value != null) {
value = encodeURL(value);
}
ExternalContext externalContext = context.getExternalContext();
Map<String, Object> properties = new HashMap<>();
if (domain != null) {
properties.put("domain", domain);
}
if (path != null) {
properties.put("path", path);
}
properties.put("maxAge", maxAge);
properties.put("secure", ((HttpServletRequest) externalContext.getRequest()).isSecure());
externalContext.addResponseCookie(name, value, properties);
}
/**
* {@inheritDoc}
* @see Faces#removeResponseCookie(String, String)
*/
public static void removeResponseCookie(FacesContext context, String name, String path) {
addResponseCookie(context, name, null, path, 0);
}
// HTTP session ---------------------------------------------------------------------------------------------------
/**
* {@inheritDoc}
* @see Faces#getSession()
*/
public static HttpSession getSession(FacesContext context) {
return getSession(context, true);
}
/**
* {@inheritDoc}
* @see Faces#getSession(boolean)
*/
public static HttpSession getSession(FacesContext context, boolean create) {
return (HttpSession) context.getExternalContext().getSession(create);
}
/**
* {@inheritDoc}
* @see Faces#getSessionId()
*/
public static String getSessionId(FacesContext context) {
HttpSession session = getSession(context, false);
return (session != null) ? session.getId() : null;
}
/**
* {@inheritDoc}
* @see Faces#invalidateSession()
*/
public static void invalidateSession(FacesContext context) {
context.getExternalContext().invalidateSession();
}
/**
* {@inheritDoc}
* @see Faces#hasSession()
*/
public static boolean hasSession(FacesContext context) {
return getSession(context, false) != null;
}
/**
* {@inheritDoc}
* @see Faces#isSessionNew()
*/
public static boolean isSessionNew(FacesContext context) {
HttpSession session = getSession(context, false);
return (session != null && session.isNew());
}
/**
* {@inheritDoc}
* @see Faces#getSessionCreationTime()
*/
public static long getSessionCreationTime(FacesContext context) {
return getSession(context).getCreationTime();
}
/**
* {@inheritDoc}
* @see Faces#getSessionLastAccessedTime()
*/
public static long getSessionLastAccessedTime(FacesContext context) {
return getSession(context).getLastAccessedTime();
}
/**
* {@inheritDoc}
* @see Faces#getSessionMaxInactiveInterval()
*/
public static int getSessionMaxInactiveInterval(FacesContext context) {
// Note that JSF 2.1 has this method on ExternalContext. We don't use it in order to be JSF 2.0 compatible.
return getSession(context).getMaxInactiveInterval();
}
/**
* {@inheritDoc}
* @see Faces#setSessionMaxInactiveInterval(int)
*/
public static void setSessionMaxInactiveInterval(FacesContext context, int seconds) {
// Note that JSF 2.1 has this method on ExternalContext. We don't use it in order to be JSF 2.0 compatible.
getSession(context).setMaxInactiveInterval(seconds);
}
/**
* {@inheritDoc}
* @see Faces#hasSessionTimedOut()
*/
public static boolean hasSessionTimedOut(FacesContext context) {
HttpServletRequest request = getRequest(context);
return request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid();
}
// Servlet context ------------------------------------------------------------------------------------------------
/**
* {@inheritDoc}
* @see Faces#getServletContext()
*/
public static ServletContext getServletContext(FacesContext context) {
return (ServletContext) context.getExternalContext().getContext();
}
/**
* {@inheritDoc}
* @see Faces#getInitParameterMap()
*/
@SuppressWarnings("unchecked")
public static Map<String, String> getInitParameterMap(FacesContext context) {
return context.getExternalContext().getInitParameterMap();
}
/**
* {@inheritDoc}
* @see Faces#getInitParameter(String)
*/
public static String getInitParameter(FacesContext context, String name) {
return context.getExternalContext().getInitParameter(name);
}
/**
* {@inheritDoc}
* @see Faces#getMimeType(String)
*/
public static String getMimeType(FacesContext context, String name) {
String mimeType = context.getExternalContext().getMimeType(name);
if (mimeType == null) {
mimeType = DEFAULT_MIME_TYPE;
}
return mimeType;
}
/**
* {@inheritDoc}
* @see Faces#getResource(String)
*/
public static URL getResource(FacesContext context, String path) throws MalformedURLException {
return context.getExternalContext().getResource(path);
}
/**
* {@inheritDoc}
* @see Faces#getResourceAsStream(String)
*/
public static InputStream getResourceAsStream(FacesContext context, String path) {
return context.getExternalContext().getResourceAsStream(path);
}
/**
* {@inheritDoc}
* @see Faces#getResourcePaths(String)
*/
public static Set<String> getResourcePaths(FacesContext context, String path) {
return context.getExternalContext().getResourcePaths(path);
}
/**
* {@inheritDoc}
* @see Faces#getRealPath(String)
*/
public static String getRealPath(FacesContext context, String webContentPath) {
return context.getExternalContext().getRealPath(webContentPath);
}
// Request scope --------------------------------------------------------------------------------------------------
/**
* {@inheritDoc}
* @see Faces#getRequestMap()
*/
public static Map<String, Object> getRequestMap(FacesContext context) {
return context.getExternalContext().getRequestMap();
}
/**
* {@inheritDoc}
* @see Faces#getRequestAttribute(String)
*/
@SuppressWarnings("unchecked")
public static <T> T getRequestAttribute(FacesContext context, String name) {
return (T) getRequestMap(context).get(name);
}
/**
* {@inheritDoc}
* @see Faces#setRequestAttribute(String, Object)
*/
public static void setRequestAttribute(FacesContext context, String name, Object value) {
getRequestMap(context).put(name, value);
}
/**
* {@inheritDoc}
* @see Faces#removeRequestAttribute(String)
*/
@SuppressWarnings("unchecked")
public static <T> T removeRequestAttribute(FacesContext context, String name) {
return (T) getRequestMap(context).remove(name);
}
// Flash scope ----------------------------------------------------------------------------------------------------
/**
* {@inheritDoc}
* @see Faces#getFlash()
*/
public static Flash getFlash(FacesContext context) {
return context.getExternalContext().getFlash();
}
/**
* {@inheritDoc}
* @see Faces#getFlashAttribute(String)
*/
@SuppressWarnings("unchecked")
public static <T> T getFlashAttribute(FacesContext context, String name) {
return (T) getFlash(context).get(name);
}
/**
* {@inheritDoc}
* @see Faces#setFlashAttribute(String, Object)
*/
public static void setFlashAttribute(FacesContext context, String name, Object value) {
getFlash(context).put(name, value);
}
/**
* {@inheritDoc}
* @see Faces#removeFlashAttribute(String)
*/
@SuppressWarnings("unchecked")
public static <T> T removeFlashAttribute(FacesContext context, String name) {
return (T) getFlash(context).remove(name);
}
// View scope -----------------------------------------------------------------------------------------------------
/**
* {@inheritDoc}
* @see Faces#getViewMap()
*/
public static Map<String, Object> getViewMap(FacesContext context) {
return context.getViewRoot().getViewMap();
}
/**
* {@inheritDoc}
* @see Faces#getViewAttribute(String)
*/
@SuppressWarnings("unchecked")
public static <T> T getViewAttribute(FacesContext context, String name) {
return (T) getViewMap(context).get(name);
}
/**
* {@inheritDoc}
* @see Faces#setViewAttribute(String, Object)
*/
public static void setViewAttribute(FacesContext context, String name, Object value) {
getViewMap(context).put(name, value);
}
/**
* {@inheritDoc}
* @see Faces#removeViewAttribute(String)
*/
@SuppressWarnings("unchecked")
public static <T> T removeViewAttribute(FacesContext context, String name) {
return (T) getViewMap(context).remove(name);
}
// Session scope --------------------------------------------------------------------------------------------------
/**
* {@inheritDoc}
* @see Faces#getSessionMap()
*/
public static Map<String, Object> getSessionMap(FacesContext context) {
return context.getExternalContext().getSessionMap();
}
/**
* {@inheritDoc}
* @see Faces#getSessionAttribute(String)
*/
@SuppressWarnings("unchecked")
public static <T> T getSessionAttribute(FacesContext context, String name) {
return (T) getSessionMap(context).get(name);
}
/**
* {@inheritDoc}
* @see Faces#setSessionAttribute(String, Object)
*/
public static void setSessionAttribute(FacesContext context, String name, Object value) {
getSessionMap(context).put(name, value);
}
/**
* {@inheritDoc}
* @see Faces#removeSessionAttribute(String)
*/
@SuppressWarnings("unchecked")
public static <T> T removeSessionAttribute(FacesContext context, String name) {
return (T) getSessionMap(context).remove(name);
}
// Application scope ----------------------------------------------------------------------------------------------
/**
* {@inheritDoc}
* @see Faces#getApplicationMap()
*/
public static Map<String, Object> getApplicationMap(FacesContext context) {
return context.getExternalContext().getApplicationMap();
}
/**
* {@inheritDoc}
* @see Faces#getApplicationAttribute(String)
*/
@SuppressWarnings("unchecked")
public static <T> T getApplicationAttribute(FacesContext context, String name) {
return (T) getApplicationMap(context).get(name);
}
/**
* {@inheritDoc}
* @see Faces#setApplicationAttribute(String, Object)
*/
public static void setApplicationAttribute(FacesContext context, String name, Object value) {
getApplicationMap(context).put(name, value);
}
/**
* {@inheritDoc}
* @see Faces#removeApplicationAttribute(String)
*/
@SuppressWarnings("unchecked")
public static <T> T removeApplicationAttribute(FacesContext context, String name) {
return (T) getApplicationMap(context).remove(name);
}
// File download --------------------------------------------------------------------------------------------------
/**
* {@inheritDoc}
* @see Faces#sendFile(File, boolean)
*/
public static void sendFile(FacesContext context, File file, boolean attachment) throws IOException {
sendFile(context, new FileInputStream(file), file.getName(), file.length(), attachment);
}
/**
* {@inheritDoc}
* @see Faces#sendFile(byte[], String, boolean)
*/
public static void sendFile(FacesContext context, byte[] content, String filename, boolean attachment)
throws IOException
{
sendFile(context, new ByteArrayInputStream(content), filename, content.length, attachment);
}
/**
* {@inheritDoc}
* @see Faces#sendFile(InputStream, String, boolean)
*/
public static void sendFile(FacesContext context, InputStream content, String filename, boolean attachment)
throws IOException
{
sendFile(context, content, filename, -1, attachment);
}
/**
* Internal global method to send the given input stream to the response.
* @param input The file content as input stream.
* @param filename The file name which should appear in content disposition header.
* @param contentLength The content length, or -1 if it is unknown.
* @param attachment Whether the file should be provided as attachment, or just inline.
* @throws IOException Whenever something fails at I/O level. The caller should preferably not catch it, but just
* redeclare it in the action method. The servletcontainer will handle it.
*/
private static void sendFile
(FacesContext context, InputStream input, String filename, long contentLength, boolean attachment)
throws IOException
{
ExternalContext externalContext = context.getExternalContext();
// Prepare the response and set the necessary headers.
externalContext.setResponseBufferSize(DEFAULT_SENDFILE_BUFFER_SIZE);
externalContext.setResponseContentType(getMimeType(context, filename));
externalContext.setResponseHeader("Content-Disposition", String.format(SENDFILE_HEADER,
(attachment ? "attachment" : "inline"), encodeURL(filename)));
// Not exactly mandatory, but this fixes at least a MSIE quirk: http://support.microsoft.com/kb/316431
if (((HttpServletRequest) externalContext.getRequest()).isSecure()) {
externalContext.setResponseHeader("Cache-Control", "public");
externalContext.setResponseHeader("Pragma", "public");
}
// If content length is known, set it. Note that setResponseContentLength() cannot be used as it takes only int.
if (contentLength != -1) {
externalContext.setResponseHeader("Content-Length", String.valueOf(contentLength));
}
long size = Utils.stream(input, externalContext.getResponseOutputStream());
// This may be on time for files smaller than the default buffer size, but is otherwise ignored anyway.
if (contentLength == -1) {
externalContext.setResponseHeader("Content-Length", String.valueOf(size));
}
context.responseComplete();
}
}