View Javadoc

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