View Javadoc

    1   //========================================================================
    2   //$Id: Injection.java 4029 2008-11-12 01:04:26Z 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 }