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.ByteArrayInputStream;
34  import java.io.ByteArrayOutputStream;
35  import java.io.IOException;
36  import java.lang.reflect.UndeclaredThrowableException;
37  import java.net.URISyntaxException;
38  import java.net.URL;
39  import java.text.MessageFormat;
40  import java.util.Enumeration;
41  import java.util.LinkedList;
42  import java.util.List;
43  import java.util.Locale;
44  import java.util.Map;
45  import java.util.Properties;
46  import java.util.ResourceBundle;
47  import java.util.concurrent.Callable;
48  import java.util.concurrent.CancellationException;
49  import java.util.concurrent.ExecutionException;
50  import java.util.concurrent.Future;
51  import java.util.logging.Level;
52  import javax.xml.bind.JAXBContext;
53  import javax.xml.bind.JAXBElement;
54  import javax.xml.bind.JAXBException;
55  import javax.xml.bind.util.JAXBResult;
56  import javax.xml.bind.util.JAXBSource;
57  import javax.xml.transform.ErrorListener;
58  import javax.xml.transform.Transformer;
59  import javax.xml.transform.TransformerConfigurationException;
60  import javax.xml.transform.TransformerException;
61  import javax.xml.transform.TransformerFactory;
62  import javax.xml.transform.stream.StreamSource;
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  public class DefaultModletProcessor implements ModletProcessor
73  {
74  
75      
76  
77  
78  
79  
80  
81      public static final String ENABLED_ATTRIBUTE_NAME = "org.jomc.modlet.DefaultModletProcessor.enabledAttribute";
82  
83      
84  
85  
86  
87  
88      private static final String DEFAULT_ENABLED_PROPERTY_NAME =
89          "org.jomc.modlet.DefaultModletProcessor.defaultEnabled";
90  
91      
92  
93  
94  
95  
96      private static final Boolean DEFAULT_ENABLED = Boolean.TRUE;
97  
98      
99  
100 
101     private static volatile Boolean defaultEnabled;
102 
103     
104 
105 
106     private volatile Boolean enabled;
107 
108     
109 
110 
111 
112 
113     private static final String DEFAULT_ORDINAL_PROPERTY_NAME =
114         "org.jomc.modlet.DefaultModletProcessor.defaultOrdinal";
115 
116     
117 
118 
119 
120 
121     private static final Integer DEFAULT_ORDINAL = 0;
122 
123     
124 
125 
126     private static volatile Integer defaultOrdinal;
127 
128     
129 
130 
131     private volatile Integer ordinal;
132 
133     
134 
135 
136 
137 
138 
139 
140     public static final String TRANSFORMER_LOCATION_ATTRIBUTE_NAME =
141         "org.jomc.modlet.DefaultModletProcessor.transformerLocationAttribute";
142 
143     
144 
145 
146 
147 
148     private static final String DEFAULT_TRANSFORMER_LOCATION_PROPERTY_NAME =
149         "org.jomc.modlet.DefaultModletProcessor.defaultTransformerLocation";
150 
151     
152 
153 
154 
155 
156     private static final String DEFAULT_TRANSFORMER_LOCATION = "META-INF/jomc-modlet.xsl";
157 
158     
159 
160 
161     private static volatile String defaultTransformerLocation;
162 
163     
164 
165 
166     private volatile String transformerLocation;
167 
168     
169 
170 
171     public DefaultModletProcessor()
172     {
173         super();
174     }
175 
176     
177 
178 
179 
180 
181 
182 
183 
184 
185 
186 
187 
188 
189 
190     public static boolean isDefaultEnabled()
191     {
192         if ( defaultEnabled == null )
193         {
194             defaultEnabled = Boolean.valueOf( System.getProperty(
195                 DEFAULT_ENABLED_PROPERTY_NAME, Boolean.toString( DEFAULT_ENABLED ) ) );
196 
197         }
198 
199         return defaultEnabled;
200     }
201 
202     
203 
204 
205 
206 
207 
208 
209     public static void setDefaultEnabled( final Boolean value )
210     {
211         defaultEnabled = value;
212     }
213 
214     
215 
216 
217 
218 
219 
220 
221 
222     public final boolean isEnabled()
223     {
224         if ( this.enabled == null )
225         {
226             this.enabled = isDefaultEnabled();
227         }
228 
229         return this.enabled;
230     }
231 
232     
233 
234 
235 
236 
237 
238 
239     public final void setEnabled( final Boolean value )
240     {
241         this.enabled = value;
242     }
243 
244     
245 
246 
247 
248 
249 
250 
251 
252 
253 
254 
255 
256     public static int getDefaultOrdinal()
257     {
258         if ( defaultOrdinal == null )
259         {
260             defaultOrdinal = Integer.getInteger( DEFAULT_ORDINAL_PROPERTY_NAME, DEFAULT_ORDINAL );
261         }
262 
263         return defaultOrdinal;
264     }
265 
266     
267 
268 
269 
270 
271 
272 
273     public static void setDefaultOrdinal( final Integer value )
274     {
275         defaultOrdinal = value;
276     }
277 
278     
279 
280 
281 
282 
283 
284 
285 
286     public final int getOrdinal()
287     {
288         if ( this.ordinal == null )
289         {
290             this.ordinal = getDefaultOrdinal();
291         }
292 
293         return this.ordinal;
294     }
295 
296     
297 
298 
299 
300 
301 
302 
303     public final void setOrdinal( final Integer value )
304     {
305         this.ordinal = value;
306     }
307 
308     
309 
310 
311 
312 
313 
314 
315 
316 
317 
318 
319 
320 
321     public static String getDefaultTransformerLocation()
322     {
323         if ( defaultTransformerLocation == null )
324         {
325             defaultTransformerLocation =
326                 System.getProperty( DEFAULT_TRANSFORMER_LOCATION_PROPERTY_NAME, DEFAULT_TRANSFORMER_LOCATION );
327 
328         }
329 
330         return defaultTransformerLocation;
331     }
332 
333     
334 
335 
336 
337 
338 
339 
340     public static void setDefaultTransformerLocation( final String value )
341     {
342         defaultTransformerLocation = value;
343     }
344 
345     
346 
347 
348 
349 
350 
351 
352 
353     public final String getTransformerLocation()
354     {
355         if ( this.transformerLocation == null )
356         {
357             this.transformerLocation = getDefaultTransformerLocation();
358         }
359 
360         return this.transformerLocation;
361     }
362 
363     
364 
365 
366 
367 
368 
369 
370     public final void setTransformerLocation( final String value )
371     {
372         this.transformerLocation = value;
373     }
374 
375     
376 
377 
378 
379 
380 
381 
382 
383 
384 
385 
386 
387     public List<Transformer> findTransformers( final ModelContext context, final String location ) throws ModelException
388     {
389         if ( context == null )
390         {
391             throw new NullPointerException( "context" );
392         }
393         if ( location == null )
394         {
395             throw new NullPointerException( "location" );
396         }
397 
398         try
399         {
400             final long t0 = System.nanoTime();
401             final List<Transformer> transformers = new LinkedList<Transformer>();
402             final Enumeration<URL> transformerResourceEnumeration = context.findResources( location );
403             final ErrorListener errorListener = new ErrorListener()
404             {
405 
406                 public void warning( final TransformerException exception ) throws TransformerException
407                 {
408                     if ( context.isLoggable( Level.WARNING ) )
409                     {
410                         context.log( Level.WARNING, getMessage( exception ), exception );
411                     }
412                 }
413 
414                 public void error( final TransformerException exception ) throws TransformerException
415                 {
416                     if ( context.isLoggable( Level.SEVERE ) )
417                     {
418                         context.log( Level.SEVERE, getMessage( exception ), exception );
419                     }
420 
421                     throw exception;
422                 }
423 
424                 public void fatalError( final TransformerException exception ) throws TransformerException
425                 {
426                     if ( context.isLoggable( Level.SEVERE ) )
427                     {
428                         context.log( Level.SEVERE, getMessage( exception ), exception );
429                     }
430 
431                     throw exception;
432                 }
433 
434             };
435 
436             final Properties parameters = getTransformerParameters();
437             final ThreadLocal<TransformerFactory> threadLocalTransformerFactory = new ThreadLocal<TransformerFactory>();
438 
439             class CreateTansformerTask implements Callable<Transformer>
440             {
441 
442                 private final URL resource;
443 
444                 CreateTansformerTask( final URL resource )
445                 {
446                     super();
447                     this.resource = resource;
448                 }
449 
450                 public Transformer call() throws ModelException
451                 {
452                     try
453                     {
454                         TransformerFactory transformerFactory = threadLocalTransformerFactory.get();
455                         if ( transformerFactory == null )
456                         {
457                             transformerFactory = TransformerFactory.newInstance();
458                             transformerFactory.setErrorListener( errorListener );
459                             threadLocalTransformerFactory.set( transformerFactory );
460                         }
461 
462                         if ( context.isLoggable( Level.FINEST ) )
463                         {
464                             context.log( Level.FINEST, getMessage( "processing", this.resource.toExternalForm() ),
465                                          null );
466 
467                         }
468 
469                         final Transformer transformer = transformerFactory.newTransformer(
470                             new StreamSource( this.resource.toURI().toASCIIString() ) );
471 
472                         transformer.setErrorListener( errorListener );
473 
474                         for ( final Map.Entry<Object, Object> e : parameters.entrySet() )
475                         {
476                             transformer.setParameter( e.getKey().toString(), e.getValue() );
477                         }
478 
479                         return transformer;
480                     }
481                     catch ( final TransformerConfigurationException e )
482                     {
483                         String message = getMessage( e );
484                         if ( message == null && e.getException() != null )
485                         {
486                             message = getMessage( e.getException() );
487                         }
488 
489                         throw new ModelException( message, e );
490                     }
491                     catch ( final URISyntaxException e )
492                     {
493                         throw new ModelException( getMessage( e ), e );
494                     }
495                 }
496 
497             }
498 
499             final List<CreateTansformerTask> tasks = new LinkedList<CreateTansformerTask>();
500 
501             while ( transformerResourceEnumeration.hasMoreElements() )
502             {
503                 tasks.add( new CreateTansformerTask( transformerResourceEnumeration.nextElement() ) );
504             }
505 
506             if ( context.getExecutorService() != null && tasks.size() > 1 )
507             {
508                 for ( final Future<Transformer> task : context.getExecutorService().invokeAll( tasks ) )
509                 {
510                     transformers.add( task.get() );
511                 }
512             }
513             else
514             {
515                 for ( final CreateTansformerTask task : tasks )
516                 {
517                     transformers.add( task.call() );
518                 }
519             }
520 
521             if ( context.isLoggable( Level.FINE ) )
522             {
523                 context.log( Level.FINE, getMessage( "contextReport", tasks.size(), location, System.nanoTime() - t0 ),
524                              null );
525 
526             }
527 
528             return transformers.isEmpty() ? null : transformers;
529         }
530         catch ( final CancellationException e )
531         {
532             throw new ModelException( getMessage( e ), e );
533         }
534         catch ( final InterruptedException e )
535         {
536             throw new ModelException( getMessage( e ), e );
537         }
538         catch ( final ExecutionException e )
539         {
540             if ( e.getCause() instanceof ModelException )
541             {
542                 throw (ModelException) e.getCause();
543             }
544             else if ( e.getCause() instanceof RuntimeException )
545             {
546                 
547                 
548                 if ( e.getCause().getCause() instanceof ModelException )
549                 {
550                     throw (ModelException) e.getCause().getCause();
551                 }
552                 else if ( e.getCause().getCause() instanceof RuntimeException )
553                 {
554                     throw (RuntimeException) e.getCause().getCause();
555                 }
556                 else if ( e.getCause().getCause() instanceof Error )
557                 {
558                     throw (Error) e.getCause().getCause();
559                 }
560                 else if ( e.getCause().getCause() instanceof Exception )
561                 {
562                     
563                     throw new UndeclaredThrowableException( e.getCause().getCause() );
564                 }
565                 else
566                 {
567                     throw (RuntimeException) e.getCause();
568                 }
569             }
570             else if ( e.getCause() instanceof Error )
571             {
572                 throw (Error) e.getCause();
573             }
574             else
575             {
576                 
577                 throw new UndeclaredThrowableException( e.getCause() );
578             }
579         }
580     }
581 
582     
583 
584 
585 
586 
587 
588 
589 
590 
591     public Modlets processModlets( final ModelContext context, final Modlets modlets ) throws ModelException
592     {
593         if ( context == null )
594         {
595             throw new NullPointerException( "context" );
596         }
597         if ( modlets == null )
598         {
599             throw new NullPointerException( "modlets" );
600         }
601 
602         try
603         {
604             Modlets processed = null;
605 
606             boolean contextEnabled = this.isEnabled();
607             if ( DEFAULT_ENABLED == contextEnabled
608                      && context.getAttribute( ENABLED_ATTRIBUTE_NAME ) instanceof Boolean )
609             {
610                 contextEnabled = (Boolean) context.getAttribute( ENABLED_ATTRIBUTE_NAME );
611             }
612 
613             String contextTransformerLocation = this.getTransformerLocation();
614             if ( DEFAULT_TRANSFORMER_LOCATION.equals( contextTransformerLocation )
615                      && context.getAttribute( TRANSFORMER_LOCATION_ATTRIBUTE_NAME ) instanceof String )
616             {
617                 contextTransformerLocation = (String) context.getAttribute( TRANSFORMER_LOCATION_ATTRIBUTE_NAME );
618             }
619 
620             if ( contextEnabled )
621             {
622                 final org.jomc.modlet.ObjectFactory objectFactory = new org.jomc.modlet.ObjectFactory();
623                 final JAXBContext jaxbContext = context.createContext( ModletObject.MODEL_PUBLIC_ID );
624                 final List<Transformer> transformers = this.findTransformers( context, contextTransformerLocation );
625 
626                 if ( transformers != null )
627                 {
628                     processed = modlets.clone();
629 
630                     for ( int i = 0, s0 = transformers.size(); i < s0; i++ )
631                     {
632                         final JAXBElement<Modlets> e = objectFactory.createModlets( processed );
633                         final JAXBSource source = new JAXBSource( jaxbContext, e );
634                         final JAXBResult result = new JAXBResult( jaxbContext );
635                         transformers.get( i ).transform( source, result );
636 
637                         if ( result.getResult() instanceof JAXBElement<?>
638                                  && ( (JAXBElement<?>) result.getResult() ).getValue() instanceof Modlets )
639                         {
640                             processed = (Modlets) ( (JAXBElement<?>) result.getResult() ).getValue();
641                         }
642                         else
643                         {
644                             throw new ModelException( getMessage( "illegalTransformationResult" ) );
645                         }
646                     }
647                 }
648             }
649             else if ( context.isLoggable( Level.FINER ) )
650             {
651                 context.log( Level.FINER, getMessage( "disabled", this.getClass().getSimpleName() ), null );
652             }
653 
654             return processed;
655         }
656         catch ( final TransformerException e )
657         {
658             String message = getMessage( e );
659             if ( message == null && e.getException() != null )
660             {
661                 message = getMessage( e.getException() );
662             }
663 
664             throw new ModelException( message, e );
665         }
666         catch ( final JAXBException e )
667         {
668             String message = getMessage( e );
669             if ( message == null && e.getLinkedException() != null )
670             {
671                 message = getMessage( e.getLinkedException() );
672             }
673 
674             throw new ModelException( message, e );
675         }
676     }
677 
678     private static Properties getTransformerParameters() throws ModelException
679     {
680         final Properties properties = new Properties();
681 
682         ByteArrayInputStream in = null;
683         ByteArrayOutputStream out = null;
684         try
685         {
686             out = new ByteArrayOutputStream();
687             System.getProperties().store( out, DefaultModletProcessor.class.getName() );
688             out.close();
689             final byte[] bytes = out.toByteArray();
690             out = null;
691 
692             in = new ByteArrayInputStream( bytes );
693             properties.load( in );
694             in.close();
695             in = null;
696         }
697         catch ( final IOException e )
698         {
699             throw new ModelException( getMessage( e ), e );
700         }
701         finally
702         {
703             try
704             {
705                 if ( out != null )
706                 {
707                     out.close();
708                 }
709             }
710             catch ( final IOException e )
711             {
712                 
713             }
714             finally
715             {
716                 try
717                 {
718                     if ( in != null )
719                     {
720                         in.close();
721                     }
722                 }
723                 catch ( final IOException e )
724                 {
725                     
726                 }
727             }
728         }
729 
730         return properties;
731     }
732 
733     private static String getMessage( final String key, final Object... args )
734     {
735         return MessageFormat.format( ResourceBundle.getBundle( DefaultModletProcessor.class.getName(),
736                                                                Locale.getDefault() ).getString( key ), args );
737 
738     }
739 
740     private static String getMessage( final Throwable t )
741     {
742         return t != null
743                    ? t.getMessage() != null && t.getMessage().trim().length() > 0
744                          ? t.getMessage()
745                          : getMessage( t.getCause() )
746                    : null;
747 
748     }
749 
750 }