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.config.annotation;
20  
21  import java.lang.reflect.InvocationTargetException;
22  import java.security.AccessController;
23  import java.security.PrivilegedActionException;
24  import java.util.Iterator;
25  import java.util.List;
26  import java.util.logging.Level;
27  import java.util.logging.Logger;
28  
29  import javax.faces.FacesException;
30  import javax.faces.context.ExternalContext;
31  import javax.naming.Context;
32  import javax.naming.InitialContext;
33  import javax.naming.NamingException;
34  
35  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
36  import org.apache.myfaces.shared.util.ClassUtils;
37  import org.apache.myfaces.spi.ServiceProviderFinderFactory;
38  
39  /*
40   * Date: Mar 12, 2007
41   * Time: 9:53:40 PM
42   */
43  public class DefaultLifecycleProviderFactory extends LifecycleProviderFactory {
44      //private static Log log = LogFactory.getLog(DefaultLifecycleProviderFactory.class);
45      private static Logger log = Logger.getLogger(DefaultLifecycleProviderFactory.class.getName());
46  
47      /**
48       * Define the class implementing LifecycleProvider2 interface to handle PostConstruct and PreDestroy annotations.
49       * 
50       * <p>This also can be configured using a SPI entry (/META-INF/services/...).
51       * </p>
52       */
53      public static final String LIFECYCLE_PROVIDER_INSTANCE_KEY = LifecycleProvider.class.getName() + ".LIFECYCLE_PROVIDER_INSTANCE";
54  
55      @JSFWebConfigParam(name="org.apache.myfaces.config.annotation.LifecycleProvider", since="1.1")
56      public static final String LIFECYCLE_PROVIDER = LifecycleProvider.class.getName();
57  
58  
59      public DefaultLifecycleProviderFactory()
60      {
61      }
62  
63      @Override
64      public LifecycleProvider getLifecycleProvider(ExternalContext externalContext)
65      {
66          LifecycleProvider lifecycleProvider = null;
67          if (externalContext == null)
68          {
69              // Really in jsf 2.0, this will not happen, because a Startup/Shutdown
70              // FacesContext and ExternalContext are provided on initialization and shutdown,
71              // and in other scenarios the real FacesContext/ExternalContext is provided.
72              log.info("No ExternalContext using fallback LifecycleProvider.");
73              lifecycleProvider = resolveFallbackLifecycleProvider();
74          }
75          else
76          {
77              lifecycleProvider = (LifecycleProvider) externalContext.getApplicationMap().get(LIFECYCLE_PROVIDER_INSTANCE_KEY);
78          }
79          if (lifecycleProvider == null)
80          {
81              if (!resolveLifecycleProviderFromExternalContext(externalContext))
82              {
83                  if (!resolveLifecycleProviderFromService(externalContext))
84                  {
85                      lifecycleProvider = resolveFallbackLifecycleProvider();
86                      externalContext.getApplicationMap().put(LIFECYCLE_PROVIDER_INSTANCE_KEY, lifecycleProvider);
87                  }
88                  else
89                  {
90                      //Retrieve it because it was resolved
91                      lifecycleProvider = (LifecycleProvider) externalContext.getApplicationMap().get(LIFECYCLE_PROVIDER_INSTANCE_KEY);
92                  }
93              }
94              else
95              {
96                  //Retrieve it because it was resolved
97                  lifecycleProvider = (LifecycleProvider) externalContext.getApplicationMap().get(LIFECYCLE_PROVIDER_INSTANCE_KEY);
98              }
99              log.info("Using LifecycleProvider "+ lifecycleProvider.getClass().getName());
100         }
101         return lifecycleProvider;
102     }
103 
104     @Override
105     public void release() {
106 
107     }
108 
109 
110 
111     private boolean resolveLifecycleProviderFromExternalContext(ExternalContext externalContext)
112     {
113         try
114         {
115             String lifecycleProvider = externalContext.getInitParameter(LIFECYCLE_PROVIDER);
116             if (lifecycleProvider != null)
117             {
118 
119                 Object obj = createClass(lifecycleProvider, externalContext);
120 
121                 if (obj instanceof LifecycleProvider) {
122                     externalContext.getApplicationMap().put(LIFECYCLE_PROVIDER_INSTANCE_KEY, (LifecycleProvider) obj);
123                     return true;
124                 }
125             }
126         }
127         catch (ClassNotFoundException e)
128         {
129             log.log(Level.SEVERE, "", e);
130         }
131         catch (InstantiationException e)
132         {
133             log.log(Level.SEVERE, "", e);
134         }
135         catch (IllegalAccessException e)
136         {
137             log.log(Level.SEVERE, "", e);
138         }
139         catch (InvocationTargetException e)
140         {
141             log.log(Level.SEVERE, "", e);
142         }
143         return false;
144     }
145 
146 
147     private boolean resolveLifecycleProviderFromService(
148             ExternalContext externalContext)
149     {
150         boolean returnValue = false;
151         final ExternalContext extContext = externalContext;
152         try
153         {
154             if (System.getSecurityManager() != null)
155             {
156                 returnValue = AccessController.doPrivileged(new java.security.PrivilegedExceptionAction<Boolean>()
157                         {
158                             public Boolean run() throws ClassNotFoundException,
159                                     NoClassDefFoundError,
160                                     InstantiationException,
161                                     IllegalAccessException,
162                                     InvocationTargetException,
163                                     PrivilegedActionException
164                             {
165                                 List<String> classList = ServiceProviderFinderFactory.getServiceProviderFinder(extContext).getServiceProviderList(LIFECYCLE_PROVIDER);
166                                 Iterator<String> iter = classList.iterator();
167                                 while (iter.hasNext())
168                                 {
169                                     String className = iter.next();
170                                     Object obj = createClass(className,extContext);
171                                     if (DiscoverableLifecycleProvider.class.isAssignableFrom(obj.getClass()))
172                                     {
173                                         DiscoverableLifecycleProvider discoverableLifecycleProvider = (DiscoverableLifecycleProvider) obj;
174                                         if (discoverableLifecycleProvider.isAvailable())
175                                         {
176                                             extContext.getApplicationMap().put(LIFECYCLE_PROVIDER_INSTANCE_KEY, discoverableLifecycleProvider);
177                                             return (Boolean) true;
178                                         }
179                                     }
180                                 }
181                                 return (Boolean) false;
182                             }
183                         });
184             }
185             else
186             {
187                 List<String> classList = ServiceProviderFinderFactory.getServiceProviderFinder(extContext).getServiceProviderList(LIFECYCLE_PROVIDER);
188                 Iterator<String> iter = classList.iterator();
189                 while (iter.hasNext())
190                 {
191                     String className = iter.next();
192                     Object obj = createClass(className,extContext);
193                     if (DiscoverableLifecycleProvider.class.isAssignableFrom(obj.getClass()))
194                     {
195                         DiscoverableLifecycleProvider discoverableLifecycleProvider = (DiscoverableLifecycleProvider) obj;
196                         if (discoverableLifecycleProvider.isAvailable())
197                         {
198                             extContext.getApplicationMap().put(LIFECYCLE_PROVIDER_INSTANCE_KEY, discoverableLifecycleProvider);
199                             return (Boolean) true;
200                         }
201                     }
202                 }
203             }
204         }
205         catch (ClassNotFoundException e)
206         {
207             // ignore
208         }
209         catch (NoClassDefFoundError e)
210         {
211             // ignore
212         }
213         catch (InstantiationException e)
214         {
215             log.log(Level.SEVERE, "", e);
216         }
217         catch (IllegalAccessException e)
218         {
219             log.log(Level.SEVERE, "", e);
220         }
221         catch (InvocationTargetException e)
222         {
223             log.log(Level.SEVERE, "", e);
224         }
225         catch (PrivilegedActionException e)
226         {
227             throw new FacesException(e);
228         }
229         return returnValue;
230     }
231 
232     private Object createClass(String className, ExternalContext externalContext)
233             throws InstantiationException, IllegalAccessException, InvocationTargetException, ClassNotFoundException
234     {
235         Class<?> clazz = ClassUtils.classForName(className);
236 
237         try
238         {
239             return ClassUtils.newInstance(clazz, new Class<?>[]{ ExternalContext.class }, externalContext);
240         }
241         catch (NoSuchMethodException e)
242         {
243             return ClassUtils.newInstance(clazz);
244         }
245     }
246 
247 
248     private LifecycleProvider resolveFallbackLifecycleProvider()
249     {
250         try
251         {
252                 ClassUtils.classForName("javax.annotation.PreDestroy");
253         }
254         catch (ClassNotFoundException e)
255         {
256             // no annotation available don't process annotations
257             return new NoAnnotationLifecyleProvider(); 
258         }
259         Context context;
260         try
261         {
262             context = new InitialContext();
263             try
264             {
265                 ClassUtils.classForName("javax.ejb.EJB");
266                 // Asume full JEE 5 container
267                 return new AllAnnotationLifecycleProvider(context);
268             }
269             catch (ClassNotFoundException e)
270             {
271                 // something else
272                 return new ResourceAnnotationLifecycleProvider(context);
273             }
274         }
275         catch (NamingException e)
276         {
277             // no initial context available no injection
278             log.log(Level.SEVERE, "No InitialContext found. Using NoInjectionAnnotationProcessor.", e);
279             return new NoInjectionAnnotationLifecycleProvider();
280         }
281     }
282 }