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 org.apache.commons.logging.Log;
22  import org.apache.commons.logging.LogFactory;
23  import org.apache.commons.discovery.resource.ClassLoaders;
24  import org.apache.commons.discovery.resource.names.DiscoverServiceNames;
25  import org.apache.commons.discovery.ResourceNameIterator;
26  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
27  import org.apache.myfaces.shared_impl.util.ClassUtils;
28  
29  import javax.faces.context.ExternalContext;
30  import javax.naming.Context;
31  import javax.naming.InitialContext;
32  import javax.naming.NamingException;
33  import java.lang.reflect.InvocationTargetException;
34  import java.lang.reflect.Constructor;
35  
36  /*
37   * Date: Mar 12, 2007
38   * Time: 9:53:40 PM
39   */
40  public class DefaultLifecycleProviderFactory extends LifecycleProviderFactory {
41      private static Log log = LogFactory.getLog(DefaultLifecycleProviderFactory.class);
42      public static final String LIFECYCLE_PROVIDER_INSTANCE_KEY = LifecycleProvider.class.getName() + ".LIFECYCLE_PROVIDER_INSTANCE";
43  
44      @JSFWebConfigParam(name="org.apache.myfaces.config.annotation.LifecycleProvider", since="1.1")
45      public static final String LIFECYCLE_PROVIDER = LifecycleProvider.class.getName();
46  
47  
48      public DefaultLifecycleProviderFactory()
49      {
50      }
51  
52      @Override
53      public LifecycleProvider getLifecycleProvider(ExternalContext externalContext)
54      {
55          LifecycleProvider lifecycleProvider = null;
56          if (externalContext == null)
57          {
58              log.info("No ExternalContext using fallback LifecycleProvider.");
59              lifecycleProvider = resolveFallbackLifecycleProvider();
60          }
61          else
62          {
63              lifecycleProvider = (LifecycleProvider) externalContext.getApplicationMap().get(LIFECYCLE_PROVIDER_INSTANCE_KEY);
64          }
65          if (lifecycleProvider == null)
66          {
67              if (!resolveLifecycleProviderFromExternalContext(externalContext))
68              {
69                  if (!resolveLifecycleProviderFromService(externalContext))
70                  {
71                      lifecycleProvider = resolveFallbackLifecycleProvider();
72                      externalContext.getApplicationMap().put(LIFECYCLE_PROVIDER_INSTANCE_KEY, lifecycleProvider);
73                  }
74                  else
75                  {
76                      //Retrieve it because it was resolved
77                      lifecycleProvider = (LifecycleProvider) externalContext.getApplicationMap().get(LIFECYCLE_PROVIDER_INSTANCE_KEY);
78                  }
79              }
80              else
81              {
82                  //Retrieve it because it was resolved
83                  lifecycleProvider = (LifecycleProvider) externalContext.getApplicationMap().get(LIFECYCLE_PROVIDER_INSTANCE_KEY);
84              }
85              log.info("Using LifecycleProvider "+ lifecycleProvider.getClass().getName());
86          }
87          return lifecycleProvider;
88      }
89  
90      @Override
91      public void release() {
92  
93      }
94  
95  
96  
97      private boolean resolveLifecycleProviderFromExternalContext(ExternalContext externalContext)
98      {
99          try
100         {
101             String lifecycleProvider = externalContext.getInitParameter(LIFECYCLE_PROVIDER);
102             if (lifecycleProvider != null)
103             {
104 
105                 Object obj = createClass(lifecycleProvider, externalContext);
106 
107                 if (obj instanceof LifecycleProvider) {
108                     externalContext.getApplicationMap().put(LIFECYCLE_PROVIDER_INSTANCE_KEY, (LifecycleProvider) obj);
109                     return true;
110                 }
111             }
112         }
113         catch (ClassNotFoundException e)
114         {
115             log.error("", e);
116         }
117         catch (InstantiationException e)
118         {
119             log.error("", e);
120         }
121         catch (IllegalAccessException e)
122         {
123             log.error("", e);
124         }
125         catch (InvocationTargetException e)
126         {
127             log.error("", e);
128         }
129         return false;
130     }
131 
132 
133     private boolean resolveLifecycleProviderFromService(ExternalContext externalContext) {
134         ClassLoader classLoader = ClassUtils.getContextClassLoader();
135         ClassLoaders loaders = new ClassLoaders();
136         loaders.put(classLoader);
137         loaders.put(this.getClass().getClassLoader());
138         DiscoverServiceNames dsn = new DiscoverServiceNames(loaders);
139         ResourceNameIterator iter = dsn.findResourceNames(LIFECYCLE_PROVIDER);
140         while (iter.hasNext()) {
141             String className = iter.nextResourceName();
142             try
143             {
144                 Object obj = createClass(className, externalContext);
145                 if (DiscoverableLifecycleProvider.class.isAssignableFrom(obj.getClass())) {
146                     DiscoverableLifecycleProvider discoverableLifecycleProvider =
147                             (DiscoverableLifecycleProvider) obj;
148                     if (discoverableLifecycleProvider.isAvailable()) {
149                         externalContext.getApplicationMap().put(LIFECYCLE_PROVIDER_INSTANCE_KEY, discoverableLifecycleProvider);
150                         return true;
151                     }
152                 }
153             }
154             catch (ClassNotFoundException e)
155             {
156                 // ignore
157             }
158             catch (NoClassDefFoundError e)
159             {
160                 // ignore
161             }
162             catch (InstantiationException e)
163             {
164                 log.error("", e);
165             }
166             catch (IllegalAccessException e)
167             {
168                 log.error("", e);
169             }
170             catch (InvocationTargetException e)
171             {
172                 log.error("", e);
173             }
174         }
175         return false;
176     }
177 
178     private Object createClass(String className, ExternalContext externalContext)
179             throws InstantiationException, IllegalAccessException, InvocationTargetException, ClassNotFoundException
180     {
181         Class clazz = ClassUtils.classForName(className);
182 
183         Object obj;
184         try
185         {
186             Constructor constructor = clazz.getConstructor(ExternalContext.class);
187             obj = constructor.newInstance(externalContext);
188         }
189         catch (NoSuchMethodException e)
190         {
191             obj = clazz.newInstance();
192         }
193         return obj;
194     }
195 
196 
197     private LifecycleProvider resolveFallbackLifecycleProvider()
198     {
199         try
200         {
201                 ClassUtils.classForName("javax.annotation.PreDestroy");
202         }
203         catch (ClassNotFoundException e)
204         {
205             // no annotation available don't process annotations
206             return new NoAnnotationLifecyleProvider(); 
207         }
208         Context context;
209         try
210         {
211             context = new InitialContext();
212             try
213             {
214                 ClassUtils.classForName("javax.ejb.EJB");
215                 // Asume full JEE 5 container
216                 return new AllAnnotationLifecycleProvider(context);
217             }
218             catch (ClassNotFoundException e)
219             {
220                 // something else
221                 return new ResourceAnnotationLifecycleProvider(context);
222             }
223         }
224         catch (NamingException e)
225         {
226             // no initial context available no injection
227             log.error("No InitialContext found. Using NoInjectionAnnotationProcessor.", e);
228             return new NoInjectionAnnotationLifecycleProvider();
229         }
230     }
231 }