View Javadoc
1   /*
2    *   Copyright (C) 2005 Christian Schulte <cs@schulte.it>
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 5179 2016-04-15 02:58:23Z 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 5179 2016-04-15 02:58:23Z 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 
452         try
453         {
454             classLoader = this.newProjectClassLoader();
455             final ModelContext modelContext = this.newModelContext( classLoader );
456             final Model model = this.getModel( modelContext );
457             final Marshaller marshaller = modelContext.createMarshaller( this.getModel() );
458             final ModelValidationReport validationReport = modelContext.validateModel(
459                 this.getModel(), new JAXBSource( marshaller, new ObjectFactory().createModel( model ) ) );
460 
461             this.logValidationReport( modelContext, validationReport );
462             marshaller.setProperty( Marshaller.JAXB_ENCODING, this.getModelEncoding() );
463             marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
464 
465             Model displayModel = new Model();
466             displayModel.setIdentifier( this.getModel() );
467 
468             final Specification s = this.getSpecification( model );
469             if ( s != null )
470             {
471                 displayModel.getAny().add( new org.jomc.model.ObjectFactory().createSpecification( s ) );
472 
473                 if ( this.getSpecificationModelFile() != null )
474                 {
475                     this.log( Messages.getMessage( "writingSpecification", s.getIdentifier(),
476                                                    this.getSpecificationModelFile().getAbsolutePath() ),
477                               Project.MSG_INFO );
478 
479                     marshaller.marshal( new org.jomc.model.ObjectFactory().createSpecification( s ),
480                                         this.getSpecificationModelFile() );
481 
482                 }
483             }
484 
485             final Instance i = this.getInstance( model );
486             if ( i != null )
487             {
488                 displayModel.getAny().add( new org.jomc.model.ObjectFactory().createInstance( i ) );
489 
490                 if ( this.getInstanceModelFile() != null )
491                 {
492                     this.log( Messages.getMessage( "writingInstance", i.getIdentifier(),
493                                                    this.getInstanceModelFile().getAbsolutePath() ),
494                               Project.MSG_INFO );
495 
496                     marshaller.marshal( new org.jomc.model.ObjectFactory().createInstance( i ),
497                                         this.getInstanceModelFile() );
498 
499                 }
500             }
501 
502             final Module m = this.getModule( model );
503             if ( m != null )
504             {
505                 displayModel.getAny().add( new org.jomc.model.ObjectFactory().createModule( m ) );
506 
507                 if ( this.getModuleModelFile() != null )
508                 {
509                     this.log( Messages.getMessage( "writingModule", m.getName(),
510                                                    this.getModuleModelFile().getAbsolutePath() ),
511                               Project.MSG_INFO );
512 
513                     marshaller.marshal( new org.jomc.model.ObjectFactory().createModule( m ),
514                                         this.getModuleModelFile() );
515 
516                 }
517             }
518 
519             if ( displayModel.getAny().isEmpty() )
520             {
521                 displayModel = model;
522             }
523 
524             if ( this.getModelFile() != null )
525             {
526                 this.log( Messages.getMessage( "writingModelObjects", this.getModel(),
527                                                this.getModelFile().getAbsolutePath() ), Project.MSG_INFO );
528 
529                 marshaller.marshal( new ObjectFactory().createModel( displayModel ), this.getModelFile() );
530             }
531             else
532             {
533                 this.log( Messages.getMessage( "showingModelObjects", this.getModel() ), Project.MSG_INFO );
534 
535                 final StringWriter writer = new StringWriter();
536                 marshaller.marshal( new ObjectFactory().createModel( displayModel ), writer );
537 
538                 reader = new BufferedReader( new StringReader( writer.toString() ) );
539 
540                 for ( String line = reader.readLine(); line != null; line = reader.readLine() )
541                 {
542                     this.log( line, Project.MSG_INFO );
543                 }
544 
545                 reader.close();
546                 reader = null;
547             }
548 
549             classLoader.close();
550             classLoader = null;
551         }
552         catch ( final IOException e )
553         {
554             throw new BuildException( Messages.getMessage( e ), e, this.getLocation() );
555         }
556         catch ( final JAXBException e )
557         {
558             String message = Messages.getMessage( e );
559             if ( message == null )
560             {
561                 message = Messages.getMessage( e.getLinkedException() );
562             }
563 
564             throw new BuildException( message, e, this.getLocation() );
565         }
566         catch ( final ModelException e )
567         {
568             throw new BuildException( Messages.getMessage( e ), e, this.getLocation() );
569         }
570         finally
571         {
572             try
573             {
574                 if ( reader != null )
575                 {
576                     reader.close();
577                 }
578             }
579             catch ( final IOException e )
580             {
581                 this.logMessage( Level.SEVERE, Messages.getMessage( e ), e );
582             }
583             finally
584             {
585                 try
586                 {
587                     if ( classLoader != null )
588                     {
589                         classLoader.close();
590                     }
591                 }
592                 catch ( final IOException e )
593                 {
594                     this.logMessage( Level.SEVERE, Messages.getMessage( e ), e );
595                 }
596             }
597         }
598     }
599 
600     /**
601      * {@inheritDoc}
602      */
603     @Override
604     public WriteModelTask clone()
605     {
606         return (WriteModelTask) super.clone();
607     }
608 
609 }