1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.callbackparams.support;
18
19 import java.lang.reflect.Constructor;
20 import java.lang.reflect.InvocationTargetException;
21 import java.util.Arrays;
22 import java.util.HashMap;
23 import java.util.Map;
24
25
26
27
28
29
30
31
32 public class ClassWrapper {
33
34 private Class wrappedClass;
35
36
37
38
39 private Map constructors = new HashMap();
40
41 public ClassWrapper(Class wrappedClass) {
42 this.wrappedClass = wrappedClass;
43 }
44
45 public Class getWrappedClass() {
46 return wrappedClass;
47 }
48
49
50
51
52
53 public Object newInstance() {
54 try {
55 Constructor constr = wrappedClass.getDeclaredConstructor(null);
56 try {
57 constr.setAccessible(true);
58 } catch(SecurityException neverMind) {
59 return constr.newInstance(null);
60 } catch (Exception x) {
61 throw ExceptionUtil.unchecked(x);
62 }
63 }
64
65
66
67
68
69 public Object newInstance(Object singleConstructorArgument) {
70 final Constructor constr;
71 if (null == singleConstructorArgument) {
72 constr = chooseNullConstructor();
73 if (0 == constr.getParameterTypes().length) {
74 return newInstance();
75 }
76 } else {
77 constr = chooseConstructor(singleConstructorArgument.getClass());
78 }
79 try {
80 return constr.newInstance(new Object[] {singleConstructorArgument});
81 } catch (Exception x) {
82 throw new Error(x);
83 }
84 }
85
86 public Object newInstance(final Object[] multiargConstructorArguments) {
87 final Constructor[] constructors = getWrappedClass().getConstructors();
88 for (int i = 0 ; i < constructors.length ; ++i) {
89 if (multiargConstructorArguments.length
90 != constructors[i].getParameterTypes().length) {
91 continue;
92 }
93 try {
94 return constructors[i]
95 .newInstance(multiargConstructorArguments);
96 } catch (InstantiationException couldTheClassBeAbstract) {
97 throw new Error(couldTheClassBeAbstract);
98 } catch (IllegalAccessException shouldNeverHappen) {
99 throw new Error(shouldNeverHappen);
100 } catch (IllegalArgumentException unsuiteableConstructor) {
101 continue;
102 } catch (InvocationTargetException ex) {
103 throwUnchecked(ex);
104 }
105 }
106 throw new Error("Could not find any suiteable constructor for arguments"
107 + Arrays.asList(multiargConstructorArguments));
108 }
109
110 private Constructor chooseNullConstructor() {
111 Constructor constr = (Constructor) this.constructors.get(null);
112 if (null != constr) {
113 return constr;
114
115 } else {
116 try {
117 constr = getWrappedClass().getConstructor(new Class[]{});
118 } catch (NoSuchMethodException x) {
119 final Constructor[] allConstructors =
120 getWrappedClass().getConstructors();
121 for (int i = 0 ; i < allConstructors.length ; ++i) {
122 final Class[] paramTypes =
123 allConstructors[i].getParameterTypes();
124 if (1 == paramTypes.length
125 && false == paramTypes[0].isPrimitive()) {
126 constr = allConstructors[0];
127 break;
128 }
129 }
130 }
131 if (null == constr) {
132 throw new NoSuchMethodError("Cannot find any constructor that"
133 + " accepts as null as argument");
134 } else {
135 this.constructors.put(null, constr);
136 return constr;
137 }
138 }
139
140 }
141
142 private Constructor chooseConstructor(Class argumentClass) {
143 Constructor constr = (Constructor) this.constructors.get(argumentClass);
144 if (null != constr) {
145 return constr;
146
147 } else {
148 constr = lookupExactOrPrimitiveConstructor(argumentClass);
149 if (null == constr) {
150 final Constructor[] allConstructors =
151 getWrappedClass().getConstructors();
152 for (int i = 0 ; i < allConstructors.length ; ++i) {
153 final Class[] paramTypes =
154 allConstructors[i].getParameterTypes();
155 if (1 == paramTypes.length
156 && paramTypes[0].isAssignableFrom(argumentClass)) {
157 constr = allConstructors[i];
158 break;
159 }
160 }
161 }
162 if (null == constr) {
163 throw new NoSuchMethodError("Cannot find any constructor that"
164 + " accepts a single " + argumentClass + " argument.");
165 } else {
166 this.constructors.put(argumentClass, constr);
167 return constr;
168 }
169 }
170 }
171
172 private Constructor lookupExactOrPrimitiveConstructor(Class argumentClass) {
173 Class[] paramClassArray = {argumentClass};
174 try {
175 return getWrappedClass().getConstructor(paramClassArray);
176 } catch (NoSuchMethodException x) {
177 if (Integer.class == argumentClass) {
178 paramClassArray[0] = int.class;
179 } else if (Boolean.class == argumentClass) {
180 paramClassArray[0] = boolean.class;
181 } else if (Character.class == argumentClass) {
182 paramClassArray[0] = char.class;
183 } else if (Byte.class == argumentClass) {
184 paramClassArray[0] = byte.class;
185 } else if (Long.class == argumentClass) {
186 paramClassArray[0] = long.class;
187 } else if (Double.class == argumentClass) {
188 paramClassArray[0] = double.class;
189 } else if (Float.class == argumentClass) {
190 paramClassArray[0] = float.class;
191 } else if (Short.class == argumentClass) {
192 paramClassArray[0] = short.class;
193 } else {
194 return null;
195 }
196 try {
197 return getWrappedClass().getConstructor(paramClassArray);
198 } catch (NoSuchMethodException ex) {
199 return null;
200 }
201 }
202 }
203
204 private void throwUnchecked(InvocationTargetException x)
205 throws RuntimeException, Error {
206 Throwable t = x.getTargetException();
207 if (t instanceof RuntimeException) {
208 throw (RuntimeException)t;
209 } else if (t instanceof Error) {
210 throw (Error)t;
211 } else {
212 throw new Error(t);
213 }
214 }
215 }