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