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