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