001/***************************************************************************** 002 * Copyright (C) PicoContainer Organization. All rights reserved. * 003 * ------------------------------------------------------------------------- * 004 * The software in this package is published under the terms of the BSD * 005 * style license a copy of which has been included with this distribution in * 006 * the LICENSE.txt file. * 007 * * 008 * Original code by * 009 *****************************************************************************/ 010package org.picocontainer.injectors; 011 012import org.picocontainer.ComponentMonitor; 013import org.picocontainer.NameBinding; 014import org.picocontainer.Parameter; 015import org.picocontainer.PicoContainer; 016import org.picocontainer.annotations.Bind; 017 018import java.lang.annotation.Annotation; 019import java.lang.reflect.AccessibleObject; 020import java.lang.reflect.Field; 021import java.lang.reflect.InvocationTargetException; 022import java.lang.reflect.Type; 023import java.security.AccessController; 024import java.security.PrivilegedAction; 025import java.util.ArrayList; 026import java.util.Arrays; 027import java.util.Collections; 028import java.util.List; 029import java.util.Set; 030 031/** 032 * Injection happens after instantiation, and fields are marked as 033 * injection points via a named field. 034 */ 035@SuppressWarnings("serial") 036public class NamedFieldInjector<T> extends AbstractFieldInjector<T> { 037 038 private final List<String> fieldNames; 039 040 public NamedFieldInjector(Object key, 041 Class<?> impl, 042 Parameter[] parameters, 043 ComponentMonitor componentMonitor, 044 String fieldNames) { 045 046 super(key, impl, parameters, componentMonitor, true); 047 this.fieldNames = Arrays.asList(fieldNames.trim().split(" ")); 048 } 049 050 @Override 051 protected void initializeInjectionMembersAndTypeLists() { 052 injectionMembers = new ArrayList<AccessibleObject>(); 053 List<Annotation> bindingIds = new ArrayList<Annotation>(); 054 final List<Type> typeList = new ArrayList<Type>(); 055 final Field[] fields = getFields(); 056 for (final Field field : fields) { 057 if (isNamedForInjection(field)) { 058 injectionMembers.add(field); 059 typeList.add(box(field.getType())); 060 bindingIds.add(getBinding(field)); 061 } 062 } 063 injectionTypes = typeList.toArray(new Type[0]); 064 bindings = bindingIds.toArray(new Annotation[0]); 065 } 066 067 private Annotation getBinding(Field field) { 068 Annotation[] annotations = field.getAnnotations(); 069 for (Annotation annotation : annotations) { 070 if (annotation.annotationType().isAnnotationPresent(Bind.class)) { 071 return annotation; 072 } 073 } 074 return null; 075 } 076 077 protected boolean isNamedForInjection(Field field) { 078 return fieldNames.contains(field.getName()); 079 } 080 081 private Field[] getFields() { 082 return AccessController.doPrivileged(new PrivilegedAction<Field[]>() { 083 public Field[] run() { 084 return getComponentImplementation().getDeclaredFields(); 085 } 086 }); 087 } 088 089 090 protected Object injectIntoMember(AccessibleObject member, Object componentInstance, Object toInject) 091 throws IllegalAccessException, InvocationTargetException { 092 Field field = (Field) member; 093 field.setAccessible(true); 094 field.set(componentInstance, toInject); 095 return null; 096 } 097 098 @Override 099 public String getDescriptor() { 100 return "NamedFieldInjector-"; 101 } 102 103 @Override 104 protected NameBinding makeParameterNameImpl(final AccessibleObject member) { 105 return new NameBinding() { 106 public String getName() { 107 return ((Field) member).getName(); 108 } 109 }; 110 } 111 112 protected Object memberInvocationReturn(Object lastReturn, AccessibleObject member, Object instance) { 113 return instance; 114 } 115 116 List<String> getInjectionFieldNames() { 117 return Collections.unmodifiableList(fieldNames); 118 } 119 120 121}