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 }