View Javadoc

1   //========================================================================
2   //$Id: Injection.java 3944 2008-10-29 16:15:18Z jesse $
3   //Copyright 2006 Mort Bay Consulting Pty. Ltd.
4   //------------------------------------------------------------------------
5   //Licensed under the Apache License, Version 2.0 (the "License");
6   //you may not use this file except in compliance with the License.
7   //You may obtain a copy of the License at 
8   //http://www.apache.org/licenses/LICENSE-2.0
9   //Unless required by applicable law or agreed to in writing, software
10  //distributed under the License is distributed on an "AS IS" BASIS,
11  //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  //See the License for the specific language governing permissions and
13  //limitations under the License.
14  //========================================================================
15  
16  package org.mortbay.jetty.plus.annotation;
17  
18  import java.lang.reflect.Field;
19  import java.lang.reflect.Member;
20  import java.lang.reflect.Method;
21  
22  
23  
24  import javax.naming.InitialContext;
25  import javax.naming.NamingException;
26  
27  import org.mortbay.log.Log;
28  import org.mortbay.util.IntrospectionUtil;
29  
30  /**
31   * Injection
32   *
33   * Represents the injection of a resource into a target (method or field).
34   * The injection is performed by doing an ENC lookup using the jndi
35   * name provided, and setting the object obtained on the target.
36   *
37   */
38  public class Injection
39  {
40      private Class _targetClass;
41      private String _jndiName;
42      private String _mappingName;
43      private Member _target;
44      
45      
46      public Injection ()
47      {}
48      
49  
50      /**
51       * @return the _className
52       */
53      public Class getTargetClass()
54      {
55          return _targetClass;
56      }
57  
58  
59      /**
60       * @param name the _className to set
61       */
62      public void setTargetClass(Class clazz)
63      {
64          _targetClass = clazz;
65      }
66      
67      /**
68       * @return the jndiName
69       */
70      public String getJndiName()
71      {
72          return _jndiName;
73      }
74      /**
75       * @param jndiName the jndiName to set
76       */
77      public void setJndiName(String jndiName)
78      {
79          this._jndiName = jndiName;
80      }
81      /**
82       * @return the mappingName
83       */
84      public String getMappingName()
85      {
86          return _mappingName;
87      }
88      /**
89       * @param mappingName the mappingName to set
90       */
91      public void setMappingName(String mappingName)
92      {
93          this._mappingName = mappingName;
94      }
95      
96      /**
97       * @return the target
98       */
99      public Member getTarget()
100     {
101         return _target;
102     }
103     
104     /**
105      * @param target the target to set
106      */
107     public void setTarget(Member target)
108     {
109         this._target = target;
110     }
111 
112     //TODO: define an equals method
113     
114     public void setTarget (Class clazz, String targetName, Class targetType)
115     {
116         //first look for a javabeans style setter matching the targetName
117         String setter = "set"+targetName.substring(0,1).toUpperCase()+targetName.substring(1);
118         try
119         {
120             Log.debug("Looking for method for setter: "+setter+" with arg "+targetType);
121             _target = IntrospectionUtil.findMethod(clazz, setter, new Class[] {targetType}, true, false); 
122             _targetClass = clazz;
123         }
124         catch (NoSuchMethodException me)
125         {
126             //try as a field
127             try
128             {
129                 _target = IntrospectionUtil.findField(clazz, targetName, targetType, true, false);
130                 _targetClass = clazz;
131             }
132             catch (NoSuchFieldException fe)
133             {
134                 throw new IllegalArgumentException("No such field or method "+targetName+" on class "+_targetClass);
135             }
136         }
137     }
138 
139     
140     /**
141      * Inject a value for a Resource from JNDI into an object
142      * @param injectable
143      * @throws Exception
144      */
145     public void inject (Object injectable)
146     {
147         Member theTarget = getTarget(); 
148         if (theTarget instanceof Field)
149         {
150             injectField((Field)theTarget, injectable);
151         }
152         else if (theTarget instanceof Method)
153         {
154             injectMethod((Method)theTarget, injectable);
155         }
156     }
157 
158     
159     /**
160      * The Resource must already exist in the ENC of this webapp.
161      * @return
162      * @throws Exception
163      */
164     public Object lookupInjectedValue ()
165     throws NamingException
166     {
167         InitialContext context = new InitialContext();
168         return context.lookup("java:comp/env/"+getJndiName());
169     }
170     
171     
172 
173     /**
174      * Inject value from jndi into a field of an instance
175      * @param field
176      * @param injectable
177      */
178     public void injectField (Field field, Object injectable)
179     {           
180         try
181         {
182             //validateInjection(field, injectable);
183             boolean accessibility = field.isAccessible();
184             field.setAccessible(true);
185             field.set(injectable, lookupInjectedValue());
186             field.setAccessible(accessibility);
187         }
188         catch (Exception e)
189         {
190             throw new IllegalStateException(e.getMessage());
191         }
192     }
193     
194     /**
195      * Inject value from jndi into a setter method of an instance
196      * @param method
197      * @param injectable
198      */
199     public void injectMethod (Method method, Object injectable)
200     {
201         //validateInjection(method, injectable);
202         try
203         {
204             boolean accessibility = method.isAccessible();
205             method.setAccessible(true);
206             method.invoke(injectable, new Object[] {lookupInjectedValue()});
207             method.setAccessible(accessibility);
208         }
209         catch (Exception e)
210         {
211             throw new IllegalStateException(e.getMessage());
212         }
213     }
214     
215   
216 
217     
218     private void validateInjection (Method method, Object injectable)
219     throws NoSuchMethodException
220     {
221         if ((injectable==null) || (method==null))
222             return;
223         //check the injection target actually has a matching method
224         //TODO: think about this, they have to be assignable
225         injectable.getClass().getMethod(method.getName(), method.getParameterTypes());    
226     }
227     
228     private void validateInjection (Field field, Object injectable) 
229     throws NoSuchFieldException
230     {
231         if ((field==null) || (injectable==null))
232             return;
233 
234         Field f = injectable.getClass().getField(field.getName());
235         if (!f.getType().isAssignableFrom(field.getType()))
236             throw new NoSuchFieldException("Mismatching type of field: "+f.getType().getName()+" v "+field.getType().getName());
237     }   
238 }