001: /* ====================================================================
002: The Jicarilla Software License
003:
004: Copyright (c) 2003 Leo Simons.
005: All rights reserved.
006:
007: Permission is hereby granted, free of charge, to any person obtaining
008: a copy of this software and associated documentation files (the
009: "Software"), to deal in the Software without restriction, including
010: without limitation the rights to use, copy, modify, merge, publish,
011: distribute, sublicense, and/or sell copies of the Software, and to
012: permit persons to whom the Software is furnished to do so, subject to
013: the following conditions:
014:
015: The above copyright notice and this permission notice shall be
016: included in all copies or substantial portions of the Software.
017:
018: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
019: EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
020: MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
021: IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
022: CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
023: TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
024: SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
025: ==================================================================== */
026: package org.jicarilla.container.util;
027:
028: import org.jicarilla.container.Resolver;
029: import org.jicarilla.container.UnsatisfiableDependencyException;
030: import org.jicarilla.lang.Assert;
031:
032: import java.lang.reflect.InvocationTargetException;
033: import java.lang.reflect.Method;
034: import java.util.ArrayList;
035: import java.util.HashSet;
036: import java.util.List;
037: import java.util.Set;
038:
039: /**
040: * Utility methods that encapsulate reflection magic and heuristics to deal
041: * with type 2 components, especially type 2 components that implement
042: * awareness interfaces.
043: *
044: * @author <a href="mail at leosimons dot com">Leo Simons</a>
045: * @version $Id: Type2Util.java,v 1.4 2004/03/23 13:37:52 lsimons Exp $
046: */
047: public class Type2Util {
048: /**
049: * The postfix on interfaces that determines whether they are
050: * considered an "awareness" interface, ie, the string "Aware".
051: */
052: public final static String AWARENESS_INTERFACE_POSTFIX = "Aware";
053:
054: /**
055: * Retrieve all the methods of a class that are considered
056: * "awareness methods".
057: *
058: * @param clazz
059: * @return
060: */
061: public static Method[] getAwarenessMethods(final Class clazz) {
062: final Class[] interfaces = ReflectionUtil
063: .getAllInterfaces(clazz);
064:
065: final List methodList = new ArrayList();
066:
067: for (int i = 0; i < interfaces.length; i++) {
068: final Class interf = interfaces[i];
069: if (!interf.getName().endsWith(AWARENESS_INTERFACE_POSTFIX))
070: continue;
071:
072: getAwarenessMethod(interf, methodList);
073: }
074:
075: return (Method[]) methodList.toArray(new Method[methodList
076: .size()]);
077: }
078:
079: /**
080: * Figures out all the awareness methods of an instance, and calls each and
081: * everyone one of them using instances retrieved from the provided
082: * resolver. The keys fed to that resolver are the classes of the
083: * parameters of the awareness interfaces.
084: *
085: * @param instance
086: * @param container
087: * @throws IllegalAccessException
088: * @throws InvocationTargetException
089: */
090: public static void callAwarenessMethods(final Object instance,
091: final Resolver container) throws IllegalAccessException,
092: InvocationTargetException {
093: Assert.assertNotNull("instance argument may not be null",
094: instance);
095: Assert.assertNotNull("container argument may not be null",
096: container);
097:
098: final Method[] methods = Type2Util.getAwarenessMethods(instance
099: .getClass());
100: for (int i = 0; i < methods.length; i++) {
101: final Method method = methods[i];
102:
103: final Class key = method.getParameterTypes()[0];
104: final Object argument = container.get(key);
105: method.invoke(instance, new Object[] { argument });
106: }
107: }
108:
109: /**
110: * Retrieves the arguments to an array of awareness methods. If the
111: * provided array contains methods that are not awareness methods, the
112: * result is undefined.
113: *
114: * @param methods
115: * @return
116: */
117: public static Class[] getType2DependencyClasses(
118: final Method[] methods) {
119: Assert.assertNotNull("methods argument may not be null",
120: methods);
121:
122: final List allKeys = new ArrayList();
123: for (int i = 0; i < methods.length; i++) {
124: final Method method = methods[i];
125:
126: final Class key = method.getParameterTypes()[0];
127: allKeys.add(key);
128: }
129: return (Class[]) allKeys.toArray(new Class[allKeys.size()]);
130: }
131:
132: /**
133: * Determines whether the provided resolver contains all of the neccessary
134: * components to be able to call all of the "type 2 methods" (they don't
135: * need to be awareness methods) that are provided.
136: *
137: * @param clazz
138: * @param type2Methods
139: * @param dependencyProvider
140: */
141: public static void checkDepencenciesAreSatisfiable(
142: final Class clazz, final Method[] type2Methods,
143: final Resolver dependencyProvider) {
144: Assert.assertNotNull("clazz argument may not be null", clazz);
145: Assert.assertNotNull("type2Methods argument may not be null",
146: type2Methods);
147: Assert.assertNotNull(
148: "dependencyProvider argument may not be null",
149: dependencyProvider);
150:
151: final Set problematicKeys = new HashSet();
152: for (int i = 0; i < type2Methods.length; i++) {
153: final Method method = type2Methods[i];
154:
155: final Class key = method.getParameterTypes()[0];
156:
157: if (!dependencyProvider.contains(key))
158: problematicKeys.add(key);
159: }
160: if (problematicKeys.size() > 0)
161: throw new UnsatisfiableDependencyException(clazz,
162: problematicKeys);
163: }
164:
165: /**
166: * Retrieves the "awareness method" of an awareness interface and adds it
167: * to the provided list.
168: *
169: * @param interf
170: * @param methodList
171: */
172: protected static void getAwarenessMethod(final Class interf,
173: final List methodList) {
174: final Method[] methods = interf.getMethods();
175:
176: Assert.assertTrue(interf.getName()
177: + " must have a single public method, not "
178: + methods.length, methods.length == 1);
179:
180: final Method method = methods[0];
181: /* redundant! boolean accessible =
182: Modifier.isPublic(method.getModifiers());
183: if( !accessible )
184: continue;*/
185:
186: final Object returnType = method.getReturnType();
187: Assert.assertTrue("The " + interf.getName()
188: + " awareness method does not have a void return type",
189: Void.TYPE.equals(returnType));
190:
191: final Class[] parameterTypes = method.getParameterTypes();
192: Assert
193: .assertTrue(
194: "The "
195: + interf.getName()
196: + ""
197: + "awareness method does not have but a single parameter",
198: parameterTypes.length == 1);
199:
200: methodList.add(method);
201: }
202: }
|