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.NoPublicConstructorAvailableException;
029: import org.jicarilla.container.NoSatisfiableConstructorAvailableException;
030: import org.jicarilla.container.Resolver;
031: import org.jicarilla.lang.Assert;
032:
033: import java.lang.reflect.Constructor;
034: import java.lang.reflect.InvocationTargetException;
035: import java.lang.reflect.Modifier;
036: import java.util.Arrays;
037: import java.util.Comparator;
038: import java.util.HashSet;
039: import java.util.Set;
040:
041: /**
042: * Utility methods that encapsulate reflection magic and heuristics to deal
043: * with type 3 components.
044: *
045: * @author <a href="mail at leosimons dot com">Leo Simons</a>
046: * @version $Id: Type3Util.java,v 1.3 2004/03/23 13:37:52 lsimons Exp $
047: */
048: public class Type3Util {
049: public static Constructor getGreediestSatisfiableConstructor(
050: final Class clazz, final Resolver dependencyProvider) {
051: // this is the picocontainer algorithm
052: Assert.assertNotNull("clazz argument may not be null", clazz);
053: final Constructor[] constructors = clazz.getConstructors();
054:
055: if (constructors.length == 0)
056: throw new NoPublicConstructorAvailableException(clazz);
057:
058: sortConstructorsByGreediness(constructors);
059:
060: final Set unsatisfiedDependencies = new HashSet();
061: for (int i = 0; i < constructors.length; i++) {
062: final Constructor constructor = constructors[i];
063: final Class[] parameterTypes = constructor
064: .getParameterTypes();
065:
066: boolean found = true;
067: for (int j = 0; j < parameterTypes.length; j++) {
068: final Class parameterType = parameterTypes[j];
069: if (!dependencyProvider.contains(parameterType)) {
070: unsatisfiedDependencies.add(parameterType);
071: found = false;
072: // get all of them -- break;
073: }
074: }
075: if (!found)
076: continue;
077:
078: return constructor;
079: }
080:
081: throw new NoSatisfiableConstructorAvailableException(clazz,
082: constructors[constructors.length - 1],
083: unsatisfiedDependencies);
084: }
085:
086: public static Constructor getGreediestConstructor(final Class clazz) {
087: Assert.assertNotNull("clazz argument may not be null", clazz);
088: // PicoContainer uses a 'greediest satisfiable constructor
089: // algorithm'; here, we do a simpler 'greediest constructor
090: // algoritm'
091: final Constructor[] constructors = clazz.getConstructors();
092:
093: if (constructors.length == 0)
094: throw new NoPublicConstructorAvailableException(clazz);
095:
096: sortConstructorsByGreediness(constructors);
097:
098: final Constructor constructor = constructors[0];
099:
100: // can't happen if( !Modifier.isPublic( constructor.getModifiers() ) )
101: // throw new NoPublicConstructorAvailableException();
102:
103: return constructor;
104: }
105:
106: public static void sortConstructorsByGreediness(
107: final Constructor[] constr) {
108: Assert.assertNotNull("constr argument may not be null", constr);
109:
110: /*Constructor[] constructors = new Constructor[constr.length];
111: System.arraycopy( constr, 0, constructors, 0, constr.length );*/
112:
113: Arrays.sort(constr, new Comparator() {
114: public int compare(final Object o1, final Object o2) {
115: final Constructor c1 = (Constructor) o1;
116: final Constructor c2 = (Constructor) o2;
117:
118: // compare accessibility
119: if (Modifier.isPublic(c1.getModifiers())) {
120: if (!Modifier.isPublic(c2.getModifiers()))
121: return -1; // more important
122: } else if (Modifier.isPublic(c2.getModifiers())) {
123: return 1; // more important
124: }
125:
126: // both accessible, compare length
127: final int a1 = c1.getParameterTypes().length;
128: final int a2 = c2.getParameterTypes().length;
129:
130: if (a1 > a2)
131: return -1; // more important
132: if (a1 == a2)
133: return 0;
134:
135: return 1;
136: }
137: });
138: //return constructors;
139: }
140:
141: public static Object newType3Instance(final Class clazz,
142: final Constructor constructor,
143: final Resolver dependencyProvider)
144: throws IllegalAccessException, InvocationTargetException,
145: InstantiationException {
146: final Class[] parameterTypes = constructor.getParameterTypes();
147:
148: final Object instance;
149: if (parameterTypes.length > 0) {
150: final Object[] parameters = new Object[parameterTypes.length];
151: for (int i = 0; i < parameters.length; i++) {
152: // this should not throw an exception, since
153: // the container said it contained the parameter type!
154: parameters[i] = dependencyProvider
155: .get(parameterTypes[i]);
156: }
157: instance = constructor.newInstance(parameters);
158: } else {
159: instance = clazz.newInstance();
160: }
161: return instance;
162: }
163: }
|