View Javadoc

1   /*
2    * Grapht, an open source dependency injector.
3    * Copyright 2014-2015 various contributors (see CONTRIBUTORS.txt)
4    * Copyright 2010-2014 Regents of the University of Minnesota
5    *
6    * This program is free software; you can redistribute it and/or modify
7    * it under the terms of the GNU Lesser General Public License as
8    * published by the Free Software Foundation; either version 2.1 of the
9    * License, or (at your option) any later version.
10   *
11   * This program is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13   * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14   * details.
15   *
16   * You should have received a copy of the GNU General Public License along with
17   * this program; if not, write to the Free Software Foundation, Inc., 51
18   * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19   */
20  /**
21   * Helper methods for instantiate() method
22   * ClassInstantiator
23   *
24   * @author <a href="http://grouplens.org">GroupLens Research</a>
25   */
26  
27  package org.grouplens.grapht.reflect.internal;
28  
29  import org.grouplens.grapht.ConstructionException;
30  import org.grouplens.grapht.Instantiator;
31  import org.grouplens.grapht.reflect.InjectionPoint;
32  import org.grouplens.grapht.util.LogContext;
33  import org.slf4j.Logger;
34  import org.slf4j.LoggerFactory;
35  
36  import java.lang.reflect.Field;
37  import java.lang.reflect.InvocationTargetException;
38  import java.lang.reflect.Method;
39  import java.util.Map;
40  
41  enum InjectionStrategy {
42  
43      // method invoked for Field-Injection type 
44      FIELD {
45          @Override
46          public void inject(InjectionPoint ip, Object instance, Instantiator provider,
47                                 Map<Method, ClassInstantiator.InjectionArgs> settersAndArguments)
48                                 throws ConstructionException {
49              Field field;
50              Object value;
51              FieldInjectionPoint fd = (FieldInjectionPoint)ip;
52              try {
53                  value = ClassInstantiator.checkNull(fd, provider.instantiate());
54                  field = fd.getMember();
55                  logger.trace("Setting field {} with arguments {}", field, value);
56                  field.setAccessible(true);
57                  field.set(instance, value);
58              } catch (IllegalAccessException e) {
59                  throw new ConstructionException(fd, e);
60              }
61          }
62      },
63  
64      // method invoked for Setter-Injection type
65      SETTER {
66          @Override
67          public void inject(InjectionPoint ip, Object instance, Instantiator provider,
68                                 Map<Method, ClassInstantiator.InjectionArgs> settersAndArguments)
69                                 throws ConstructionException {
70              SetterInjectionPoint st = (SetterInjectionPoint)ip;
71              ClassInstantiator.InjectionArgs args = settersAndArguments.get(st.getMember());
72              Method setter = st.getMember();
73              if (args == null) {
74                  //first encounter of this method
75                  args = new ClassInstantiator.InjectionArgs(setter.getParameterTypes().length);
76                  settersAndArguments.put(setter, args);
77              }
78                  args.set(st.getParameterIndex(), ClassInstantiator.checkNull(st, provider.instantiate()));
79  
80              if (args.isCompleted()) {
81                  // all parameters initialized, invoke the setter with all arguments
82                  try {
83                      logger.trace("Invoking setter {} with arguments {}", setter, args.arguments);
84                      setter.setAccessible(true);
85                      setter.invoke(instance, args.arguments);
86                  } catch (InvocationTargetException e) {
87                      String message = "Exception thrown by ";
88                      if (args.arguments.length == 1) {
89                          message += st;
90                      } else {
91                          message += setter;
92                      }
93                      throw new ConstructionException(st, message, e);
94                  } catch (IllegalAccessException e) {
95                      String message = "Access violation calling ";
96                      if (args.arguments.length == 1) {
97                          message += st;
98                      } else {
99                          message += setter;
100                     }
101                     throw new ConstructionException(st, message, e);
102                 }
103             }
104         }
105     },
106 
107     // method invoked for NoArgument-Injection type.
108     NOARGUMENT {
109         @Override
110         public void inject(InjectionPoint ip, Object instance, Instantiator provider,
111                               Map<Method, ClassInstantiator.InjectionArgs> settersAndArguments)
112                               throws ConstructionException {
113             Method method = null;
114             NoArgumentInjectionPoint noArugment = (NoArgumentInjectionPoint)ip;
115             try {
116                 method = noArugment.getMember();
117                 logger.trace("Injection point method with no argument in progress {}",noArugment);
118                 logger.trace("Invoking no-argument injection point {}", ip);
119                 method.setAccessible(true);
120                 method.invoke(instance);
121             } catch (InvocationTargetException e) {
122                 throw new ConstructionException(ip, "Exception throw by " + method, e);
123             } catch (IllegalAccessException e) {
124                 throw new ConstructionException(ip, "Access violation invoking " + method, e);
125             }
126         }
127     },
128 
129     DEFAULTCASE {
130         @Override
131         public void inject(InjectionPoint ip, Object instance, Instantiator provider,
132                               Map<Method, ClassInstantiator.InjectionArgs> settersAndArguments)
133                               throws ConstructionException {
134         }
135     };
136 
137     private static final Logger logger = LoggerFactory.getLogger(InjectionStrategy.class);
138 
139     public abstract void inject(InjectionPoint ip, Object instance, Instantiator provider,
140                                    Map<Method, ClassInstantiator.InjectionArgs> settersAndArguments)
141                                    throws ConstructionException;
142 
143     public static InjectionStrategy forInjectionPoint(InjectionPoint ip) {
144         if(ip instanceof FieldInjectionPoint) {
145             return InjectionStrategy.FIELD;
146         }
147         else if(ip instanceof SetterInjectionPoint) {
148             return InjectionStrategy.SETTER;
149         }
150         else if(ip instanceof NoArgumentInjectionPoint) {
151             return InjectionStrategy.NOARGUMENT;
152         }
153         else {
154             return InjectionStrategy.DEFAULTCASE;
155         }
156     }
157 }