View Javadoc
1   /*
2    *   Copyright (C) Christian Schulte <cs@schulte.it>, 2005-206
3    *   All rights reserved.
4    *
5    *   Redistribution and use in source and binary forms, with or without
6    *   modification, are permitted provided that the following conditions
7    *   are met:
8    *
9    *     o Redistributions of source code must retain the above copyright
10   *       notice, this list of conditions and the following disclaimer.
11   *
12   *     o Redistributions in binary form must reproduce the above copyright
13   *       notice, this list of conditions and the following disclaimer in
14   *       the documentation and/or other materials provided with the
15   *       distribution.
16   *
17   *   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
18   *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19   *   AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20   *   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
21   *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22   *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23   *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24   *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25   *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26   *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27   *
28   *   $JOMC: WriteModelTask.java 5043 2015-05-27 07:03:39Z schulte $
29   *
30   */
31  package org.jomc.ant;
32  
33  import java.io.BufferedReader;
34  import java.io.ByteArrayOutputStream;
35  import java.io.File;
36  import java.io.IOException;
37  import java.io.OutputStreamWriter;
38  import java.io.StringReader;
39  import java.io.StringWriter;
40  import java.util.logging.Level;
41  import javax.xml.bind.JAXBException;
42  import javax.xml.bind.Marshaller;
43  import javax.xml.bind.util.JAXBSource;
44  import org.apache.tools.ant.BuildException;
45  import org.apache.tools.ant.Project;
46  import org.jomc.model.Instance;
47  import org.jomc.model.Module;
48  import org.jomc.model.Modules;
49  import org.jomc.model.Specification;
50  import org.jomc.model.modlet.ModelHelper;
51  import org.jomc.modlet.Model;
52  import org.jomc.modlet.ModelContext;
53  import org.jomc.modlet.ModelException;
54  import org.jomc.modlet.ModelValidationReport;
55  import org.jomc.modlet.ObjectFactory;
56  
57  /**
58   * Task for writing model objects.
59   *
60   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
61   * @version $JOMC: WriteModelTask.java 5043 2015-05-27 07:03:39Z schulte $
62   */
63  public final class WriteModelTask extends JomcModelTask
64  {
65  
66      /**
67       * The identifier of a specification to write.
68       */
69      private String specification;
70  
71      /**
72       * The identifier of an implementation to write.
73       */
74      private String implementation;
75  
76      /**
77       * The name of a module to write.
78       */
79      private String module;
80  
81      /**
82       * The encoding to use when writing the model.
83       */
84      private String modelEncoding;
85  
86      /**
87       * File to write the model to.
88       */
89      private File modelFile;
90  
91      /**
92       * File to write the specification to.
93       *
94       * @since 1.6
95       */
96      private File specificationModelFile;
97  
98      /**
99       * File to write the instance to.
100      *
101      * @since 1.6
102      */
103     private File instanceModelFile;
104 
105     /**
106      * File to write the module to.
107      *
108      * @since 1.6
109      */
110     private File moduleModelFile;
111 
112     /**
113      * Creates a new {@code WriteModelTask} instance.
114      */
115     public WriteModelTask()
116     {
117         super();
118     }
119 
120     /**
121      * Gets the encoding of the model resource.
122      *
123      * @return The encoding of the model resource.
124      *
125      * @see #setModelEncoding(java.lang.String)
126      */
127     public String getModelEncoding()
128     {
129         if ( this.modelEncoding == null )
130         {
131             this.modelEncoding = new OutputStreamWriter( new ByteArrayOutputStream() ).getEncoding();
132         }
133 
134         return this.modelEncoding;
135     }
136 
137     /**
138      * Sets the encoding of the model resource.
139      *
140      * @param value The new encoding of the model resource or {@code null}.
141      *
142      * @see #getModelEncoding()
143      */
144     public void setModelEncoding( final String value )
145     {
146         this.modelEncoding = value;
147     }
148 
149     /**
150      * Gets the file to write the model to.
151      *
152      * @return The file to write the model to or {@code null}.
153      *
154      * @see #setModelFile(java.io.File)
155      */
156     public File getModelFile()
157     {
158         return this.modelFile;
159     }
160 
161     /**
162      * Sets the file to write the model to.
163      *
164      * @param value The new file to write the model to or {@code null}.
165      *
166      * @see #getModelFile()
167      */
168     public void setModelFile( final File value )
169     {
170         this.modelFile = value;
171     }
172 
173     /**
174      * Gets the file to write the specification to.
175      *
176      * @return The file to write the specification to or {@code null}.
177      *
178      * @see #setSpecificationModelFile(java.io.File)
179      *
180      * @since 1.6
181      */
182     public File getSpecificationModelFile()
183     {
184         return this.specificationModelFile;
185     }
186 
187     /**
188      * Sets the file to write the specification to.
189      *
190      * @param value The new file to write the specification to or {@code null}.
191      *
192      * @see #getSpecificationModelFile()
193      *
194      * @since 1.6
195      */
196     public void setSpecificationModelFile( final File value )
197     {
198         this.specificationModelFile = value;
199     }
200 
201     /**
202      * Gets the file to write the instance to.
203      *
204      * @return The file to write the instance to or {@code null}.
205      *
206      * @see #setInstanceModelFile(java.io.File)
207      *
208      * @since 1.6
209      */
210     public File getInstanceModelFile()
211     {
212         return this.instanceModelFile;
213     }
214 
215     /**
216      * Sets the file to write the instance to.
217      *
218      * @param value The new file to write the instance to or {@code null}.
219      *
220      * @see #getInstanceModelFile()
221      *
222      * @since 1.6
223      */
224     public void setInstanceModelFile( final File value )
225     {
226         this.instanceModelFile = value;
227     }
228 
229     /**
230      * Gets the file to write the module to.
231      *
232      * @return The file to write the module to or {@code null}.
233      *
234      * @see #setModuleModelFile(java.io.File)
235      *
236      * @since 1.6
237      */
238     public File getModuleModelFile()
239     {
240         return this.moduleModelFile;
241     }
242 
243     /**
244      * Sets the file to write the module to.
245      *
246      * @param value The new file to write the module to or {@code null}.
247      *
248      * @see #getModuleModelFile()
249      *
250      * @since 1.6
251      */
252     public void setModuleModelFile( final File value )
253     {
254         this.moduleModelFile = value;
255     }
256 
257     /**
258      * Gets the identifier of a specification to write.
259      *
260      * @return The identifier of a specification to write or {@code null}.
261      *
262      * @see #setSpecification(java.lang.String)
263      */
264     public String getSpecification()
265     {
266         return this.specification;
267     }
268 
269     /**
270      * Sets the identifier of a specification to write.
271      *
272      * @param value The new identifier of a specification to write or {@code null}.
273      *
274      * @see #getSpecification()
275      */
276     public void setSpecification( final String value )
277     {
278         this.specification = value;
279     }
280 
281     /**
282      * Gets the specification to write from a given model.
283      *
284      * @param model The model to get the specification to write from.
285      *
286      * @return The specification to write or {@code null}.
287      *
288      * @throws NullPointerException if {@code model} is {@code null}.
289      *
290      * @see #getSpecification()
291      */
292     public Specification getSpecification( final Model model )
293     {
294         if ( model == null )
295         {
296             throw new NullPointerException( "model" );
297         }
298 
299         Specification s = null;
300 
301         if ( this.getSpecification() != null )
302         {
303             final Modules modules = ModelHelper.getModules( model );
304 
305             if ( modules != null )
306             {
307                 s = modules.getSpecification( this.getSpecification() );
308             }
309 
310             if ( s == null )
311             {
312                 this.log( Messages.getMessage( "specificationNotFound", this.getSpecification() ), Project.MSG_WARN );
313             }
314         }
315 
316         return s;
317     }
318 
319     /**
320      * Gets the identifier of an implementation to write.
321      *
322      * @return The identifier of an implementation to write or {@code null}.
323      *
324      * @see #setImplementation(java.lang.String)
325      */
326     public String getImplementation()
327     {
328         return this.implementation;
329     }
330 
331     /**
332      * Sets the identifier of an implementation to write.
333      *
334      * @param value The new identifier of an implementation to write or {@code null}.
335      *
336      * @see #getImplementation()
337      */
338     public void setImplementation( final String value )
339     {
340         this.implementation = value;
341     }
342 
343     /**
344      * Gets the instance to write from a given model.
345      *
346      * @param model The model to get the instance to write from.
347      *
348      * @return The instance to write or {@code null}.
349      *
350      * @throws NullPointerException if {@code model} is {@code null}.
351      *
352      * @see #getImplementation()
353      */
354     public Instance getInstance( final Model model )
355     {
356         if ( model == null )
357         {
358             throw new NullPointerException( "model" );
359         }
360 
361         Instance i = null;
362 
363         if ( this.getImplementation() != null )
364         {
365             final Modules modules = ModelHelper.getModules( model );
366 
367             if ( modules != null )
368             {
369                 i = modules.getInstance( this.getImplementation() );
370             }
371 
372             if ( i == null )
373             {
374                 this.log( Messages.getMessage( "implementationNotFound", this.getImplementation() ), Project.MSG_WARN );
375             }
376         }
377 
378         return i;
379     }
380 
381     /**
382      * Gets the identifier of a module to write.
383      *
384      * @return The identifier of a module to write or {@code null}.
385      *
386      * @see #setModule(java.lang.String)
387      */
388     public String getModule()
389     {
390         return this.module;
391     }
392 
393     /**
394      * Sets the identifier of a module to write.
395      *
396      * @param value The new identifier of a module to write or {@code null}.
397      *
398      * @see #getModule()
399      */
400     public void setModule( final String value )
401     {
402         this.module = value;
403     }
404 
405     /**
406      * Gets the module to write from a given model.
407      *
408      * @param model The model to get the module to write from.
409      *
410      * @return The module to write or {@code null}.
411      *
412      * @throws NullPointerException if {@code model} is {@code null}.
413      *
414      * @see #getModule()
415      */
416     public Module getModule( final Model model )
417     {
418         if ( model == null )
419         {
420             throw new NullPointerException( "model" );
421         }
422 
423         Module m = null;
424 
425         if ( this.getModule() != null )
426         {
427             final Modules modules = ModelHelper.getModules( model );
428 
429             if ( modules != null )
430             {
431                 m = modules.getModule( this.getModule() );
432             }
433 
434             if ( m == null )
435             {
436                 this.log( Messages.getMessage( "moduleNotFound", this.getModule() ), Project.MSG_WARN );
437             }
438         }
439 
440         return m;
441     }
442 
443     /**
444      * {@inheritDoc}
445      */
446     @Override
447     public void executeTask() throws BuildException
448     {
449         BufferedReader reader = null;
450         ProjectClassLoader classLoader = null;
451         boolean suppressExceptionOnClose = true;
452 
453         try
454         {
455             classLoader = this.newProjectClassLoader();
456             final ModelContext modelContext = this.newModelContext( classLoader );
457             final Model model = this.getModel( modelContext );
458             final Marshaller marshaller = modelContext.createMarshaller( this.getModel() );
459             final ModelValidationReport validationReport = modelContext.validateModel(
460                 this.getModel(), new JAXBSource( marshaller, new ObjectFactory().createModel( model ) ) );
461 
462             this.logValidationReport( modelContext, validationReport );
463             marshaller.setProperty( Marshaller.JAXB_ENCODING, this.getModelEncoding() );
464             marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
465 
466             Model displayModel = new Model();
467             displayModel.setIdentifier( this.getModel() );
468 
469             final Specification s = this.getSpecification( model );
470             if ( s != null )
471             {
472                 displayModel.getAny().add( new org.jomc.model.ObjectFactory().createSpecification( s ) );
473 
474                 if ( this.getSpecificationModelFile() != null )
475                 {
476                     this.log( Messages.getMessage( "writingSpecification", s.getIdentifier(),
477                                                    this.getSpecificationModelFile().getAbsolutePath() ),
478                               Project.MSG_INFO );
479 
480                     marshaller.marshal( new org.jomc.model.ObjectFactory().createSpecification( s ),
481                                         this.getSpecificationModelFile() );
482 
483                 }
484             }
485 
486             final Instance i = this.getInstance( model );
487             if ( i != null )
488             {
489                 displayModel.getAny().add( new org.jomc.model.ObjectFactory().createInstance( i ) );
490 
491                 if ( this.getInstanceModelFile() != null )
492                 {
493                     this.log( Messages.getMessage( "writingInstance", i.getIdentifier(),
494                                                    this.getInstanceModelFile().getAbsolutePath() ),
495                               Project.MSG_INFO );
496 
497                     marshaller.marshal( new org.jomc.model.ObjectFactory().createInstance( i ),
498                                         this.getInstanceModelFile() );
499 
500                 }
501             }
502 
503             final Module m = this.getModule( model );
504             if ( m != null )
505             {
506                 displayModel.getAny().add( new org.jomc.model.ObjectFactory().createModule( m ) );
507 
508                 if ( this.getModuleModelFile() != null )
509                 {
510                     this.log( Messages.getMessage( "writingModule", m.getName(),
511                                                    this.getModuleModelFile().getAbsolutePath() ),
512                               Project.MSG_INFO );
513 
514                     marshaller.marshal( new org.jomc.model.ObjectFactory().createModule( m ),
515                                         this.getModuleModelFile() );
516 
517                 }
518             }
519 
520             if ( displayModel.getAny().isEmpty() )
521             {
522                 displayModel = model;
523             }
524 
525             if ( this.getModelFile() != null )
526             {
527                 this.log( Messages.getMessage( "writingModelObjects", this.getModel(),
528                                                this.getModelFile().getAbsolutePath() ), Project.MSG_INFO );
529 
530                 marshaller.marshal( new ObjectFactory().createModel( displayModel ), this.getModelFile() );
531             }
532             else
533             {
534                 this.log( Messages.getMessage( "showingModelObjects", this.getModel() ), Project.MSG_INFO );
535 
536                 final StringWriter writer = new StringWriter();
537                 marshaller.marshal( new ObjectFactory().createModel( displayModel ), writer );
538 
539                 reader = new BufferedReader( new StringReader( writer.toString() ) );
540                 String line;
541 
542                 while ( ( line = reader.readLine() ) != null )
543                 {
544                     this.log( line, Project.MSG_INFO );
545                 }
546             }
547 
548             suppressExceptionOnClose = false;
549         }
550         catch ( final IOException e )
551         {
552             throw new BuildException( Messages.getMessage( e ), e, this.getLocation() );
553         }
554         catch ( final JAXBException e )
555         {
556             String message = Messages.getMessage( e );
557             if ( message == null )
558             {
559                 message = Messages.getMessage( e.getLinkedException() );
560             }
561 
562             throw new BuildException( message, e, this.getLocation() );
563         }
564         catch ( final ModelException e )
565         {
566             throw new BuildException( Messages.getMessage( e ), e, this.getLocation() );
567         }
568         finally
569         {
570             try
571             {
572                 if ( reader != null )
573                 {
574                     reader.close();
575                 }
576             }
577             catch ( final IOException e )
578             {
579                 if ( suppressExceptionOnClose )
580                 {
581                     this.logMessage( Level.SEVERE, Messages.getMessage( e ), e );
582                 }
583                 else
584                 {
585                     throw new BuildException( Messages.getMessage( e ), e, this.getLocation() );
586                 }
587             }
588             finally
589             {
590                 try
591                 {
592                     if ( classLoader != null )
593                     {
594                         classLoader.close();
595                     }
596                 }
597                 catch ( final IOException e )
598                 {
599                     if ( suppressExceptionOnClose )
600                     {
601                         this.logMessage( Level.SEVERE, Messages.getMessage( e ), e );
602                     }
603                     else
604                     {
605                         throw new BuildException( Messages.getMessage( e ), e, this.getLocation() );
606                     }
607                 }
608             }
609         }
610     }
611 
612     /**
613      * {@inheritDoc}
614      */
615     @Override
616     public WriteModelTask clone()
617     {
618         return (WriteModelTask) super.clone();
619     }
620 
621 }