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     *****************************************************************************/
010    package org.picocontainer.injectors;
011    
012    import org.picocontainer.ComponentMonitor;
013    import org.picocontainer.Parameter;
014    import org.picocontainer.behaviors.PropertyApplicator;
015    import org.picocontainer.behaviors.Cached;
016    
017    import java.lang.reflect.Method;
018    import java.lang.reflect.AccessibleObject;
019    import java.lang.reflect.InvocationTargetException;
020    
021    /**
022     * Instantiates components using empty constructors and
023     * <a href="http://picocontainer.org/setter-injection.html">Setter Injection</a>.
024     * For easy setting of primitive properties, also see {@link PropertyApplicator}.
025     * <p/>
026     * <em>
027     * Note that this class doesn't cache instances. If you want caching,
028     * use a {@link Cached} around this one.
029     * </em>
030     * </p>
031     *
032     * @author Aslak Helles&oslash;y
033     * @author J&ouml;rg Schaible
034     * @author Mauro Talevi
035     * @author Paul Hammant
036     */
037    @SuppressWarnings("serial")
038    public class SetterInjector<T> extends IterativeInjector<T> {
039    
040        protected final String prefix;
041    
042        /**
043         * Constructs a SetterInjector
044         *
045         * @param componentKey            the search key for this implementation
046         * @param componentImplementation the concrete implementation
047         * @param parameters              the parameters to use for the initialization
048         * @param monitor                 the component monitor used by this addAdapter
049         * @param prefix                  the prefix to use (e.g. 'set')
050         * @throws org.picocontainer.injectors.AbstractInjector.NotConcreteRegistrationException
051         *                              if the implementation is not a concrete class.
052         * @throws NullPointerException if one of the parameters is <code>null</code>
053         */
054        public SetterInjector(final Object componentKey,
055                              final Class componentImplementation,
056                              Parameter[] parameters,
057                              ComponentMonitor monitor,
058                              String prefix, boolean useNames) throws  NotConcreteRegistrationException {
059            super(componentKey, componentImplementation, parameters, monitor, useNames);
060            this.prefix = prefix;
061        }
062    
063        protected Object memberInvocationReturn(Object lastReturn, AccessibleObject member, Object instance) {
064            return member != null && ((Method)member).getReturnType()!=void.class ? lastReturn : instance;
065        }
066    
067        @Override
068        protected Object injectIntoMember(AccessibleObject member, Object componentInstance, Object toInject)
069            throws IllegalAccessException, InvocationTargetException {
070            return ((Method)member).invoke(componentInstance, toInject);
071        }
072    
073        @Override
074        protected boolean isInjectorMethod(Method method) {
075            String methodName = method.getName();
076            return methodName.length() >= getInjectorPrefix().length() + 1 && methodName.startsWith(getInjectorPrefix()) && Character.isUpperCase(methodName.charAt(getInjectorPrefix().length()));
077        }
078    
079        protected String getInjectorPrefix() {
080            return prefix;
081        }
082    
083        @Override
084        public String getDescriptor() {
085            return "SetterInjector-"; 
086        }
087    
088    
089    }