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