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.lang.reflect.Field;
22  import java.util.logging.Level;
23  import java.util.logging.Logger;
24  
25  import javax.faces.FacesException;
26  import javax.faces.FactoryFinder;
27  import javax.faces.application.ApplicationFactory;
28  import javax.faces.context.ExceptionHandlerFactory;
29  import javax.faces.context.ExternalContext;
30  import javax.faces.context.ExternalContextFactory;
31  import javax.faces.context.FacesContext;
32  import javax.faces.context.FacesContextFactory;
33  import javax.faces.context.PartialViewContextFactory;
34  import javax.faces.lifecycle.Lifecycle;
35  import javax.faces.render.RenderKitFactory;
36  
37  import org.apache.myfaces.context.servlet.FacesContextImpl;
38  import org.apache.myfaces.shared.util.ClassUtils;
39  
40  /**
41   * DOCUMENT ME!
42   * 
43   * @author Manfred Geiler (latest modification by $Author$)
44   * @version $Revision$ $Date$
45   */
46  public class FacesContextFactoryImpl extends FacesContextFactory
47      implements ReleaseableFacesContextFactory
48  {
49      //private static final Log log = LogFactory.getLog(FacesContextFactoryImpl.class);
50      private static final Logger log = Logger.getLogger(FacesContextFactoryImpl.class.getName());
51      
52      /**
53       * Reference to factory to prevent unnecessary lookups
54       */
55      private final ExternalContextFactory _externalContextFactory;
56      
57      /**
58       * Reference to factory to prevent unnecessary lookups
59       */
60      private final ExceptionHandlerFactory _exceptionHandlerFactory;
61      
62      private final ApplicationFactory _applicationFactory;
63      
64      private final RenderKitFactory _renderKitFactory;
65      
66      private final PartialViewContextFactory _partialViewContextFactory;
67      
68      /**
69       * This var is assigned as the same as javax.faces.context.ExternalContext._firstInstance,
70       * and since it is a static reference and does not change, we can cache it here safely.
71       * 
72       * We need
73       */
74      private final ThreadLocal<ExternalContext> _firstExternalContextInstance;
75      
76      @SuppressWarnings("unchecked")
77      public FacesContextFactoryImpl()
78      {
79          super();
80          ThreadLocal<ExternalContext> firstExternalContextInstance = null;
81          try
82          {
83              Class clazz = ClassUtils.classForName("javax.faces.context._MyFacesExternalContextHelper");
84              Field externalContextFirstInstance = clazz.getDeclaredField("firstInstance");
85              externalContextFirstInstance.setAccessible(true);
86              
87              if (externalContextFirstInstance != null)
88              {
89                  if (firstExternalContextInstance == null)
90                  {
91                      firstExternalContextInstance = 
92                          (ThreadLocal<ExternalContext>) externalContextFirstInstance.get(null);
93                  }
94              }
95          }
96          catch (SecurityException e)
97          {
98              // It could happen, but we can ignore it.
99              if (log.isLoggable(Level.FINE))
100             {
101                 log.log(Level.FINE, "Cannot access field firstInstance"
102                         + "from _MyFacesExternalContextHelper ", e);
103             }
104         }
105         catch (Exception e)
106         {
107             if (log.isLoggable(Level.SEVERE))
108             {
109                 log.log(Level.SEVERE, "Cannot find field firstInstance"
110                         + "from _MyFacesExternalContextHelper ", e);
111             }
112         }
113         
114         _firstExternalContextInstance = firstExternalContextInstance;
115         
116         _externalContextFactory = (ExternalContextFactory)
117             FactoryFinder.getFactory(FactoryFinder.EXTERNAL_CONTEXT_FACTORY);
118 
119         _exceptionHandlerFactory = (ExceptionHandlerFactory)
120             FactoryFinder.getFactory(FactoryFinder.EXCEPTION_HANDLER_FACTORY);
121         
122         _applicationFactory = (ApplicationFactory)
123             FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY);
124         
125         _renderKitFactory = (RenderKitFactory)
126             FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
127 
128         _partialViewContextFactory = (PartialViewContextFactory) 
129             FactoryFinder.getFactory(FactoryFinder.PARTIAL_VIEW_CONTEXT_FACTORY);
130     }
131 
132     @Override
133     public FacesContext getFacesContext(Object context, Object request, Object response, Lifecycle lifecycle)
134         throws FacesException
135     {
136         if (context == null)
137         {
138             throw new NullPointerException("context");
139         }
140         if (request == null)
141         {
142             throw new NullPointerException("request");
143         }
144         if (response == null)
145         {
146             throw new NullPointerException("response");
147         }
148         if (lifecycle == null)
149         {
150             throw new NullPointerException("lifecycle");
151         }
152         
153         ExternalContext externalContext = _externalContextFactory.getExternalContext(context, request, response);
154 
155         ExternalContext defaultExternalContext = null;
156         
157         if (_firstExternalContextInstance != null)
158         {
159             defaultExternalContext = (ExternalContext)
160                 externalContext.getRequestMap().remove(
161                         ExternalContextFactoryImpl.EXTERNAL_CONTEXT_KEY);
162             
163             if (defaultExternalContext != null)
164             {
165                 // Initialize the firstExternalContext that old jsf 1.2 or lower
166                 // implementations of ExternalContext should fall when call jsf 2.0
167                 // methods.
168                 _firstExternalContextInstance.set(defaultExternalContext);
169             }
170         }
171         
172         //if (context instanceof ServletContext)
173         //{
174             FacesContext facesContext;
175             if (externalContext instanceof ReleaseableExternalContext)
176             {
177                 facesContext = new FacesContextImpl(externalContext, (ReleaseableExternalContext) externalContext,
178                                                     this, _applicationFactory, _renderKitFactory, 
179                                                     _partialViewContextFactory);
180             }
181             else if (defaultExternalContext != null && defaultExternalContext instanceof ReleaseableExternalContext)
182             {
183                 facesContext = new FacesContextImpl(externalContext,
184                                                     (ReleaseableExternalContext) defaultExternalContext, this,
185                                                     _applicationFactory, _renderKitFactory, 
186                                                     _partialViewContextFactory);
187             }
188             else
189             {
190                 facesContext = new FacesContextImpl(externalContext, null, this,
191                                                     _applicationFactory, _renderKitFactory, 
192                                                     _partialViewContextFactory);
193             }
194             
195             facesContext.setExceptionHandler(_exceptionHandlerFactory.getExceptionHandler());
196             
197             return facesContext;
198             //return new FacesContextImpl((ServletContext)context, (ServletRequest)request, (ServletResponse)response);
199         //}
200 
201         //throw new FacesException("Unsupported context type " + context.getClass().getName());
202     }
203 
204     public void release()
205     {
206         if (_firstExternalContextInstance != null)
207         {
208             _firstExternalContextInstance.remove();
209         }
210     }
211 }