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.spi.impl;
20  
21  import java.lang.reflect.InvocationTargetException;
22  import java.lang.reflect.Method;
23  import java.util.Map;
24  import java.util.WeakHashMap;
25  import javax.faces.context.ExternalContext;
26  import javax.faces.context.FacesContext;
27  import javax.naming.NamingException;
28  
29  import org.apache.myfaces.shared.util.ClassUtils;
30  import org.apache.myfaces.spi.InjectionProvider;
31  import org.apache.myfaces.spi.InjectionProviderException;
32  import org.apache.myfaces.util.ExternalSpecifications;
33  import org.apache.tomcat.InstanceManager;
34  
35  /**
36   * An annotation lifecycle provider for Tomcat 7.
37   */
38  public class Tomcat7AnnotationInjectionProvider extends InjectionProvider
39  {
40  
41      private WeakHashMap<ClassLoader, InstanceManager> instanceManagers = null;
42  
43      public Tomcat7AnnotationInjectionProvider(ExternalContext externalContext)
44      {
45          instanceManagers = new WeakHashMap<ClassLoader, InstanceManager>();
46      }
47  
48      @Override
49      public Object inject(Object instance) throws InjectionProviderException
50      {
51          return null;
52      }
53  
54      @Override
55      public void preDestroy(Object instance, Object creationMetaData) throws InjectionProviderException
56      {
57          InstanceManager manager = instanceManagers
58                  .get(ClassUtils.getContextClassLoader());
59  
60          if (manager != null)
61          {
62              try
63              {
64                  manager.destroyInstance(instance);
65              }
66              catch (IllegalAccessException ex)
67              {
68                  throw new InjectionProviderException(ex);
69              }
70              catch (InvocationTargetException ex)
71              {
72                  throw new InjectionProviderException(ex);
73              }
74          }
75      }
76  
77      @Override
78      public void postConstruct(Object instance, Object creationMetaData) throws InjectionProviderException
79      {
80          InstanceManager manager = instanceManagers
81                  .get(ClassUtils.getContextClassLoader());
82          if (manager == null)
83          {
84              //Initialize manager
85              manager = initManager();
86          }
87  
88          //Is initialized
89          if (manager != null)
90          {
91              //Inject resources
92              try 
93              {
94                  manager.newInstance(instance);
95              }
96              catch (IllegalAccessException ex)
97              {
98                  throw new InjectionProviderException(ex);
99              }
100             catch (InvocationTargetException ex)
101             {
102                 throw new InjectionProviderException(ex);
103             }
104             catch (NamingException e)
105             {
106                 throw new InjectionProviderException(e);
107             }
108         }
109     }
110 
111     @Override
112     public boolean isAvailable()
113     {
114         try
115         {
116             Class c = Class.forName("org.apache.tomcat.InstanceManager",
117                     true, ClassUtils.getContextClassLoader());
118             if (c != null)
119             {
120                 // Tomcat 7 Available, check CDI integration. If there is no CDI available,
121                 // things goes as usual just connect to the server. If CDI is available,
122                 // the injection provider should check if we can inject a bean through tomcat
123                 // otherwise, we need to prefer an integration against CDI, and from CDI to
124                 // the underlying server.
125                 FacesContext facesContext = FacesContext.getCurrentInstance();
126                 if (ExternalSpecifications.isCDIAvailable(facesContext.getExternalContext()))
127                 {
128                     
129                     ExternalContext extCtx = facesContext.getExternalContext();
130                     Map<String, Object> applicationMap = extCtx.getApplicationMap();
131                     InstanceManager instanceManager = (InstanceManager)
132                             applicationMap.get(InstanceManager.class.getName());                    
133                     
134                     Class clazz = ClassUtils.classForName(
135                         "org.apache.myfaces.cdi.checkenv.DummyInjectableBean");
136                     Object dummyInjectableBean = clazz.newInstance();
137  
138                     instanceManager.newInstance(dummyInjectableBean);
139                     
140                     Method m = clazz.getDeclaredMethod("isDummyBeanInjected");
141                     Object value = m.invoke(dummyInjectableBean);
142                     if (Boolean.TRUE.equals(value))
143                     {
144                         // Bean is injectable. We can use this approach.
145                         return true;
146                     }
147                     else
148                     {
149                         // Bean is not injectable with this method. We should try to 
150                         // inject using CDI Injection Provider. Theorically CDI 
151                         // has a similar code to integrate with the underlying web server.
152                         return false;
153                     }
154                 }
155             }
156             return true;
157         }
158         catch (Exception e)
159         {
160             // ignore
161         }
162         return false;
163     }
164 
165     private InstanceManager initManager()
166     {
167         FacesContext context = FacesContext.getCurrentInstance();
168         if (context == null)
169         {
170             return null;
171         }
172 
173         ExternalContext extCtx = context.getExternalContext();
174         if (extCtx == null)
175         {
176             return null;
177         }
178 
179         // get application map to access ServletContext attributes
180         Map<String, Object> applicationMap = extCtx.getApplicationMap();
181 
182         InstanceManager instanceManager = (InstanceManager)
183                 applicationMap.get(InstanceManager.class.getName());
184         if (instanceManager != null)
185         {
186             instanceManagers.put(ClassUtils.getContextClassLoader(),
187                     instanceManager);
188         }
189 
190         return instanceManager;
191     }
192 
193 }