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
35
36 package org.exolab.castor.mapping.loader;
37
38 import java.lang.reflect.Constructor;
39 import java.lang.reflect.Modifier;
40 import java.io.Serializable;
41 import java.math.BigDecimal;
42 import java.math.BigInteger;
43 import java.util.Vector;
44
45 import org.castor.core.util.Messages;
46 import org.exolab.castor.types.Duration;
47
48
49
50
51
52
53
54
55
56 public class Types {
57
58
59
60
61 private static TypeInfo[] typeInfos;
62
63 static {
64 typeInfos = new TypeInfo[] {
65
66
67 new TypeInfo("other", null, java.lang.Object.class, false, null),
68 new TypeInfo("string", null, java.lang.String.class, true, null),
69 new TypeInfo("integer", java.lang.Integer.TYPE, java.lang.Integer.class, true,
70 Integer.valueOf(0)),
71 new TypeInfo("int", java.lang.Integer.TYPE, java.lang.Integer.TYPE, true,
72 Integer.valueOf(0)),
73 new TypeInfo("long", java.lang.Long.TYPE, java.lang.Long.class, true, Long.valueOf(0L)),
74 new TypeInfo("big-integer", null, java.math.BigInteger.class, true, BigInteger.valueOf(0)),
75 new TypeInfo("boolean", java.lang.Boolean.TYPE, java.lang.Boolean.class, true,
76 Boolean.FALSE),
77 new TypeInfo("double", java.lang.Double.TYPE, java.lang.Double.class, true,
78 Double.valueOf(0.0)),
79 new TypeInfo("float", java.lang.Float.TYPE, java.lang.Float.class, true,
80 Float.valueOf(0.0f)),
81 new TypeInfo("big-decimal", null, java.math.BigDecimal.class, true, BigDecimal.ZERO),
82 new TypeInfo("byte", java.lang.Byte.TYPE, java.lang.Byte.class, true,
83 Byte.valueOf((byte) 0)),
84 new TypeInfo("date", null, java.util.Date.class, true, null),
85 new TypeInfo("timestamp", null, java.sql.Timestamp.class, true, null),
86 new TypeInfo("sqldate", null, java.sql.Date.class, true, null),
87 new TypeInfo("sqltime", null, java.sql.Time.class, true, null),
88 new TypeInfo("short", java.lang.Short.TYPE, java.lang.Short.class, true,
89 Short.valueOf((short) 0)),
90 new TypeInfo("char", java.lang.Character.TYPE, java.lang.Character.class, true,
91 Character.valueOf((char) 0)),
92 new TypeInfo("bytes", null, byte[].class, false, null),
93 new TypeInfo("chars", null, char[].class, false, null),
94 new TypeInfo("strings", null, String[].class, false, null),
95 new TypeInfo("locale", null, java.util.Locale.class, true, null),
96 new TypeInfo("stream", null, java.io.InputStream.class, true, null),
97 new TypeInfo("clob", null, getClobClass(), true, null),
98 new TypeInfo("serializable", null, java.io.Serializable.class, false, null),
99
100
101
102
103
104 new TypeInfo("[Lbyte;", null, byte[].class, false, null),
105 new TypeInfo("[Lchar;", null, char[].class, false, null),
106 new TypeInfo("[Ldouble;", null, double[].class, false, null),
107 new TypeInfo("[Lfloat;", null, float[].class, false, null),
108 new TypeInfo("[Lint;", null, int[].class, false, null),
109 new TypeInfo("[Llong;", null, long[].class, false, null),
110 new TypeInfo("[Lshort;", null, int[].class, false, null),
111 new TypeInfo("[Lboolean;", null, int[].class, false, null),
112
113
114
115
116
117 new TypeInfo("duration", null, org.exolab.castor.types.Duration.class, false,
118 new Duration(0)),
119 new TypeInfo("xml-date", null, org.exolab.castor.types.Date.class, false,
120 new org.exolab.castor.types.Date(0)),
121 new TypeInfo("xml-time", null, org.exolab.castor.types.Time.class, false,
122 new org.exolab.castor.types.Time(0))
123
124 };
125 }
126
127
128
129
130
131
132
133
134
135
136
137
138 public static Class<?> typeFromName(ClassLoader loader, String typeName)
139 throws ClassNotFoundException {
140 for (TypeInfo typeInfo : typeInfos) {
141 if (typeName.equals(typeInfo.getShortName()))
142 return (typeInfo.getPrimitive() != null ? typeInfo.getPrimitive() : typeInfo.getJavaType());
143 }
144 if (loader != null) {
145 Class<?> aClass = Class.forName(typeName, false, loader);
146 return aClass;
147 }
148 return Class.forName(typeName);
149 }
150
151
152
153
154
155
156
157
158
159 public static Object getDefault(Class<?> type) {
160 for (TypeInfo typeInfo : typeInfos) {
161 if (typeInfo.getPrimitive() == type || typeInfo.getJavaType() == type)
162 return typeInfo.getDefaultValue();
163 }
164 return null;
165 }
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187 public static Class<?> typeFromPrimitive(Class<?> type) {
188
189 if ((type != null) && (type.isArray()) && !type.getComponentType().isPrimitive()) {
190 return typeFromPrimitive(type.getComponentType());
191 }
192
193 for (TypeInfo typeInfo : typeInfos) {
194 if (typeInfo.getPrimitive() == type) {
195 return typeInfo.getJavaType();
196 }
197 }
198 return type;
199 }
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219 public static boolean isSimpleType(Class<?> type) {
220 for (TypeInfo typeInfo : typeInfos) {
221 if (typeInfo.getJavaType() == type || typeInfo.getPrimitive() == type)
222 return true;
223 }
224 return false;
225 }
226
227
228
229
230
231
232
233
234 public static boolean isPrimitiveType(Class<?> type) {
235 for (TypeInfo typeInfo : typeInfos) {
236 if (typeInfo.getPrimitive() == type
237 || (typeInfo.getJavaType() == type && typeInfo.getPrimitive() != null)) {
238 return true;
239 }
240 }
241 return false;
242 }
243
244 private static final Vector<Class<?>> ENUMS = new Vector<>();
245
246 public static void addEnumType(Class<?> type) {
247 ENUMS.add(type);
248 }
249
250 public static boolean isEnumType(Class<?> type) {
251 return ENUMS.contains(type);
252 }
253
254 private static final Vector<Class<?>> CONVERTIBLE = new Vector<>();
255
256 public static void addConvertibleType(Class<?> type) {
257 CONVERTIBLE.add(type);
258 }
259
260 public static boolean isConvertibleType(Class<?> type) {
261 return CONVERTIBLE.contains(type);
262 }
263
264
265
266
267
268
269
270
271
272 public static Object newInstance(Class<?> type) throws IllegalStateException {
273 try {
274 return type.newInstance();
275 } catch (IllegalAccessException except) {
276
277 throw new IllegalStateException(
278 Messages.format("mapping.schemaNotConstructable", type.getName(), except.getMessage()));
279 } catch (InstantiationException except) {
280
281 throw new IllegalStateException(
282 Messages.format("mapping.schemaNotConstructable", type.getName(), except.getMessage()));
283 }
284 }
285
286
287
288
289
290
291
292
293
294
295 public static Object newInstance(Class<?> type, Object args[]) throws IllegalStateException {
296
297 if ((args == null) || (args.length == 0))
298 return newInstance(type);
299
300 try {
301 Constructor<?> cons = findConstructor(type, args);
302 return cons.newInstance(args);
303 } catch (NoSuchMethodException except) {
304 throw new IllegalStateException(
305 Messages.format("mapping.constructorNotFound", type.getName(), except.getMessage()));
306 } catch (java.lang.reflect.InvocationTargetException except) {
307
308 throw new IllegalStateException(
309 Messages.format("mapping.schemaNotConstructable", type.getName(), except.getMessage()));
310 } catch (IllegalAccessException except) {
311
312 throw new IllegalStateException(
313 Messages.format("mapping.schemaNotConstructable", type.getName(), except.getMessage()));
314 } catch (InstantiationException except) {
315
316 throw new IllegalStateException(
317 Messages.format("mapping.schemaNotConstructable", type.getName(), except.getMessage()));
318 }
319 }
320
321
322
323
324
325
326
327
328 public static boolean isConstructable(Class<?> type) {
329 return isConstructable(type, false);
330 }
331
332
333
334
335
336
337
338
339
340
341 public static boolean isConstructable(Class<?> type, boolean allowAbstractOrInterface) {
342 try {
343 if ((type.getModifiers() & Modifier.PUBLIC) == 0) {
344 return false;
345 }
346 if ((!allowAbstractOrInterface)
347 && ((type.getModifiers() & (Modifier.ABSTRACT | Modifier.INTERFACE)) != 0)) {
348 return false;
349 }
350 if ((type.getConstructor(new Class[0]).getModifiers() & Modifier.PUBLIC) != 0) {
351 return true;
352 }
353 } catch (NoSuchMethodException except) {
354
355 } catch (SecurityException except) {
356
357 }
358 return false;
359 }
360
361
362
363
364
365
366
367 public static boolean isSerializable(Class<?> type) {
368 return (Serializable.class.isAssignableFrom(type));
369 }
370
371
372
373
374
375
376
377 public static boolean isImmutable(Class<?> type) {
378 for (TypeInfo typeInfo : typeInfos) {
379 if (typeInfo.getJavaType() == type || typeInfo.getPrimitive() == type)
380 return typeInfo.immutable;
381 }
382 return false;
383 }
384
385
386
387
388
389
390
391 public static boolean isCloneable(Class<?> type) {
392 return (Cloneable.class.isAssignableFrom(type));
393 }
394
395
396
397
398
399
400
401
402
403
404 private static Constructor<?> findConstructor(Class<?> type, Object[] args)
405 throws NoSuchMethodException {
406
407 Constructor<?>[] constructors = type.getConstructors();
408 Constructor<?> cons = null;
409 int rank = 0;
410
411 for (int c = 0; c < constructors.length; c++) {
412 Class<?>[] paramTypes = constructors[c].getParameterTypes();
413 if (paramTypes.length != args.length)
414 continue;
415
416 int tmpRank = 0;
417 boolean matches = true;
418 for (int p = 0; p < paramTypes.length; p++) {
419 if (args[p] == null) {
420 if (paramTypes[p].isPrimitive()) {
421 matches = false;
422 break;
423 }
424
425 continue;
426 }
427
428
429 if (paramTypes[p] == args[p].getClass()) {
430 ++tmpRank;
431 continue;
432 }
433
434
435 if (paramTypes[p].isAssignableFrom(args[p].getClass())) {
436
437 continue;
438 }
439
440 if (paramTypes[p].isPrimitive()) {
441 Class<?> pType = typeFromPrimitive(paramTypes[p]);
442 if (pType.isAssignableFrom(args[p].getClass())) {
443
444 continue;
445 }
446 }
447 matches = false;
448 break;
449 }
450
451 if (matches) {
452 if (tmpRank == paramTypes.length)
453 return constructors[c];
454 if ((cons == null) || (tmpRank > rank)) {
455 cons = constructors[c];
456 rank = tmpRank;
457 }
458 }
459 }
460
461 if (cons == null)
462 throw new NoSuchMethodException();
463
464 return cons;
465 }
466
467
468
469
470 static class TypeInfo {
471
472 private final String shortName;
473
474
475 private final Class<?> primitive;
476
477
478 private final Class<?> javaType;
479
480
481 private final boolean immutable;
482
483
484 private final Object defaultValue;
485
486 TypeInfo(final String shortName, final Class<?> primitive, final Class<?> javaType,
487 final boolean immutable, final Object defaultValue) {
488 this.shortName = shortName;
489 this.primitive = primitive;
490 this.javaType = javaType;
491 this.immutable = immutable;
492 this.defaultValue = defaultValue;
493 }
494
495 Class<?> getJavaType() {
496 return javaType;
497 }
498
499 String getShortName() {
500 return shortName;
501 }
502
503 Class<?> getPrimitive() {
504 return primitive;
505 }
506
507 boolean isImmutable() {
508 return immutable;
509 }
510
511 Object getDefaultValue() {
512 return defaultValue;
513 }
514 }
515
516
517
518
519
520
521
522 private static final Class<?> getClobClass() {
523 Class<?> type = null;
524 try {
525 type = Class.forName("java.sql.Clob");
526 } catch (ClassNotFoundException cnfe) {
527
528
529 }
530 return type;
531 }
532
533 }