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.context;
20  
21  import java.util.ArrayList;
22  import java.util.Collections;
23  import java.util.EnumSet;
24  import java.util.HashMap;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.Set;
28  
29  import javax.faces.application.ResourceDependency;
30  import javax.faces.component.UIComponent;
31  import javax.faces.component.UIViewRoot;
32  import javax.faces.component.visit.VisitCallback;
33  import javax.faces.component.visit.VisitContext;
34  import javax.faces.component.visit.VisitHint;
35  import javax.faces.component.visit.VisitResult;
36  import javax.faces.context.FacesContext;
37  
38  /**
39   *
40   * @author  Leonardo Uribe (latest modification by $Author$)
41   * @version $Revision$ $Date$
42   * @since 2.0.2
43   */
44  public class RequestViewContext
45  {
46  
47      public static final String VIEW_CONTEXT_KEY = "oam.VIEW_CONTEXT";
48      
49      public static final String RESOURCE_DEPENDENCY_INSPECTED_CLASS = "oam.RDClass";
50      
51      private static final String SKIP_ITERATION_HINT = "javax.faces.visit.SKIP_ITERATION";
52      
53      private static final Set<VisitHint> VISIT_HINTS = Collections.unmodifiableSet( 
54              EnumSet.of(VisitHint.SKIP_ITERATION));
55  
56      private RequestViewMetadata requestViewMetadata;
57      
58      private Map<String, Boolean> renderTargetMap = null;
59      private Map<String, List<UIComponent>> renderTargetMapComponents = null;
60      
61      public RequestViewContext()
62      {
63          this.requestViewMetadata = new RequestViewMetadata();
64      }
65      
66      public RequestViewContext(RequestViewMetadata rvm)
67      {
68          this.requestViewMetadata = new RequestViewMetadata();
69      }
70  
71      static public RequestViewContext getCurrentInstance()
72      {
73          FacesContext ctx = FacesContext.getCurrentInstance();
74          return getCurrentInstance(ctx);
75      }
76      
77      static public RequestViewContext getCurrentInstance(FacesContext ctx)
78      {
79          return getCurrentInstance(ctx, ctx.getViewRoot());
80      }
81      
82      @SuppressWarnings("unchecked")
83      static public RequestViewContext getCurrentInstance(FacesContext ctx, UIViewRoot root)
84      {
85          Map<UIViewRoot, RequestViewContext> map
86                  = (Map<UIViewRoot, RequestViewContext>) ctx.getAttributes().get(VIEW_CONTEXT_KEY);
87          RequestViewContext rvc = null;        
88          if (map == null)
89          {
90              map = new HashMap<UIViewRoot, RequestViewContext>();
91              rvc = new RequestViewContext();
92              map.put(root, rvc);
93              ctx.getAttributes().put(VIEW_CONTEXT_KEY, map);
94              return rvc;
95          }
96          else
97          {
98              rvc = map.get(root); 
99              if (rvc == null)
100             {
101                 rvc = new RequestViewContext();
102                 map.put(root, rvc);
103             }
104             return rvc;
105         }
106     }
107     
108     static public RequestViewContext getCurrentInstance(FacesContext ctx, UIViewRoot root, boolean create)
109     {
110         if (create)
111         {
112             return getCurrentInstance(ctx, root);
113         }
114         Map<UIViewRoot, RequestViewContext> map
115                 = (Map<UIViewRoot, RequestViewContext>) ctx.getAttributes().get(VIEW_CONTEXT_KEY);
116         if (map != null)
117         {
118             return map.get(root);
119         }
120         return null;
121     }
122     
123     static public RequestViewContext newInstance(RequestViewMetadata rvm)
124     {
125         RequestViewContext clone = new RequestViewContext(rvm.cloneInstance());
126         return clone;
127     }
128     
129     static public void setCurrentInstance(FacesContext ctx, UIViewRoot root, RequestViewContext rvc)
130     {
131         Map<UIViewRoot, RequestViewContext> map
132                 = (Map<UIViewRoot, RequestViewContext>) ctx.getAttributes().get(VIEW_CONTEXT_KEY);
133         if (map == null)
134         {
135             map = new HashMap<UIViewRoot, RequestViewContext>();
136             rvc = new RequestViewContext();
137             map.put(root, rvc);
138             ctx.getAttributes().put(VIEW_CONTEXT_KEY, map);
139         }
140         else
141         {
142             map.put(root, rvc);
143         }
144     }
145 
146     public boolean isResourceDependencyAlreadyProcessed(ResourceDependency dependency)
147     {
148         return requestViewMetadata.isResourceDependencyAlreadyProcessed(dependency);
149     }
150     
151     public void setResourceDependencyAsProcessed(ResourceDependency dependency)
152     {
153         requestViewMetadata.setResourceDependencyAsProcessed(dependency);
154     }
155 
156     public boolean isClassAlreadyProcessed(Class<?> inspectedClass)
157     {
158         return requestViewMetadata.isClassAlreadyProcessed(inspectedClass);
159     }
160 
161     public void setClassProcessed(Class<?> inspectedClass)
162     {
163         requestViewMetadata.setClassProcessed(inspectedClass);
164     }
165     
166     public boolean isRenderTarget(String target)
167     {
168         if (renderTargetMap != null)
169         {
170             return Boolean.TRUE.equals(renderTargetMap.get(target));
171         }
172         return false;
173     }
174     
175     public void setRenderTarget(String target, boolean value, UIComponent component)
176     {
177         if (renderTargetMap == null)
178         {
179             renderTargetMap = new HashMap<String, Boolean>(8);
180         }
181         renderTargetMap.put(target, value);
182         if (renderTargetMapComponents == null)
183         {
184             renderTargetMapComponents = new HashMap<String, List<UIComponent>>(8);
185         }
186         List<UIComponent> componentList = renderTargetMapComponents.get(target);
187         if (componentList == null)
188         {
189             componentList = new ArrayList<UIComponent>(8);
190             renderTargetMapComponents.put(target, componentList);
191         }
192         if (!componentList.contains(component))
193         {
194             componentList.add(component);
195         }
196     }
197     
198     public List<UIComponent> getRenderTargetComponentList(String target)
199     {
200         if (renderTargetMapComponents == null)
201         {
202             return Collections.emptyList();
203         }
204         List<UIComponent> list = renderTargetMapComponents.get(target);
205         return list != null ? list : Collections.emptyList();
206     }
207     
208     /**
209      * Scans UIViewRoot facets with added component resources by the effect of
210      * ResourceDependency annotation, and register the associated inspected classes
211      * so new component resources will not be added to the component tree again and again.
212      * 
213      * @param facesContext
214      * @param root 
215      */
216     public void refreshRequestViewContext(FacesContext facesContext, UIViewRoot root)
217     {
218         for (Map.Entry<String, UIComponent> entry : root.getFacets().entrySet())
219         {
220             UIComponent facet = entry.getValue();
221             if (facet.getId() != null && facet.getId().startsWith("javax_faces_location_"))
222             {
223                 try
224                 {
225                     facesContext.getAttributes().put(SKIP_ITERATION_HINT, Boolean.TRUE);
226 
227                     VisitContext visitContext = VisitContext.createVisitContext(facesContext, null, VISIT_HINTS);
228                     facet.visitTree(visitContext, new RefreshViewContext());
229                 }
230                 finally
231                 {
232                     // We must remove hint in finally, because an exception can break this phase,
233                     // but lifecycle can continue, if custom exception handler swallows the exception
234                     facesContext.getAttributes().remove(SKIP_ITERATION_HINT);
235                 }
236             }
237         }
238     }
239     
240     private class RefreshViewContext implements VisitCallback
241     {
242         @Override
243         public VisitResult visit(VisitContext context, UIComponent target)
244         {
245             Class<?> inspectedClass = (Class<?>)target.getAttributes().get(RESOURCE_DEPENDENCY_INSPECTED_CLASS);
246             if (inspectedClass != null)
247             {
248                 setClassProcessed(inspectedClass);
249             }            
250             return VisitResult.ACCEPT;
251         }
252     }
253     
254     public RequestViewMetadata getRequestViewMetadata()
255     {
256         return requestViewMetadata;
257     }
258 
259     /**
260      * @param requestViewMetadata the requestViewMetadata to set
261      */
262     public void setRequestViewMetadata(RequestViewMetadata requestViewMetadata)
263     {
264         this.requestViewMetadata = requestViewMetadata;
265     }
266 }