View Javadoc

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