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.model.modlet;
32
33 import java.net.URISyntaxException;
34 import java.net.URL;
35 import java.text.MessageFormat;
36 import java.util.Enumeration;
37 import java.util.LinkedList;
38 import java.util.List;
39 import java.util.Locale;
40 import java.util.Map;
41 import java.util.ResourceBundle;
42 import java.util.logging.Level;
43 import javax.xml.bind.JAXBContext;
44 import javax.xml.bind.JAXBElement;
45 import javax.xml.bind.JAXBException;
46 import javax.xml.bind.util.JAXBResult;
47 import javax.xml.bind.util.JAXBSource;
48 import javax.xml.transform.ErrorListener;
49 import javax.xml.transform.Transformer;
50 import javax.xml.transform.TransformerConfigurationException;
51 import javax.xml.transform.TransformerException;
52 import javax.xml.transform.TransformerFactory;
53 import javax.xml.transform.stream.StreamSource;
54 import org.jomc.modlet.Model;
55 import org.jomc.modlet.ModelContext;
56 import org.jomc.modlet.ModelException;
57 import org.jomc.modlet.ModelProcessor;
58
59
60
61
62
63
64
65
66 public class DefaultModelProcessor implements ModelProcessor
67 {
68
69
70
71
72
73
74
75
76 public static final String ENABLED_ATTRIBUTE_NAME = "org.jomc.model.modlet.DefaultModelProcessor.enabledAttribute";
77
78
79
80
81
82
83 private static final String DEFAULT_ENABLED_PROPERTY_NAME =
84 "org.jomc.model.modlet.DefaultModelProcessor.defaultEnabled";
85
86
87
88
89
90 private static final String DEPRECATED_DEFAULT_ENABLED_PROPERTY_NAME =
91 "org.jomc.model.DefaultModelProcessor.defaultEnabled";
92
93
94
95
96
97
98
99 private static final Boolean DEFAULT_ENABLED = Boolean.TRUE;
100
101
102
103
104 private static volatile Boolean defaultEnabled;
105
106
107
108
109 private Boolean enabled;
110
111
112
113
114
115
116
117
118 public static final String TRANSFORMER_LOCATION_ATTRIBUTE_NAME =
119 "org.jomc.model.modlet.DefaultModelProcessor.transformerLocationAttribute";
120
121
122
123
124
125
126 private static final String DEFAULT_TRANSFORMER_LOCATION_PROPERTY_NAME =
127 "org.jomc.model.modlet.DefaultModelProcessor.defaultTransformerLocation";
128
129
130
131
132
133 private static final String DEPRECATED_DEFAULT_TRANSFORMER_LOCATION_PROPERTY_NAME =
134 "org.jomc.model.DefaultModelProcessor.defaultTransformerLocation";
135
136
137
138
139
140
141 private static final String DEFAULT_TRANSFORMER_LOCATION = "META-INF/jomc.xsl";
142
143
144
145
146 private static volatile String defaultTransformerLocation;
147
148
149
150
151 private String transformerLocation;
152
153
154
155
156 public DefaultModelProcessor()
157 {
158 super();
159 }
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174 public static boolean isDefaultEnabled()
175 {
176 if ( defaultEnabled == null )
177 {
178 defaultEnabled =
179 Boolean.valueOf( System.getProperty( DEFAULT_ENABLED_PROPERTY_NAME,
180 System.getProperty( DEPRECATED_DEFAULT_ENABLED_PROPERTY_NAME,
181 Boolean.toString( DEFAULT_ENABLED ) ) ) );
182
183 }
184
185 return defaultEnabled;
186 }
187
188
189
190
191
192
193
194
195 public static void setDefaultEnabled( final Boolean value )
196 {
197 defaultEnabled = value;
198 }
199
200
201
202
203
204
205
206
207
208 public final boolean isEnabled()
209 {
210 if ( this.enabled == null )
211 {
212 this.enabled = isDefaultEnabled();
213 }
214
215 return this.enabled;
216 }
217
218
219
220
221
222
223
224
225 public final void setEnabled( final Boolean value )
226 {
227 this.enabled = value;
228 }
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243 public static String getDefaultTransformerLocation()
244 {
245 if ( defaultTransformerLocation == null )
246 {
247 defaultTransformerLocation =
248 System.getProperty( DEFAULT_TRANSFORMER_LOCATION_PROPERTY_NAME,
249 System.getProperty( DEPRECATED_DEFAULT_TRANSFORMER_LOCATION_PROPERTY_NAME,
250 DEFAULT_TRANSFORMER_LOCATION ) );
251
252 }
253
254 return defaultTransformerLocation;
255 }
256
257
258
259
260
261
262
263
264 public static void setDefaultTransformerLocation( final String value )
265 {
266 defaultTransformerLocation = value;
267 }
268
269
270
271
272
273
274
275
276
277 public final String getTransformerLocation()
278 {
279 if ( this.transformerLocation == null )
280 {
281 this.transformerLocation = getDefaultTransformerLocation();
282 }
283
284 return this.transformerLocation;
285 }
286
287
288
289
290
291
292
293
294 public final void setTransformerLocation( final String value )
295 {
296 this.transformerLocation = value;
297 }
298
299
300
301
302
303
304
305
306
307
308
309
310
311 public List<Transformer> findTransformers( final ModelContext context, final String location ) throws ModelException
312 {
313 if ( context == null )
314 {
315 throw new NullPointerException( "context" );
316 }
317 if ( location == null )
318 {
319 throw new NullPointerException( "location" );
320 }
321
322 try
323 {
324 final long t0 = System.currentTimeMillis();
325 final List<Transformer> transformers = new LinkedList<Transformer>();
326 final TransformerFactory transformerFactory = TransformerFactory.newInstance();
327 final Enumeration<URL> resources = context.findResources( location );
328 final ErrorListener errorListener = new ErrorListener()
329 {
330
331 public void warning( final TransformerException exception ) throws TransformerException
332 {
333 if ( context.isLoggable( Level.WARNING ) )
334 {
335 context.log( Level.WARNING, getMessage( exception ), exception );
336 }
337 }
338
339 public void error( final TransformerException exception ) throws TransformerException
340 {
341 if ( context.isLoggable( Level.SEVERE ) )
342 {
343 context.log( Level.SEVERE, getMessage( exception ), exception );
344 }
345
346 throw exception;
347 }
348
349 public void fatalError( final TransformerException exception ) throws TransformerException
350 {
351 if ( context.isLoggable( Level.SEVERE ) )
352 {
353 context.log( Level.SEVERE, getMessage( exception ), exception );
354 }
355
356 throw exception;
357 }
358
359 };
360
361 transformerFactory.setErrorListener( errorListener );
362
363 int count = 0;
364 while ( resources.hasMoreElements() )
365 {
366 count++;
367 final URL url = resources.nextElement();
368
369 if ( context.isLoggable( Level.FINEST ) )
370 {
371 context.log( Level.FINEST, getMessage( "processing", url.toExternalForm() ), null );
372 }
373
374 final Transformer transformer =
375 transformerFactory.newTransformer( new StreamSource( url.toURI().toASCIIString() ) );
376
377 transformer.setErrorListener( errorListener );
378
379 for ( final Map.Entry<Object, Object> e : System.getProperties().entrySet() )
380 {
381 transformer.setParameter( e.getKey().toString(), e.getValue() );
382 }
383
384 transformers.add( transformer );
385 }
386
387 if ( context.isLoggable( Level.FINE ) )
388 {
389 context.log( Level.FINE, getMessage( "contextReport", count, location,
390 Long.valueOf( System.currentTimeMillis() - t0 ) ), null );
391
392 }
393
394 return transformers.isEmpty() ? null : transformers;
395 }
396 catch ( final URISyntaxException e )
397 {
398 throw new ModelException( getMessage( e ), e );
399 }
400 catch ( final TransformerConfigurationException e )
401 {
402 String message = getMessage( e );
403 if ( message == null && e.getException() != null )
404 {
405 message = getMessage( e.getException() );
406 }
407
408 throw new ModelException( message, e );
409 }
410 }
411
412
413
414
415
416
417
418
419
420
421 public Model processModel( final ModelContext context, final Model model ) throws ModelException
422 {
423 if ( context == null )
424 {
425 throw new NullPointerException( "context" );
426 }
427 if ( model == null )
428 {
429 throw new NullPointerException( "model" );
430 }
431
432 try
433 {
434 Model processed = model;
435
436 boolean contextEnabled = this.isEnabled();
437 if ( DEFAULT_ENABLED == contextEnabled
438 && context.getAttribute( ENABLED_ATTRIBUTE_NAME ) instanceof Boolean )
439 {
440 contextEnabled = (Boolean) context.getAttribute( ENABLED_ATTRIBUTE_NAME );
441 }
442
443 String contextTransformerLocation = this.getTransformerLocation();
444 if ( DEFAULT_TRANSFORMER_LOCATION.equals( contextTransformerLocation )
445 && context.getAttribute( TRANSFORMER_LOCATION_ATTRIBUTE_NAME ) instanceof String )
446 {
447 contextTransformerLocation = (String) context.getAttribute( TRANSFORMER_LOCATION_ATTRIBUTE_NAME );
448 }
449
450 if ( contextEnabled )
451 {
452 final org.jomc.modlet.ObjectFactory objectFactory = new org.jomc.modlet.ObjectFactory();
453 final JAXBContext jaxbContext = context.createContext( model.getIdentifier() );
454 final List<Transformer> transformers = this.findTransformers( context, contextTransformerLocation );
455 processed = model.clone();
456
457 if ( transformers != null )
458 {
459 for ( int i = 0, s0 = transformers.size(); i < s0; i++ )
460 {
461 final JAXBElement<Model> e = objectFactory.createModel( processed );
462 final JAXBSource source = new JAXBSource( jaxbContext, e );
463 final JAXBResult result = new JAXBResult( jaxbContext );
464 transformers.get( i ).transform( source, result );
465
466 if ( result.getResult() instanceof JAXBElement<?>
467 && ( (JAXBElement<?>) result.getResult() ).getValue() instanceof Model )
468 {
469 processed = (Model) ( (JAXBElement<?>) result.getResult() ).getValue();
470 }
471 else
472 {
473 throw new ModelException( getMessage(
474 "illegalTransformationResult", model.getIdentifier() ) );
475
476 }
477 }
478 }
479 }
480 else if ( context.isLoggable( Level.FINER ) )
481 {
482 context.log( Level.FINER, getMessage( "disabled", this.getClass().getSimpleName(),
483 model.getIdentifier() ), null );
484
485 }
486
487 return processed;
488 }
489 catch ( final TransformerException e )
490 {
491 String message = getMessage( e );
492 if ( message == null && e.getException() != null )
493 {
494 message = getMessage( e.getException() );
495 }
496
497 throw new ModelException( message, e );
498 }
499 catch ( final JAXBException e )
500 {
501 String message = getMessage( e );
502 if ( message == null && e.getLinkedException() != null )
503 {
504 message = getMessage( e.getLinkedException() );
505 }
506
507 throw new ModelException( message, e );
508 }
509 }
510
511 private static String getMessage( final String key, final Object... args )
512 {
513 return MessageFormat.format( ResourceBundle.getBundle(
514 DefaultModelProcessor.class.getName().replace( '.', '/' ), Locale.getDefault() ).getString( key ), args );
515
516 }
517
518 private static String getMessage( final Throwable t )
519 {
520 return t != null
521 ? t.getMessage() != null && t.getMessage().trim().length() > 0
522 ? t.getMessage()
523 : getMessage( t.getCause() )
524 : null;
525
526 }
527
528 }