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.io.BufferedReader;
34 import java.io.File;
35 import java.io.FileInputStream;
36 import java.io.IOException;
37 import java.io.InputStream;
38 import java.io.InputStreamReader;
39 import java.io.Reader;
40 import java.net.URI;
41 import java.net.URISyntaxException;
42 import java.net.URL;
43 import java.text.MessageFormat;
44 import java.util.ArrayList;
45 import java.util.Collection;
46 import java.util.Collections;
47 import java.util.Comparator;
48 import java.util.Enumeration;
49 import java.util.HashSet;
50 import java.util.List;
51 import java.util.Map;
52 import java.util.ResourceBundle;
53 import java.util.Set;
54 import java.util.StringTokenizer;
55 import java.util.TreeMap;
56 import java.util.jar.Attributes;
57 import java.util.jar.Manifest;
58 import java.util.logging.Level;
59 import javax.xml.XMLConstants;
60 import javax.xml.bind.JAXBContext;
61 import javax.xml.bind.JAXBException;
62 import javax.xml.bind.Marshaller;
63 import javax.xml.bind.Unmarshaller;
64 import javax.xml.transform.Source;
65 import javax.xml.transform.sax.SAXSource;
66 import javax.xml.validation.SchemaFactory;
67 import javax.xml.validation.Validator;
68 import org.w3c.dom.ls.LSInput;
69 import org.w3c.dom.ls.LSResourceResolver;
70 import org.xml.sax.EntityResolver;
71 import org.xml.sax.ErrorHandler;
72 import org.xml.sax.InputSource;
73 import org.xml.sax.SAXException;
74 import org.xml.sax.SAXParseException;
75 import org.xml.sax.helpers.DefaultHandler;
76
77
78
79
80
81
82
83
84 public class DefaultModelContext extends ModelContext
85 {
86
87
88
89
90
91
92
93
94 public static final String PROVIDER_LOCATION_ATTRIBUTE_NAME =
95 "org.jomc.modlet.DefaultModelContext.providerLocationAttribute";
96
97
98
99
100
101
102
103
104 public static final String PLATFORM_PROVIDER_LOCATION_ATTRIBUTE_NAME =
105 "org.jomc.modlet.DefaultModelContext.platformProviderLocationAttribute";
106
107
108
109
110 private static final String[] SCHEMA_EXTENSIONS = new String[]
111 {
112 "xsd"
113 };
114
115
116
117
118
119
120 private static final String DEFAULT_PROVIDER_LOCATION = "META-INF/services";
121
122
123
124
125
126
127 private static final String DEFAULT_PLATFORM_PROVIDER_LOCATION =
128 new StringBuilder( 255 ).append( System.getProperty( "java.home" ) ).append( File.separator ).append( "lib" ).
129 append( File.separator ).append( "jomc.properties" ).toString();
130
131
132
133
134
135
136 private static final String MARSHALLER_LISTENER_SERVICE = "javax.xml.bind.Marshaller.Listener";
137
138
139
140
141
142
143 private static final String UNMARSHALLER_LISTENER_SERVICE = "javax.xml.bind.Unmarshaller.Listener";
144
145
146
147
148 private static volatile String defaultProviderLocation;
149
150
151
152
153 private static volatile String defaultPlatformProviderLocation;
154
155
156
157
158 private String providerLocation;
159
160
161
162
163 private String platformProviderLocation;
164
165
166
167
168
169
170 public DefaultModelContext()
171 {
172 super();
173 }
174
175
176
177
178
179
180 public DefaultModelContext( final ClassLoader classLoader )
181 {
182 super( classLoader );
183 }
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198 public static String getDefaultProviderLocation()
199 {
200 if ( defaultProviderLocation == null )
201 {
202 defaultProviderLocation = System.getProperty(
203 "org.jomc.modlet.DefaultModelContext.defaultProviderLocation", DEFAULT_PROVIDER_LOCATION );
204
205 }
206
207 return defaultProviderLocation;
208 }
209
210
211
212
213
214
215
216
217 public static void setDefaultProviderLocation( final String value )
218 {
219 defaultProviderLocation = value;
220 }
221
222
223
224
225
226
227
228
229
230
231 public final String getProviderLocation()
232 {
233 if ( this.providerLocation == null )
234 {
235 this.providerLocation = getDefaultProviderLocation();
236
237 if ( DEFAULT_PROVIDER_LOCATION.equals( this.providerLocation )
238 && this.getAttribute( PROVIDER_LOCATION_ATTRIBUTE_NAME ) instanceof String )
239 {
240 final String contextProviderLocation = (String) this.getAttribute( PROVIDER_LOCATION_ATTRIBUTE_NAME );
241
242 if ( this.isLoggable( Level.CONFIG ) )
243 {
244 this.log( Level.CONFIG, getMessage( "contextProviderLocationInfo",
245 contextProviderLocation ), null );
246 }
247
248 this.providerLocation = null;
249 return contextProviderLocation;
250 }
251 else if ( this.isLoggable( Level.CONFIG ) )
252 {
253 this.log( Level.CONFIG, getMessage( "defaultProviderLocationInfo", this.providerLocation ), null );
254 }
255 }
256
257 return this.providerLocation;
258 }
259
260
261
262
263
264
265
266
267 public final void setProviderLocation( final String value )
268 {
269 this.providerLocation = value;
270 }
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285 public static String getDefaultPlatformProviderLocation()
286 {
287 if ( defaultPlatformProviderLocation == null )
288 {
289 defaultPlatformProviderLocation = System.getProperty(
290 "org.jomc.modlet.DefaultModelContext.defaultPlatformProviderLocation",
291 DEFAULT_PLATFORM_PROVIDER_LOCATION );
292
293 }
294
295 return defaultPlatformProviderLocation;
296 }
297
298
299
300
301
302
303
304
305 public static void setDefaultPlatformProviderLocation( final String value )
306 {
307 defaultPlatformProviderLocation = value;
308 }
309
310
311
312
313
314
315
316
317
318
319 public final String getPlatformProviderLocation()
320 {
321 if ( this.platformProviderLocation == null )
322 {
323 this.platformProviderLocation = getDefaultPlatformProviderLocation();
324
325 if ( DEFAULT_PLATFORM_PROVIDER_LOCATION.equals( this.platformProviderLocation )
326 && this.getAttribute( PLATFORM_PROVIDER_LOCATION_ATTRIBUTE_NAME ) instanceof String )
327 {
328 final String contextPlatformProviderLocation =
329 (String) this.getAttribute( PLATFORM_PROVIDER_LOCATION_ATTRIBUTE_NAME );
330
331 if ( this.isLoggable( Level.CONFIG ) )
332 {
333 this.log( Level.CONFIG, getMessage( "contextPlatformProviderLocationInfo",
334 contextPlatformProviderLocation ), null );
335
336 }
337
338 this.platformProviderLocation = null;
339 return contextPlatformProviderLocation;
340 }
341 else if ( this.isLoggable( Level.CONFIG ) )
342 {
343 this.log( Level.CONFIG,
344 getMessage( "defaultPlatformProviderLocationInfo", this.platformProviderLocation ), null );
345
346 }
347 }
348
349 return this.platformProviderLocation;
350 }
351
352
353
354
355
356
357
358
359 public final void setPlatformProviderLocation( final String value )
360 {
361 this.platformProviderLocation = value;
362 }
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377 @Override
378 @Deprecated
379 public Modlets findModlets() throws ModelException
380 {
381 return this.findModlets( new Modlets() );
382 }
383
384
385
386
387
388
389
390
391
392
393
394
395
396 @Override
397 public Modlets findModlets( final Modlets modlets ) throws ModelException
398 {
399 if ( modlets == null )
400 {
401 throw new NullPointerException( "modlets" );
402 }
403
404 Modlets found = modlets.clone();
405 final Collection<ModletProvider> providers = this.loadModletServices( ModletProvider.class );
406
407 for ( final ModletProvider provider : providers )
408 {
409 if ( this.isLoggable( Level.FINER ) )
410 {
411 this.log( Level.FINER, getMessage( "creatingModlets", provider.toString() ), null );
412 }
413
414 final Modlets provided = provider.findModlets( this, found );
415
416 if ( provided != null )
417 {
418 found = provided;
419 }
420 }
421
422 if ( this.isLoggable( Level.FINEST ) )
423 {
424 for ( final Modlet m : found.getModlet() )
425 {
426 this.log( Level.FINEST,
427 getMessage( "modletInfo", m.getName(), m.getModel(),
428 m.getVendor() != null
429 ? m.getVendor() : getMessage( "noVendor" ),
430 m.getVersion() != null
431 ? m.getVersion() : getMessage( "noVersion" ) ), null );
432
433 if ( m.getSchemas() != null )
434 {
435 for ( final Schema s : m.getSchemas().getSchema() )
436 {
437 this.log( Level.FINEST,
438 getMessage( "modletSchemaInfo", m.getName(), s.getPublicId(), s.getSystemId(),
439 s.getContextId() != null
440 ? s.getContextId() : getMessage( "noContext" ),
441 s.getClasspathId() != null
442 ? s.getClasspathId() : getMessage( "noClasspathId" ) ), null );
443
444 }
445 }
446
447 if ( m.getServices() != null )
448 {
449 for ( final Service s : m.getServices().getService() )
450 {
451 this.log( Level.FINEST, getMessage( "modletServiceInfo", m.getName(), s.getOrdinal(),
452 s.getIdentifier(), s.getClazz() ), null );
453
454 }
455 }
456 }
457 }
458
459 return found;
460 }
461
462
463
464
465
466
467
468
469
470
471
472
473
474 @Override
475 public Modlets processModlets( final Modlets modlets ) throws ModelException
476 {
477 if ( modlets == null )
478 {
479 throw new NullPointerException( "modlets" );
480 }
481
482 Modlets result = modlets.clone();
483 final Collection<ModletProcessor> processors = this.loadModletServices( ModletProcessor.class );
484
485 for ( final ModletProcessor processor : processors )
486 {
487 if ( this.isLoggable( Level.FINER ) )
488 {
489 this.log( Level.FINER, getMessage( "processingModlets", processor.toString() ), null );
490 }
491
492 final Modlets processed = processor.processModlets( this, result );
493
494 if ( processed != null )
495 {
496 result = processed;
497 }
498 }
499
500 return result;
501 }
502
503
504
505
506
507
508
509
510
511
512
513
514
515 @Override
516 public ModelValidationReport validateModlets( final Modlets modlets ) throws ModelException
517 {
518 if ( modlets == null )
519 {
520 throw new NullPointerException( "modlets" );
521 }
522
523 final ModelValidationReport report = new ModelValidationReport();
524 final Collection<ModletValidator> modletValidators = this.loadModletServices( ModletValidator.class );
525
526 for ( final ModletValidator modletValidator : modletValidators )
527 {
528 if ( this.isLoggable( Level.FINER ) )
529 {
530 this.log( Level.FINER, getMessage( "validatingModlets", modletValidator.toString() ), null );
531 }
532
533 final ModelValidationReport current = modletValidator.validateModlets( this, modlets );
534
535 if ( current != null )
536 {
537 report.getDetails().addAll( current.getDetails() );
538 }
539 }
540
541 return report;
542 }
543
544
545
546
547
548
549
550
551
552
553
554
555 @Override
556 public Model findModel( final String model ) throws ModelException
557 {
558 if ( model == null )
559 {
560 throw new NullPointerException( "model" );
561 }
562
563 final Model m = new Model();
564 m.setIdentifier( model );
565
566 return this.findModel( m );
567 }
568
569
570
571
572
573
574
575
576
577
578
579
580
581 @Override
582 public Model findModel( final Model model ) throws ModelException
583 {
584 if ( model == null )
585 {
586 throw new NullPointerException( "model" );
587 }
588
589 Model m = model.clone();
590 final long t0 = System.currentTimeMillis();
591
592 for ( final ModelProvider provider
593 : this.createServiceObjects( model.getIdentifier(), ModelProvider.class.getName(),
594 ModelProvider.class ) )
595 {
596 if ( this.isLoggable( Level.FINER ) )
597 {
598 this.log( Level.FINER, getMessage( "creatingModel", m.getIdentifier(), provider.toString() ), null );
599 }
600
601 final Model provided = provider.findModel( this, m );
602
603 if ( provided != null )
604 {
605 m = provided;
606 }
607 }
608
609 if ( this.isLoggable( Level.FINE ) )
610 {
611 this.log( Level.FINE, getMessage( "findModelReport", m.getIdentifier(), System.currentTimeMillis() - t0 ),
612 null );
613
614 }
615
616 return m;
617 }
618
619
620
621
622
623
624
625
626
627
628
629 @Override
630 public Model processModel( final Model model ) throws ModelException
631 {
632 if ( model == null )
633 {
634 throw new NullPointerException( "model" );
635 }
636
637 Model processed = model;
638 final long t0 = System.currentTimeMillis();
639
640 for ( final ModelProcessor processor
641 : this.createServiceObjects( model.getIdentifier(), ModelProcessor.class.getName(),
642 ModelProcessor.class ) )
643 {
644 if ( this.isLoggable( Level.FINER ) )
645 {
646 this.log( Level.FINER, getMessage( "processingModel", model.getIdentifier(),
647 processor.toString() ), null );
648
649 }
650
651 final Model current = processor.processModel( this, processed );
652
653 if ( current != null )
654 {
655 processed = current;
656 }
657 }
658
659 if ( this.isLoggable( Level.FINE ) )
660 {
661 this.log( Level.FINE, getMessage( "processModelReport", model.getIdentifier(),
662 System.currentTimeMillis() - t0 ), null );
663
664 }
665
666 return processed;
667 }
668
669
670
671
672
673
674
675
676
677
678
679 @Override
680 public ModelValidationReport validateModel( final Model model ) throws ModelException
681 {
682 if ( model == null )
683 {
684 throw new NullPointerException( "model" );
685 }
686
687 final long t0 = System.currentTimeMillis();
688 final ModelValidationReport report = new ModelValidationReport();
689
690 for ( final ModelValidator validator
691 : this.createServiceObjects( model.getIdentifier(), ModelValidator.class.getName(),
692 ModelValidator.class ) )
693 {
694 if ( this.isLoggable( Level.FINER ) )
695 {
696 this.log( Level.FINER, getMessage( "validatingModel", model.getIdentifier(),
697 validator.toString() ), null );
698
699 }
700
701 final ModelValidationReport current = validator.validateModel( this, model );
702
703 if ( current != null )
704 {
705 report.getDetails().addAll( current.getDetails() );
706 }
707 }
708
709 if ( this.isLoggable( Level.FINE ) )
710 {
711 this.log( Level.FINE, getMessage( "validateModelReport", model.getIdentifier(),
712 System.currentTimeMillis() - t0 ), null );
713
714 }
715
716 return report;
717 }
718
719
720
721
722
723
724 @Override
725 public ModelValidationReport validateModel( final String model, final Source source ) throws ModelException
726 {
727 if ( model == null )
728 {
729 throw new NullPointerException( "model" );
730 }
731 if ( source == null )
732 {
733 throw new NullPointerException( "source" );
734 }
735
736 final long t0 = System.currentTimeMillis();
737 final javax.xml.validation.Schema schema = this.createSchema( model );
738 final Validator validator = schema.newValidator();
739 final ModelErrorHandler modelErrorHandler = new ModelErrorHandler( this );
740 validator.setErrorHandler( modelErrorHandler );
741
742 try
743 {
744 validator.validate( source );
745 }
746 catch ( final SAXException e )
747 {
748 String message = getMessage( e );
749 if ( message == null && e.getException() != null )
750 {
751 message = getMessage( e.getException() );
752 }
753
754 if ( this.isLoggable( Level.FINE ) )
755 {
756 this.log( Level.FINE, message, e );
757 }
758
759 if ( modelErrorHandler.getReport().isModelValid() )
760 {
761 throw new ModelException( message, e );
762 }
763 }
764 catch ( final IOException e )
765 {
766 throw new ModelException( getMessage( e ), e );
767 }
768
769 if ( this.isLoggable( Level.FINE ) )
770 {
771 this.log( Level.FINE, getMessage( "validateModelReport", model, System.currentTimeMillis() - t0 ), null );
772 }
773
774 return modelErrorHandler.getReport();
775 }
776
777 @Override
778 public EntityResolver createEntityResolver( final String model ) throws ModelException
779 {
780 if ( model == null )
781 {
782 throw new NullPointerException( "model" );
783 }
784
785 return this.createEntityResolver( this.getModlets().getSchemas( model ) );
786 }
787
788 @Override
789 @Deprecated
790 public EntityResolver createEntityResolver( final URI publicId ) throws ModelException
791 {
792 if ( publicId == null )
793 {
794 throw new NullPointerException( "publicId" );
795 }
796
797 return this.createEntityResolver( this.getModlets().getSchemas( publicId ) );
798 }
799
800 @Override
801 public LSResourceResolver createResourceResolver( final String model ) throws ModelException
802 {
803 if ( model == null )
804 {
805 throw new NullPointerException( "model" );
806 }
807
808 return this.createResourceResolver( this.createEntityResolver( model ) );
809 }
810
811 @Override
812 @Deprecated
813 public LSResourceResolver createResourceResolver( final URI publicId ) throws ModelException
814 {
815 if ( publicId == null )
816 {
817 throw new NullPointerException( "publicId" );
818 }
819
820 return this.createResourceResolver( this.createEntityResolver( publicId ) );
821 }
822
823 @Override
824 public javax.xml.validation.Schema createSchema( final String model ) throws ModelException
825 {
826 if ( model == null )
827 {
828 throw new NullPointerException( "model" );
829 }
830
831 return this.createSchema( this.getModlets().getSchemas( model ), this.createEntityResolver( model ),
832 this.createResourceResolver( model ), model, null );
833
834 }
835
836 @Override
837 @Deprecated
838 public javax.xml.validation.Schema createSchema( final URI publicId ) throws ModelException
839 {
840 if ( publicId == null )
841 {
842 throw new NullPointerException( "publicId" );
843 }
844
845 return this.createSchema( this.getModlets().getSchemas( publicId ), this.createEntityResolver( publicId ),
846 this.createResourceResolver( publicId ), null, publicId );
847
848 }
849
850 @Override
851 public JAXBContext createContext( final String model ) throws ModelException
852 {
853 if ( model == null )
854 {
855 throw new NullPointerException( "model" );
856 }
857
858 return this.createContext( this.getModlets().getSchemas( model ), model, null );
859 }
860
861 @Override
862 @Deprecated
863 public JAXBContext createContext( final URI publicId ) throws ModelException
864 {
865 if ( publicId == null )
866 {
867 throw new NullPointerException( "publicId" );
868 }
869
870 return this.createContext( this.getModlets().getSchemas( publicId ), null, publicId );
871 }
872
873 @Override
874 public Marshaller createMarshaller( final String model ) throws ModelException
875 {
876 if ( model == null )
877 {
878 throw new NullPointerException( "model" );
879 }
880
881 return this.createMarshaller( model, null );
882 }
883
884 @Override
885 @Deprecated
886 public Marshaller createMarshaller( final URI publicId ) throws ModelException
887 {
888 if ( publicId == null )
889 {
890 throw new NullPointerException( "publicId" );
891 }
892
893 return this.createMarshaller( null, publicId );
894 }
895
896 @Override
897 public Unmarshaller createUnmarshaller( final String model ) throws ModelException
898 {
899 if ( model == null )
900 {
901 throw new NullPointerException( "model" );
902 }
903
904 return this.createUnmarshaller( model, null );
905 }
906
907 @Override
908 @Deprecated
909 public Unmarshaller createUnmarshaller( final URI publicId ) throws ModelException
910 {
911 if ( publicId == null )
912 {
913 throw new NullPointerException( "publicId" );
914 }
915
916 return this.createUnmarshaller( null, publicId );
917 }
918
919
920
921
922
923
924
925
926
927
928 @Override
929 public <T> Collection<? extends T> createServiceObjects( final String model, final String service,
930 final Class<T> type )
931 throws ModelException
932 {
933 if ( model == null )
934 {
935 throw new NullPointerException( "model" );
936 }
937 if ( service == null )
938 {
939 throw new NullPointerException( "service" );
940 }
941 if ( type == null )
942 {
943 throw new NullPointerException( "type" );
944 }
945
946 final Services modelServices = this.getModlets().getServices( model );
947 final Collection<T> serviceObjects =
948 new ArrayList<T>( modelServices != null ? modelServices.getService().size() : 0 );
949
950 if ( modelServices != null )
951 {
952 final Collection<ServiceFactory> factories = this.loadModletServices( ServiceFactory.class );
953
954 for ( final Service s : modelServices.getServices( service ) )
955 {
956 serviceObjects.add( this.createServiceObject( s, type, factories ) );
957 }
958 }
959
960 return Collections.unmodifiableCollection( serviceObjects );
961 }
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977 @Override
978 @Deprecated
979 public <T> T createServiceObject( final Service service, final Class<T> type ) throws ModelException
980 {
981 if ( service == null )
982 {
983 throw new NullPointerException( "service" );
984 }
985 if ( type == null )
986 {
987 throw new NullPointerException( "type" );
988 }
989
990 return this.createServiceObject( service, type, this.loadModletServices( ServiceFactory.class ) );
991 }
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007 private <T> T createServiceObject( final Service service, final Class<T> type,
1008 final Collection<ServiceFactory> factories ) throws ModelException
1009 {
1010 if ( service == null )
1011 {
1012 throw new NullPointerException( "service" );
1013 }
1014 if ( type == null )
1015 {
1016 throw new NullPointerException( "type" );
1017 }
1018 if ( factories == null )
1019 {
1020 throw new NullPointerException( "factories" );
1021 }
1022
1023 T serviceObject = null;
1024
1025 for ( final ServiceFactory factory : factories )
1026 {
1027 final T current = factory.createServiceObject( this, service, type );
1028
1029 if ( current != null )
1030 {
1031 if ( this.isLoggable( Level.FINER ) )
1032 {
1033 this.log( Level.FINER, getMessage( "creatingService", service.getOrdinal(), service.getIdentifier(),
1034 service.getClazz(), factory.toString() ), null );
1035
1036 }
1037
1038 serviceObject = current;
1039 break;
1040 }
1041 }
1042
1043 if ( serviceObject == null )
1044 {
1045 throw new ModelException( getMessage( "serviceNotCreated", service.getOrdinal(), service.getIdentifier(),
1046 service.getClazz() ), null );
1047
1048 }
1049
1050 return serviceObject;
1051 }
1052
1053 private <T> Collection<T> loadModletServices( final Class<T> serviceClass ) throws ModelException
1054 {
1055 try
1056 {
1057 final String serviceNamePrefix = serviceClass.getName() + ".";
1058 final Map<String, T> sortedPlatformServices = new TreeMap<String, T>( new Comparator<String>()
1059 {
1060
1061 public int compare( final String key1, final String key2 )
1062 {
1063 return key1.compareTo( key2 );
1064 }
1065
1066 } );
1067
1068 final File platformServices = new File( this.getPlatformProviderLocation() );
1069
1070 if ( platformServices.exists() )
1071 {
1072 if ( this.isLoggable( Level.FINEST ) )
1073 {
1074 this.log( Level.FINEST, getMessage( "processing", platformServices.getAbsolutePath() ), null );
1075 }
1076
1077 InputStream in = null;
1078 boolean suppressExceptionOnClose = true;
1079 final java.util.Properties p = new java.util.Properties();
1080
1081 try
1082 {
1083 in = new FileInputStream( platformServices );
1084 p.load( in );
1085 suppressExceptionOnClose = false;
1086 }
1087 finally
1088 {
1089 try
1090 {
1091 if ( in != null )
1092 {
1093 in.close();
1094 }
1095 }
1096 catch ( final IOException e )
1097 {
1098 if ( suppressExceptionOnClose )
1099 {
1100 this.log( Level.SEVERE, getMessage( e ), e );
1101 }
1102 else
1103 {
1104 throw e;
1105 }
1106 }
1107 }
1108
1109 for ( final Map.Entry<Object, Object> e : p.entrySet() )
1110 {
1111 if ( e.getKey().toString().startsWith( serviceNamePrefix ) )
1112 {
1113 final String configuration = e.getValue().toString();
1114
1115 if ( this.isLoggable( Level.FINEST ) )
1116 {
1117 this.log( Level.FINEST, getMessage( "serviceInfo", platformServices.getAbsolutePath(),
1118 serviceClass.getName(), configuration ), null );
1119
1120 }
1121
1122 sortedPlatformServices.put( e.getKey().toString(),
1123 this.createModletServiceObject( serviceClass, configuration ) );
1124
1125 }
1126 }
1127 }
1128
1129 final Enumeration<URL> classpathServices =
1130 this.findResources( this.getProviderLocation() + '/' + serviceClass.getName() );
1131
1132 int count = 0;
1133 final long t0 = System.currentTimeMillis();
1134 final List<T> sortedClasspathServices = new ArrayList<T>();
1135
1136 while ( classpathServices.hasMoreElements() )
1137 {
1138 count++;
1139 final URL url = classpathServices.nextElement();
1140
1141 if ( this.isLoggable( Level.FINEST ) )
1142 {
1143 this.log( Level.FINEST, getMessage( "processing", url.toExternalForm() ), null );
1144 }
1145
1146 BufferedReader reader = null;
1147 boolean suppressExceptionOnClose = true;
1148
1149 try
1150 {
1151 reader = new BufferedReader( new InputStreamReader( url.openStream(), "UTF-8" ) );
1152
1153 String line;
1154 while ( ( line = reader.readLine() ) != null )
1155 {
1156 if ( line.contains( "#" ) )
1157 {
1158 continue;
1159 }
1160
1161 if ( this.isLoggable( Level.FINEST ) )
1162 {
1163 this.log( Level.FINEST, getMessage( "serviceInfo", url.toExternalForm(),
1164 serviceClass.getName(), line ), null );
1165
1166 }
1167
1168 final T serviceObject = this.createModletServiceObject( serviceClass, line );
1169 sortedClasspathServices.add( serviceObject );
1170 }
1171
1172 Collections.sort( sortedClasspathServices,
1173 new Comparator<Object>()
1174 {
1175
1176 public int compare( final Object o1, final Object o2 )
1177 {
1178 return ordinalOf( o1 ) - ordinalOf( o2 );
1179 }
1180
1181 } );
1182
1183 suppressExceptionOnClose = false;
1184 }
1185 finally
1186 {
1187 try
1188 {
1189 if ( reader != null )
1190 {
1191 reader.close();
1192 }
1193 }
1194 catch ( final IOException e )
1195 {
1196 if ( suppressExceptionOnClose )
1197 {
1198 this.log( Level.SEVERE, getMessage( e ), e );
1199 }
1200 else
1201 {
1202 throw new ModelException( getMessage( e ), e );
1203 }
1204 }
1205 }
1206 }
1207
1208 if ( this.isLoggable( Level.FINE ) )
1209 {
1210 this.log( Level.FINE, getMessage( "contextReport", count,
1211 this.getProviderLocation() + '/' + serviceClass.getName(),
1212 System.currentTimeMillis() - t0 ), null );
1213
1214 }
1215
1216 final List<T> services =
1217 new ArrayList<T>( sortedPlatformServices.size() + sortedClasspathServices.size() );
1218
1219 services.addAll( sortedPlatformServices.values() );
1220 services.addAll( sortedClasspathServices );
1221
1222 return services;
1223 }
1224 catch ( final IOException e )
1225 {
1226 throw new ModelException( getMessage( e ), e );
1227 }
1228 }
1229
1230 private <T> T createModletServiceObject( final Class<T> serviceClass, final String configuration )
1231 throws ModelException
1232 {
1233 String className = configuration;
1234 final int i0 = configuration.indexOf( '[' );
1235 final int i1 = configuration.lastIndexOf( ']' );
1236 final Service service = new Service();
1237 service.setIdentifier( serviceClass.getName() );
1238
1239 if ( i0 != -1 && i1 != -1 )
1240 {
1241 className = configuration.substring( 0, i0 );
1242 final StringTokenizer propertyTokens =
1243 new StringTokenizer( configuration.substring( i0 + 1, i1 ), "," );
1244
1245 while ( propertyTokens.hasMoreTokens() )
1246 {
1247 final String property = propertyTokens.nextToken();
1248 final int d0 = property.indexOf( '=' );
1249
1250 String propertyName = property;
1251 String propertyValue = null;
1252
1253 if ( d0 != -1 )
1254 {
1255 propertyName = property.substring( 0, d0 );
1256 propertyValue = property.substring( d0 + 1, property.length() );
1257 }
1258
1259 final Property p = new Property();
1260 service.getProperty().add( p );
1261
1262 p.setName( propertyName );
1263 p.setValue( propertyValue );
1264 }
1265 }
1266
1267 service.setClazz( className );
1268
1269
1270 return new DefaultServiceFactory().createServiceObject( this, service, serviceClass );
1271 }
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283 private Set<URI> getSchemaResources() throws IOException, URISyntaxException, ModelException
1284 {
1285 final Set<URI> resources = new HashSet<URI>();
1286 final long t0 = System.currentTimeMillis();
1287 int count = 0;
1288
1289 for ( final Enumeration<URL> e = this.findResources( "META-INF/MANIFEST.MF" );
1290 e.hasMoreElements(); )
1291 {
1292 InputStream manifestStream = null;
1293 boolean suppressExceptionOnClose = true;
1294
1295 try
1296 {
1297 count++;
1298 final URL manifestUrl = e.nextElement();
1299 final String externalForm = manifestUrl.toExternalForm();
1300 final String baseUrl = externalForm.substring( 0, externalForm.indexOf( "META-INF" ) );
1301 manifestStream = manifestUrl.openStream();
1302 final Manifest mf = new Manifest( manifestStream );
1303
1304 if ( this.isLoggable( Level.FINEST ) )
1305 {
1306 this.log( Level.FINEST, getMessage( "processing", externalForm ), null );
1307 }
1308
1309 for ( final Map.Entry<String, Attributes> entry : mf.getEntries().entrySet() )
1310 {
1311 for ( int i = SCHEMA_EXTENSIONS.length - 1; i >= 0; i-- )
1312 {
1313 if ( entry.getKey().toLowerCase().endsWith( '.' + SCHEMA_EXTENSIONS[i].toLowerCase() ) )
1314 {
1315 final URL schemaUrl = new URL( baseUrl + entry.getKey() );
1316 resources.add( schemaUrl.toURI() );
1317
1318 if ( this.isLoggable( Level.FINEST ) )
1319 {
1320 this.log( Level.FINEST, getMessage( "foundSchemaCandidate",
1321 schemaUrl.toExternalForm() ), null );
1322
1323 }
1324 }
1325 }
1326 }
1327
1328 suppressExceptionOnClose = false;
1329 }
1330 finally
1331 {
1332 try
1333 {
1334 if ( manifestStream != null )
1335 {
1336 manifestStream.close();
1337 }
1338 }
1339 catch ( final IOException ex )
1340 {
1341 if ( suppressExceptionOnClose )
1342 {
1343 this.log( Level.SEVERE, getMessage( ex ), ex );
1344 }
1345 else
1346 {
1347 throw ex;
1348 }
1349 }
1350 }
1351 }
1352
1353 if ( this.isLoggable( Level.FINE ) )
1354 {
1355 this.log( Level.FINE, getMessage( "contextReport", count, "META-INF/MANIFEST.MF",
1356 System.currentTimeMillis() - t0 ), null );
1357
1358 }
1359
1360 return resources;
1361 }
1362
1363 private EntityResolver createEntityResolver( final Schemas schemas )
1364 {
1365 return new DefaultHandler()
1366 {
1367
1368 @Override
1369 public InputSource resolveEntity( final String publicId, final String systemId )
1370 throws SAXException, IOException
1371 {
1372 InputSource schemaSource = null;
1373
1374 try
1375 {
1376 Schema s = null;
1377
1378 if ( schemas != null )
1379 {
1380 if ( systemId != null && !"".equals( systemId ) )
1381 {
1382 s = schemas.getSchemaBySystemId( systemId );
1383 }
1384 else if ( publicId != null )
1385 {
1386 s = schemas.getSchemaByPublicId( publicId );
1387 }
1388 }
1389
1390 if ( s != null )
1391 {
1392 schemaSource = new InputSource();
1393 schemaSource.setPublicId( s.getPublicId() );
1394 schemaSource.setSystemId( s.getSystemId() );
1395
1396 if ( s.getClasspathId() != null )
1397 {
1398 final URL resource = findResource( s.getClasspathId() );
1399
1400 if ( resource != null )
1401 {
1402 schemaSource.setSystemId( resource.toExternalForm() );
1403 }
1404 else if ( isLoggable( Level.WARNING ) )
1405 {
1406 log( Level.WARNING, getMessage( "resourceNotFound", s.getClasspathId() ), null );
1407 }
1408 }
1409
1410 if ( isLoggable( Level.FINEST ) )
1411 {
1412 log( Level.FINEST, getMessage( "resolutionInfo", publicId + ", " + systemId,
1413 schemaSource.getPublicId() + ", "
1414 + schemaSource.getSystemId() ), null );
1415
1416 }
1417 }
1418
1419 if ( schemaSource == null && systemId != null && !"".equals( systemId ) )
1420 {
1421 final URI systemUri = new URI( systemId );
1422 String schemaName = systemUri.getPath();
1423
1424 if ( schemaName != null )
1425 {
1426 final int lastIndexOfSlash = schemaName.lastIndexOf( '/' );
1427 if ( lastIndexOfSlash != -1 && lastIndexOfSlash < schemaName.length() )
1428 {
1429 schemaName = schemaName.substring( lastIndexOfSlash + 1 );
1430 }
1431
1432 for ( final URI uri : getSchemaResources() )
1433 {
1434 if ( uri.getSchemeSpecificPart() != null
1435 && uri.getSchemeSpecificPart().endsWith( schemaName ) )
1436 {
1437 schemaSource = new InputSource();
1438 schemaSource.setPublicId( publicId );
1439 schemaSource.setSystemId( uri.toASCIIString() );
1440
1441 if ( isLoggable( Level.FINEST ) )
1442 {
1443 log( Level.FINEST, getMessage( "resolutionInfo", systemUri.toASCIIString(),
1444 schemaSource.getSystemId() ), null );
1445
1446 }
1447
1448 break;
1449 }
1450 }
1451 }
1452 else
1453 {
1454 if ( isLoggable( Level.WARNING ) )
1455 {
1456 log( Level.WARNING, getMessage( "unsupportedIdUri", systemId,
1457 systemUri.toASCIIString() ), null );
1458
1459 }
1460
1461 schemaSource = null;
1462 }
1463 }
1464 }
1465 catch ( final URISyntaxException e )
1466 {
1467 if ( isLoggable( Level.WARNING ) )
1468 {
1469 log( Level.WARNING, getMessage( "unsupportedIdUri", systemId, getMessage( e ) ), null );
1470 }
1471
1472 schemaSource = null;
1473 }
1474 catch ( final ModelException e )
1475 {
1476 String message = getMessage( e );
1477 if ( message == null )
1478 {
1479 message = "";
1480 }
1481 else if ( message.length() > 0 )
1482 {
1483 message = " " + message;
1484 }
1485
1486 String resource = "";
1487 if ( publicId != null )
1488 {
1489 resource = publicId + ", ";
1490 }
1491 resource += systemId;
1492
1493
1494 throw (IOException) new IOException( getMessage(
1495 "failedResolving", resource, message ) ).initCause( e );
1496
1497 }
1498
1499 return schemaSource;
1500 }
1501
1502 };
1503 }
1504
1505 private LSResourceResolver createResourceResolver( final EntityResolver entityResolver )
1506 {
1507 if ( entityResolver == null )
1508 {
1509 throw new NullPointerException( "entityResolver" );
1510 }
1511
1512 return new LSResourceResolver()
1513 {
1514
1515 public LSInput resolveResource( final String type, final String namespaceURI, final String publicId,
1516 final String systemId, final String baseURI )
1517 {
1518 final String resolvePublicId = namespaceURI == null ? publicId : namespaceURI;
1519 final String resolveSystemId = systemId == null ? "" : systemId;
1520
1521 try
1522 {
1523 if ( XMLConstants.W3C_XML_SCHEMA_NS_URI.equals( type ) )
1524 {
1525 final InputSource schemaSource =
1526 entityResolver.resolveEntity( resolvePublicId, resolveSystemId );
1527
1528 if ( schemaSource != null )
1529 {
1530 return new LSInput()
1531 {
1532
1533 public Reader getCharacterStream()
1534 {
1535 return schemaSource.getCharacterStream();
1536 }
1537
1538 public void setCharacterStream( final Reader characterStream )
1539 {
1540 if ( isLoggable( Level.WARNING ) )
1541 {
1542 log( Level.WARNING, getMessage(
1543 "unsupportedOperation", "setCharacterStream",
1544 DefaultModelContext.class.getName() + ".LSResourceResolver" ), null );
1545
1546 }
1547 }
1548
1549 public InputStream getByteStream()
1550 {
1551 return schemaSource.getByteStream();
1552 }
1553
1554 public void setByteStream( final InputStream byteStream )
1555 {
1556 if ( isLoggable( Level.WARNING ) )
1557 {
1558 log( Level.WARNING, getMessage(
1559 "unsupportedOperation", "setByteStream",
1560 DefaultModelContext.class.getName() + ".LSResourceResolver" ), null );
1561
1562 }
1563 }
1564
1565 public String getStringData()
1566 {
1567 return null;
1568 }
1569
1570 public void setStringData( final String stringData )
1571 {
1572 if ( isLoggable( Level.WARNING ) )
1573 {
1574 log( Level.WARNING, getMessage(
1575 "unsupportedOperation", "setStringData",
1576 DefaultModelContext.class.getName() + ".LSResourceResolver" ), null );
1577
1578 }
1579 }
1580
1581 public String getSystemId()
1582 {
1583 return schemaSource.getSystemId();
1584 }
1585
1586 public void setSystemId( final String systemId )
1587 {
1588 if ( isLoggable( Level.WARNING ) )
1589 {
1590 log( Level.WARNING, getMessage(
1591 "unsupportedOperation", "setSystemId",
1592 DefaultModelContext.class.getName() + ".LSResourceResolver" ), null );
1593
1594 }
1595 }
1596
1597 public String getPublicId()
1598 {
1599 return schemaSource.getPublicId();
1600 }
1601
1602 public void setPublicId( final String publicId )
1603 {
1604 if ( isLoggable( Level.WARNING ) )
1605 {
1606 log( Level.WARNING, getMessage(
1607 "unsupportedOperation", "setPublicId",
1608 DefaultModelContext.class.getName() + ".LSResourceResolver" ), null );
1609
1610 }
1611 }
1612
1613 public String getBaseURI()
1614 {
1615 return baseURI;
1616 }
1617
1618 public void setBaseURI( final String baseURI )
1619 {
1620 if ( isLoggable( Level.WARNING ) )
1621 {
1622 log( Level.WARNING, getMessage(
1623 "unsupportedOperation", "setBaseURI",
1624 DefaultModelContext.class.getName() + ".LSResourceResolver" ), null );
1625
1626 }
1627 }
1628
1629 public String getEncoding()
1630 {
1631 return schemaSource.getEncoding();
1632 }
1633
1634 public void setEncoding( final String encoding )
1635 {
1636 if ( isLoggable( Level.WARNING ) )
1637 {
1638 log( Level.WARNING, getMessage(
1639 "unsupportedOperation", "setEncoding",
1640 DefaultModelContext.class.getName() + ".LSResourceResolver" ), null );
1641
1642 }
1643 }
1644
1645 public boolean getCertifiedText()
1646 {
1647 return false;
1648 }
1649
1650 public void setCertifiedText( final boolean certifiedText )
1651 {
1652 if ( isLoggable( Level.WARNING ) )
1653 {
1654 log( Level.WARNING, getMessage(
1655 "unsupportedOperation", "setCertifiedText",
1656 DefaultModelContext.class.getName() + ".LSResourceResolver" ), null );
1657
1658 }
1659 }
1660
1661 };
1662 }
1663
1664 }
1665 else if ( isLoggable( Level.WARNING ) )
1666 {
1667 log( Level.WARNING, getMessage( "unsupportedResourceType", type ), null );
1668 }
1669 }
1670 catch ( final SAXException e )
1671 {
1672 String message = getMessage( e );
1673 if ( message == null && e.getException() != null )
1674 {
1675 message = getMessage( e.getException() );
1676 }
1677 if ( message == null )
1678 {
1679 message = "";
1680 }
1681 else if ( message.length() > 0 )
1682 {
1683 message = " " + message;
1684 }
1685
1686 String resource = "";
1687 if ( resolvePublicId != null )
1688 {
1689 resource = resolvePublicId + ", ";
1690 }
1691 resource += resolveSystemId;
1692
1693 if ( isLoggable( Level.SEVERE ) )
1694 {
1695 log( Level.SEVERE, getMessage( "failedResolving", resource, message ), e );
1696 }
1697 }
1698 catch ( final IOException e )
1699 {
1700 String message = getMessage( e );
1701 if ( message == null )
1702 {
1703 message = "";
1704 }
1705 else if ( message.length() > 0 )
1706 {
1707 message = " " + message;
1708 }
1709
1710 String resource = "";
1711 if ( resolvePublicId != null )
1712 {
1713 resource = resolvePublicId + ", ";
1714 }
1715 resource += resolveSystemId;
1716
1717 if ( isLoggable( Level.SEVERE ) )
1718 {
1719 log( Level.SEVERE, getMessage( "failedResolving", resource, message ), e );
1720 }
1721 }
1722
1723 return null;
1724 }
1725
1726 };
1727 }
1728
1729 private javax.xml.validation.Schema createSchema( final Schemas schemas, final EntityResolver entityResolver,
1730 final LSResourceResolver resourceResolver, final String model,
1731 final URI publicId ) throws ModelException
1732 {
1733 if ( entityResolver == null )
1734 {
1735 throw new NullPointerException( "entityResolver" );
1736 }
1737 if ( model != null && publicId != null )
1738 {
1739 throw new IllegalArgumentException( "model=" + model + ", publicId=" + publicId.toASCIIString() );
1740 }
1741
1742 try
1743 {
1744 final long t0 = System.currentTimeMillis();
1745 final SchemaFactory f = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI );
1746 final List<Source> sources = new ArrayList<Source>( schemas != null ? schemas.getSchema().size() : 0 );
1747
1748 if ( schemas != null )
1749 {
1750 for ( final Schema s : schemas.getSchema() )
1751 {
1752 final InputSource inputSource = entityResolver.resolveEntity( s.getPublicId(), s.getSystemId() );
1753
1754 if ( inputSource != null )
1755 {
1756 sources.add( new SAXSource( inputSource ) );
1757 }
1758 }
1759 }
1760
1761 if ( sources.isEmpty() )
1762 {
1763 if ( model != null )
1764 {
1765 throw new ModelException( getMessage( "missingSchemasForModel", model ) );
1766 }
1767 if ( publicId != null )
1768 {
1769 throw new ModelException( getMessage( "missingSchemasForPublicId", publicId ) );
1770 }
1771 }
1772
1773 f.setResourceResolver( resourceResolver );
1774 f.setErrorHandler( new ErrorHandler()
1775 {
1776
1777
1778 public void warning( final SAXParseException e ) throws SAXException
1779 {
1780 String message = getMessage( e );
1781 if ( message == null && e.getException() != null )
1782 {
1783 message = getMessage( e.getException() );
1784 }
1785
1786 if ( isLoggable( Level.WARNING ) )
1787 {
1788 log( Level.WARNING, message, e );
1789 }
1790 }
1791
1792 public void error( final SAXParseException e ) throws SAXException
1793 {
1794 throw e;
1795 }
1796
1797 public void fatalError( final SAXParseException e ) throws SAXException
1798 {
1799 throw e;
1800 }
1801
1802 } );
1803
1804 final javax.xml.validation.Schema schema = f.newSchema( sources.toArray( new Source[ sources.size() ] ) );
1805
1806 if ( this.isLoggable( Level.FINE ) )
1807 {
1808 final StringBuilder schemaInfo = new StringBuilder( sources.size() * 50 );
1809
1810 for ( final Source s : sources )
1811 {
1812 schemaInfo.append( ", " ).append( s.getSystemId() );
1813 }
1814
1815 this.log( Level.FINE, getMessage( "creatingSchema", schemaInfo.substring( 2 ),
1816 System.currentTimeMillis() - t0 ), null );
1817
1818 }
1819
1820 return schema;
1821 }
1822 catch ( final IOException e )
1823 {
1824 throw new ModelException( getMessage( e ), e );
1825 }
1826 catch ( final SAXException e )
1827 {
1828 String message = getMessage( e );
1829 if ( message == null && e.getException() != null )
1830 {
1831 message = getMessage( e.getException() );
1832 }
1833
1834 throw new ModelException( message, e );
1835 }
1836 }
1837
1838 private JAXBContext createContext( final Schemas schemas, final String model, final URI publicId )
1839 throws ModelException
1840 {
1841 if ( model != null && publicId != null )
1842 {
1843 throw new IllegalArgumentException( "model=" + model + ", publicId=" + publicId.toASCIIString() );
1844 }
1845
1846 try
1847 {
1848 StringBuilder packageNames = null;
1849 final long t0 = System.currentTimeMillis();
1850
1851 if ( schemas != null )
1852 {
1853 packageNames = new StringBuilder( schemas.getSchema().size() * 25 );
1854
1855 for ( final Schema schema : schemas.getSchema() )
1856 {
1857 if ( schema.getContextId() != null )
1858 {
1859 packageNames.append( ':' ).append( schema.getContextId() );
1860 }
1861 }
1862 }
1863
1864 if ( packageNames == null || packageNames.length() == 0 )
1865 {
1866 if ( model != null )
1867 {
1868 throw new ModelException( getMessage( "missingSchemasForModel", model ) );
1869 }
1870 if ( publicId != null )
1871 {
1872 throw new ModelException( getMessage( "missingSchemasForPublicId", publicId ) );
1873 }
1874 }
1875
1876 final JAXBContext context = JAXBContext.newInstance( packageNames.substring( 1 ), this.getClassLoader() );
1877
1878 if ( this.isLoggable( Level.FINE ) )
1879 {
1880 this.log( Level.FINE, getMessage( "creatingContext", packageNames.substring( 1 ),
1881 System.currentTimeMillis() - t0 ), null );
1882 }
1883
1884 return context;
1885 }
1886 catch ( final JAXBException e )
1887 {
1888 String message = getMessage( e );
1889 if ( message == null && e.getLinkedException() != null )
1890 {
1891 message = getMessage( e.getLinkedException() );
1892 }
1893
1894 throw new ModelException( message, e );
1895 }
1896 }
1897
1898 private Marshaller createMarshaller( final String model, final URI publicId )
1899 throws ModelException
1900 {
1901 if ( model != null && publicId != null )
1902 {
1903 throw new IllegalArgumentException( "model=" + model + ", publicId=" + publicId.toASCIIString() );
1904 }
1905
1906 Schemas schemas = null;
1907
1908 if ( model != null )
1909 {
1910 schemas = this.getModlets().getSchemas( model );
1911 }
1912
1913 if ( publicId != null )
1914 {
1915 schemas = this.getModlets().getSchemas( publicId );
1916 }
1917
1918 try
1919 {
1920 StringBuilder packageNames = null;
1921 StringBuilder schemaLocation = null;
1922 final long t0 = System.currentTimeMillis();
1923
1924 if ( schemas != null )
1925 {
1926 packageNames = new StringBuilder( schemas.getSchema().size() * 25 );
1927 schemaLocation = new StringBuilder( schemas.getSchema().size() * 50 );
1928
1929 for ( final Schema schema : schemas.getSchema() )
1930 {
1931 if ( schema.getContextId() != null )
1932 {
1933 packageNames.append( ':' ).append( schema.getContextId() );
1934 }
1935 if ( schema.getPublicId() != null && schema.getSystemId() != null )
1936 {
1937 schemaLocation.append( ' ' ).append( schema.getPublicId() ).append( ' ' ).
1938 append( schema.getSystemId() );
1939
1940 }
1941 }
1942 }
1943
1944 if ( packageNames == null || packageNames.length() == 0 )
1945 {
1946 if ( model != null )
1947 {
1948 throw new ModelException( getMessage( "missingSchemasForModel", model ) );
1949 }
1950 if ( publicId != null )
1951 {
1952 throw new ModelException( getMessage( "missingSchemasForPublicId", publicId ) );
1953 }
1954 }
1955
1956 final Marshaller m =
1957 JAXBContext.newInstance( packageNames.substring( 1 ), this.getClassLoader() ).createMarshaller();
1958
1959 if ( schemaLocation != null && schemaLocation.length() != 0 )
1960 {
1961 m.setProperty( Marshaller.JAXB_SCHEMA_LOCATION, schemaLocation.substring( 1 ) );
1962 }
1963
1964 MarshallerListenerList listenerList = null;
1965
1966 if ( model != null )
1967 {
1968 final Collection<? extends Marshaller.Listener> listeners =
1969 this.createServiceObjects( model, MARSHALLER_LISTENER_SERVICE, Marshaller.Listener.class );
1970
1971 if ( !listeners.isEmpty() )
1972 {
1973 listenerList = new MarshallerListenerList();
1974 listenerList.getListeners().addAll( listeners );
1975 m.setListener( listenerList );
1976 }
1977 }
1978
1979 if ( this.isLoggable( Level.FINE ) )
1980 {
1981 if ( listenerList == null )
1982 {
1983 this.log( Level.FINE, getMessage( "creatingMarshaller", packageNames.substring( 1 ),
1984 schemaLocation.substring( 1 ),
1985 System.currentTimeMillis() - t0 ), null );
1986
1987 }
1988 else
1989 {
1990 final StringBuilder b = new StringBuilder( listenerList.getListeners().size() * 100 );
1991
1992 for ( int i = 0, s0 = listenerList.getListeners().size(); i < s0; i++ )
1993 {
1994 b.append( ',' ).append( listenerList.getListeners().get( i ) );
1995 }
1996
1997 this.log( Level.FINE, getMessage( "creatingMarshallerWithListeners", packageNames.substring( 1 ),
1998 schemaLocation.substring( 1 ), b.substring( 1 ),
1999 System.currentTimeMillis() - t0 ), null );
2000
2001 }
2002 }
2003
2004 return m;
2005 }
2006 catch ( final JAXBException e )
2007 {
2008 String message = getMessage( e );
2009 if ( message == null && e.getLinkedException() != null )
2010 {
2011 message = getMessage( e.getLinkedException() );
2012 }
2013
2014 throw new ModelException( message, e );
2015 }
2016 }
2017
2018 private Unmarshaller createUnmarshaller( final String model, final URI publicId )
2019 throws ModelException
2020 {
2021 if ( model != null && publicId != null )
2022 {
2023 throw new IllegalArgumentException( "model=" + model + ", publicId=" + publicId.toASCIIString() );
2024 }
2025
2026 Schemas schemas = null;
2027
2028 if ( model != null )
2029 {
2030 schemas = this.getModlets().getSchemas( model );
2031 }
2032
2033 if ( publicId != null )
2034 {
2035 schemas = this.getModlets().getSchemas( publicId );
2036 }
2037
2038 try
2039 {
2040 StringBuilder packageNames = null;
2041 final long t0 = System.currentTimeMillis();
2042
2043 if ( schemas != null )
2044 {
2045 packageNames = new StringBuilder( schemas.getSchema().size() * 25 );
2046
2047 for ( final Schema schema : schemas.getSchema() )
2048 {
2049 if ( schema.getContextId() != null )
2050 {
2051 packageNames.append( ':' ).append( schema.getContextId() );
2052 }
2053 }
2054 }
2055
2056 if ( packageNames == null || packageNames.length() == 0 )
2057 {
2058 if ( model != null )
2059 {
2060 throw new ModelException( getMessage( "missingSchemasForModel", model ) );
2061 }
2062 if ( publicId != null )
2063 {
2064 throw new ModelException( getMessage( "missingSchemasForPublicId", publicId ) );
2065 }
2066 }
2067
2068 final Unmarshaller u =
2069 JAXBContext.newInstance( packageNames.substring( 1 ), this.getClassLoader() ).createUnmarshaller();
2070
2071 UnmarshallerListenerList listenerList = null;
2072
2073 if ( model != null )
2074 {
2075 final Collection<? extends Unmarshaller.Listener> listeners =
2076 this.createServiceObjects( model, UNMARSHALLER_LISTENER_SERVICE, Unmarshaller.Listener.class );
2077
2078 if ( !listeners.isEmpty() )
2079 {
2080 listenerList = new UnmarshallerListenerList();
2081 listenerList.getListeners().addAll( listeners );
2082 u.setListener( listenerList );
2083 }
2084 }
2085
2086 if ( this.isLoggable( Level.FINE ) )
2087 {
2088 if ( listenerList == null )
2089 {
2090 this.log( Level.FINE, getMessage( "creatingUnmarshaller", packageNames.substring( 1 ),
2091 System.currentTimeMillis() - t0 ), null );
2092
2093 }
2094 else
2095 {
2096 final StringBuilder b = new StringBuilder( listenerList.getListeners().size() * 100 );
2097
2098 for ( int i = 0, s0 = listenerList.getListeners().size(); i < s0; i++ )
2099 {
2100 b.append( ',' ).append( listenerList.getListeners().get( i ) );
2101 }
2102
2103 this.log( Level.FINE, getMessage( "creatingUnmarshallerWithListeners",
2104 packageNames.substring( 1 ), b.substring( 1 ),
2105 System.currentTimeMillis() - t0 ), null );
2106
2107 }
2108 }
2109
2110 return u;
2111 }
2112 catch ( final JAXBException e )
2113 {
2114 String message = getMessage( e );
2115 if ( message == null && e.getLinkedException() != null )
2116 {
2117 message = getMessage( e.getLinkedException() );
2118 }
2119
2120 throw new ModelException( message, e );
2121 }
2122 }
2123
2124 private static int ordinalOf( final Object serviceObject )
2125 {
2126 int ordinal = 0;
2127
2128 if ( serviceObject instanceof ModletProvider )
2129 {
2130 ordinal = ( (ModletProvider) serviceObject ).getOrdinal();
2131 }
2132 if ( serviceObject instanceof ModletProcessor )
2133 {
2134 ordinal = ( (ModletProcessor) serviceObject ).getOrdinal();
2135 }
2136 if ( serviceObject instanceof ModletValidator )
2137 {
2138 ordinal = ( (ModletValidator) serviceObject ).getOrdinal();
2139 }
2140 if ( serviceObject instanceof ServiceFactory )
2141 {
2142 ordinal = ( (ServiceFactory) serviceObject ).getOrdinal();
2143 }
2144
2145 return ordinal;
2146 }
2147
2148 private static String getMessage( final String key, final Object... arguments )
2149 {
2150 return MessageFormat.format( ResourceBundle.getBundle(
2151 DefaultModelContext.class.getName().replace( '.', '/' ) ).getString( key ), arguments );
2152
2153 }
2154
2155 private static String getMessage( final Throwable t )
2156 {
2157 return t != null
2158 ? t.getMessage() != null && t.getMessage().trim().length() > 0
2159 ? t.getMessage()
2160 : getMessage( t.getCause() )
2161 : null;
2162
2163 }
2164
2165 }
2166
2167
2168
2169
2170
2171
2172
2173 class ModelErrorHandler extends DefaultHandler
2174 {
2175
2176
2177
2178
2179 private ModelContext context;
2180
2181
2182
2183
2184 private ModelValidationReport report;
2185
2186
2187
2188
2189
2190
2191 ModelErrorHandler( final ModelContext context )
2192 {
2193 this( context, null );
2194 }
2195
2196
2197
2198
2199
2200
2201
2202 ModelErrorHandler( final ModelContext context, final ModelValidationReport report )
2203 {
2204 super();
2205 this.context = context;
2206 this.report = report;
2207 }
2208
2209
2210
2211
2212
2213
2214 public ModelValidationReport getReport()
2215 {
2216 if ( this.report == null )
2217 {
2218 this.report = new ModelValidationReport();
2219 }
2220
2221 return this.report;
2222 }
2223
2224 @Override
2225 public void warning( final SAXParseException exception ) throws SAXException
2226 {
2227 String message = getMessage( exception );
2228 if ( message == null && exception.getException() != null )
2229 {
2230 message = getMessage( exception.getException() );
2231 }
2232
2233 if ( this.context != null && this.context.isLoggable( Level.FINE ) )
2234 {
2235 this.context.log( Level.FINE, message, exception );
2236 }
2237
2238 this.getReport().getDetails().add( new ModelValidationReport.Detail(
2239 "W3C XML 1.0 Recommendation - Warning condition", Level.WARNING, message, null ) );
2240
2241 }
2242
2243 @Override
2244 public void error( final SAXParseException exception ) throws SAXException
2245 {
2246 String message = getMessage( exception );
2247 if ( message == null && exception.getException() != null )
2248 {
2249 message = getMessage( exception.getException() );
2250 }
2251
2252 if ( this.context != null && this.context.isLoggable( Level.FINE ) )
2253 {
2254 this.context.log( Level.FINE, message, exception );
2255 }
2256
2257 this.getReport().getDetails().add( new ModelValidationReport.Detail(
2258 "W3C XML 1.0 Recommendation - Section 1.2 - Error", Level.SEVERE, message, null ) );
2259
2260 }
2261
2262 @Override
2263 public void fatalError( final SAXParseException exception ) throws SAXException
2264 {
2265 String message = getMessage( exception );
2266 if ( message == null && exception.getException() != null )
2267 {
2268 message = getMessage( exception.getException() );
2269 }
2270
2271 if ( this.context != null && this.context.isLoggable( Level.FINE ) )
2272 {
2273 this.context.log( Level.FINE, message, exception );
2274 }
2275
2276 this.getReport().getDetails().add( new ModelValidationReport.Detail(
2277 "W3C XML 1.0 Recommendation - Section 1.2 - Fatal Error", Level.SEVERE, message, null ) );
2278
2279 }
2280
2281 private static String getMessage( final Throwable t )
2282 {
2283 return t != null
2284 ? t.getMessage() != null && t.getMessage().trim().length() > 0
2285 ? t.getMessage()
2286 : getMessage( t.getCause() )
2287 : null;
2288
2289 }
2290
2291 }
2292
2293
2294
2295
2296
2297
2298
2299
2300 class MarshallerListenerList extends Marshaller.Listener
2301 {
2302
2303
2304
2305
2306 private List<Marshaller.Listener> listeners;
2307
2308
2309
2310
2311 MarshallerListenerList()
2312 {
2313 super();
2314 }
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326 List<Marshaller.Listener> getListeners()
2327 {
2328 if ( this.listeners == null )
2329 {
2330 this.listeners = new ArrayList<Marshaller.Listener>();
2331 }
2332
2333 return this.listeners;
2334 }
2335
2336 @Override
2337 public void beforeMarshal( final Object source )
2338 {
2339 for ( int i = 0, s0 = this.getListeners().size(); i < s0; i++ )
2340 {
2341 this.getListeners().get( i ).beforeMarshal( source );
2342 }
2343 }
2344
2345 @Override
2346 public void afterMarshal( final Object source )
2347 {
2348 for ( int i = 0, s0 = this.getListeners().size(); i < s0; i++ )
2349 {
2350 this.getListeners().get( i ).afterMarshal( source );
2351 }
2352 }
2353
2354 }
2355
2356
2357
2358
2359
2360
2361
2362
2363 class UnmarshallerListenerList extends Unmarshaller.Listener
2364 {
2365
2366
2367
2368
2369 private List<Unmarshaller.Listener> listeners;
2370
2371
2372
2373
2374 UnmarshallerListenerList()
2375 {
2376 super();
2377 }
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389 List<Unmarshaller.Listener> getListeners()
2390 {
2391 if ( this.listeners == null )
2392 {
2393 this.listeners = new ArrayList<Unmarshaller.Listener>();
2394 }
2395
2396 return this.listeners;
2397 }
2398
2399 @Override
2400 public void beforeUnmarshal( final Object target, final Object parent )
2401 {
2402 for ( int i = 0, s0 = this.getListeners().size(); i < s0; i++ )
2403 {
2404 this.getListeners().get( i ).beforeUnmarshal( target, parent );
2405 }
2406 }
2407
2408 @Override
2409 public void afterUnmarshal( final Object target, final Object parent )
2410 {
2411 for ( int i = 0, s0 = this.getListeners().size(); i < s0; i++ )
2412 {
2413 this.getListeners().get( i ).afterUnmarshal( target, parent );
2414 }
2415 }
2416
2417 }