View Javadoc
1   /*
2    * Copyright 2016 Function1. All Rights Reserved.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *    http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package tools.gsf.config.inject;
17  
18  import COM.FutureTense.Interfaces.ICS;
19  import com.fatwire.cs.core.db.Util;
20  import org.apache.commons.lang3.StringUtils;
21  import org.slf4j.Logger;
22  import org.slf4j.LoggerFactory;
23  
24  import javax.servlet.http.HttpSession;
25  import java.lang.reflect.Field;
26  import java.util.Date;
27  
28  /**
29   * Helper to bind variables to an Object based on annotated fields.
30   *
31   * @author Dolf Dijkstra
32   * @since 12 mei 2012
33   */
34  public final class BindInjector implements Injector {
35  
36      private static final Logger LOG = LoggerFactory.getLogger("tools.gsf.config.inject.AnnotationBinder");
37  
38      private final ICS ics;
39  
40      public BindInjector(ICS ics) {
41          this.ics = ics;
42      }
43  
44      /**
45       * Inject ICS runtime objects into the object. Objects flagged with the
46       * {@link Bind} annotation will be populated by this method by
47       * retrieving the value from ics context, request context, or session, as per the scope of the Bind annotation.
48       *
49       * @param dependent the object to inject into.
50       */
51      public void inject(final Object dependent) {
52          if (dependent == null) {
53              throw new IllegalArgumentException("Target cannot be null.");
54          }
55          Class<?> c = dependent.getClass();
56          // all annotated fields.
57          while (c != Object.class && c != null) {
58              for (final Field field : c.getDeclaredFields()) {
59                  if (field.isAnnotationPresent(Bind.class)) {
60                      bindToField(dependent, ics, field);
61                  }
62  
63              }
64  
65              c = c.getSuperclass();
66          }
67      }
68  
69      /**
70       * @param object object to bind to
71       * @param ics    the ics context
72       * @param field  the field to inject to
73       * @throws SecurityException security exception
74       */
75      private static void bindToField(final Object object, final ICS ics, final Field field) throws SecurityException {
76  
77          if (!field.isAccessible()) {
78              field.setAccessible(true); // make private fields accessible
79          }
80          final Bind ifr = field.getAnnotation(Bind.class);
81  
82          String name = ifr.value();
83          if (StringUtils.isBlank(name)) {
84              name = field.getName();
85          }
86          try {
87  
88              switch (ifr.scope()) {
89                  case ics:
90                      if (!field.getType().isArray()) {
91                          String var = ics.GetVar(name);
92                          if (StringUtils.isBlank(var)) {
93                              put(object, field, ics.GetObj(name));
94                          } else {
95                              put(object, field, var);
96                          }
97                      }
98                      break;
99                  case request:
100                 	if (!field.getType().isArray()) {
101                 		put(object, field, ics.getAttribute(name));
102                 	}
103                     break;
104                 case session:
105                     @SuppressWarnings("deprecation")
106                     HttpSession s = ics.getIServlet().getServletRequest().getSession(false);
107                     if (s != null) {
108                     	if (!field.getType().isArray()) {
109                     		put(object, field, s.getAttribute(name));
110                     	}
111                     }
112                     break;
113 
114             }
115         } catch (final IllegalAccessException e) {
116             throw new RuntimeException(e);
117         }
118 
119     }
120 
121     private static void putPrimitive(Object object, Field field, Object v) throws IllegalAccessException {
122         try {
123             if (field.getType() == Byte.TYPE) {
124                 field.setByte(object, (Byte) v);
125             } else if (field.getType() == Integer.TYPE) {
126                 field.setInt(object, (Integer) v);
127             } else if (field.getType() == Double.TYPE) {
128                 field.setDouble(object, (Double) (v));
129             } else if (field.getType() == Float.TYPE) {
130                 field.setFloat(object, (Float) (v));
131             } else if (field.getType() == Long.TYPE) {
132                 field.setLong(object, (Long) (v));
133             } else if (field.getType() == Short.TYPE) {
134                 field.setShort(object, (Short) (v));
135             } else if (field.getType() == Boolean.TYPE) {
136                 field.setBoolean(object, (Boolean) (v));
137             } else {
138                 LOG.debug("Can't set primitive field {} to {}", field.getName(), v);
139             }
140         } catch (final IllegalAccessException e) {
141             throw new IllegalAccessException("IllegalAccessException binding " + v + " to field " + field.getName());
142         }
143 
144     }
145 
146     private static void put(Object object, Field field, Object value) throws IllegalAccessException {
147         if (value == null) {
148             return;
149         }
150         if (value instanceof String) {
151             put(object, field, (String) value);
152         } else if (field.getType().isPrimitive()) {
153             putPrimitive(object, field, value);
154         }
155 
156     }
157 
158     private static void put(Object object, Field field, String var) throws IllegalAccessException {
159         if (StringUtils.isBlank(var)) {
160             return;
161         }
162         if (field.getType().isPrimitive()) {
163             putPrimitive(object, field, var);
164         } else {
165 
166             Object value = null;
167             if (field.getType() == String.class) {
168                 value = var;
169             } else if (field.getType() == Date.class) {
170                 value = Util.parseJdbcDate(var);
171             } else if (field.getType() == Integer.class) {
172                 value = new Integer(var);
173             } else if (field.getType() == Double.class) {
174                 value = new Double(var);
175             } else if (field.getType() == Character.class) {
176                 value = var.charAt(0);
177             } else if (field.getType() == Long.class) {
178                 value = new Long(var);
179             } else {
180             	if (LOG.isDebugEnabled()) {
181             		LOG.debug("Annotated field {} has type {} but the object being bound has type {} which is not explicitly supported (yet)", field.getName(), field.getType(), var.getClass().getName());
182             	}
183             }
184             LOG.debug("Binding {} to field {} for {}", value, field.getName(), object.getClass().getName());
185             try {
186                 field.set(object, value);
187             } catch (final IllegalArgumentException e) {
188                 throw new IllegalArgumentException("IllegalArgumentException binding " + value + " to field "
189                         + field.getName(), e);
190             } catch (final IllegalAccessException e) {
191                 throw new IllegalAccessException("IllegalAccessException binding " + value + " to field "
192                         + field.getName());
193             }
194         }
195 
196     }
197 
198     private static void putPrimitive(Object object, Field field, String s) throws IllegalAccessException {
199         if (StringUtils.isBlank(s)) {
200             return;
201         }
202         try {
203             if (field.getType() == Byte.TYPE) {
204                 field.setByte(object, Byte.parseByte(s));
205             } else if (field.getType() == Integer.TYPE) {
206                 field.setInt(object, Integer.parseInt(s));
207             } else if (field.getType() == Double.TYPE) {
208                 field.setDouble(object, Double.parseDouble(s));
209             } else if (field.getType() == Float.TYPE) {
210                 field.setFloat(object, Float.parseFloat(s));
211             } else if (field.getType() == Long.TYPE) {
212                 field.setLong(object, Long.parseLong(s));
213             } else if (field.getType() == Short.TYPE) {
214                 field.setShort(object, Short.parseShort(s));
215             } else if (field.getType() == Boolean.TYPE) {
216                 field.setBoolean(object, Boolean.parseBoolean(s));
217             } else {
218                 LOG.debug("Can't set primitive field {} to {}", field.getName(), s);
219             }
220         } catch (final IllegalAccessException e) {
221             throw new IllegalAccessException("IllegalAccessException binding " + s + " to field " + field.getName());
222         }
223     }
224 }