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
32
33 package org.jomc.model.bootstrap;
34
35 import java.io.BufferedReader;
36 import java.io.File;
37 import java.io.FileInputStream;
38 import java.io.IOException;
39 import java.io.InputStream;
40 import java.io.InputStreamReader;
41 import java.lang.reflect.Constructor;
42 import java.lang.reflect.InvocationTargetException;
43 import java.net.URL;
44 import java.util.Collection;
45 import java.util.Comparator;
46 import java.util.Enumeration;
47 import java.util.Map;
48 import java.util.TreeMap;
49 import javax.xml.bind.JAXBContext;
50 import javax.xml.bind.JAXBException;
51 import javax.xml.bind.Marshaller;
52 import javax.xml.bind.Unmarshaller;
53 import javax.xml.bind.util.JAXBSource;
54 import javax.xml.validation.Validator;
55 import org.xml.sax.SAXException;
56
57
58
59
60
61
62
63
64 public abstract class BootstrapContext
65 {
66
67
68 private static volatile String bootstrapContextClassName;
69
70
71 private ClassLoader classLoader;
72
73
74
75
76
77
78 public BootstrapContext( final ClassLoader classLoader )
79 {
80 super();
81 this.classLoader = classLoader;
82 }
83
84
85
86
87
88
89 public ClassLoader getClassLoader()
90 {
91 if ( this.classLoader == null )
92 {
93 this.classLoader = new ClassLoader( null )
94 {
95
96 @Override
97 public String toString()
98 {
99 return BootstrapContext.class.getName() + ".BootstrapClassLoader@" +
100 System.identityHashCode( this );
101
102 }
103
104 };
105
106 }
107
108 return this.classLoader;
109 }
110
111
112
113
114
115
116
117
118
119
120
121
122 public static String getBootstrapContextClassName()
123 {
124 if ( bootstrapContextClassName == null )
125 {
126 bootstrapContextClassName = System.getProperty( "org.jomc.model.bootstrap.BootstrapContext.className",
127 DefaultBootstrapContext.class.getName() );
128
129 }
130
131 return bootstrapContextClassName;
132 }
133
134
135
136
137
138
139
140
141 public static void setBootstrapContextClassName( final String value )
142 {
143 bootstrapContextClassName = value;
144 }
145
146
147
148
149
150
151
152
153
154
155
156 public Class findClass( final String name ) throws BootstrapException
157 {
158 if ( name == null )
159 {
160 throw new NullPointerException( "name" );
161 }
162
163 try
164 {
165 return Class.forName( name, true, this.getClassLoader() );
166 }
167 catch ( final ClassNotFoundException e )
168 {
169 return null;
170 }
171 }
172
173
174
175
176
177
178
179
180
181
182
183 public URL findResource( final String name ) throws BootstrapException
184 {
185 if ( name == null )
186 {
187 throw new NullPointerException( "name" );
188 }
189
190 return this.getClassLoader().getResource( name );
191 }
192
193
194
195
196
197
198
199
200
201
202
203
204 public Enumeration<URL> findResources( final String name ) throws BootstrapException
205 {
206 if ( name == null )
207 {
208 throw new NullPointerException( "name" );
209 }
210
211 try
212 {
213 return this.getClassLoader().getResources( name );
214 }
215 catch ( final IOException e )
216 {
217 throw new BootstrapException( e );
218 }
219 }
220
221
222
223
224
225
226
227
228
229
230
231
232
233 public Schemas findSchemas() throws BootstrapException
234 {
235 try
236 {
237 final Schemas schemas = new Schemas();
238
239 final Collection<Class<SchemaProvider>> providers = this.loadProviders( SchemaProvider.class );
240 for ( Class<SchemaProvider> provider : providers )
241 {
242 final SchemaProvider schemaProvider = provider.newInstance();
243 final Schemas provided = schemaProvider.findSchemas( this );
244 if ( provided != null )
245 {
246 schemas.getSchema().addAll( provided.getSchema() );
247 }
248 }
249
250 final javax.xml.validation.Schema bootstrapSchema = this.createSchema();
251 final Validator validator = bootstrapSchema.newValidator();
252 validator.validate( new JAXBSource( this.createContext(), new ObjectFactory().createSchemas( schemas ) ) );
253
254 return schemas;
255 }
256 catch ( final InstantiationException e )
257 {
258 throw new BootstrapException( e );
259 }
260 catch ( final IllegalAccessException e )
261 {
262 throw new BootstrapException( e );
263 }
264 catch ( final JAXBException e )
265 {
266 throw new BootstrapException( e );
267 }
268 catch ( final SAXException e )
269 {
270 throw new BootstrapException( e );
271 }
272 catch ( final IOException e )
273 {
274 throw new BootstrapException( e );
275 }
276 }
277
278
279
280
281
282
283
284
285
286
287
288
289
290 public Services findServices() throws BootstrapException
291 {
292 try
293 {
294 final Services services = new Services();
295
296 final Collection<Class<ServiceProvider>> providers = this.loadProviders( ServiceProvider.class );
297 for ( Class<ServiceProvider> provider : providers )
298 {
299 final ServiceProvider serviceProvider = provider.newInstance();
300 final Services provided = serviceProvider.findServices( this );
301 if ( provided != null )
302 {
303 services.getService().addAll( provided.getService() );
304 }
305 }
306
307 final javax.xml.validation.Schema bootstrapSchema = this.createSchema();
308 final Validator validator = bootstrapSchema.newValidator();
309 validator.validate( new JAXBSource( this.createContext(), new ObjectFactory().createServices( services ) ) );
310
311 return services;
312 }
313 catch ( final InstantiationException e )
314 {
315 throw new BootstrapException( e );
316 }
317 catch ( final IllegalAccessException e )
318 {
319 throw new BootstrapException( e );
320 }
321 catch ( final JAXBException e )
322 {
323 throw new BootstrapException( e );
324 }
325 catch ( final SAXException e )
326 {
327 throw new BootstrapException( e );
328 }
329 catch ( final IOException e )
330 {
331 throw new BootstrapException( e );
332 }
333 }
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348 public static BootstrapContext createBootstrapContext( final ClassLoader classLoader ) throws BootstrapException
349 {
350 if ( DefaultBootstrapContext.class.getName().equals( getBootstrapContextClassName() ) )
351 {
352 return new DefaultBootstrapContext( classLoader );
353 }
354
355 try
356 {
357 final Class clazz = Class.forName( getBootstrapContextClassName(), true, classLoader );
358 final Constructor ctor = clazz.getConstructor( ClassLoader.class );
359 return (BootstrapContext) ctor.newInstance( classLoader );
360 }
361 catch ( final ClassNotFoundException e )
362 {
363 throw new BootstrapException( e );
364 }
365 catch ( final NoSuchMethodException e )
366 {
367 throw new BootstrapException( e );
368 }
369 catch ( final InstantiationException e )
370 {
371 throw new BootstrapException( e );
372 }
373 catch ( final IllegalAccessException e )
374 {
375 throw new BootstrapException( e );
376 }
377 catch ( final InvocationTargetException e )
378 {
379 throw new BootstrapException( e );
380 }
381 catch ( final ClassCastException e )
382 {
383 throw new BootstrapException( e );
384 }
385 }
386
387
388
389
390
391
392
393
394
395 public abstract javax.xml.validation.Schema createSchema() throws BootstrapException;
396
397
398
399
400
401
402
403
404
405 public abstract JAXBContext createContext() throws BootstrapException;
406
407
408
409
410
411
412
413
414
415 public abstract Marshaller createMarshaller() throws BootstrapException;
416
417
418
419
420
421
422
423
424
425 public abstract Unmarshaller createUnmarshaller() throws BootstrapException;
426
427 private <T> Collection<Class<T>> loadProviders( final Class<T> providerClass ) throws BootstrapException
428 {
429 try
430 {
431 final String providerNamePrefix = providerClass.getName() + ".";
432 final Map<String, Class<T>> providers = new TreeMap<String, Class<T>>( new Comparator<String>()
433 {
434
435 public int compare( final String key1, final String key2 )
436 {
437 return key1.compareTo( key2 );
438 }
439
440 } );
441
442 final File platformProviders = new File( new StringBuilder().append( System.getProperty( "java.home" ) ).
443 append( File.separator ).append( "jre" ).append( File.separator ).append( "lib" ).
444 append( File.separator ).append( "jomc.properties" ).toString() );
445
446 if ( platformProviders.exists() )
447 {
448 InputStream in = null;
449 final java.util.Properties p = new java.util.Properties();
450
451 try
452 {
453 in = new FileInputStream( platformProviders );
454 p.load( in );
455 }
456 finally
457 {
458 if ( in != null )
459 {
460 in.close();
461 }
462 }
463
464 for ( Map.Entry e : p.entrySet() )
465 {
466 if ( e.getKey().toString().startsWith( providerNamePrefix ) )
467 {
468 final Class<T> provider = this.findClass( e.getValue().toString() );
469 if ( provider != null )
470 {
471 providers.put( e.getKey().toString(), provider );
472 }
473 }
474 }
475 }
476
477 final Enumeration<URL> serviceProviders =
478 this.findResources( "META-INF/services/" + providerClass.getName() );
479
480 while ( serviceProviders.hasMoreElements() )
481 {
482 final URL url = serviceProviders.nextElement();
483 final BufferedReader reader = new BufferedReader( new InputStreamReader( url.openStream(), "UTF-8" ) );
484
485 String line = null;
486 while ( ( line = reader.readLine() ) != null )
487 {
488 if ( line.contains( "#" ) )
489 {
490 continue;
491 }
492
493 final Class<T> provider = this.findClass( line );
494 if ( provider != null )
495 {
496 providers.put( providerNamePrefix + providers.size(), provider );
497 }
498 }
499
500 reader.close();
501 }
502
503 return providers.values();
504 }
505 catch ( final IOException e )
506 {
507 throw new BootstrapException( e );
508 }
509 }
510
511 }