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 *****************************************************************************/ 009package org.picocontainer.injectors; 010 011import org.picocontainer.Characteristics; 012import org.picocontainer.ComponentAdapter; 013import org.picocontainer.LifecycleStrategy; 014import org.picocontainer.PicoCompositionException; 015import org.picocontainer.PicoContainer; 016import org.picocontainer.PicoVisitor; 017import org.picocontainer.lifecycle.NullLifecycleStrategy; 018 019import java.lang.reflect.Method; 020import java.lang.reflect.Type; 021import 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 */ 030public 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}