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.resolver;
20  
21  import java.beans.FeatureDescriptor;
22  import java.util.Iterator;
23  
24  import javax.el.ELContext;
25  import javax.el.ELException;
26  import javax.el.ELResolver;
27  import javax.faces.application.Resource;
28  import javax.faces.application.ResourceHandler;
29  import javax.faces.component.UIComponent;
30  import javax.faces.context.FacesContext;
31  import javax.faces.view.Location;
32  import org.apache.myfaces.shared.renderkit.html.util.ResourceUtils;
33  import org.apache.myfaces.shared.resource.ContractResource;
34  
35  import org.apache.myfaces.view.facelets.el.CompositeComponentELUtils;
36  import org.apache.myfaces.view.facelets.el.ResourceELUtils;
37  
38  /**
39   * See JSF 2.0 spec section 5.6.1.3 and 5.6.2.4
40   * 
41   * @author Leonardo Uribe
42   *
43   */
44  public final class ResourceResolver extends ELResolver
45  {
46  
47      private static final String LIBRARY_THIS = "this";
48      
49      /** Creates a new instance of ResourceBundleResolver */
50      public ResourceResolver()
51      {
52      }
53  
54      @Override
55      public Class<?> getCommonPropertyType(final ELContext context,
56              final Object base)
57      {
58          return base == null ? Object.class : null;
59      }
60  
61      @Override
62      public Iterator<FeatureDescriptor> getFeatureDescriptors(
63              final ELContext context, final Object base)
64      {
65          return null;
66      }
67  
68      @Override
69      public Class<?> getType(final ELContext context, final Object base,
70              final Object property)
71      {
72          return null;
73      }
74  
75      @Override
76      public Object getValue(final ELContext context, final Object base,
77              final Object property)
78      {
79          if (base != null && property != null && base instanceof ResourceHandler)
80          {
81              String reference = (String) property;
82              int colonIndex = (reference).indexOf(':');
83              Resource resource;
84              
85              if (colonIndex == -1)
86              {
87                  // No library name, just create as a simple resource.
88                  
89                  resource = ((ResourceHandler) base).createResource (reference);
90              }
91              
92              else
93              {
94                  String contractName = null;
95                  if (reference.lastIndexOf (':') != colonIndex)
96                  {
97                      // Max of one ":" allowed, so throw an exception.
98                      
99                      throw new ELException ("Malformed resource reference found when " +
100                         "resolving " + property);
101                 }
102                 
103                 else
104                 {
105                     // Otherwise, portion before the ":" is the library name.
106                     String libraryName = reference.substring (0, colonIndex);
107                     FacesContext facesContext = facesContext(context);
108                     
109                     if (LIBRARY_THIS.equals(libraryName))
110                     {
111                         // note in this case we don't need to resolve to an specific 
112                         // composite component, instead we need to find the libraryName of the
113                         // composite component associated with the Location. For any composite component
114                         // instance that is created under the same facelet it will be the same,
115                         // so it is enought to get the first one matching the Location object.
116                         Location location = ResourceELUtils.getResourceLocationForResolver(facesContext);
117                         if (location != null)
118                         {
119                             // There are two options:
120                             UIComponent cc = CompositeComponentELUtils.
121                                     getCompositeComponentBasedOnLocation(facesContext, location);
122                             Resource ccResource = (Resource) cc.getAttributes().get(
123                                     Resource.COMPONENT_RESOURCE_KEY); 
124                             libraryName = ccResource.getLibraryName();
125                             contractName = ResourceUtils.getContractName(ccResource);
126                         }
127                         else
128                         {
129                             // JSF 2.2 "this" identifier can refer to a library or contract.
130                             libraryName = ResourceELUtils.getResourceLibraryForResolver(facesContext);
131                             contractName = ResourceELUtils.getResourceContractForResolver(facesContext);
132                         }
133                     }
134                     
135                     try
136                     {
137                         if (contractName != null)
138                         {
139                             facesContext.getAttributes().put(ContractResource.CONTRACT_SELECTED, contractName);
140                         }
141                         resource = ((ResourceHandler) base).createResource(reference.substring(colonIndex+1),
142                                 libraryName);
143                     }
144                     finally
145                     {
146                         if (contractName != null)
147                         {
148                             facesContext.getAttributes().remove(ContractResource.CONTRACT_SELECTED);
149                         }
150                     }
151                 }
152             }
153             
154             context.setPropertyResolved(true);
155             if (resource != null)
156             {
157                 return resource.getRequestPath();
158             }
159         }
160         return null;
161     }
162     
163     // get the FacesContext from the ELContext
164     private static FacesContext facesContext(final ELContext context)
165     {
166         return (FacesContext)context.getContext(FacesContext.class);
167     }
168 
169     @Override
170     public boolean isReadOnly(final ELContext context, final Object base,
171             final Object property)
172     {
173         //Return false on all cases
174         return false;
175     }
176 
177     @Override
178     public void setValue(final ELContext context, final Object base,
179             final Object property, final Object val)
180     {
181         //No action takes place
182     }
183 
184 }