View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.el.unified;
20  
21  import java.util.Collections;
22  import java.util.List;
23  import java.util.function.Predicate;
24  import java.util.logging.Level;
25  import java.util.logging.Logger;
26  
27  import javax.el.ELResolver;
28  import javax.enterprise.inject.spi.BeanManager;
29  import javax.faces.annotation.FacesConfig;
30  import javax.faces.context.FacesContext;
31  import javax.faces.el.PropertyResolver;
32  import javax.faces.el.VariableResolver;
33  
34  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
35  import org.apache.myfaces.cdi.config.FacesConfigBeanHolder;
36  import org.apache.myfaces.cdi.util.CDIUtils;
37  import org.apache.myfaces.config.RuntimeConfig;
38  import org.apache.myfaces.el.convert.PropertyResolverToELResolver;
39  import org.apache.myfaces.el.convert.VariableResolverToELResolver;
40  import org.apache.myfaces.el.unified.resolver.FacesCompositeELResolver.Scope;
41  import org.apache.myfaces.shared.config.MyfacesConfig;
42  import org.apache.myfaces.util.ExternalSpecifications;
43  
44  /**
45   * @author Mathias Broekelmann (latest modification by $Author$)
46   * @version $Revision$ $Date$
47   */
48  @SuppressWarnings("deprecation")
49  public class ResolverBuilderBase
50  {
51      
52      private static final Logger log = Logger.getLogger(ResolverBuilderBase.class.getName());
53      
54      /**
55       * Define a custom comparator class used to sort the ELResolvers.
56       * 
57       * <p>This is useful when it is necessary to put an ELResolver on top of other resolvers. Note set
58       * this param override the default ordering described by JSF spec section 5. 
59       * </p>
60       */
61      @JSFWebConfigParam(since = "1.2.10, 2.0.2", group="EL",
62              desc = "The Class of an Comparator&lt;ELResolver&gt; implementation.")
63      public static final String EL_RESOLVER_COMPARATOR = "org.apache.myfaces.EL_RESOLVER_COMPARATOR";
64      
65      @JSFWebConfigParam(since = "2.1.0", group="EL",
66          desc="The Class of an java.util.function.Predicate&lt;ELResolver&gt; implementation."
67               + "If used and returns false for a ELResolver instance, such resolver will not be installed in "
68               + "ELResolvers chain. Use with caution - can break functionality defined in JSF specification "
69               + "'ELResolver Instances Provided by Faces'")
70      public static final String EL_RESOLVER_PREDICATE = "org.apache.myfaces.EL_RESOLVER_PREDICATE";
71      
72      private final RuntimeConfig _config;
73  
74      public ResolverBuilderBase(RuntimeConfig config)
75      {
76          _config = config;
77      }
78  
79      /**
80       * add the el resolvers from the faces config, the el resolver wrapper for variable resolver, the el resolver
81       * wrapper for the property resolver and the el resolvers added by
82       * {@link javax.faces.application.Application#addELResolver(ELResolver)}.
83       * The resolvers where only added if they are not null
84       * 
85       * @param resolvers
86       */
87      protected void addFromRuntimeConfig(List<ELResolver> resolvers)
88      {
89          if (_config.getFacesConfigElResolvers() != null)
90          {
91              resolvers.addAll(_config.getFacesConfigElResolvers());
92          }
93  
94          FacesContext facesContext = FacesContext.getCurrentInstance();
95          if (facesContext == null)
96          {
97              // Should not happen, but if by some reason happens,
98              // initialize as usual.
99              if (_config.getVariableResolver() != null)
100             {
101                 resolvers.add(createELResolver(_config.getVariableResolver()));
102             }
103             else if (_config.getVariableResolverChainHead() != null)
104             {
105                 resolvers.add(createELResolver(_config.getVariableResolverChainHead()));
106             }
107 
108             if (_config.getPropertyResolver() != null)
109             {
110                 resolvers.add(createELResolver(_config.getPropertyResolver()));
111             }
112             else if (_config.getPropertyResolverChainHead() != null)
113             {
114                 resolvers.add(createELResolver(_config.getPropertyResolverChainHead()));
115             }
116         }
117         else if (facesContext != null && MyfacesConfig.getCurrentInstance(
118                 facesContext.getExternalContext()).isSupportJSPAndFacesEL())
119         {
120             if (_config.getVariableResolver() != null)
121             {
122                 resolvers.add(createELResolver(_config.getVariableResolver()));
123             }
124             else if (_config.getVariableResolverChainHead() != null)
125             {
126                 resolvers.add(createELResolver(_config.getVariableResolverChainHead()));
127             }
128 
129             if (_config.getPropertyResolver() != null)
130             {
131                 resolvers.add(createELResolver(_config.getPropertyResolver()));
132             }
133             else if (_config.getPropertyResolverChainHead() != null)
134             {
135                 resolvers.add(createELResolver(_config.getPropertyResolverChainHead()));
136             }
137         }
138 
139         if (_config.getApplicationElResolvers() != null)
140         {
141             resolvers.addAll(_config.getApplicationElResolvers());
142         }
143     }
144     
145     /**
146      * Sort the ELResolvers with a custom Comparator provided by the user.
147      * @param resolvers
148      * @param scope scope of ELResolvers (Faces,JSP)  
149      * @since 1.2.10, 2.0.2
150      */
151     @SuppressWarnings("unchecked")
152     protected void sortELResolvers(List<ELResolver> resolvers, Scope scope)
153     {
154         if (_config.getELResolverComparator() != null)
155         {
156             try
157             {
158                 // sort the resolvers
159                 Collections.sort(resolvers, _config.getELResolverComparator());
160                 
161                 if (log.isLoggable(Level.INFO))
162                 {
163                     log.log(Level.INFO, "Chain of EL resolvers for {0} sorted with: {1} and the result order is {2}", 
164                             new Object [] {scope, _config.getELResolverComparator(), resolvers});
165                 }
166             }
167             catch (Exception e)
168             {
169                 log.log(Level.WARNING, 
170                         "Could not sort ELResolvers with custom Comparator", e);
171             }
172         }
173     }
174     
175     /**
176      * Filters the ELResolvers  with a custom Predicate provided by the user.
177      * @param resolvers list of ELResolvers
178      * @param scope scope of ELResolvers (Faces,JSP)
179      * @return Iterable instance of Iterable containing filtered ELResolvers 
180      */
181     protected Iterable<ELResolver> filterELResolvers(List<ELResolver> resolvers, Scope scope)
182     {
183         
184         Predicate<ELResolver> predicate = _config.getELResolverPredicate();
185         if (predicate != null)
186         {
187             try
188             {
189                 // filter the resolvers
190                 resolvers.removeIf(elResolver -> !predicate.test(elResolver));
191 
192                 if (log.isLoggable(Level.INFO))
193                 {
194                     log.log(Level.INFO, "Chain of EL resolvers for {0} filtered with: {1} and the result is {2}", 
195                             new Object [] {scope, predicate, resolvers});
196                 }
197             }
198             catch (Exception e)
199             {
200                 log.log(Level.WARNING, 
201                         "Could not filter ELResolvers with custom Predicate", e);
202             }
203         }
204         return resolvers;
205     }
206     
207     protected ELResolver createELResolver(VariableResolver resolver)
208     {
209         return new VariableResolverToELResolver(resolver);
210     }
211 
212     protected ELResolver createELResolver(PropertyResolver resolver)
213     {
214         return new PropertyResolverToELResolver(resolver);
215     }
216 
217     protected RuntimeConfig getRuntimeConfig()
218     {
219         return _config;
220     }
221     
222     protected boolean isReplaceImplicitObjectResolverWithCDIResolver(FacesContext facesContext)
223     {
224         if (!ExternalSpecifications.isCDIAvailable(facesContext.getExternalContext()))
225         {
226             return false;
227         }
228 
229         BeanManager beanManager = CDIUtils.getBeanManager(facesContext.getExternalContext());
230         if (beanManager != null)
231         {
232             FacesConfigBeanHolder holder = CDIUtils.lookup(beanManager, FacesConfigBeanHolder.class);
233             if (holder != null)
234             {
235                 FacesConfig.Version version = holder.getFacesConfigVersion();
236                 if (version == null)
237                 {
238                     return false;
239                 }
240                 else if (version.ordinal() >= FacesConfig.Version.JSF_2_3.ordinal())
241                 {
242                     return true;
243                 }
244                 else
245                 {
246                     return false;
247                 }
248             }
249         }
250         return false;
251     }
252 }