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.ant;
32  
33  import java.io.ByteArrayOutputStream;
34  import java.io.File;
35  import java.io.IOException;
36  import java.io.InputStream;
37  import java.io.OutputStreamWriter;
38  import java.net.HttpURLConnection;
39  import java.net.SocketTimeoutException;
40  import java.net.URISyntaxException;
41  import java.net.URL;
42  import java.net.URLConnection;
43  import java.util.ArrayList;
44  import java.util.HashSet;
45  import java.util.Iterator;
46  import java.util.LinkedList;
47  import java.util.List;
48  import java.util.Set;
49  import java.util.logging.Level;
50  import javax.xml.bind.JAXBElement;
51  import javax.xml.bind.JAXBException;
52  import javax.xml.bind.Marshaller;
53  import javax.xml.bind.Unmarshaller;
54  import javax.xml.bind.util.JAXBResult;
55  import javax.xml.bind.util.JAXBSource;
56  import javax.xml.transform.Source;
57  import javax.xml.transform.Transformer;
58  import javax.xml.transform.TransformerConfigurationException;
59  import javax.xml.transform.TransformerException;
60  import javax.xml.transform.stream.StreamSource;
61  import org.apache.tools.ant.BuildException;
62  import org.apache.tools.ant.Project;
63  import org.jomc.ant.types.NameType;
64  import org.jomc.ant.types.ResourceType;
65  import org.jomc.ant.types.TransformerResourceType;
66  import org.jomc.model.Module;
67  import org.jomc.model.Modules;
68  import org.jomc.model.ObjectFactory;
69  import org.jomc.model.modlet.DefaultModelProvider;
70  import org.jomc.modlet.ModelContext;
71  import org.jomc.modlet.ModelException;
72  import org.jomc.modlet.ModelValidationReport;
73  
74  
75  
76  
77  
78  
79  
80  public final class MergeModulesTask extends JomcModelTask
81  {
82  
83      
84  
85  
86      private String moduleEncoding;
87  
88      
89  
90  
91      private File moduleFile;
92  
93      
94  
95  
96      private String moduleName;
97  
98      
99  
100 
101     private String moduleVersion;
102 
103     
104 
105 
106     private String moduleVendor;
107 
108     
109 
110 
111     private Set<NameType> moduleIncludes;
112 
113     
114 
115 
116     private Set<NameType> moduleExcludes;
117 
118     
119 
120 
121     private List<TransformerResourceType> modelObjectStylesheetResources;
122 
123     
124 
125 
126     public MergeModulesTask()
127     {
128         super();
129     }
130 
131     
132 
133 
134 
135 
136 
137 
138     public File getModuleFile()
139     {
140         return this.moduleFile;
141     }
142 
143     
144 
145 
146 
147 
148 
149 
150     public void setModuleFile( final File value )
151     {
152         this.moduleFile = value;
153     }
154 
155     
156 
157 
158 
159 
160 
161 
162     public String getModuleEncoding()
163     {
164         if ( this.moduleEncoding == null )
165         {
166             this.moduleEncoding = new OutputStreamWriter( new ByteArrayOutputStream() ).getEncoding();
167         }
168 
169         return this.moduleEncoding;
170     }
171 
172     
173 
174 
175 
176 
177 
178 
179     public void setModuleEncoding( final String value )
180     {
181         this.moduleEncoding = value;
182     }
183 
184     
185 
186 
187 
188 
189 
190 
191     public String getModuleName()
192     {
193         return this.moduleName;
194     }
195 
196     
197 
198 
199 
200 
201 
202 
203     public void setModuleName( final String value )
204     {
205         this.moduleName = value;
206     }
207 
208     
209 
210 
211 
212 
213 
214 
215     public String getModuleVersion()
216     {
217         return this.moduleVersion;
218     }
219 
220     
221 
222 
223 
224 
225 
226 
227     public void setModuleVersion( final String value )
228     {
229         this.moduleVersion = value;
230     }
231 
232     
233 
234 
235 
236 
237 
238 
239     public String getModuleVendor()
240     {
241         return this.moduleVendor;
242     }
243 
244     
245 
246 
247 
248 
249 
250 
251     public void setModuleVendor( final String value )
252     {
253         this.moduleVendor = value;
254     }
255 
256     
257 
258 
259 
260 
261 
262 
263 
264 
265 
266 
267 
268     public Set<NameType> getModuleIncludes()
269     {
270         if ( this.moduleIncludes == null )
271         {
272             this.moduleIncludes = new HashSet<NameType>();
273         }
274 
275         return this.moduleIncludes;
276     }
277 
278     
279 
280 
281 
282 
283 
284 
285     public NameType createModuleInclude()
286     {
287         final NameType moduleInclude = new NameType();
288         this.getModuleIncludes().add( moduleInclude );
289         return moduleInclude;
290     }
291 
292     
293 
294 
295 
296 
297 
298 
299 
300 
301 
302 
303 
304     public Set<NameType> getModuleExcludes()
305     {
306         if ( this.moduleExcludes == null )
307         {
308             this.moduleExcludes = new HashSet<NameType>();
309         }
310 
311         return this.moduleExcludes;
312     }
313 
314     
315 
316 
317 
318 
319 
320 
321     public NameType createModuleExclude()
322     {
323         final NameType moduleExclude = new NameType();
324         this.getModuleExcludes().add( moduleExclude );
325         return moduleExclude;
326     }
327 
328     
329 
330 
331 
332 
333 
334 
335 
336 
337 
338 
339 
340     public List<TransformerResourceType> getModelObjectStylesheetResources()
341     {
342         if ( this.modelObjectStylesheetResources == null )
343         {
344             this.modelObjectStylesheetResources = new LinkedList<TransformerResourceType>();
345         }
346 
347         return this.modelObjectStylesheetResources;
348     }
349 
350     
351 
352 
353 
354 
355 
356 
357     public TransformerResourceType createModelObjectStylesheetResource()
358     {
359         final TransformerResourceType modelObjectStylesheetResource = new TransformerResourceType();
360         this.getModelObjectStylesheetResources().add( modelObjectStylesheetResource );
361         return modelObjectStylesheetResource;
362     }
363 
364     
365 
366 
367     @Override
368     public void preExecuteTask() throws BuildException
369     {
370         super.preExecuteTask();
371 
372         this.assertNotNull( "moduleFile", this.getModuleFile() );
373         this.assertNotNull( "moduleName", this.getModuleName() );
374         this.assertNamesNotNull( this.getModuleExcludes() );
375         this.assertNamesNotNull( this.getModuleIncludes() );
376         this.assertLocationsNotNull( this.getModelObjectStylesheetResources() );
377     }
378 
379     
380 
381 
382 
383 
384     @Override
385     public void executeTask() throws BuildException
386     {
387         ProjectClassLoader classLoader = null;
388 
389         try
390         {
391             this.log( Messages.getMessage( "mergingModules", this.getModel() ) );
392 
393             classLoader = this.newProjectClassLoader();
394             final Modules modules = new Modules();
395             final Set<ResourceType> resources = new HashSet<ResourceType>( this.getModuleResources() );
396             final ModelContext context = this.newModelContext( classLoader );
397             final Marshaller marshaller = context.createMarshaller( this.getModel() );
398             final Unmarshaller unmarshaller = context.createUnmarshaller( this.getModel() );
399 
400             if ( this.isModelResourceValidationEnabled() )
401             {
402                 unmarshaller.setSchema( context.createSchema( this.getModel() ) );
403             }
404 
405             if ( resources.isEmpty() )
406             {
407                 final ResourceType defaultResource = new ResourceType();
408                 defaultResource.setLocation( DefaultModelProvider.getDefaultModuleLocation() );
409                 defaultResource.setOptional( true );
410                 resources.add( defaultResource );
411             }
412 
413             for ( final ResourceType resource : resources )
414             {
415                 final URL[] urls = this.getResources( context, resource.getLocation() );
416 
417                 if ( urls.length == 0 )
418                 {
419                     if ( resource.isOptional() )
420                     {
421                         this.logMessage( Level.WARNING, Messages.getMessage( "moduleResourceNotFound",
422                                                                              resource.getLocation() ) );
423 
424                     }
425                     else
426                     {
427                         throw new BuildException(
428                             Messages.getMessage( "moduleResourceNotFound", resource.getLocation() ),
429                             this.getLocation() );
430 
431                     }
432                 }
433 
434                 for ( int i = urls.length - 1; i >= 0; i-- )
435                 {
436                     URLConnection con = null;
437                     InputStream in = null;
438 
439                     try
440                     {
441                         this.logMessage( Level.FINEST, Messages.getMessage( "reading", urls[i].toExternalForm() ) );
442 
443                         con = urls[i].openConnection();
444                         con.setConnectTimeout( resource.getConnectTimeout() );
445                         con.setReadTimeout( resource.getReadTimeout() );
446                         con.connect();
447                         in = con.getInputStream();
448 
449                         final Source source = new StreamSource( in, urls[i].toURI().toASCIIString() );
450 
451                         Object o = unmarshaller.unmarshal( source );
452                         if ( o instanceof JAXBElement<?> )
453                         {
454                             o = ( (JAXBElement<?>) o ).getValue();
455                         }
456 
457                         if ( o instanceof Module )
458                         {
459                             modules.getModule().add( (Module) o );
460                         }
461                         else if ( o instanceof Modules )
462                         {
463                             modules.getModule().addAll( ( (Modules) o ).getModule() );
464                         }
465                         else
466                         {
467                             this.log( Messages.getMessage( "unsupportedModuleResource", urls[i].toExternalForm() ),
468                                       Project.MSG_WARN );
469 
470                         }
471 
472                         in.close();
473                         in = null;
474                     }
475                     catch ( final SocketTimeoutException e )
476                     {
477                         String message = Messages.getMessage( e );
478                         message = Messages.getMessage( "resourceTimeout", message != null ? " " + message : "" );
479 
480                         if ( resource.isOptional() )
481                         {
482                             this.getProject().log( message, e, Project.MSG_WARN );
483                         }
484                         else
485                         {
486                             throw new BuildException( message, e, this.getLocation() );
487                         }
488                     }
489                     catch ( final IOException e )
490                     {
491                         String message = Messages.getMessage( e );
492                         message = Messages.getMessage( "resourceFailure", message != null ? " " + message : "" );
493 
494                         if ( resource.isOptional() )
495                         {
496                             this.getProject().log( message, e, Project.MSG_WARN );
497                         }
498                         else
499                         {
500                             throw new BuildException( message, e, this.getLocation() );
501                         }
502                     }
503                     finally
504                     {
505                         try
506                         {
507                             if ( in != null )
508                             {
509                                 in.close();
510                             }
511                         }
512                         catch ( final IOException e )
513                         {
514                             this.logMessage( Level.SEVERE, Messages.getMessage( e ), e );
515                         }
516                         finally
517                         {
518                             if ( con instanceof HttpURLConnection )
519                             {
520                                 ( (HttpURLConnection) con ).disconnect();
521                             }
522                         }
523                     }
524                 }
525             }
526 
527             for ( final Iterator<Module> it = modules.getModule().iterator(); it.hasNext(); )
528             {
529                 final Module module = it.next();
530 
531                 if ( !this.isModuleIncluded( module ) || this.isModuleExcluded( module ) )
532                 {
533                     it.remove();
534                     this.log( Messages.getMessage( "excludingModule", module.getName() ) );
535                 }
536                 else
537                 {
538                     this.log( Messages.getMessage( "includingModule", module.getName() ) );
539                 }
540             }
541 
542             Module classpathModule = null;
543             if ( this.isModelObjectClasspathResolutionEnabled() )
544             {
545                 classpathModule = modules.getClasspathModule( Modules.getDefaultClasspathModuleName(), classLoader );
546 
547                 if ( classpathModule != null && modules.getModule( Modules.getDefaultClasspathModuleName() ) == null )
548                 {
549                     modules.getModule().add( classpathModule );
550                 }
551                 else
552                 {
553                     classpathModule = null;
554                 }
555             }
556 
557             final ModelValidationReport validationReport = context.validateModel(
558                 this.getModel(), new JAXBSource( marshaller, new ObjectFactory().createModules( modules ) ) );
559 
560             this.logValidationReport( context, validationReport );
561 
562             if ( !validationReport.isModelValid() )
563             {
564                 throw new ModelException( Messages.getMessage( "invalidModel", this.getModel() ) );
565             }
566 
567             if ( classpathModule != null )
568             {
569                 modules.getModule().remove( classpathModule );
570             }
571 
572             Module mergedModule = modules.getMergedModule( this.getModuleName() );
573             mergedModule.setVendor( this.getModuleVendor() );
574             mergedModule.setVersion( this.getModuleVersion() );
575 
576             for ( int i = 0, s0 = this.getModelObjectStylesheetResources().size(); i < s0; i++ )
577             {
578                 final Transformer transformer =
579                     this.getTransformer( this.getModelObjectStylesheetResources().get( i ) );
580 
581                 if ( transformer != null )
582                 {
583                     final JAXBSource source =
584                         new JAXBSource( marshaller, new ObjectFactory().createModule( mergedModule ) );
585 
586                     final JAXBResult result = new JAXBResult( unmarshaller );
587                     transformer.transform( source, result );
588 
589                     if ( result.getResult() instanceof JAXBElement<?>
590                              && ( (JAXBElement<?>) result.getResult() ).getValue() instanceof Module )
591                     {
592                         mergedModule = (Module) ( (JAXBElement<?>) result.getResult() ).getValue();
593                     }
594                     else
595                     {
596                         throw new BuildException( Messages.getMessage(
597                             "illegalTransformationResult",
598                             this.getModelObjectStylesheetResources().get( i ).getLocation() ), this.getLocation() );
599 
600                     }
601                 }
602             }
603 
604             this.log( Messages.getMessage( "writingEncoded", this.getModuleFile().getAbsolutePath(),
605                                            this.getModuleEncoding() ) );
606 
607             marshaller.setProperty( Marshaller.JAXB_ENCODING, this.getModuleEncoding() );
608             marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
609             marshaller.setSchema( context.createSchema( this.getModel() ) );
610             marshaller.marshal( new ObjectFactory().createModule( mergedModule ), this.getModuleFile() );
611 
612             classLoader.close();
613             classLoader = null;
614         }
615         catch ( final IOException e )
616         {
617             throw new BuildException( Messages.getMessage( e ), e, this.getLocation() );
618         }
619         catch ( final URISyntaxException e )
620         {
621             throw new BuildException( Messages.getMessage( e ), e, this.getLocation() );
622         }
623         catch ( final JAXBException e )
624         {
625             String message = Messages.getMessage( e );
626             if ( message == null )
627             {
628                 message = Messages.getMessage( e.getLinkedException() );
629             }
630 
631             throw new BuildException( message, e, this.getLocation() );
632         }
633         catch ( final TransformerConfigurationException e )
634         {
635             throw new BuildException( Messages.getMessage( e ), e, this.getLocation() );
636         }
637         catch ( final TransformerException e )
638         {
639             throw new BuildException( Messages.getMessage( e ), e, this.getLocation() );
640         }
641         catch ( final ModelException e )
642         {
643             throw new BuildException( Messages.getMessage( e ), e, this.getLocation() );
644         }
645         finally
646         {
647             try
648             {
649                 if ( classLoader != null )
650                 {
651                     classLoader.close();
652                 }
653             }
654             catch ( final IOException e )
655             {
656                 this.logMessage( Level.SEVERE, Messages.getMessage( e ), e );
657             }
658         }
659     }
660 
661     
662 
663 
664 
665 
666 
667 
668 
669 
670 
671 
672     public boolean isModuleIncluded( final Module module )
673     {
674         if ( module == null )
675         {
676             throw new NullPointerException( "module" );
677         }
678 
679         for ( final NameType include : this.getModuleIncludes() )
680         {
681             if ( include.getName().equals( module.getName() ) )
682             {
683                 return true;
684             }
685         }
686 
687         return this.getModuleIncludes().isEmpty() ? true : false;
688     }
689 
690     
691 
692 
693 
694 
695 
696 
697 
698 
699 
700 
701     public boolean isModuleExcluded( final Module module )
702     {
703         if ( module == null )
704         {
705             throw new NullPointerException( "module" );
706         }
707 
708         for ( final NameType exclude : this.getModuleExcludes() )
709         {
710             if ( exclude.getName().equals( module.getName() ) )
711             {
712                 return true;
713             }
714         }
715 
716         return false;
717     }
718 
719     
720 
721 
722     @Override
723     public MergeModulesTask clone()
724     {
725         final MergeModulesTask clone = (MergeModulesTask) super.clone();
726         clone.moduleFile = this.moduleFile != null ? new File( this.moduleFile.getAbsolutePath() ) : null;
727 
728         if ( this.moduleExcludes != null )
729         {
730             clone.moduleExcludes = new HashSet<NameType>( this.moduleExcludes.size() );
731             for ( final NameType e : this.moduleExcludes )
732             {
733                 clone.moduleExcludes.add( e.clone() );
734             }
735         }
736 
737         if ( this.moduleIncludes != null )
738         {
739             clone.moduleIncludes = new HashSet<NameType>( this.moduleIncludes.size() );
740             for ( final NameType e : this.moduleIncludes )
741             {
742                 clone.moduleIncludes.add( e.clone() );
743             }
744         }
745 
746         if ( this.modelObjectStylesheetResources != null )
747         {
748             clone.modelObjectStylesheetResources =
749                 new ArrayList<TransformerResourceType>( this.modelObjectStylesheetResources.size() );
750 
751             for ( final TransformerResourceType e : this.modelObjectStylesheetResources )
752             {
753                 clone.modelObjectStylesheetResources.add( e.clone() );
754             }
755         }
756 
757         return clone;
758     }
759 
760 }