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 }