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 }