1 package org.objectweb.celtix.common.injection; 2 3 4 import java.lang.annotation.Annotation ; 5 import java.lang.reflect.Field ; 6 import java.lang.reflect.InvocationTargetException ; 7 import java.lang.reflect.Method ; 8 import java.util.Collection ; 9 import java.util.LinkedList ; 10 import java.util.List ; 11 import java.util.logging.Level ; 12 import java.util.logging.Logger ; 13 import javax.annotation.PostConstruct; 14 import javax.annotation.Resource; 15 import javax.annotation.Resources; 16 import org.objectweb.celtix.common.annotation.AnnotationProcessor; 17 import org.objectweb.celtix.common.annotation.AnnotationVisitor; 18 import org.objectweb.celtix.common.logging.LogUtils; 19 import org.objectweb.celtix.resource.ResourceManager; 20 21 22 26 public class ResourceInjector implements AnnotationVisitor { 27 28 private static final Logger LOG = LogUtils.getL7dLogger(ResourceInjector.class); 29 30 private final ResourceManager resourceManager; 31 private Object target; 32 33 public ResourceInjector(ResourceManager resMgr) { 34 resourceManager = resMgr; 35 } 36 37 public void inject(Object o) { 38 39 AnnotationProcessor processor = new AnnotationProcessor(o); 40 processor.accept(this); 41 42 invokePostConstruct(); 43 } 44 45 46 47 49 public final void visitClass(final Class <?> clz, final Annotation annotation) { 50 51 assert annotation instanceof Resource || annotation instanceof Resources : annotation; 52 53 if (annotation instanceof Resource) { 54 injectResourceClassLevel(clz, (Resource)annotation); 55 } else if (annotation instanceof Resources) { 56 Resources resources = (Resources)annotation; 57 for (Resource resource : resources.value()) { 58 injectResourceClassLevel(clz, resource); 59 } 60 } 61 62 } 63 64 private void injectResourceClassLevel(Class <?> clz, Resource res) { 65 if (res.name() == null || "".equals(res.name())) { 66 LOG.log(Level.INFO, "RESOURCE_NAME_NOT_SPECIFIED", target.getClass().getName()); 67 return; 68 } 69 70 Object resource = null; 71 Method setter = findSetterForResource(res); 73 if (setter != null) { 74 Class <?> type = getResourceType(res, setter); 75 resource = resourceManager.resolveResource(res.name(), type); 76 if (resource == null) { 77 LOG.log(Level.INFO, "RESOURCE_RESOLVE_FAILED"); 78 return; 79 } 80 81 invokeSetter(setter, resource); 82 return; 83 } 84 85 Field field = findFieldForResource(res); 86 if (field != null) { 87 Class <?> type = getResourceType(res, field); 88 resource = resourceManager.resolveResource(res.name(), type); 89 if (resource == null) { 90 LOG.log(Level.INFO, "RESOURCE_RESOLVE_FAILED"); 91 return; 92 } 93 injectField(field, resource); 94 return; 95 } 96 LOG.log(Level.SEVERE, "NO_SETTER_OR_FIELD_FOR_RESOURCE", getTarget().getClass().getName()); 97 } 98 99 public final List <Class <? extends Annotation >> getTargetAnnotations() { 100 List <Class <? extends Annotation >> al = new LinkedList <Class <? extends Annotation >>(); 101 al.add(Resource.class); 102 al.add(Resources.class); 103 return al; 104 } 105 106 public final void visitField(final Field field, final Annotation annotation) { 107 108 assert annotation instanceof Resource : annotation; 109 110 Resource res = (Resource)annotation; 111 112 String name = getFieldNameForResource(res, field); 113 Class <?> type = getResourceType(res, field); 114 115 Object resource = resourceManager.resolveResource(name, type); 116 if (resource != null) { 117 injectField(field, resource); 118 } else { 119 LOG.log(Level.INFO, "RESOURCE_RESOLVE_FAILED", name); 120 } 121 } 122 123 public final void visitMethod(final Method method, final Annotation annotation) { 124 125 assert annotation instanceof Resource : annotation; 126 127 Resource res = (Resource)annotation; 128 129 String resourceName = getResourceName(res, method); 130 Class <?> clz = getResourceType(res, method); 131 132 Object resource = resourceManager.resolveResource(resourceName, clz); 133 if (resource != null) { 134 invokeSetter(method, resource); 135 } else { 136 LOG.log(Level.INFO, "RESOURCE_RESOLVE_FAILED", new Object [] {resourceName, clz}); 137 } 138 } 139 140 141 public final void setTarget(final Object object) { 142 target = object; 143 } 144 145 public final Object getTarget() { 146 return target; 147 } 148 149 private Field findFieldForResource(Resource res) { 150 assert target != null; 151 assert res.name() != null; 152 153 for (Field field : target.getClass().getFields()) { 154 if (field.getName().equals(res.name())) { 155 return field; 156 } 157 } 158 159 for (Field field : target.getClass().getDeclaredFields()) { 160 if (field.getName().equals(res.name())) { 161 return field; 162 } 163 } 164 return null; 165 } 166 167 168 private Method findSetterForResource(Resource res) { 169 assert target != null; 170 171 String setterName = resourceNameToSetter(res.name()); 172 Method setterMethod = null; 173 174 for (Method method : getTarget().getClass().getMethods()) { 175 if (setterName.equals(method.getName())) { 176 setterMethod = method; 177 break; 178 } 179 } 180 181 if (setterMethod != null && setterMethod.getParameterTypes().length != 1) { 182 LOG.log(Level.WARNING, "SETTER_INJECTION_WITH_INCORRECT_TYPE", setterMethod); 183 } 184 return setterMethod; 185 } 186 187 188 private String resourceNameToSetter(String resName) { 189 190 return "set" + Character.toUpperCase(resName.charAt(0)) + resName.substring(1); 191 } 192 193 194 private void invokeSetter(Method method, Object resource) { 195 try { 196 method.invoke(getTarget(), resource); 197 } catch (IllegalAccessException e) { 198 LOG.log(Level.SEVERE, "INJECTION_SETTER_NOT_VISIBLE", method); 199 } catch (InvocationTargetException e) { 200 LogUtils.log(LOG, Level.SEVERE, "INJECTION_SETTER_RAISED_EXCEPTION", e, method); 201 } 202 } 203 204 205 private String getResourceName(Resource res, Method method) { 206 assert method != null; 207 assert res != null; 208 assert method.getName().startsWith("set") : method; 209 210 if (res.name() == null || "".equals(res.name())) { 211 String name = method.getName(); 212 name = name.substring(3); 213 name = Character.toLowerCase(name.charAt(0)) + name.substring(1); 214 return name; 215 } 216 return res.name(); 217 } 218 219 220 221 private void injectField(Field field, Object resource) { 222 assert field != null; 223 assert resource != null; 224 225 boolean accessible = field.isAccessible(); 226 try { 227 if (field.getType().isAssignableFrom(resource.getClass())) { 228 field.setAccessible(true); 229 field.set(getTarget(), resource); 230 } 231 } catch (IllegalAccessException e) { 232 e.printStackTrace(); 233 LOG.severe("FAILED_TO_INJECT_FIELD"); 234 } finally { 235 field.setAccessible(accessible); 236 } 237 } 238 239 240 private void invokePostConstruct() { 241 242 boolean accessible = false; 243 for (Method method : getPostConstructMethods()) { 244 PostConstruct pc = method.getAnnotation(PostConstruct.class); 245 if (pc != null) { 246 try { 247 method.setAccessible(true); 248 method.invoke(target); 249 } catch (IllegalAccessException e) { 250 LOG.log(Level.WARNING, "INJECTION_COMPLETE_NOT_VISIBLE", method); 251 } catch (InvocationTargetException e) { 252 LOG.log(Level.WARNING, "INJECTION_COMPLETE_THREW_EXCEPTION", e); 253 } finally { 254 method.setAccessible(accessible); 255 } 256 } 257 } 258 } 259 260 private Collection <Method > getPostConstructMethods() { 261 262 Collection <Method > methods = new LinkedList <Method >(); 263 addPostConstructMethods(getTarget().getClass().getMethods(), methods); 264 addPostConstructMethods(getTarget().getClass().getDeclaredMethods(), methods); 265 return methods; 266 } 267 268 private void addPostConstructMethods(Method [] methods, Collection <Method > postConstructMethods) { 269 for (Method method : methods) { 270 if (method.getAnnotation(PostConstruct.class) != null 271 && !postConstructMethods.contains(method)) { 272 postConstructMethods.add(method); 273 } 274 } 275 } 276 277 278 281 protected Class <?> getResourceType(Resource res, Field field) { 282 assert res != null; 283 Class type = res.type(); 284 if (res.type() == null || Object .class == res.type()) { 285 type = field.getType(); 286 } 287 return type; 288 } 289 290 291 private Class <?> getResourceType(Resource res, Method method) { 292 return res.type() != null && !Object .class.equals(res.type()) 293 ? res.type() 294 : method.getParameterTypes()[0]; 295 } 296 297 298 private String getFieldNameForResource(Resource res, Field field) { 299 assert res != null; 300 if (res.name() == null || "".equals(res.name())) { 301 return field.getName(); 302 } 303 return res.name(); 304 } 305 306 } 307 | Popular Tags |