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