com.sun.faces.el.ELUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of javax.faces Show documentation
Show all versions of javax.faces Show documentation
This is the master POM file for Oracle's Implementation of the JSF 2.1 Specification.
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.faces.el;
import com.sun.faces.application.ApplicationAssociate;
import com.sun.faces.context.flash.FlashELResolver;
import com.sun.faces.mgbean.BeanManager;
import com.sun.faces.util.MessageUtils;
import javax.el.ArrayELResolver;
import javax.el.BeanELResolver;
import javax.el.CompositeELResolver;
import javax.el.ELContext;
import javax.el.ELResolver;
import javax.el.ListELResolver;
import javax.el.MapELResolver;
import javax.el.ResourceBundleELResolver;
import javax.el.ValueExpression;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.el.EvaluationException;
import javax.faces.el.PropertyResolver;
import javax.faces.el.ReferenceSyntaxException;
import javax.faces.el.VariableResolver;
import javax.faces.component.UIViewRoot;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Utility class for EL related methods.
*/
public class ELUtils {
/**
* Helps to determine if a EL expression represents a composite component
* EL expression.
*/
private static final Pattern COMPOSITE_COMPONENT_EXPRESSION =
Pattern.compile(".(?:[ ]+|[\\[{,(])cc[.].+[}]");
/**
* Used to determine if EL method arguments are being passed to a
* composite component lookup expression.
*
* For example:
*
* #{cc.attrs.label('foo')}
*
* is illegal, while:
*
* #{cc.attrs.bean.label('foo')}
*
* is legal.
*/
private static final Pattern COMPOSITE_COMPONENT_LOOKUP_WITH_ARGS =
Pattern.compile("(?:[ ]+|[\\[{,(])cc[.]attrs[.]\\w+[(].+[)]");
/**
* Use to determine if an expression being considered as a
* MethodExpression is a simple lookup (i.e. #{cc.attrs.myaction}).
*/
private static final Pattern METHOD_EXPRESSION_LOOKUP =
Pattern.compile(".[{]cc[.]attrs[.]\\w+[}]");
private static final String APPLICATION_SCOPE = "applicationScope";
private static final String SESSION_SCOPE = "sessionScope";
private static final String REQUEST_SCOPE = "requestScope";
private static final String VIEW_SCOPE = "viewScope";
private static final String COOKIE_IMPLICIT_OBJ = "cookie";
private static final String FACES_CONTEXT_IMPLICIT_OBJ = "facesContext";
private static final String HEADER_IMPLICIT_OBJ = "header";
private static final String HEADER_VALUES_IMPLICIT_OBJ = "headerValues";
private static final String INIT_PARAM_IMPLICIT_OBJ = "initParam";
private static final String PARAM_IMPLICIT_OBJ = "param";
private static final String PARAM_VALUES_IMPLICIT_OBJ = "paramValues";
private static final String VIEW_IMPLICIT_OBJ = "view";
public enum Scope {
NONE("none"),
REQUEST("request"),
VIEW("view"),
SESSION("session"),
APPLICATION("application");
String scope;
Scope(String scope) {
this.scope = scope;
}
public String toString() {
return scope;
}
}
public static final ArrayELResolver ARRAY_RESOLVER = new ArrayELResolver();
public static final BeanELResolver BEAN_RESOLVER = new BeanELResolver();
public static final FacesResourceBundleELResolver FACES_BUNDLE_RESOLVER =
new FacesResourceBundleELResolver();
public static final ImplicitObjectELResolverForJsp IMPLICIT_JSP_RESOLVER =
new ImplicitObjectELResolverForJsp();
public static final ImplicitObjectELResolver IMPLICIT_RESOLVER =
new ImplicitObjectELResolver();
public static final FlashELResolver FLASH_RESOLVER =
new FlashELResolver();
public static final ListELResolver LIST_RESOLVER = new ListELResolver();
public static final ManagedBeanELResolver MANAGED_BEAN_RESOLVER =
new ManagedBeanELResolver();
public static final MapELResolver MAP_RESOLVER = new MapELResolver();
public static final ResourceBundleELResolver BUNDLE_RESOLVER =
new ResourceBundleELResolver();
public static final ScopedAttributeELResolver SCOPED_RESOLVER =
new ScopedAttributeELResolver();
public static final ResourceELResolver RESOURCE_RESOLVER =
new ResourceELResolver();
public static final CompositeComponentAttributesELResolver COMPOSITE_COMPONENT_ATTRIBUTES_EL_RESOLVER =
new CompositeComponentAttributesELResolver();
// ------------------------------------------------------------ Constructors
private ELUtils() {
throw new IllegalStateException();
}
// ---------------------------------------------------------- Public Methods
public static boolean isCompositeComponentExpr(String expression) {
// TODO we should be trying to re-use the Matcher by calling
// m.reset(expression);
Matcher m = COMPOSITE_COMPONENT_EXPRESSION.matcher(expression);
return m.find();
}
public static boolean isCompositeComponentMethodExprLookup(String expression) {
Matcher m = METHOD_EXPRESSION_LOOKUP.matcher(expression);
return m.matches();
}
public static boolean isCompositeComponentLookupWithArgs(String expression) {
// TODO we should be trying to re-use the Matcher by calling
// m.reset(expression);
Matcher m = COMPOSITE_COMPONENT_LOOKUP_WITH_ARGS.matcher(expression);
return m.find();
}
/**
* Create the ELResolver
chain for programmatic EL calls.
* @param composite a CompositeELResolver
* @param associate our ApplicationAssociate
*/
public static void buildFacesResolver(FacesCompositeELResolver composite,
ApplicationAssociate associate) {
if (associate == null) {
String message = MessageUtils.getExceptionMessageString
(MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "associate");
throw new NullPointerException(message);
}
if (composite == null) {
String message = MessageUtils.getExceptionMessageString
(MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "composite");
throw new NullPointerException(message);
}
composite.addRootELResolver(IMPLICIT_RESOLVER);
composite.add(FLASH_RESOLVER);
composite.addPropertyELResolver(COMPOSITE_COMPONENT_ATTRIBUTES_EL_RESOLVER);
addELResolvers(composite, associate.getELResolversFromFacesConfig());
addVariableResolvers(composite, FacesCompositeELResolver.ELResolverChainType.Faces,
associate);
addPropertyResolvers(composite, associate);
composite.add(associate.getApplicationELResolvers());
composite.addRootELResolver(MANAGED_BEAN_RESOLVER);
composite.addPropertyELResolver(RESOURCE_RESOLVER);
composite.addPropertyELResolver(BUNDLE_RESOLVER);
composite.addRootELResolver(FACES_BUNDLE_RESOLVER);
composite.addPropertyELResolver(MAP_RESOLVER);
composite.addPropertyELResolver(LIST_RESOLVER);
composite.addPropertyELResolver(ARRAY_RESOLVER);
composite.addPropertyELResolver(BEAN_RESOLVER);
composite.addRootELResolver(SCOPED_RESOLVER);
}
/**
* Create the ELResolver
chain for JSP.
* @param composite a CompositeELResolver
* @param associate our ApplicationAssociate
*/
public static void buildJSPResolver(FacesCompositeELResolver composite,
ApplicationAssociate associate) {
if (associate == null) {
String message = MessageUtils.getExceptionMessageString
(MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "associate");
throw new NullPointerException(message);
}
if (composite == null) {
String message = MessageUtils.getExceptionMessageString
(MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "composite");
throw new NullPointerException(message);
}
composite.addRootELResolver(IMPLICIT_JSP_RESOLVER);
composite.add(FLASH_RESOLVER);
composite.addRootELResolver(MANAGED_BEAN_RESOLVER);
composite.addPropertyELResolver(RESOURCE_RESOLVER);
composite.addRootELResolver(FACES_BUNDLE_RESOLVER);
addELResolvers(composite, associate.getELResolversFromFacesConfig());
addVariableResolvers(composite, FacesCompositeELResolver.ELResolverChainType.JSP,
associate);
addPropertyResolvers(composite, associate);
composite.add(associate.getApplicationELResolvers());
}
public static Object evaluateValueExpression(ValueExpression expression,
ELContext elContext) {
if (expression.isLiteralText()) {
return expression.getExpressionString();
} else {
return expression.getValue(elContext);
}
}
/**
* @param associate the ApplicationAssociate
* @param provideDefault whether or not to return a
* DummpyPropertyResolverImpl
* @return the PropertyResolver
s set via
* {@link javax.faces.application.Application#setPropertyResolver(javax.faces.el.PropertyResolver)}
* or, if that is null
, return the PropertyResolver
* chain from the parsed configuration resources. If either of those are
* null, and provideDefault
is true
,
* return the DummyPropertyResolverImpl
.
*/
@SuppressWarnings("deprecation")
public static PropertyResolver getDelegatePR(ApplicationAssociate associate,
boolean provideDefault) {
PropertyResolver pr = associate.getLegacyPropertyResolver();
if (pr == null) {
pr = associate.getLegacyPRChainHead();
if (pr == null && provideDefault) {
pr = new DummyPropertyResolverImpl();
}
}
return pr;
}
/**
* @param associate the ApplicationAssociate
* @param provideDefault whether or not to return a
* DummpyPropertyResolverImpl
* @return the VariableResolver
s set via
* {@link javax.faces.application.Application#setVariableResolver(javax.faces.el.VariableResolver)}
* or, if that is null
, return the VariableResolver
* chain from the parsed configuration resources. If either of those are
* null, , and provideDefault
is true
,
* return the ChainAwareVariableResolver
.
*/
@SuppressWarnings("deprecation")
public static VariableResolver getDelegateVR(ApplicationAssociate associate,
boolean provideDefault) {
VariableResolver vr = associate.getLegacyVariableResolver();
if (vr == null) {
vr = associate.getLegacyVRChainHead();
if (vr == null && provideDefault) {
vr = new ChainAwareVariableResolver();
}
}
return vr;
}
/**
* @param expressionString the expression string, with delimiters
* intact.
* @return a List of expressions from the expressionString
* @throws ReferenceSyntaxException if the expression string is invalid
*/
@SuppressWarnings("deprecation")
public static List getExpressionsFromString(String expressionString)
throws ReferenceSyntaxException {
if (null == expressionString) {
return Collections.emptyList();
}
//noinspection CollectionWithoutInitialCapacity
List result = new ArrayList();
int i, j, len = expressionString.length(), cur = 0;
while (cur < len &&
-1 != (i = expressionString.indexOf("#{", cur))) {
if (-1 == (j = expressionString.indexOf('}', i + 2))) {
throw new ReferenceSyntaxException(
MessageUtils.getExceptionMessageString(
MessageUtils.INVALID_EXPRESSION_ID,
expressionString));
}
cur = j + 1;
result.add(expressionString.substring(i, cur));
}
return result;
}
/**
* This method is used by the ManagedBeanFactory to ensure that
* properties set by an expression point to an object with an
* accepted lifespan.
*
* get the scope of the expression. Return null
if
* it isn't scoped
*
* For example, the expression:
* sessionScope.TestBean.one
should return "session"
* as the scope.
*
* @param valueBinding the expression
*
* @param outString an allocated String Array into which we put the
* first segment.
*
* @return the scope of the expression
*
* @throws ReferenceSyntaxException if valueBinding is syntactically invalid
*/
@SuppressWarnings("deprecation")
public static ELUtils.Scope getScope(String valueBinding, String[] outString)
throws ReferenceSyntaxException {
if (valueBinding == null || 0 == valueBinding.length()) {
return null;
}
valueBinding = stripBracketsIfNecessary(valueBinding);
int segmentIndex = getFirstSegmentIndex(valueBinding);
//examine first segment and see if it is a scope
String identifier = valueBinding;
if (segmentIndex > 0) {
//get first segment designated by a "." or "["
identifier = valueBinding.substring(0, segmentIndex);
}
//check to see if the identifier is a named scope.
FacesContext context = FacesContext.getCurrentInstance();
ExternalContext ec = context.getExternalContext();
if (null != outString) {
outString[0] = identifier;
}
if (REQUEST_SCOPE.equalsIgnoreCase(identifier)) {
return Scope.REQUEST;
}
if (VIEW_SCOPE.equalsIgnoreCase(identifier)) {
return Scope.VIEW;
}
if (SESSION_SCOPE.equalsIgnoreCase(identifier)) {
return Scope.SESSION;
}
if (APPLICATION_SCOPE.equalsIgnoreCase(identifier)) {
return Scope.APPLICATION;
}
// handle implicit objects
if (INIT_PARAM_IMPLICIT_OBJ.equalsIgnoreCase(identifier)) {
return Scope.APPLICATION;
}
if (COOKIE_IMPLICIT_OBJ.equalsIgnoreCase(identifier)) {
return Scope.REQUEST;
}
if (FACES_CONTEXT_IMPLICIT_OBJ.equalsIgnoreCase(identifier)) {
return Scope.REQUEST;
}
if (HEADER_IMPLICIT_OBJ.equalsIgnoreCase(identifier)) {
return Scope.REQUEST;
}
if (HEADER_VALUES_IMPLICIT_OBJ.equalsIgnoreCase(identifier)) {
return Scope.REQUEST;
}
if (PARAM_IMPLICIT_OBJ.equalsIgnoreCase(identifier)) {
return Scope.REQUEST;
}
if (PARAM_VALUES_IMPLICIT_OBJ.equalsIgnoreCase(identifier)) {
return Scope.REQUEST;
}
if (VIEW_IMPLICIT_OBJ.equalsIgnoreCase(identifier)) {
return Scope.REQUEST;
}
Map requestMap = ec.getRequestMap();
if (requestMap != null && requestMap.containsKey(identifier)) {
return Scope.REQUEST;
}
UIViewRoot root = context.getViewRoot();
if (root != null) {
Map viewMap = root.getViewMap(false);
if (viewMap != null && viewMap.containsKey(identifier)) {
return Scope.VIEW;
}
}
Map sessionMap = ec.getSessionMap();
if (sessionMap != null && sessionMap.containsKey(identifier)) {
return Scope.SESSION;
}
Map appMap = ec.getApplicationMap();
if (appMap != null && appMap.containsKey(identifier)) {
return Scope.APPLICATION;
}
//not present in any scope
return null;
}
/**
* Create a ValueExpression
with the expected type of
* Object.class
* @param expression an EL expression
* @return a new ValueExpression
instance based off the
* provided valueRef
*/
public static ValueExpression createValueExpression(String expression) {
return createValueExpression(expression, Object.class);
}
public static ValueExpression createValueExpression(String expression,
Class expectedType) {
FacesContext context = FacesContext.getCurrentInstance();
return context.getApplication().getExpressionFactory().
createValueExpression(context.getELContext(),
expression,
expectedType);
}
public static Object coerce(Object value, Class toType) {
FacesContext context = FacesContext.getCurrentInstance();
return context.getApplication().getExpressionFactory().coerceToType(value, toType);
}
public static Scope getScope(String scope) {
for (Scope s : Scope.values()) {
if (s.toString().equals(scope)) {
return s;
}
}
return null;
}
// --------------------------------------------------------- Private Methods
/**
* Add the ELResolvers
from the provided list
* to the target CompositeELResolver
.
*
* @param target the CompositeELResolver
to which
* the ELResolver
s will be added.
* @param resolvers a List
of ELResolver
s
*/
private static void addELResolvers(CompositeELResolver target,
List resolvers) {
if (resolvers != null && !resolvers.isEmpty()) {
for (ELResolver resolver : resolvers) {
target.add(resolver);
}
}
}
/**
* Add any PropertyResolver
s to the specified
* CompositeELResolver
.
* @param target the CompositeELResolver
to which
* the PropertyResolver
s will be added.
* @param associate our ApplicationAssociate
*/
@SuppressWarnings("deprecation")
private static void addPropertyResolvers(CompositeELResolver target,
ApplicationAssociate associate) {
PropertyResolver pr = getDelegatePR(associate, false);
if (pr != null) {
target.add(new PropertyResolverChainWrapper(pr));
}
}
/**
* Add any VariableResolver
s to the specified
* CompositeELResolver
.
* @param target the CompositeELResolver
to which
* the VariableResolver
s will be added.
* @param associate our ApplicationAssociate
*/
@SuppressWarnings("deprecation")
private static void addVariableResolvers(FacesCompositeELResolver target,
FacesCompositeELResolver.ELResolverChainType chainType,
ApplicationAssociate associate) {
VariableResolver vr = getDelegateVR(associate, true);
if (vr != null) {
VariableResolverChainWrapper vrChainWrapper = new VariableResolverChainWrapper(vr);
target.addRootELResolver(vrChainWrapper);
if (chainType == FacesCompositeELResolver.ELResolverChainType.JSP) {
associate.setLegacyVRChainHeadWrapperForJsp(vrChainWrapper);
} else {
associate.setLegacyVRChainHeadWrapperForFaces(vrChainWrapper);
}
}
}
/**
*
* The the first segment of a String tokenized by a "." or "["
*
* @param valueBinding the expression from which the first segment
* will be obtained
* @return index of the first occurrence of . or [
*/
private static int getFirstSegmentIndex(String valueBinding) {
int segmentIndex = valueBinding.indexOf('.');
int bracketIndex = valueBinding.indexOf('[');
//there is no "." in the valueBinding so take the bracket value
if (segmentIndex < 0) {
segmentIndex = bracketIndex;
} else {
//if there is a bracket proceed
if (bracketIndex > 0) {
//if the bracket index is before the "." then
//get the bracket index
if (segmentIndex > bracketIndex) {
segmentIndex = bracketIndex;
}
}
}
return segmentIndex;
}
@SuppressWarnings("deprecation")
private static String stripBracketsIfNecessary(String expression)
throws ReferenceSyntaxException {
assert (null != expression);
// look for invalid expressions
if (expression.charAt(0) == '#') {
if (expression.charAt(1) != '{') {
throw new ReferenceSyntaxException(MessageUtils.getExceptionMessageString(
MessageUtils.INVALID_EXPRESSION_ID,
expression));
}
int len = expression.length();
if (expression.charAt(len - 1) != '}') {
throw new ReferenceSyntaxException(MessageUtils.getExceptionMessageString(
MessageUtils.INVALID_EXPRESSION_ID,
expression));
}
expression = expression.substring(2, len - 1);
}
return expression;
}
public static Scope getScopeForExpression(String expression) {
if (SharedUtils.isMixedExpression(expression)) {
return (getNarrowestScopeFromExpression(expression));
} else {
return (getScopeForSingleExpression(expression));
}
}
@SuppressWarnings("deprecation")
public static boolean hasValidLifespan(Scope expressionScope, Scope beanScope)
throws EvaluationException {
//if the managed bean's scope is "none" but the scope of the
//referenced object is not "none", scope is invalid
if (beanScope == Scope.NONE) {
return expressionScope == Scope.NONE;
}
//if the managed bean's scope is "request" it is able to refer
//to objects in any scope
if (beanScope == Scope.REQUEST) {
return true;
}
//if the managed bean's scope is "view" it is able to refer to
//objects in other "view", "session", "application" or "none" scopes.
if (beanScope == Scope.VIEW) {
return expressionScope != Scope.REQUEST;
}
//if the managed bean's scope is "session" it is able to refer
//to objects in other "session", "application", or "none" scopes
if (beanScope == Scope.SESSION) {
return !(expressionScope == Scope.REQUEST
|| expressionScope == Scope.VIEW);
}
//if the managed bean's scope is "application" it is able to refer
//to objects in other "application", or "none" scopes
if (beanScope == Scope.APPLICATION) {
return !(expressionScope == Scope.REQUEST
|| expressionScope == Scope.VIEW
|| expressionScope == Scope.SESSION);
}
//the managed bean is required to be in either "request", "view",
// "session", "application", or "none" scopes. One of the previous decision
//statements must be true.
//noinspection ConstantConditions
assert (false);
return false;
}
@SuppressWarnings("deprecation")
public static ELUtils.Scope getScopeForSingleExpression(String value)
throws EvaluationException {
String[] firstSegment = new String[1];
ELUtils.Scope valueScope = ELUtils.getScope(value, firstSegment);
if (null == valueScope) {
// Perhaps the bean hasn't been created yet. See what its
// scope would be when it is created.
if (firstSegment[0] != null) {
BeanManager manager =
ApplicationAssociate.getCurrentInstance().getBeanManager();
if (manager.isManaged(firstSegment[0])) {
valueScope = ELUtils.getScope(manager.getBuilder(firstSegment[0]).getScope());
}
} else {
// we are referring to a bean that doesn't exist in the
// configuration file. Give it a wide scope...
valueScope = Scope.APPLICATION;
}
}
return valueScope;
}
@SuppressWarnings("deprecation")
public static Scope getNarrowestScopeFromExpression(String expression)
throws ReferenceSyntaxException {
// break the argument expression up into its component
// expressions, ignoring literals.
List expressions = ELUtils.getExpressionsFromString(expression);
int shortestScope = Scope.NONE.ordinal();
Scope result = Scope.NONE;
for (String expr : expressions) {
// loop over the expressions
Scope lScope = getScopeForSingleExpression(expr);
// don't consider none
if (null == lScope || lScope == Scope.NONE) {
continue;
}
int currentScope = lScope.ordinal();
// if we have no basis for comparison
if (Scope.NONE.ordinal() == shortestScope) {
shortestScope = currentScope;
result = lScope;
} else {
// we have a basis for comparison
if (currentScope < shortestScope) {
shortestScope = currentScope;
result = lScope;
}
}
}
return result;
}
public static boolean isScopeValid(String scopeName) {
if (scopeName == null) {
return false;
}
for (Scope scope : Scope.values()) {
if (scopeName.equals(scope.toString())) {
return true;
}
}
return false;
}
}