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 javax.naming.NamingException;
22  import javax.naming.Context;
23  import javax.annotation.Resource;
24  import java.lang.reflect.Method;
25  import java.lang.reflect.InvocationTargetException;
26  import java.lang.reflect.Field;
27  
28  // TODO @Resources
29  public class ResourceAnnotationLifecycleProvider extends NoInjectionAnnotationLifecycleProvider
30  {
31  
32      protected Context context;
33      private static final String JAVA_COMP_ENV = "java:comp/env/";
34  
35      public ResourceAnnotationLifecycleProvider(Context context)
36      {
37          this.context = context;
38      }
39  
40  
41      /**
42       * Inject resources in specified instance.
43       */
44      protected void processAnnotations(Object instance)
45              throws IllegalAccessException, InvocationTargetException, NamingException
46      {
47  
48          if (context == null)
49          {
50              // No resource injection
51              return;
52          }
53  
54          checkAnnotation(instance.getClass(), instance);
55  
56          /* TODO the servlet spec is not clear about searching in superclass??
57           * May be only check non private fields and methods
58           * for @Resource (JSR 250), if used all superclasses MUST be examined
59           * to discover all uses of this annotation.
60  
61          Class superclass = instance.getClass().getSuperclass();
62          while (superclass != null && (!superclass.equals(Object.class)))
63          {
64              checkAnnotation(superclass, instance);
65              superclass = superclass.getSuperclass();
66          } */
67      }
68  
69      private void checkAnnotation(Class clazz, Object instance)
70              throws NamingException, IllegalAccessException, InvocationTargetException
71      {
72          // Initialize fields annotations
73          Field[] fields = clazz.getDeclaredFields();
74          for (Field field : fields)
75          {
76              checkFieldAnnotation(field, instance);
77          }
78  
79          // Initialize methods annotations
80          Method[] methods = clazz.getDeclaredMethods();
81          for (Method method : methods)
82          {
83              checkMethodAnnotation(method, instance);
84          }
85      }
86  
87      protected void checkMethodAnnotation(Method method, Object instance)
88              throws NamingException, IllegalAccessException, InvocationTargetException
89      {
90          if (method.isAnnotationPresent(Resource.class))
91          {
92              Resource annotation = method.getAnnotation(Resource.class);
93              lookupMethodResource(context, instance, method, annotation.name());
94          }
95      }
96  
97      protected void checkFieldAnnotation(Field field, Object instance)
98              throws NamingException, IllegalAccessException
99      {
100         if (field.isAnnotationPresent(Resource.class))
101         {
102             Resource annotation = field.getAnnotation(Resource.class);
103             lookupFieldResource(context, instance, field, annotation.name());
104         }
105     }
106 
107     /**
108      * Inject resources in specified field.
109      */
110     protected static void lookupFieldResource(javax.naming.Context context,
111             Object instance, Field field, String name)
112             throws NamingException, IllegalAccessException
113     {
114 
115         Object lookedupResource;
116 
117         if ((name != null) && (name.length() > 0))
118         {
119             // TODO local or global JNDI
120             lookedupResource = context.lookup(JAVA_COMP_ENV + name);
121         }
122         else
123         {
124             // TODO local or global JNDI 
125             lookedupResource = context.lookup(JAVA_COMP_ENV + instance.getClass().getName() + "/" + field.getName());
126         }
127 
128         boolean accessibility = field.isAccessible();
129         field.setAccessible(true);
130         field.set(instance, lookedupResource);
131         field.setAccessible(accessibility);
132     }
133 
134 
135     /**
136      * Inject resources in specified method.
137      */
138     protected static void lookupMethodResource(javax.naming.Context context,
139             Object instance, Method method, String name)
140             throws NamingException, IllegalAccessException, InvocationTargetException
141     {
142 
143         if (!method.getName().startsWith("set")
144                 || method.getParameterTypes().length != 1
145                 || !method.getReturnType().getName().equals("void"))
146         {
147             throw new IllegalArgumentException("Invalid method resource injection annotation");
148         }
149 
150         Object lookedupResource;
151 
152         if ((name != null) && (name.length() > 0))
153         {
154             // TODO local or global JNDI
155             lookedupResource = context.lookup(JAVA_COMP_ENV + name);
156         }
157         else
158         {
159             // TODO local or global JNDI
160             lookedupResource =
161                     context.lookup(JAVA_COMP_ENV + instance.getClass().getName() + "/" + getFieldName(method));
162         }
163 
164         boolean accessibility = method.isAccessible();
165         method.setAccessible(true);
166         method.invoke(instance, lookedupResource);
167         method.setAccessible(accessibility);
168     }
169 
170     /**
171      * Returns the field name for the given Method.
172      * E.g. setName() will be "name". 
173      *
174      * @param setter the setter method
175      * @return the field name of the given setter method
176      */
177     protected static String getFieldName(Method setter)
178     {
179         StringBuilder name = new StringBuilder(setter.getName());
180 
181         // remove 'set'
182         name.delete(0, 3);
183 
184         // lowercase first char
185         name.setCharAt(0, Character.toLowerCase(name.charAt(0)));
186 
187         return name.toString();
188     }
189 
190 }