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 package org.jomc.modlet;
32
33 import java.lang.reflect.InvocationTargetException;
34 import java.lang.reflect.Method;
35 import java.lang.reflect.Modifier;
36 import java.text.MessageFormat;
37 import java.util.ResourceBundle;
38 import java.util.logging.Level;
39
40
41
42
43
44
45
46
47
48 public class DefaultServiceFactory implements ServiceFactory
49 {
50
51
52
53
54
55
56 private static final String DEFAULT_ORDINAL_PROPERTY_NAME =
57 "org.jomc.modlet.DefaultServiceFactory.defaultOrdinal";
58
59
60
61
62
63
64 private static final Integer DEFAULT_ORDINAL = 0;
65
66
67
68
69 private static volatile Integer defaultOrdinal;
70
71
72
73
74 private Integer ordinal;
75
76
77
78
79 public DefaultServiceFactory()
80 {
81 super();
82 }
83
84
85
86
87
88
89
90
91
92
93
94
95
96 public static int getDefaultOrdinal()
97 {
98 if ( defaultOrdinal == null )
99 {
100 defaultOrdinal = Integer.getInteger( DEFAULT_ORDINAL_PROPERTY_NAME, DEFAULT_ORDINAL );
101 }
102
103 return defaultOrdinal;
104 }
105
106
107
108
109
110
111
112
113 public static void setDefaultOrdinal( final Integer value )
114 {
115 defaultOrdinal = value;
116 }
117
118
119
120
121
122
123
124
125
126 public final int getOrdinal()
127 {
128 if ( this.ordinal == null )
129 {
130 this.ordinal = getDefaultOrdinal();
131 }
132
133 return this.ordinal;
134 }
135
136
137
138
139
140
141
142
143 public final void setOrdinal( final Integer value )
144 {
145 this.ordinal = value;
146 }
147
148 public <T> T createServiceObject( final ModelContext context, final Service service, final Class<T> type )
149 throws ModelException
150 {
151 if ( context == null )
152 {
153 throw new NullPointerException( "context" );
154 }
155 if ( service == null )
156 {
157 throw new NullPointerException( "service" );
158 }
159 if ( type == null )
160 {
161 throw new NullPointerException( "type" );
162 }
163
164 try
165 {
166 final Class<?> clazz = context.findClass( service.getClazz() );
167
168 if ( clazz == null )
169 {
170 throw new ModelException( getMessage( "serviceNotFound", service.getOrdinal(), service.
171 getIdentifier(),
172 service.getClazz() ) );
173
174 }
175
176 if ( !type.isAssignableFrom( clazz ) )
177 {
178 throw new ModelException( getMessage( "illegalService", service.getOrdinal(), service.
179 getIdentifier(),
180 service.getClazz(), type.getName() ) );
181
182 }
183
184 final T serviceObject = clazz.asSubclass( type ).newInstance();
185
186 for ( int i = 0, s0 = service.getProperty().size(); i < s0; i++ )
187 {
188 final Property p = service.getProperty().get( i );
189 this.initProperty( context, serviceObject, p.getName(), p.getValue() );
190 }
191
192 return serviceObject;
193 }
194 catch ( final InstantiationException e )
195 {
196 throw new ModelException( getMessage( "failedCreatingObject", service.getClazz() ), e );
197 }
198 catch ( final IllegalAccessException e )
199 {
200 throw new ModelException( getMessage( "failedCreatingObject", service.getClazz() ), e );
201 }
202 }
203
204 private <T> void initProperty( final ModelContext context, final T object, final String propertyName,
205 final String propertyValue )
206 throws ModelException
207 {
208 if ( object == null )
209 {
210 throw new NullPointerException( "object" );
211 }
212 if ( propertyName == null )
213 {
214 throw new NullPointerException( "propertyName" );
215 }
216
217 try
218 {
219 final char[] chars = propertyName.toCharArray();
220
221 if ( Character.isLowerCase( chars[0] ) )
222 {
223 chars[0] = Character.toUpperCase( chars[0] );
224 }
225
226 final String methodNameSuffix = String.valueOf( chars );
227 Method getterMethod = null;
228
229 try
230 {
231 getterMethod = object.getClass().getMethod( "get" + methodNameSuffix );
232 }
233 catch ( final NoSuchMethodException e )
234 {
235 if ( context.isLoggable( Level.FINEST ) )
236 {
237 context.log( Level.FINEST, null, e );
238 }
239
240 getterMethod = null;
241 }
242
243 if ( getterMethod == null )
244 {
245 try
246 {
247 getterMethod = object.getClass().getMethod( "is" + methodNameSuffix );
248 }
249 catch ( final NoSuchMethodException e )
250 {
251 if ( context.isLoggable( Level.FINEST ) )
252 {
253 context.log( Level.FINEST, null, e );
254 }
255
256 getterMethod = null;
257 }
258 }
259
260 if ( getterMethod == null )
261 {
262 throw new ModelException( getMessage( "getterMethodNotFound", object.getClass().getName(),
263 propertyName ) );
264
265 }
266
267 final Class<?> propertyType = getterMethod.getReturnType();
268 Class<?> boxedPropertyType = propertyType;
269 Class<?> unboxedPropertyType = propertyType;
270
271 if ( Boolean.TYPE.equals( propertyType ) )
272 {
273 boxedPropertyType = Boolean.class;
274 }
275 else if ( Character.TYPE.equals( propertyType ) )
276 {
277 boxedPropertyType = Character.class;
278 }
279 else if ( Byte.TYPE.equals( propertyType ) )
280 {
281 boxedPropertyType = Byte.class;
282 }
283 else if ( Short.TYPE.equals( propertyType ) )
284 {
285 boxedPropertyType = Short.class;
286 }
287 else if ( Integer.TYPE.equals( propertyType ) )
288 {
289 boxedPropertyType = Integer.class;
290 }
291 else if ( Long.TYPE.equals( propertyType ) )
292 {
293 boxedPropertyType = Long.class;
294 }
295 else if ( Float.TYPE.equals( propertyType ) )
296 {
297 boxedPropertyType = Float.class;
298 }
299 else if ( Double.TYPE.equals( propertyType ) )
300 {
301 boxedPropertyType = Double.class;
302 }
303
304 if ( Boolean.class.equals( propertyType ) )
305 {
306 unboxedPropertyType = Boolean.TYPE;
307 }
308 else if ( Character.class.equals( propertyType ) )
309 {
310 unboxedPropertyType = Character.TYPE;
311 }
312 else if ( Byte.class.equals( propertyType ) )
313 {
314 unboxedPropertyType = Byte.TYPE;
315 }
316 else if ( Short.class.equals( propertyType ) )
317 {
318 unboxedPropertyType = Short.TYPE;
319 }
320 else if ( Integer.class.equals( propertyType ) )
321 {
322 unboxedPropertyType = Integer.TYPE;
323 }
324 else if ( Long.class.equals( propertyType ) )
325 {
326 unboxedPropertyType = Long.TYPE;
327 }
328 else if ( Float.class.equals( propertyType ) )
329 {
330 unboxedPropertyType = Float.TYPE;
331 }
332 else if ( Double.class.equals( propertyType ) )
333 {
334 unboxedPropertyType = Double.TYPE;
335 }
336
337 Method setterMethod = null;
338
339 try
340 {
341 setterMethod = object.getClass().getMethod( "set" + methodNameSuffix, boxedPropertyType );
342 }
343 catch ( final NoSuchMethodException e )
344 {
345 if ( context.isLoggable( Level.FINEST ) )
346 {
347 context.log( Level.FINEST, null, e );
348 }
349
350 setterMethod = null;
351 }
352
353 if ( setterMethod == null && !boxedPropertyType.equals( unboxedPropertyType ) )
354 {
355 try
356 {
357 setterMethod = object.getClass().getMethod( "set" + methodNameSuffix, unboxedPropertyType );
358 }
359 catch ( final NoSuchMethodException e )
360 {
361 if ( context.isLoggable( Level.FINEST ) )
362 {
363 context.log( Level.FINEST, null, e );
364 }
365
366 setterMethod = null;
367 }
368 }
369
370 if ( setterMethod == null )
371 {
372 throw new ModelException( getMessage( "setterMethodNotFound", object.getClass().getName(),
373 propertyName ) );
374
375 }
376
377 if ( boxedPropertyType.equals( Character.class ) )
378 {
379 if ( propertyValue == null || propertyValue.length() != 1 )
380 {
381 throw new ModelException( getMessage( "unsupportedCharacterValue", object.getClass().getName(),
382 propertyName ) );
383
384 }
385
386 setterMethod.invoke( object, propertyValue.charAt( 0 ) );
387 }
388 else if ( propertyValue != null )
389 {
390 invocation:
391 {
392 if ( boxedPropertyType.equals( String.class ) )
393 {
394 setterMethod.invoke( object, propertyValue );
395 break invocation;
396 }
397
398 try
399 {
400 setterMethod.invoke( object, boxedPropertyType.getConstructor( String.class ).
401 newInstance( propertyValue ) );
402
403 break invocation;
404 }
405 catch ( final NoSuchMethodException e1 )
406 {
407 if ( context.isLoggable( Level.FINEST ) )
408 {
409 context.log( Level.FINEST, null, e1 );
410 }
411 }
412
413 try
414 {
415 final Method valueOf = boxedPropertyType.getMethod( "valueOf", String.class );
416
417 if ( Modifier.isStatic( valueOf.getModifiers() )
418 && ( valueOf.getReturnType().equals( boxedPropertyType )
419 || valueOf.getReturnType().equals( unboxedPropertyType ) ) )
420 {
421 setterMethod.invoke( object, valueOf.invoke( null, propertyValue ) );
422 break invocation;
423 }
424 }
425 catch ( final NoSuchMethodException e2 )
426 {
427 if ( context.isLoggable( Level.FINEST ) )
428 {
429 context.log( Level.FINEST, null, e2 );
430 }
431 }
432
433 throw new ModelException( getMessage( "unsupportedPropertyType", object.getClass().getName(),
434 propertyName, propertyType.getName() ) );
435
436 }
437 }
438 else
439 {
440 setterMethod.invoke( object, (Object) null );
441 }
442 }
443 catch ( final IllegalAccessException e )
444 {
445 throw new ModelException( getMessage( "failedSettingProperty", propertyName, object.toString(),
446 object.getClass().getName() ), e );
447
448 }
449 catch ( final InvocationTargetException e )
450 {
451 throw new ModelException( getMessage( "failedSettingProperty", propertyName, object.toString(),
452 object.getClass().getName() ), e );
453
454 }
455 catch ( final InstantiationException e )
456 {
457 throw new ModelException( getMessage( "failedSettingProperty", propertyName, object.toString(),
458 object.getClass().getName() ), e );
459
460 }
461 }
462
463 private static String getMessage( final String key, final Object... arguments )
464 {
465 return MessageFormat.format( ResourceBundle.getBundle(
466 DefaultServiceFactory.class.getName().replace( '.', '/' ) ).getString( key ), arguments );
467
468 }
469
470 }