blob: 0ead9ff76a2759610adb24c021e316f978121307 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.myfaces.extensions.cdi.jsf.impl.util;
import javax.enterprise.inject.Typed;
import javax.faces.FactoryFinder;
import javax.faces.application.FacesMessage;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseListener;
import javax.faces.lifecycle.Lifecycle;
import javax.faces.lifecycle.LifecycleFactory;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import org.apache.myfaces.extensions.cdi.core.impl.scope.conversation.spi.WindowContextManager;
import org.apache.myfaces.extensions.cdi.core.impl.util.CodiUtils;
import org.apache.myfaces.extensions.cdi.jsf.impl.config.view.PageParameterContext;
/**
* keep in sync with extval!
*/
@Typed()
public abstract class JsfUtils
{
public static final String FACES_CONTEXT_MANUAL_WRAPPER_KEY =
"javax.faces.context.FacesContext:manuallyWrappedByCodi";
private JsfUtils()
{
// prevent instantiation
}
/**
* Resets the conversation cache of the current request
*/
public static void resetConversationCache()
{
RequestCache.resetConversationCache();
}
/**
* Resets all caches of the current request
*/
public static void resetCaches()
{
RequestCache.resetCache();
}
/**
* Adds the given {@link PhaseListener} to the application
* @param phaseListener current phase-listener
*/
public static void registerPhaseListener(PhaseListener phaseListener)
{
LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder.getFactory(
FactoryFinder.LIFECYCLE_FACTORY);
String currentId;
Lifecycle currentLifecycle;
Iterator lifecycleIds = lifecycleFactory.getLifecycleIds();
while (lifecycleIds.hasNext())
{
currentId = (String) lifecycleIds.next();
currentLifecycle = lifecycleFactory.getLifecycle(currentId);
currentLifecycle.addPhaseListener(phaseListener);
}
}
/**
* Exposes the default message-bundle of jsf for the given {@link Locale}
* @param locale current local
* @return default message-bundle
*/
public static ResourceBundle getDefaultFacesMessageBundle(Locale locale)
{
return ResourceBundle.getBundle(FacesMessage.FACES_MESSAGES, locale);
}
/**
* Exposes the (optional) custom message-bundle configured in the faces-config for the given {@link Locale}
* @param locale current local
* @return custom message-bundle
*/
public static ResourceBundle getCustomFacesMessageBundle(Locale locale)
{
FacesContext facesContext = FacesContext.getCurrentInstance();
String bundleName = facesContext.getApplication().getMessageBundle();
if (bundleName == null)
{
return null;
}
return ResourceBundle.getBundle(bundleName, locale);
}
/**
* Encodes the given value using URLEncoder.encode() with the charset returned
* from ExternalContext.getResponseCharacterEncoding().
* This is exactly how the ExternalContext impl encodes URL parameter values.
*
* @param value value which should be encoded
* @param externalContext current external-context
* @return encoded value
*/
public static String encodeURLParameterValue(String value, ExternalContext externalContext)
{
// copied from MyFaces ServletExternalContextImpl.encodeURL()
try
{
return URLEncoder.encode(value, externalContext.getResponseCharacterEncoding());
}
catch (UnsupportedEncodingException e)
{
throw new UnsupportedOperationException("Encoding type="
+ externalContext.getResponseCharacterEncoding() + " not supported", e);
}
}
/**
* Adds the current request-parameters to the given url
* @param externalContext current external-context
* @param url current url
* @param addRequestParameter flag which indicates if the request params should be added or not
* @param addPageParameter flag which indicates if the view params should be added or not {@see ViewParameter}
* @param encodeValues flag which indicates if parameter values should be encoded or not
* @return url with request-parameters
*/
public static String addParameters(ExternalContext externalContext, String url,
boolean addRequestParameter, boolean addPageParameter, boolean encodeValues)
{
StringBuilder finalUrl = new StringBuilder(url);
boolean existingParameters = url.contains("?");
boolean urlContainsWindowId = url.contains(WindowContextManager.WINDOW_CONTEXT_ID_PARAMETER_KEY + "=");
for(RequestParameter requestParam :
getParameters(externalContext, true, addRequestParameter, addPageParameter))
{
String key = requestParam.getKey();
//TODO eval if we should also filter the other params
if(WindowContextManager.WINDOW_CONTEXT_ID_PARAMETER_KEY.equals(key) && urlContainsWindowId)
{
continue;
}
for(String parameterValue : requestParam.getValues())
{
if(!url.contains(key + "=" + parameterValue) &&
!url.contains(key + "=" + encodeURLParameterValue(parameterValue, externalContext)))
{
if(!existingParameters)
{
finalUrl.append("?");
existingParameters = true;
}
else
{
finalUrl.append("&");
}
finalUrl.append(key);
finalUrl.append("=");
if(encodeValues)
{
finalUrl.append(JsfUtils.encodeURLParameterValue(parameterValue, externalContext));
}
else
{
finalUrl.append(parameterValue);
}
}
}
}
return finalUrl.toString();
}
/**
* Exposes all request-parameters (including or excluding the view-state)
* @param externalContext current external-context
* @param filterViewState flag which indicates if the view-state should be added or not
* @param addRequestParameter flag which indicates if the request params should be added or not
* @param addPageParameter flag which indicates if the view params should be added or not {@see ViewParameter}
* @return current request-parameters
*/
public static Set<RequestParameter> getParameters(ExternalContext externalContext,
boolean filterViewState,
boolean addRequestParameter,
boolean addPageParameter)
{
Set<RequestParameter> result = new HashSet<RequestParameter>();
if(externalContext == null || //detection of early config for different mojarra versions
externalContext.getRequestParameterValuesMap() == null || externalContext.getRequest() == null)
{
return result;
}
if(addRequestParameter)
{
String key;
for(Map.Entry<String, String[]> entry : externalContext.getRequestParameterValuesMap().entrySet())
{
key = entry.getKey();
if(filterViewState && "javax.faces.ViewState".equals(key))
{
continue;
}
result.add(new RequestParameter(key, entry.getValue()));
}
}
if(addPageParameter)
{
PageParameterContext pageParameterContext =
CodiUtils.getContextualReferenceByClass(PageParameterContext.class, true);
if(pageParameterContext != null)
{
for(Map.Entry<String, String> entry : pageParameterContext.getPageParameters().entrySet())
{
//TODO add multi-value support - see comment in PageParameterContext
result.add(new RequestParameter(entry.getKey(), new String[] {entry.getValue()}));
}
}
}
return result;
}
public static <T> T getValueOfExpression(String expression, Class<T> targetType)
{
FacesContext facesContext = FacesContext.getCurrentInstance();
return (T)facesContext.getApplication().evaluateExpressionGet(facesContext, expression, targetType);
}
public static String getValueOfExpressionAsString(String expression)
{
Object result = getValueOfExpression(expression, Object.class);
return result != null ? result.toString() : "null";
}
}