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.model.modlet;
32
33 import java.lang.reflect.UndeclaredThrowableException;
34 import java.net.URL;
35 import java.text.MessageFormat;
36 import java.util.Enumeration;
37 import java.util.LinkedList;
38 import java.util.List;
39 import java.util.Locale;
40 import java.util.ResourceBundle;
41 import java.util.concurrent.Callable;
42 import java.util.concurrent.CancellationException;
43 import java.util.concurrent.ExecutionException;
44 import java.util.concurrent.Future;
45 import java.util.logging.Level;
46 import javax.xml.bind.JAXBElement;
47 import javax.xml.bind.JAXBException;
48 import javax.xml.bind.UnmarshalException;
49 import javax.xml.bind.Unmarshaller;
50 import javax.xml.validation.Schema;
51 import org.jomc.model.Module;
52 import org.jomc.model.Modules;
53 import org.jomc.model.Text;
54 import org.jomc.model.Texts;
55 import org.jomc.modlet.Model;
56 import org.jomc.modlet.ModelContext;
57 import org.jomc.modlet.ModelException;
58 import org.jomc.modlet.ModelProvider;
59
60
61
62
63
64
65
66
67 public class DefaultModelProvider implements ModelProvider
68 {
69
70
71
72
73
74
75
76
77 public static final String ENABLED_ATTRIBUTE_NAME = "org.jomc.model.modlet.DefaultModelProvider.enabledAttribute";
78
79
80
81
82
83
84 private static final String DEFAULT_ENABLED_PROPERTY_NAME =
85 "org.jomc.model.modlet.DefaultModelProvider.defaultEnabled";
86
87
88
89
90
91 private static final String DEPRECATED_DEFAULT_ENABLED_PROPERTY_NAME =
92 "org.jomc.model.DefaultModelProvider.defaultEnabled";
93
94
95
96
97
98
99
100 private static final Boolean DEFAULT_ENABLED = Boolean.TRUE;
101
102
103
104
105 private static volatile Boolean defaultEnabled;
106
107
108
109
110 private Boolean enabled;
111
112
113
114
115
116
117
118
119 public static final String MODULE_LOCATION_ATTRIBUTE_NAME =
120 "org.jomc.model.modlet.DefaultModelProvider.moduleLocationAttribute";
121
122
123
124
125
126
127 private static final String DEFAULT_MODULE_LOCATION_PROPERTY_NAME =
128 "org.jomc.model.modlet.DefaultModelProvider.defaultModuleLocation";
129
130
131
132
133
134 private static final String DEPRECATED_DEFAULT_MODULE_LOCATION_PROPERTY_NAME =
135 "org.jomc.model.DefaultModelProvider.defaultModuleLocation";
136
137
138
139
140
141
142 private static final String DEFAULT_MODULE_LOCATION = "META-INF/jomc.xml";
143
144
145
146
147 private static volatile String defaultModuleLocation;
148
149
150
151
152 private String moduleLocation;
153
154
155
156
157
158
159
160
161 public static final String VALIDATING_ATTRIBUTE_NAME =
162 "org.jomc.model.modlet.DefaultModelProvider.validatingAttribute";
163
164
165
166
167
168
169
170 private static final String DEFAULT_VALIDATING_PROPERTY_NAME =
171 "org.jomc.model.modlet.DefaultModelProvider.defaultValidating";
172
173
174
175
176
177
178
179 private static final Boolean DEFAULT_VALIDATING = Boolean.TRUE;
180
181
182
183
184
185
186 private static volatile Boolean defaultValidating;
187
188
189
190
191
192
193 private Boolean validating;
194
195
196
197
198 public DefaultModelProvider()
199 {
200 super();
201 }
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216 public static boolean isDefaultEnabled()
217 {
218 if ( defaultEnabled == null )
219 {
220 defaultEnabled =
221 Boolean.valueOf( System.getProperty( DEFAULT_ENABLED_PROPERTY_NAME,
222 System.getProperty( DEPRECATED_DEFAULT_ENABLED_PROPERTY_NAME,
223 Boolean.toString( DEFAULT_ENABLED ) ) ) );
224
225 }
226
227 return defaultEnabled;
228 }
229
230
231
232
233
234
235
236
237 public static void setDefaultEnabled( final Boolean value )
238 {
239 defaultEnabled = value;
240 }
241
242
243
244
245
246
247
248
249
250 public final boolean isEnabled()
251 {
252 if ( this.enabled == null )
253 {
254 this.enabled = isDefaultEnabled();
255 }
256
257 return this.enabled;
258 }
259
260
261
262
263
264
265
266
267 public final void setEnabled( final Boolean value )
268 {
269 this.enabled = value;
270 }
271
272
273
274
275
276
277
278
279
280
281
282
283
284 public static String getDefaultModuleLocation()
285 {
286 if ( defaultModuleLocation == null )
287 {
288 defaultModuleLocation =
289 System.getProperty( DEFAULT_MODULE_LOCATION_PROPERTY_NAME,
290 System.getProperty( DEPRECATED_DEFAULT_MODULE_LOCATION_PROPERTY_NAME,
291 DEFAULT_MODULE_LOCATION ) );
292
293 }
294
295 return defaultModuleLocation;
296 }
297
298
299
300
301
302
303
304
305 public static void setDefaultModuleLocation( final String value )
306 {
307 defaultModuleLocation = value;
308 }
309
310
311
312
313
314
315
316
317
318 public final String getModuleLocation()
319 {
320 if ( this.moduleLocation == null )
321 {
322 this.moduleLocation = getDefaultModuleLocation();
323 }
324
325 return this.moduleLocation;
326 }
327
328
329
330
331
332
333
334
335 public final void setModuleLocation( final String value )
336 {
337 this.moduleLocation = value;
338 }
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356 public static boolean isDefaultValidating()
357 {
358 if ( defaultValidating == null )
359 {
360 defaultValidating = Boolean.valueOf( System.getProperty(
361 DEFAULT_VALIDATING_PROPERTY_NAME, Boolean.toString( DEFAULT_VALIDATING ) ) );
362
363 }
364
365 return defaultValidating;
366 }
367
368
369
370
371
372
373
374
375
376
377
378 public static void setDefaultValidating( final Boolean value )
379 {
380 defaultValidating = value;
381 }
382
383
384
385
386
387
388
389
390
391
392
393
394 public final boolean isValidating()
395 {
396 if ( this.validating == null )
397 {
398 this.validating = isDefaultValidating();
399 }
400
401 return this.validating;
402 }
403
404
405
406
407
408
409
410
411
412
413 public final void setValidating( final Boolean value )
414 {
415 this.validating = value;
416 }
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433 public Modules findModules( final ModelContext context, final String model, final String location )
434 throws ModelException
435 {
436 if ( context == null )
437 {
438 throw new NullPointerException( "context" );
439 }
440 if ( model == null )
441 {
442 throw new NullPointerException( "model" );
443 }
444 if ( location == null )
445 {
446 throw new NullPointerException( "location" );
447 }
448
449 try
450 {
451 boolean contextValidating = this.isValidating();
452 if ( DEFAULT_VALIDATING == contextValidating
453 && context.getAttribute( VALIDATING_ATTRIBUTE_NAME ) instanceof Boolean )
454 {
455 contextValidating = (Boolean) context.getAttribute( VALIDATING_ATTRIBUTE_NAME );
456 }
457
458 final long t0 = System.nanoTime();
459 final Text text = new Text();
460 text.setLanguage( "en" );
461 text.setValue( getMessage( "contextModulesInfo", location ) );
462
463 final Modules modules = new Modules();
464 modules.setDocumentation( new Texts() );
465 modules.getDocumentation().setDefaultLanguage( "en" );
466 modules.getDocumentation().getText().add( text );
467
468 final ThreadLocal<Unmarshaller> threadLocalUnmarshaller = new ThreadLocal<Unmarshaller>();
469 final Schema schema = contextValidating ? context.createSchema( model ) : null;
470
471 class UnmarshallTask implements Callable<Module>
472 {
473
474 private final URL resource;
475
476 UnmarshallTask( final URL resource )
477 {
478 super();
479 this.resource = resource;
480 }
481
482 public Module call() throws ModelException
483 {
484 try
485 {
486 Module module = null;
487
488 if ( context.isLoggable( Level.FINEST ) )
489 {
490 context.log( Level.FINEST, getMessage( "processing", this.resource.toExternalForm() ),
491 null );
492
493 }
494
495 Unmarshaller u = threadLocalUnmarshaller.get();
496 if ( u == null )
497 {
498 u = context.createUnmarshaller( model );
499 u.setSchema( schema );
500 threadLocalUnmarshaller.set( u );
501 }
502
503 Object content = u.unmarshal( this.resource );
504 if ( content instanceof JAXBElement<?> )
505 {
506 content = ( (JAXBElement<?>) content ).getValue();
507 }
508
509 if ( content instanceof Module )
510 {
511 final Module m = (Module) content;
512
513 if ( context.isLoggable( Level.FINEST ) )
514 {
515 context.log( Level.FINEST, getMessage(
516 "foundModule", m.getName(), m.getVersion() == null ? "" : m.getVersion() ),
517 null );
518
519 }
520
521 module = m;
522 }
523 else if ( context.isLoggable( Level.WARNING ) )
524 {
525 context.log( Level.WARNING, getMessage( "ignoringDocument",
526 content == null ? "<>" : content.toString(),
527 this.resource.toExternalForm() ), null );
528
529 }
530
531 return module;
532 }
533 catch ( final UnmarshalException e )
534 {
535 String message = getMessage( e );
536 if ( message == null && e.getLinkedException() != null )
537 {
538 message = getMessage( e.getLinkedException() );
539 }
540
541 message = getMessage( "unmarshalException", this.resource.toExternalForm(),
542 message != null ? " " + message : "" );
543
544 throw new ModelException( message, e );
545 }
546 catch ( final JAXBException e )
547 {
548 String message = getMessage( e );
549 if ( message == null && e.getLinkedException() != null )
550 {
551 message = getMessage( e.getLinkedException() );
552 }
553
554 throw new ModelException( message, e );
555 }
556 }
557
558 }
559
560 final List<UnmarshallTask> tasks = new LinkedList<UnmarshallTask>();
561 final Enumeration<URL> resources = context.findResources( location );
562
563 while ( resources.hasMoreElements() )
564 {
565 tasks.add( new UnmarshallTask( resources.nextElement() ) );
566 }
567
568 int count = 0;
569 if ( context.getExecutorService() != null && tasks.size() > 1 )
570 {
571 for ( final Future<Module> task : context.getExecutorService().invokeAll( tasks ) )
572 {
573 final Module m = task.get();
574
575 if ( m != null )
576 {
577 modules.getModule().add( m );
578 count++;
579 }
580 }
581 }
582 else
583 {
584 for ( final UnmarshallTask task : tasks )
585 {
586 final Module m = task.call();
587 if ( m != null )
588 {
589 modules.getModule().add( m );
590 count++;
591 }
592 }
593 }
594
595 if ( context.isLoggable( Level.FINE ) )
596 {
597 context.log( Level.FINE, getMessage( "contextReport", count, location, System.nanoTime() - t0 ), null );
598 }
599
600 return modules.getModule().isEmpty() ? null : modules;
601 }
602 catch ( final CancellationException e )
603 {
604 throw new ModelException( getMessage( e ), e );
605 }
606 catch ( final InterruptedException e )
607 {
608 throw new ModelException( getMessage( e ), e );
609 }
610 catch ( final ExecutionException e )
611 {
612 if ( e.getCause() instanceof ModelException )
613 {
614 throw (ModelException) e.getCause();
615 }
616 else if ( e.getCause() instanceof RuntimeException )
617 {
618
619
620 if ( e.getCause().getCause() instanceof ModelException )
621 {
622 throw (ModelException) e.getCause().getCause();
623 }
624 else if ( e.getCause().getCause() instanceof RuntimeException )
625 {
626 throw (RuntimeException) e.getCause().getCause();
627 }
628 else if ( e.getCause().getCause() instanceof Error )
629 {
630 throw (Error) e.getCause().getCause();
631 }
632 else if ( e.getCause().getCause() instanceof Exception )
633 {
634
635 throw new UndeclaredThrowableException( e.getCause().getCause() );
636 }
637 else
638 {
639 throw (RuntimeException) e.getCause();
640 }
641 }
642 else if ( e.getCause() instanceof Error )
643 {
644 throw (Error) e.getCause();
645 }
646 else
647 {
648
649 throw new UndeclaredThrowableException( e.getCause() );
650 }
651 }
652 }
653
654
655
656
657
658
659
660
661
662
663
664
665
666 public Model findModel( final ModelContext context, final Model model ) throws ModelException
667 {
668 if ( context == null )
669 {
670 throw new NullPointerException( "context" );
671 }
672 if ( model == null )
673 {
674 throw new NullPointerException( "model" );
675 }
676
677 Model found = null;
678
679 boolean contextEnabled = this.isEnabled();
680 if ( DEFAULT_ENABLED == contextEnabled && context.getAttribute( ENABLED_ATTRIBUTE_NAME ) instanceof Boolean )
681 {
682 contextEnabled = (Boolean) context.getAttribute( ENABLED_ATTRIBUTE_NAME );
683 }
684
685 String contextModuleLocation = this.getModuleLocation();
686 if ( DEFAULT_MODULE_LOCATION.equals( contextModuleLocation )
687 && context.getAttribute( MODULE_LOCATION_ATTRIBUTE_NAME ) instanceof String )
688 {
689 contextModuleLocation = (String) context.getAttribute( MODULE_LOCATION_ATTRIBUTE_NAME );
690 }
691
692 if ( contextEnabled )
693 {
694 final Modules modules = this.findModules( context, model.getIdentifier(), contextModuleLocation );
695
696 if ( modules != null )
697 {
698 found = model.clone();
699 ModelHelper.addModules( found, modules );
700 }
701 }
702 else if ( context.isLoggable( Level.FINER ) )
703 {
704 context.log( Level.FINER, getMessage( "disabled", this.getClass().getSimpleName(),
705 model.getIdentifier() ), null );
706
707 }
708
709 return found;
710 }
711
712 private static String getMessage( final String key, final Object... args )
713 {
714 return MessageFormat.format( ResourceBundle.getBundle(
715 DefaultModelProvider.class.getName().replace( '.', '/' ), Locale.getDefault() ).getString( key ), args );
716
717 }
718
719 private static String getMessage( final Throwable t )
720 {
721 return t != null
722 ? t.getMessage() != null && t.getMessage().trim().length() > 0
723 ? t.getMessage()
724 : getMessage( t.getCause() )
725 : null;
726
727 }
728
729 }