1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package org.nuiton.util;
35
36 import org.apache.commons.beanutils.BeanUtils;
37 import org.apache.commons.beanutils.ConvertUtils;
38 import org.apache.commons.beanutils.MethodUtils;
39 import org.apache.commons.logging.Log;
40 import org.apache.commons.logging.LogFactory;
41
42 import java.io.ByteArrayInputStream;
43 import java.io.ByteArrayOutputStream;
44 import java.io.ObjectInputStream;
45 import java.io.ObjectOutputStream;
46 import java.lang.reflect.Array;
47 import java.lang.reflect.Constructor;
48 import java.lang.reflect.InvocationTargetException;
49 import java.lang.reflect.Method;
50 import java.util.ArrayList;
51 import java.util.Arrays;
52 import java.util.Collection;
53 import java.util.LinkedList;
54 import java.util.List;
55
56 import static org.nuiton.i18n.I18n.t;
57
58
59
60
61
62
63
64
65
66
67
68 public class ObjectUtil {
69
70
71 private static final Log log = LogFactory.getLog(ObjectUtil.class);
72
73
74 public static final String CLASS_METHOD_SEPARATOR = "#";
75
76 protected static final Integer ZERO = 0;
77
78 protected static final Character ZEROC = (char) 0;
79
80 protected static final Float ZEROF = 0f;
81
82 protected static final Long ZEROL = 0l;
83
84 protected static final Double ZEROD = 0.;
85
86 protected static final Byte ZEROB = 0;
87
88
89
90
91
92
93 private ObjectUtil() {
94 }
95
96
97
98
99
100
101
102
103
104
105
106
107
108 public static <E> E newInstance(Class<E> clazz,
109 Collection<?> args,
110 boolean nullIfMissing) {
111 Constructor<E>[] constructors =
112 (Constructor<E>[]) clazz.getConstructors();
113 if (constructors.length != 1) {
114 throw new IllegalArgumentException(
115 t("nuitonutil.error.class.with.more.than.one.constructor",
116 clazz));
117 }
118
119
120 List<?> container = new LinkedList(args);
121
122 Constructor<E> constructor = constructors[0];
123 Class<?>[] paramTypes = constructor.getParameterTypes();
124 Object[] params = new Object[paramTypes.length];
125
126 for (int i = 0; i < paramTypes.length; i++) {
127 Object o = choiceArgument(paramTypes[i], container, nullIfMissing);
128 params[i] = o;
129 }
130
131 try {
132 E result = constructor.newInstance(params);
133 return result;
134 } catch (Exception eee) {
135 throw new IllegalArgumentException(t(
136 t("nuitonutil.error.cant.instanciate.class",
137 clazz, Arrays.toString(params))), eee);
138 }
139 }
140
141
142
143
144
145
146
147
148
149
150
151 static protected Object choiceArgument(Class<?> clazz,
152 List args,
153 boolean nullIfMissing) {
154 Object result = null;
155 boolean addResult = false;
156 for (Object o : args) {
157 if (o != null) {
158 if (o instanceof Class<?> &&
159 clazz.isAssignableFrom((Class<?>) o)) {
160
161
162
163 result = newInstance((Class<?>) o, args, nullIfMissing);
164 addResult = true;
165 break;
166 } else if (clazz.isInstance(o)) {
167
168
169 result = o;
170 break;
171 }
172 }
173 }
174
175 if (addResult) {
176
177
178
179 args.add(0, result);
180 }
181
182
183 if (result == null && !nullIfMissing) {
184 throw new IllegalArgumentException(t(
185 t("nuitonutil.error.unfound.assignable.argument",
186 clazz, args)));
187 }
188 return result;
189 }
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209 public static Object create(String classnameAndProperties) throws
210 ClassNotFoundException,
211 InstantiationException,
212 IllegalAccessException,
213 InvocationTargetException,
214 NoSuchMethodException {
215 int p = classnameAndProperties.indexOf('(');
216 int l = classnameAndProperties.lastIndexOf(')');
217 String[] properties = null;
218 String classname;
219 if (p != -1) {
220 String tmp = classnameAndProperties.substring(p + 1, l);
221 properties = StringUtil.split(tmp, ",");
222 classname = classnameAndProperties.substring(0, p);
223 } else {
224 classname = classnameAndProperties;
225 }
226 ClassLoader loader = Thread.currentThread().getContextClassLoader();
227 Class<?> clazz = loader.loadClass(classname);
228 Object o = clazz.getConstructor().newInstance();
229 if (properties != null) {
230 for (String prop : properties) {
231 int e = prop.indexOf('=');
232 String propName = prop.substring(0, e).trim();
233 String propValue = prop.substring(e + 1).trim();
234 if (propValue.charAt(0) == '"' &&
235 propValue.charAt(propValue.length() - 1) == '"') {
236 propValue = propValue.substring(1, propValue.length() - 1);
237 } else if (propValue.charAt(0) == '\'' &&
238 propValue.charAt(propValue.length() - 1) == '\'') {
239 propValue = propValue.substring(1, propValue.length() - 1);
240 }
241 BeanUtils.setProperty(o, propName, propValue);
242 }
243 }
244 return o;
245 }
246
247 static protected Object convert(String v, Class<?> clazz) {
248 Object t = ConvertUtils.convert(v, clazz);
249
250 if (t != null &&
251 !String.class.getName().equals(clazz.getName()) &&
252 String.class.getName().equals(t.getClass().getName())) {
253 throw new IllegalArgumentException(String.format(
254 "Can convert argument to correct type. %s can't be" +
255 " converted from String to %s conversion is done to %s",
256 v, clazz.getName(), t.getClass().getName()));
257 }
258 return t;
259 }
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276 public static <E extends Cloneable> E clone(E e) throws CloneNotSupportedException {
277 try {
278 E result = (E) MethodUtils.invokeExactMethod(e, "clone", null);
279 return result;
280 } catch (Exception eee) {
281
282
283 log.error("Can't clone object", eee);
284 throw new CloneNotSupportedException();
285 }
286 }
287
288
289
290
291
292
293
294
295
296 public static <E> E deepClone(E e) throws CloneNotSupportedException {
297 try {
298 ByteArrayOutputStream bos = new ByteArrayOutputStream();
299 ObjectOutputStream oos = new ObjectOutputStream(bos);
300 try {
301 oos.writeObject(e);
302 } finally {
303 oos.close();
304 }
305
306 ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
307 E result;
308 ObjectInputStream ois = new ObjectInputStream(bis);
309 try {
310 result = (E) ois.readObject();
311 } finally {
312 ois.close();
313 }
314
315 return result;
316 } catch (Exception eee) {
317
318
319 log.error("Can't clone object", eee);
320 throw new CloneNotSupportedException();
321 }
322 }
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337 public static Object call(Object o, Method m, String... params)
338 throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
339 Class<?>[] types = m.getParameterTypes();
340 if (!m.isVarArgs() && params.length != types.length) {
341 throw new IllegalArgumentException(String.format(
342 "Bad number params we have %1$s parameters and waiting %2$s.",
343 params.length, types.length));
344 }
345
346 int last = types.length;
347 if (m.isVarArgs()) {
348
349 last--;
350 }
351
352 Object[] parameters = new Object[types.length];
353 for (int i = 0; i < last; i++) {
354 String v = params[i];
355 Class<?> clazz = types[i];
356 Object t = convert(v, clazz);
357 parameters[i] = t;
358 }
359
360 if (m.isVarArgs()) {
361 Class<?> clazz = types[last];
362 clazz = clazz.getComponentType();
363 List<Object> tmp = new ArrayList<Object>();
364 for (int i = last; i < params.length; i++) {
365 String v = params[i];
366 Object t = convert(v, clazz);
367 tmp.add(t);
368 }
369 parameters[last] = tmp.toArray((Object[]) Array.newInstance(clazz, tmp.size()));
370 }
371
372 if (log.isDebugEnabled()) {
373 log.debug(t("nuitonutil.debug.objectutil.invoke", m, Arrays.toString(parameters)));
374 }
375 Object result = m.invoke(o, parameters);
376 return result;
377 }
378
379
380
381
382
383
384
385
386
387 public static List<Method> getMethod(Class<?> clazz,
388 String methodName,
389 boolean ignoreCase) {
390 List<Method> result = new ArrayList<Method>();
391
392 Method[] methods = clazz.getMethods();
393 for (Method m : methods) {
394 if (ignoreCase && methodName.equalsIgnoreCase(m.getName()) ||
395 methodName.equals(m.getName())) {
396 result.add(m);
397 }
398 }
399
400 return result;
401 }
402
403
404
405
406
407
408
409
410
411
412 static public List<Method> getMethod(String name, boolean ignoreCase) {
413 Class<?> clazz;
414 String className;
415 String methodName;
416
417
418 int sep = name.lastIndexOf(CLASS_METHOD_SEPARATOR);
419 if (sep == -1) {
420 throw new IllegalArgumentException(String.format(
421 "Can't find method in %s", name));
422 } else {
423 className = name.substring(0, sep);
424 methodName = name.substring(sep + 1);
425 }
426
427
428 try {
429 clazz = Class.forName(className);
430 } catch (ClassNotFoundException eee) {
431 throw new IllegalArgumentException(String.format(
432 "Can't find class %s", className));
433 }
434
435 List<Method> result = ObjectUtil.getMethod(clazz, methodName, ignoreCase);
436 return result;
437 }
438
439 public static Object newInstance(String constructorWithParams) throws ClassNotFoundException {
440 int p = constructorWithParams.indexOf('(');
441 int l = constructorWithParams.lastIndexOf(')');
442 String[] params = null;
443 String classname;
444 if (p != -1) {
445 String tmp = constructorWithParams.substring(p + 1, l);
446 params = StringUtil.split(tmp, ",");
447 classname = constructorWithParams.substring(0, p);
448 } else {
449 classname = constructorWithParams;
450 }
451 Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass(classname);
452 Object result = newInstance(clazz, params);
453 return result;
454 }
455
456
457
458
459
460
461
462
463
464
465
466
467
468 public static <T> T newInstance(Class<T> clazz, String... params)
469 throws IllegalArgumentException {
470 if (params == null) {
471 params = StringUtil.EMPTY_STRING_ARRAY;
472 }
473 List<Constructor<T>> constructors = getConstructor(clazz, params.length);
474
475 for (Constructor<T> c : constructors) {
476 try {
477 Class<?>[] types = c.getParameterTypes();
478
479 int last = types.length;
480 if (c.isVarArgs()) {
481
482 last--;
483 }
484
485 Object[] parameters = new Object[types.length];
486 for (int i = 0; i < last; i++) {
487 String v = params[i];
488 Class<?> argClazz = types[i];
489 Object t = convert(v, argClazz);
490 parameters[i] = t;
491 }
492
493 if (c.isVarArgs()) {
494
495
496 Class<?> argClazz = types[last];
497
498
499 argClazz = argClazz.getComponentType();
500 List<Object> tmp = new ArrayList<Object>();
501 for (int i = last; i < params.length; i++) {
502 String v = params[i];
503 Object t = convert(v, argClazz);
504 tmp.add(t);
505 }
506 parameters[last] =
507 tmp.toArray((Object[]) Array.newInstance(
508 argClazz, tmp.size()));
509 }
510
511 if (log.isDebugEnabled()) {
512 log.debug(t("nuitonutil.debug.objectutil.create",
513 clazz, Arrays.toString(parameters)));
514 }
515 T result = c.newInstance(parameters);
516
517 return result;
518 } catch (Exception eee) {
519
520 if (log.isDebugEnabled()) {
521 log.debug("Creation failed try with next constructor");
522 }
523 }
524 }
525 throw new IllegalArgumentException(
526 t("nuitonutil.debug.objectutil.instantiate",
527 clazz, Arrays.toString(params)));
528 }
529
530
531
532
533
534
535
536
537
538
539
540 @SuppressWarnings("unchecked")
541 public static <T> List<Constructor<T>> getConstructor(Class<T> clazz,
542 int paramNumber) {
543 List<Constructor<T>> result = new ArrayList<Constructor<T>>();
544 Constructor<T>[] constructors =
545 (Constructor<T>[]) clazz.getConstructors();
546 for (Constructor<T> c : constructors) {
547 if (paramNumber < 0 ||
548 c.isVarArgs() &&
549 c.getParameterTypes().length <= paramNumber - 1 ||
550 c.getParameterTypes().length == paramNumber) {
551 result.add(c);
552 }
553 }
554
555 return result;
556 }
557
558
559
560
561
562
563
564
565
566 public static boolean isNullValue(Object value) {
567 if (value == null) {
568 return true;
569 }
570 Class<?> type = value.getClass();
571
572
573 if (type.isPrimitive()) {
574 type = MethodUtils.getPrimitiveWrapper(type);
575
576 if (Boolean.class.isAssignableFrom(type)) {
577 return Boolean.FALSE.equals(value);
578 }
579 if (Integer.class.isAssignableFrom(type)) {
580 return ZERO.equals(value);
581 }
582 if (Character.class.isAssignableFrom(type)) {
583 return ZEROC.equals(value);
584 }
585 if (Float.class.isAssignableFrom(type)) {
586 return ZEROF.equals(value);
587 }
588 if (Long.class.isAssignableFrom(type)) {
589 return ZEROL.equals(value);
590 }
591 if (Double.class.isAssignableFrom(type)) {
592 return ZEROD.equals(value);
593 }
594 if (Byte.class.isAssignableFrom(type)) {
595 return ZEROB.equals(value);
596 }
597 }
598 return false;
599 }
600
601 public static boolean isNullValue(boolean value) {
602 return Boolean.FALSE.equals(value);
603 }
604
605 public static boolean isNullValue(byte value) {
606 return value == ZEROB;
607 }
608
609 public static boolean isNullValue(int value) {
610 return value == ZEROB;
611 }
612
613 public static boolean isNullValue(char value) {
614 return value == ZEROC;
615 }
616
617 public static boolean isNullValue(float value) {
618 return value == ZEROF;
619 }
620
621 public static boolean isNullValue(double value) {
622 return value == ZEROD;
623 }
624
625
626
627
628
629
630
631 public static boolean isPrimitive(Class<?> clazz) {
632 return clazz.isPrimitive() || clazz == Boolean.class
633 || clazz == Byte.class || clazz == Character.class
634 || clazz == Short.class || clazz == Integer.class
635 || clazz == Long.class || clazz == Float.class
636 || clazz == Double.class;
637 }
638
639 }
640