    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     *****************************************************************************/
    009    package org.picocontainer.injectors;
    010
    011    import org.picocontainer.Characteristics;
    012    import org.picocontainer.ComponentAdapter;
    013    import org.picocontainer.PicoCompositionException;
    014    import org.picocontainer.PicoContainer;
    015    import org.picocontainer.PicoVisitor;
    016
    017    import java.lang.reflect.Method;
    018    import java.lang.reflect.Type;
    019    import java.util.Properties;
    020
    021
    022    /**
    023     * Providers are a type of Injector that can participate in Injection via a custom method.
    024     *
    025     * Implementors of this class must implement a single method called provide.  That method must return
    026     * the component type intended to be provided.  The method can accept parameters that PicoContainer
    027     * will satisfy.
    028     */
    029    public class ProviderAdapter implements org.picocontainer.Injector, Provider {
    030
    031        private final Object provider;
    032        private final Method provideMethod;
    033        private final Class key;
    034        private Properties properties;
    035
    036        protected ProviderAdapter() {
    037            provider = this;
    038            provideMethod = getProvideMethod(this.getClass());
    039            key = provideMethod.getReturnType();
    040            setUseNames(useNames());
    041        }
    042
    043        public ProviderAdapter(Object provider) {
    044            this(provider, false);
    045        }
    046
    047        public ProviderAdapter(Object provider, boolean useNames) {
    048            this.provider = provider;
    049            provideMethod = getProvideMethod(provider.getClass());
    050            key = provideMethod.getReturnType();
    051            setUseNames(useNames);
    052        }
    053
    054        private void setUseNames(boolean b) {
    055            if (b) {
    056                properties = Characteristics.USE_NAMES;
    057            } else {
    058                properties = Characteristics.NONE;
    059            }
    060        }
    061
    062        protected boolean useNames() {
    063            return false;
    064        }
    065
    066        public Object decorateComponentInstance(PicoContainer container, Type into, Object instance) {
    067            return null;
    068        }
    069
    070        public Object getComponentKey() {
    071            return key;
    072        }
    073
    074        public Class getComponentImplementation() {
    075            return key;
    076        }
    077
    078        @Deprecated
    079        public Object getComponentInstance(PicoContainer container) throws PicoCompositionException {
    080            return getComponentInstance(container, NOTHING.class);
    081        }
    082
    083        public Object getComponentInstance(PicoContainer container, Type into) throws PicoCompositionException {
    084            return new Reinjector(container).reinject(key, provider.getClass(), provider, properties, new MethodInjection(provideMethod));
    085        }
    086
    087        public static Method getProvideMethod(Class clazz) {
    088            Method provideMethod = null;
    089            // TODO doPrivileged
    090            for (Method method : clazz.getDeclaredMethods()) {
    091                if (method.getName().equals("provide")) {
    092                    if (provideMethod != null) {
    093                        throw newProviderMethodException("only one");
    094                    }
    095                    provideMethod = method;
    096                }
    097            }
    098            if (provideMethod == null) {
    099                throw newProviderMethodException("a");
    100            }
    101            if (provideMethod.getReturnType() == void.class) {
    102                throw newProviderMethodException("a non void returning");
    103            }
    104            return provideMethod;
    105        }
    106
    107        private static PicoCompositionException newProviderMethodException(String str) {
    108            return new PicoCompositionException("There must be "+ str +" method named 'provide' in the AbstractProvider implementation");
    109        }
    110
    111        public void verify(PicoContainer container) throws PicoCompositionException {
    112        }
    113
    114        public void accept(PicoVisitor visitor) {
    115        }
    116
    117        public ComponentAdapter getDelegate() {
    118            return null;
    119        }
    120
    121        public ComponentAdapter findAdapterOfType(Class componentAdapterType) {
    122            return null;
    123        }
    124
    125        public String getDescriptor() {
    126            return "AbstractProvider";
    127        }
    128    }