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