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