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 adapterType) {
122            return null;
123        }
124    
125        public String getDescriptor() {
126            return "AbstractProvider";
127        }
128    }