001 /** 002 * 003 */ 004 package org.picocontainer.gems.adapters; 005 006 import java.util.Properties; 007 008 import org.picocontainer.ComponentAdapter; 009 import org.picocontainer.ComponentMonitor; 010 import org.picocontainer.LifecycleStrategy; 011 import org.picocontainer.Parameter; 012 import org.picocontainer.PicoCompositionException; 013 import org.picocontainer.gems.util.DelegateMethod; 014 import org.picocontainer.injectors.AbstractInjectionFactory; 015 016 /** 017 * Mirrored AdaptorFactory for handling delegate methods. 018 * @author Michael Rimov 019 */ 020 @SuppressWarnings("serial") 021 public class DelegateAdaptorFactory extends AbstractInjectionFactory { 022 023 024 /** 025 * DelegateMethod instance key. 026 */ 027 private static final String DELEGATE = "delegateInstance"; 028 029 030 /** 031 * Delegate target instance key. 032 */ 033 private static final String INSTANCE = "targetInstance"; 034 035 /** 036 * Default constructor. 037 */ 038 public DelegateAdaptorFactory() { 039 super(); 040 } 041 042 043 /** 044 * {@inheritDoc} 045 * 046 */ 047 public <T> ComponentAdapter<T> createComponentAdapter( 048 final ComponentMonitor componentMonitor, 049 final LifecycleStrategy lifecycleStrategy, 050 final Properties componentProperties, final Object componentKey, 051 final Class<T> componentImplementation, final Parameter... parameters) 052 throws PicoCompositionException { 053 054 DelegateMethod<?, T> method = cast(componentProperties.remove(DELEGATE)); 055 056 //TODO: what to do since if there is no method, the delegate adapter won't work. 057 if (method == null) { 058 throw new IllegalArgumentException("Component properties must have a " 059 +"org.picocontainer.gems.util.DelegateMethod object stored as delegateInstance"); 060 } 061 062 Object instance = componentProperties.remove(INSTANCE); 063 if (instance == null) { 064 throw new IllegalArgumentException("Property 'instance' must exist."); 065 } 066 067 068 069 return new DelegateMethodAdapter<T>(componentKey, componentMonitor, instance, method); 070 } 071 072 073 /** 074 * Takes care of generic warnings. 075 * @param <T> 076 * @param source 077 * @return an appropriately cast object. 078 */ 079 @SuppressWarnings("unchecked") 080 private <T> T cast(final Object source) { 081 return (T) source; 082 } 083 084 /** 085 * Use this static factory method as a way of creating all the necessary properties that are required by the adapter. 086 * <p>Example:</p> 087 * <pre> 088 * DelegateAdapterFactory factory = new DelegateAdapterFactory(); 089 * HttpServletRequest request = .....; 090 * 091 * //When object is instantiated will lazily call: request.getSession(false); 092 * Properties props = createDelegateProperties(request, "getSession", false); 093 * 094 * DelegateMethodAdapter adapter = createComponentAdapter(new ConsoleComponentMonitor(), new DefaultLifecycleStrategy(), 095 * props, HttpSession.class, HttpSession.class); 096 * </pre> 097 * @param targetObject the object to be operated on. 098 * @param methodName the name of the method to invoke. 099 * @param parameters the parameters to supply upon invocation. (Also used to find matching argument). 100 * @return the appropriate properties that can be used with createComponentAdapter(). 101 */ 102 public static Properties createDelegateProprties(final Object targetObject, final String methodName, final Object... parameters) { 103 Properties props = new Properties(); 104 props.put(INSTANCE, targetObject); 105 props.put(DELEGATE, createDelegate(targetObject.getClass(), methodName, parameters)); 106 107 return props; 108 } 109 110 /** 111 * Generic-friendly instantiation. If you have control of your own code, you can also just use the DelegateMethod constructors. 112 * @param <INSTANCE> 113 * @param <RETURN_TYPE> 114 * @param targetType the type of object being instantiated. 115 * @param methodName the method name to invoke when called. 116 * @param parameters the method paramters to use. 117 * @return DelegateMethod instance. 118 */ 119 public static <INSTANCE,RETURN_TYPE> DelegateMethod<INSTANCE, RETURN_TYPE> createDelegate(final Class<INSTANCE> targetType, final String methodName, final Object... parameters) { 120 return new DelegateMethod<INSTANCE,RETURN_TYPE>(targetType, methodName, parameters); 121 } 122 }