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