View Javadoc

1   //========================================================================
2   //$Id: Injection.java 4027 2008-11-12 00:59:06Z janb $
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             Log.warn(e);
191             throw new IllegalStateException("Inject failed for field "+field.getName());
192         }
193     }
194     
195     /**
196      * Inject value from jndi into a setter method of an instance
197      * @param method
198      * @param injectable
199      */
200     public void injectMethod (Method method, Object injectable)
201     {
202         //validateInjection(method, injectable);
203         try
204         {
205             boolean accessibility = method.isAccessible();
206             method.setAccessible(true);
207             method.invoke(injectable, new Object[] {lookupInjectedValue()});
208             method.setAccessible(accessibility);
209         }
210         catch (Exception e)
211         {
212             Log.warn(e);
213             throw new IllegalStateException("Inject failed for method "+method.getName());
214         }
215     }
216     
217   
218 
219     
220     private void validateInjection (Method method, Object injectable)
221     throws NoSuchMethodException
222     {
223         if ((injectable==null) || (method==null))
224             return;
225         //check the injection target actually has a matching method
226         //TODO: think about this, they have to be assignable
227         injectable.getClass().getMethod(method.getName(), method.getParameterTypes());    
228     }
229     
230     private void validateInjection (Field field, Object injectable) 
231     throws NoSuchFieldException
232     {
233         if ((field==null) || (injectable==null))
234             return;
235 
236         Field f = injectable.getClass().getField(field.getName());
237         if (!f.getType().isAssignableFrom(field.getType()))
238             throw new NoSuchFieldException("Mismatching type of field: "+f.getType().getName()+" v "+field.getType().getName());
239     }   
240 }