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