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.UndeclaredThrowableException;
34 import java.net.MalformedURLException;
35 import java.net.URI;
36 import java.net.URISyntaxException;
37 import java.net.URL;
38 import java.text.MessageFormat;
39 import java.util.ArrayList;
40 import java.util.Enumeration;
41 import java.util.HashSet;
42 import java.util.List;
43 import java.util.ResourceBundle;
44 import java.util.Set;
45 import java.util.concurrent.Callable;
46 import java.util.concurrent.CancellationException;
47 import java.util.concurrent.ExecutionException;
48 import java.util.concurrent.Future;
49 import java.util.logging.Level;
50 import javax.xml.bind.JAXBContext;
51 import javax.xml.bind.JAXBElement;
52 import javax.xml.bind.JAXBException;
53 import javax.xml.bind.UnmarshalException;
54 import javax.xml.bind.Unmarshaller;
55
56
57
58
59
60
61
62
63 public class DefaultModletProvider implements ModletProvider
64 {
65
66
67
68
69
70
71
72
73 public static final String ENABLED_ATTRIBUTE_NAME = "org.jomc.modlet.DefaultModletProvider.enabledAttribute";
74
75
76
77
78
79
80
81 private static final String DEFAULT_ENABLED_PROPERTY_NAME =
82 "org.jomc.modlet.DefaultModletProvider.defaultEnabled";
83
84
85
86
87
88
89
90 private static final Boolean DEFAULT_ENABLED = Boolean.TRUE;
91
92
93
94
95 private static volatile Boolean defaultEnabled;
96
97
98
99
100 private volatile Boolean enabled;
101
102
103
104
105
106
107
108
109 public static final String MODLET_LOCATION_ATTRIBUTE_NAME =
110 "org.jomc.modlet.DefaultModletProvider.modletLocationAttribute";
111
112
113
114
115
116
117
118 private static final String DEFAULT_MODLET_LOCATION_PROPERTY_NAME =
119 "org.jomc.modlet.DefaultModletProvider.defaultModletLocation";
120
121
122
123
124
125
126 private static final String DEFAULT_MODLET_LOCATION = "META-INF/jomc-modlet.xml";
127
128
129
130
131 private static volatile String defaultModletLocation;
132
133
134
135
136 private volatile String modletLocation;
137
138
139
140
141
142
143
144
145 public static final String VALIDATING_ATTRIBUTE_NAME =
146 "org.jomc.modlet.DefaultModletProvider.validatingAttribute";
147
148
149
150
151
152
153
154 private static final String DEFAULT_VALIDATING_PROPERTY_NAME =
155 "org.jomc.modlet.DefaultModletProvider.defaultValidating";
156
157
158
159
160
161
162
163 private static final Boolean DEFAULT_VALIDATING = Boolean.TRUE;
164
165
166
167
168
169
170 private static volatile Boolean defaultValidating;
171
172
173
174
175
176
177 private volatile Boolean validating;
178
179
180
181
182
183
184
185 private static final String DEFAULT_ORDINAL_PROPERTY_NAME =
186 "org.jomc.modlet.DefaultModletProvider.defaultOrdinal";
187
188
189
190
191
192
193
194 private static final Integer DEFAULT_ORDINAL = 0;
195
196
197
198
199
200
201 private static volatile Integer defaultOrdinal;
202
203
204
205
206
207
208 private volatile Integer ordinal;
209
210
211
212
213 public DefaultModletProvider()
214 {
215 super();
216 }
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232 public static boolean isDefaultEnabled()
233 {
234 if ( defaultEnabled == null )
235 {
236 defaultEnabled = Boolean.valueOf( System.getProperty(
237 DEFAULT_ENABLED_PROPERTY_NAME, Boolean.toString( DEFAULT_ENABLED ) ) );
238
239 }
240
241 return defaultEnabled;
242 }
243
244
245
246
247
248
249
250
251 public static void setDefaultEnabled( final Boolean value )
252 {
253 defaultEnabled = value;
254 }
255
256
257
258
259
260
261
262
263
264 public final boolean isEnabled()
265 {
266 if ( this.enabled == null )
267 {
268 this.enabled = isDefaultEnabled();
269 }
270
271 return this.enabled;
272 }
273
274
275
276
277
278
279
280
281 public final void setEnabled( final Boolean value )
282 {
283 this.enabled = value;
284 }
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299 public static String getDefaultModletLocation()
300 {
301 if ( defaultModletLocation == null )
302 {
303 defaultModletLocation = System.getProperty(
304 DEFAULT_MODLET_LOCATION_PROPERTY_NAME, DEFAULT_MODLET_LOCATION );
305
306 }
307
308 return defaultModletLocation;
309 }
310
311
312
313
314
315
316
317
318 public static void setDefaultModletLocation( final String value )
319 {
320 defaultModletLocation = value;
321 }
322
323
324
325
326
327
328
329
330
331 public final String getModletLocation()
332 {
333 if ( this.modletLocation == null )
334 {
335 this.modletLocation = getDefaultModletLocation();
336 }
337
338 return this.modletLocation;
339 }
340
341
342
343
344
345
346
347
348 public final void setModletLocation( final String value )
349 {
350 this.modletLocation = value;
351 }
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369 public static boolean isDefaultValidating()
370 {
371 if ( defaultValidating == null )
372 {
373 defaultValidating = Boolean.valueOf( System.getProperty(
374 DEFAULT_VALIDATING_PROPERTY_NAME, Boolean.toString( DEFAULT_VALIDATING ) ) );
375
376 }
377
378 return defaultValidating;
379 }
380
381
382
383
384
385
386
387
388
389
390
391 public static void setDefaultValidating( final Boolean value )
392 {
393 defaultValidating = value;
394 }
395
396
397
398
399
400
401
402
403
404
405
406
407 public final boolean isValidating()
408 {
409 if ( this.validating == null )
410 {
411 this.validating = isDefaultValidating();
412 }
413
414 return this.validating;
415 }
416
417
418
419
420
421
422
423
424
425
426 public final void setValidating( final Boolean value )
427 {
428 this.validating = value;
429 }
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445 public static int getDefaultOrdinal()
446 {
447 if ( defaultOrdinal == null )
448 {
449 defaultOrdinal = Integer.getInteger( DEFAULT_ORDINAL_PROPERTY_NAME, DEFAULT_ORDINAL );
450 }
451
452 return defaultOrdinal;
453 }
454
455
456
457
458
459
460
461
462
463
464 public static void setDefaultOrdinal( final Integer value )
465 {
466 defaultOrdinal = value;
467 }
468
469
470
471
472
473
474
475
476
477
478
479 public final int getOrdinal()
480 {
481 if ( this.ordinal == null )
482 {
483 this.ordinal = getDefaultOrdinal();
484 }
485
486 return this.ordinal;
487 }
488
489
490
491
492
493
494
495
496
497
498 public final void setOrdinal( final Integer value )
499 {
500 this.ordinal = value;
501 }
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518 public Modlets findModlets( final ModelContext context, final String location ) throws ModelException
519 {
520 if ( context == null )
521 {
522 throw new NullPointerException( "context" );
523 }
524 if ( location == null )
525 {
526 throw new NullPointerException( "location" );
527 }
528
529 URL url = null;
530 try
531 {
532 boolean contextValidating = this.isValidating();
533 if ( DEFAULT_VALIDATING == contextValidating
534 && context.getAttribute( VALIDATING_ATTRIBUTE_NAME ) instanceof Boolean )
535 {
536 contextValidating = (Boolean) context.getAttribute( VALIDATING_ATTRIBUTE_NAME );
537 }
538
539 final Modlets modlets = new Modlets();
540 final long t0 = System.nanoTime();
541 final Enumeration<URL> modletResourceEnumeration = context.findResources( location );
542 final Set<URI> modletResources = new HashSet<URI>();
543 while ( modletResourceEnumeration.hasMoreElements() )
544 {
545 modletResources.add( modletResourceEnumeration.nextElement().toURI() );
546 }
547
548 if ( !modletResources.isEmpty() )
549 {
550 if ( context.getExecutorService() != null && modletResources.size() > 1 )
551 {
552 final JAXBContext ctx = context.createContext( ModletObject.MODEL_PUBLIC_ID );
553 final javax.xml.validation.Schema schema = context.createSchema( ModletObject.MODEL_PUBLIC_ID );
554 final ThreadLocal<Unmarshaller> threadLocalUnmarshaller = new ThreadLocal<Unmarshaller>();
555 final List<Callable<Object>> tasks = new ArrayList<Callable<Object>>( modletResources.size() );
556
557 class UnmarshalTask implements Callable<Object>
558 {
559
560 final URI resource;
561
562 final boolean validating;
563
564 UnmarshalTask( final URI resource, final boolean validating )
565 {
566 super();
567 this.resource = resource;
568 this.validating = validating;
569 }
570
571 public Object call() throws ModelException, JAXBException, MalformedURLException
572 {
573 Unmarshaller unmarshaller = threadLocalUnmarshaller.get();
574 if ( unmarshaller == null )
575 {
576 unmarshaller = ctx.createUnmarshaller();
577
578 if ( this.validating )
579 {
580 unmarshaller.setSchema( schema );
581 }
582
583 threadLocalUnmarshaller.set( unmarshaller );
584 }
585
586 return unmarshaller.unmarshal( this.resource.toURL() );
587 }
588
589 }
590
591 for ( final URI modletResoure : modletResources )
592 {
593 tasks.add( new UnmarshalTask( modletResoure, contextValidating ) );
594 }
595
596 for ( final Future<Object> task : context.getExecutorService().invokeAll( tasks ) )
597 {
598 Object content = task.get();
599 if ( content instanceof JAXBElement<?> )
600 {
601 content = ( (JAXBElement<?>) content ).getValue();
602 }
603
604 if ( content instanceof Modlet )
605 {
606 modlets.getModlet().add( (Modlet) content );
607 }
608 else if ( content instanceof Modlets )
609 {
610 modlets.getModlet().addAll( ( (Modlets) content ).getModlet() );
611 }
612 }
613 }
614 else
615 {
616 final JAXBContext ctx = context.createContext( ModletObject.MODEL_PUBLIC_ID );
617 final Unmarshaller u = ctx.createUnmarshaller();
618
619 if ( contextValidating )
620 {
621 u.setSchema( context.createSchema( ModletObject.MODEL_PUBLIC_ID ) );
622 }
623
624 for ( final URI modletResource : modletResources )
625 {
626 url = modletResource.toURL();
627 Object content = u.unmarshal( url );
628 if ( content instanceof JAXBElement<?> )
629 {
630 content = ( (JAXBElement<?>) content ).getValue();
631 }
632
633 if ( content instanceof Modlet )
634 {
635 modlets.getModlet().add( (Modlet) content );
636 }
637 else if ( content instanceof Modlets )
638 {
639 modlets.getModlet().addAll( ( (Modlets) content ).getModlet() );
640 }
641 }
642 }
643 }
644
645 if ( context.isLoggable( Level.FINE ) )
646 {
647 context.log( Level.FINE, getMessage( "contextReport",
648 modlets.getModlet().size(),
649 location, System.nanoTime() - t0 ), null );
650
651 }
652
653 return modlets.getModlet().isEmpty() ? null : modlets;
654 }
655 catch ( final CancellationException e )
656 {
657 throw new ModelException( getMessage( e ), e );
658 }
659 catch ( final InterruptedException e )
660 {
661 throw new ModelException( getMessage( e ), e );
662 }
663 catch ( final URISyntaxException e )
664 {
665 throw new ModelException( getMessage( e ), e );
666 }
667 catch ( final MalformedURLException e )
668 {
669 throw new ModelException( getMessage( e ), e );
670 }
671 catch ( final UnmarshalException e )
672 {
673 String message = getMessage( e );
674 if ( message == null && e.getLinkedException() != null )
675 {
676 message = getMessage( e.getLinkedException() );
677 }
678
679 if ( url != null )
680 {
681 message = getMessage( "unmarshalException", url.toExternalForm(),
682 message != null ? " " + message : "" );
683
684 }
685
686 throw new ModelException( message, e );
687 }
688 catch ( final JAXBException e )
689 {
690 String message = getMessage( e );
691 if ( message == null && e.getLinkedException() != null )
692 {
693 message = getMessage( e.getLinkedException() );
694 }
695
696 throw new ModelException( message, e );
697 }
698 catch ( final ExecutionException e )
699 {
700 if ( e.getCause() instanceof ModelException )
701 {
702 throw (ModelException) e.getCause();
703 }
704 else if ( e.getCause() instanceof JAXBException )
705 {
706 String message = getMessage( e.getCause() );
707 if ( message == null && ( (JAXBException) e.getCause() ).getLinkedException() != null )
708 {
709 message = getMessage( ( (JAXBException) e.getCause() ).getLinkedException() );
710 }
711
712 throw new ModelException( message, e.getCause() );
713 }
714 else if ( e.getCause() instanceof RuntimeException )
715 {
716
717
718 if ( e.getCause().getCause() instanceof ModelException )
719 {
720 throw (ModelException) e.getCause().getCause();
721 }
722 else if ( e.getCause().getCause() instanceof JAXBException )
723 {
724 String message = getMessage( e.getCause().getCause() );
725 if ( message == null && ( (JAXBException) e.getCause().getCause() ).getLinkedException() != null )
726 {
727 message = getMessage( ( (JAXBException) e.getCause().getCause() ).getLinkedException() );
728 }
729
730 throw new ModelException( message, e.getCause().getCause() );
731 }
732 else if ( e.getCause().getCause() instanceof MalformedURLException )
733 {
734 throw new ModelException( getMessage( e.getCause().getCause() ), e.getCause().getCause() );
735 }
736 else if ( e.getCause().getCause() instanceof RuntimeException )
737 {
738 throw (RuntimeException) e.getCause().getCause();
739 }
740 else if ( e.getCause().getCause() instanceof Error )
741 {
742 throw (Error) e.getCause().getCause();
743 }
744 else if ( e.getCause().getCause() instanceof Exception )
745 {
746
747 throw new UndeclaredThrowableException( e.getCause().getCause() );
748 }
749 else
750 {
751 throw (RuntimeException) e.getCause();
752 }
753 }
754 else if ( e.getCause() instanceof Error )
755 {
756 throw (Error) e.getCause();
757 }
758 else
759 {
760
761 throw new UndeclaredThrowableException( e.getCause() );
762 }
763 }
764 }
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780 @Deprecated
781 public Modlets findModlets( final ModelContext context ) throws ModelException
782 {
783 if ( context == null )
784 {
785 throw new NullPointerException( "context" );
786 }
787
788 return this.findModlets( context, new Modlets() );
789 }
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804 public Modlets findModlets( final ModelContext context, final Modlets modlets ) throws ModelException
805 {
806 if ( context == null )
807 {
808 throw new NullPointerException( "context" );
809 }
810 if ( modlets == null )
811 {
812 throw new NullPointerException( "context" );
813 }
814
815 Modlets provided = null;
816
817 boolean contextEnabled = this.isEnabled();
818 if ( DEFAULT_ENABLED == contextEnabled && context.getAttribute( ENABLED_ATTRIBUTE_NAME ) instanceof Boolean )
819 {
820 contextEnabled = (Boolean) context.getAttribute( ENABLED_ATTRIBUTE_NAME );
821 }
822
823 String contextModletLocation = this.getModletLocation();
824 if ( DEFAULT_MODLET_LOCATION.equals( contextModletLocation )
825 && context.getAttribute( MODLET_LOCATION_ATTRIBUTE_NAME ) instanceof String )
826 {
827 contextModletLocation = (String) context.getAttribute( MODLET_LOCATION_ATTRIBUTE_NAME );
828 }
829
830 if ( contextEnabled )
831 {
832 final Modlets found = this.findModlets( context, contextModletLocation );
833
834 if ( found != null )
835 {
836 provided = modlets.clone();
837 provided.getModlet().addAll( found.getModlet() );
838 }
839 }
840 else if ( context.isLoggable( Level.FINER ) )
841 {
842 context.log( Level.FINER, getMessage( "disabled", this.getClass().getSimpleName() ), null );
843 }
844
845 return provided;
846 }
847
848 private static String getMessage( final String key, final Object... arguments )
849 {
850 return MessageFormat.format( ResourceBundle.getBundle(
851 DefaultModletProvider.class.getName().replace( '.', '/' ) ).getString( key ), arguments );
852
853 }
854
855 private static String getMessage( final Throwable t )
856 {
857 return t != null
858 ? t.getMessage() != null && t.getMessage().trim().length() > 0
859 ? t.getMessage()
860 : getMessage( t.getCause() )
861 : null;
862
863 }
864
865 }