/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 1997-2017 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.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.application.applicationimpl; import static com.sun.faces.util.MessageUtils.ILLEGAL_ATTEMPT_SETTING_APPLICATION_ARTIFACT_ID; import static com.sun.faces.util.MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID; import static com.sun.faces.util.MessageUtils.getExceptionMessageString; import static com.sun.faces.util.Util.canSetAppArtifact; import static com.sun.faces.util.Util.getCdiBeanManager; import static com.sun.faces.util.Util.getWebXmlVersion; import static com.sun.faces.util.Util.notNull; import static java.util.logging.Level.FINE; import java.text.MessageFormat; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.logging.Level; import java.util.logging.Logger; import javax.el.CompositeELResolver; import javax.el.ELContextListener; import javax.el.ELException; import javax.el.ELResolver; import javax.el.ExpressionFactory; import javax.el.MethodExpression; import javax.el.ValueExpression; import javax.enterprise.inject.spi.BeanManager; import javax.faces.context.FacesContext; import javax.faces.el.MethodBinding; import javax.faces.el.PropertyResolver; import javax.faces.el.ReferenceSyntaxException; import javax.faces.el.ValueBinding; import javax.faces.el.VariableResolver; import com.sun.faces.RIConstants; import com.sun.faces.application.ApplicationAssociate; import com.sun.faces.application.MethodBindingMethodExpressionAdapter; import com.sun.faces.application.ValueBindingValueExpressionAdapter; import com.sun.faces.el.ELUtils; import com.sun.faces.el.FacesCompositeELResolver; import com.sun.faces.el.PropertyResolverImpl; import com.sun.faces.el.VariableResolverImpl; import com.sun.faces.util.FacesLogger; import com.sun.faces.util.Util; public class ExpressionLanguage { private static final Logger LOGGER = FacesLogger.APPLICATION.getLogger(); private static final ELContextListener[] EMPTY_EL_CTX_LIST_ARRAY = {}; private final ApplicationAssociate associate; private volatile PropertyResolverImpl propertyResolver; private volatile VariableResolverImpl variableResolver; private List<ELContextListener> elContextListeners; private CompositeELResolver elResolvers; private FacesCompositeELResolver compositeELResolver; private Version version = new Version(); public ExpressionLanguage(ApplicationAssociate applicationAssociate) { this.associate = applicationAssociate; propertyResolver = new PropertyResolverImpl(); variableResolver = new VariableResolverImpl(); elContextListeners = new CopyOnWriteArrayList<>(); elResolvers = new CompositeELResolver(); } /** * @see javax.faces.application.Application#addELContextListener(javax.el.ELContextListener) */ public void addELContextListener(ELContextListener listener) { if (listener != null) { elContextListeners.add(listener); } } /** * @see javax.faces.application.Application#removeELContextListener(javax.el.ELContextListener) */ public void removeELContextListener(ELContextListener listener) { if (listener != null) { elContextListeners.remove(listener); } } /** * @see javax.faces.application.Application#getELContextListeners() */ public ELContextListener[] getELContextListeners() { if (!elContextListeners.isEmpty()) { return elContextListeners.toArray(new ELContextListener[elContextListeners.size()]); } return EMPTY_EL_CTX_LIST_ARRAY; } /** * @see javax.faces.application.Application#getELResolver() */ public ELResolver getELResolver() { if (compositeELResolver == null) { performOneTimeELInitialization(); } return compositeELResolver; } /** * @see javax.faces.application.Application#addELResolver(javax.el.ELResolver) */ public void addELResolver(ELResolver resolver) { if (associate.hasRequestBeenServiced()) { throw new IllegalStateException(getExceptionMessageString(ILLEGAL_ATTEMPT_SETTING_APPLICATION_ARTIFACT_ID, "ELResolver")); } FacesContext facesContext = FacesContext.getCurrentInstance(); if (version.isJsf23() || "4.0".equals(getWebXmlVersion(facesContext))) { BeanManager cdiBeanManager = getCdiBeanManager(facesContext); if (cdiBeanManager != null && !resolver.equals(cdiBeanManager.getELResolver())) { elResolvers.add(resolver); } } else { elResolvers.add(resolver); } } /** * @see javax.faces.application.Application#getExpressionFactory() */ public ExpressionFactory getExpressionFactory() { return associate.getExpressionFactory(); } /** * @see javax.faces.application.Application#evaluateExpressionGet(javax.faces.context.FacesContext, * String, Class) */ @SuppressWarnings("unchecked") public <T> T evaluateExpressionGet(FacesContext context, String expression, Class<? extends T> expectedType) throws ELException { return (T) getExpressionFactory().createValueExpression(context.getELContext(), expression, expectedType).getValue(context.getELContext()); } public CompositeELResolver getApplicationELResolvers() { return elResolvers; } public FacesCompositeELResolver getCompositeELResolver() { return compositeELResolver; } public void setCompositeELResolver(FacesCompositeELResolver compositeELResolver) { this.compositeELResolver = compositeELResolver; } private void performOneTimeELInitialization() { if (compositeELResolver != null) { throw new IllegalStateException("Class invariant invalidated: " + "The Application instance's ELResolver is not null " + "and it should be."); } associate.initializeELResolverChains(); } /** * @see javax.faces.application.Application#setPropertyResolver(javax.faces.el.PropertyResolver) */ @Deprecated public PropertyResolver getPropertyResolver() { if (compositeELResolver == null) { performOneTimeELInitialization(); } return propertyResolver; } /** * @see javax.faces.application.Application#setPropertyResolver(javax.faces.el.PropertyResolver) */ @Deprecated public void setPropertyResolver(PropertyResolver resolver) { // Throw Illegal State Exception if a PropertyResolver is set after // a request has been processed. if (associate.hasRequestBeenServiced()) { throw new IllegalStateException(getExceptionMessageString(ILLEGAL_ATTEMPT_SETTING_APPLICATION_ARTIFACT_ID, "PropertyResolver")); } if (resolver == null) { String message = getExceptionMessageString(NULL_PARAMETERS_ERROR_MESSAGE_ID, "resolver"); throw new NullPointerException(message); } propertyResolver.setDelegate(ELUtils.getDelegatePR(associate, true)); associate.setLegacyPropertyResolver(resolver); propertyResolver = new PropertyResolverImpl(); if (LOGGER.isLoggable(FINE)) { LOGGER.fine(MessageFormat.format("set PropertyResolver Instance to ''{0}''", resolver.getClass().getName())); } } /** * @see javax.faces.application.Application#createMethodBinding(String, Class[]) */ @Deprecated public MethodBinding createMethodBinding(String ref, Class<?> params[]) { Util.notNull("ref", ref); if (!(ref.startsWith("#{") && ref.endsWith("}"))) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine(MessageFormat.format("Expression ''{0}'' does not follow the syntax #{...}", ref)); } throw new ReferenceSyntaxException(ref); } FacesContext context = FacesContext.getCurrentInstance(); MethodExpression result; try { // return a MethodBinding that wraps a MethodExpression. if (null == params) { params = RIConstants.EMPTY_CLASS_ARGS; } result = getExpressionFactory().createMethodExpression(context.getELContext(), ref, null, params); } catch (ELException elex) { throw new ReferenceSyntaxException(elex); } return new MethodBindingMethodExpressionAdapter(result); } /** * @see javax.faces.application.Application#createValueBinding(String) */ @Deprecated public ValueBinding createValueBinding(String ref) throws ReferenceSyntaxException { notNull("ref", ref); ValueExpression result; FacesContext context = FacesContext.getCurrentInstance(); // return a ValueBinding that wraps a ValueExpression. try { result = getExpressionFactory().createValueExpression(context.getELContext(), ref, Object.class); } catch (ELException elex) { throw new ReferenceSyntaxException(elex); } return new ValueBindingValueExpressionAdapter(result); } /** * @see javax.faces.application.Application#getVariableResolver() */ @Deprecated public VariableResolver getVariableResolver() { if (compositeELResolver == null) { performOneTimeELInitialization(); } return variableResolver; } /** * @see javax.faces.application.Application#setVariableResolver(javax.faces.el.VariableResolver) */ @Deprecated public void setVariableResolver(VariableResolver resolver) { notNull("variableResolver", resolver); canSetAppArtifact(associate, "VariableResolver"); variableResolver.setDelegate(ELUtils.getDelegateVR(associate, true)); associate.setLegacyVariableResolver(resolver); if (LOGGER.isLoggable(FINE)) { LOGGER.fine(MessageFormat.format("set VariableResolver Instance to ''{0}''", variableResolver.getClass().getName())); } } }