View Javadoc
1   /*
2    *   Copyright (C) Christian Schulte, 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 4866 2014-02-16 17:40:24Z 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 4866 2014-02-16 17:40:24Z schulte $
62   */
63  public final class WriteModelTask extends JomcModelTask
64  {
65  
66      /** The identifier of a specification to write. */
67      private String specification;
68  
69      /** The identifier of an implementation to write. */
70      private String implementation;
71  
72      /** The name of a module to write. */
73      private String module;
74  
75      /** The encoding to use when writing the model. */
76      private String modelEncoding;
77  
78      /** File to write the model to. */
79      private File modelFile;
80  
81      /**
82       * File to write the specification to.
83       * @since 1.6
84       */
85      private File specificationModelFile;
86  
87      /**
88       * File to write the instance to.
89       * @since 1.6
90       */
91      private File instanceModelFile;
92  
93      /**
94       * File to write the module to.
95       * @since 1.6
96       */
97      private File moduleModelFile;
98  
99      /** Creates a new {@code WriteModelTask} instance. */
100     public WriteModelTask()
101     {
102         super();
103     }
104 
105     /**
106      * Gets the encoding of the model resource.
107      *
108      * @return The encoding of the model resource.
109      *
110      * @see #setModelEncoding(java.lang.String)
111      */
112     public String getModelEncoding()
113     {
114         if ( this.modelEncoding == null )
115         {
116             this.modelEncoding = new OutputStreamWriter( new ByteArrayOutputStream() ).getEncoding();
117         }
118 
119         return this.modelEncoding;
120     }
121 
122     /**
123      * Sets the encoding of the model resource.
124      *
125      * @param value The new encoding of the model resource or {@code null}.
126      *
127      * @see #getModelEncoding()
128      */
129     public void setModelEncoding( final String value )
130     {
131         this.modelEncoding = value;
132     }
133 
134     /**
135      * Gets the file to write the model to.
136      *
137      * @return The file to write the model to or {@code null}.
138      *
139      * @see #setModelFile(java.io.File)
140      */
141     public File getModelFile()
142     {
143         return this.modelFile;
144     }
145 
146     /**
147      * Sets the file to write the model to.
148      *
149      * @param value The new file to write the model to or {@code null}.
150      *
151      * @see #getModelFile()
152      */
153     public void setModelFile( final File value )
154     {
155         this.modelFile = value;
156     }
157 
158     /**
159      * Gets the file to write the specification to.
160      *
161      * @return The file to write the specification to or {@code null}.
162      *
163      * @see #setSpecificationModelFile(java.io.File)
164      *
165      * @since 1.6
166      */
167     public File getSpecificationModelFile()
168     {
169         return this.specificationModelFile;
170     }
171 
172     /**
173      * Sets the file to write the specification to.
174      *
175      * @param value The new file to write the specification to or {@code null}.
176      *
177      * @see #getSpecificationModelFile()
178      *
179      * @since 1.6
180      */
181     public void setSpecificationModelFile( final File value )
182     {
183         this.specificationModelFile = value;
184     }
185 
186     /**
187      * Gets the file to write the instance to.
188      *
189      * @return The file to write the instance to or {@code null}.
190      *
191      * @see #setInstanceModelFile(java.io.File)
192      *
193      * @since 1.6
194      */
195     public File getInstanceModelFile()
196     {
197         return this.instanceModelFile;
198     }
199 
200     /**
201      * Sets the file to write the instance to.
202      *
203      * @param value The new file to write the instance to or {@code null}.
204      *
205      * @see #getInstanceModelFile()
206      *
207      * @since 1.6
208      */
209     public void setInstanceModelFile( final File value )
210     {
211         this.instanceModelFile = value;
212     }
213 
214     /**
215      * Gets the file to write the module to.
216      *
217      * @return The file to write the module to or {@code null}.
218      *
219      * @see #setModuleModelFile(java.io.File)
220      *
221      * @since 1.6
222      */
223     public File getModuleModelFile()
224     {
225         return this.moduleModelFile;
226     }
227 
228     /**
229      * Sets the file to write the module to.
230      *
231      * @param value The new file to write the module to or {@code null}.
232      *
233      * @see #getModuleModelFile()
234      *
235      * @since 1.6
236      */
237     public void setModuleModelFile( final File value )
238     {
239         this.moduleModelFile = value;
240     }
241 
242     /**
243      * Gets the identifier of a specification to write.
244      *
245      * @return The identifier of a specification to write or {@code null}.
246      *
247      * @see #setSpecification(java.lang.String)
248      */
249     public String getSpecification()
250     {
251         return this.specification;
252     }
253 
254     /**
255      * Sets the identifier of a specification to write.
256      *
257      * @param value The new identifier of a specification to write or {@code null}.
258      *
259      * @see #getSpecification()
260      */
261     public void setSpecification( final String value )
262     {
263         this.specification = value;
264     }
265 
266     /**
267      * Gets the specification to write from a given model.
268      *
269      * @param model The model to get the specification to write from.
270      *
271      * @return The specification to write or {@code null}.
272      *
273      * @throws NullPointerException if {@code model} is {@code null}.
274      *
275      * @see #getSpecification()
276      */
277     public Specification getSpecification( final Model model )
278     {
279         if ( model == null )
280         {
281             throw new NullPointerException( "model" );
282         }
283 
284         Specification s = null;
285 
286         if ( this.getSpecification() != null )
287         {
288             final Modules modules = ModelHelper.getModules( model );
289 
290             if ( modules != null )
291             {
292                 s = modules.getSpecification( this.getSpecification() );
293             }
294 
295             if ( s == null )
296             {
297                 this.log( Messages.getMessage( "specificationNotFound", this.getSpecification() ), Project.MSG_WARN );
298             }
299         }
300 
301         return s;
302     }
303 
304     /**
305      * Gets the identifier of an implementation to write.
306      *
307      * @return The identifier of an implementation to write or {@code null}.
308      *
309      * @see #setImplementation(java.lang.String)
310      */
311     public String getImplementation()
312     {
313         return this.implementation;
314     }
315 
316     /**
317      * Sets the identifier of an implementation to write.
318      *
319      * @param value The new identifier of an implementation to write or {@code null}.
320      *
321      * @see #getImplementation()
322      */
323     public void setImplementation( final String value )
324     {
325         this.implementation = value;
326     }
327 
328     /**
329      * Gets the instance to write from a given model.
330      *
331      * @param model The model to get the instance to write from.
332      *
333      * @return The instance to write or {@code null}.
334      *
335      * @throws NullPointerException if {@code model} is {@code null}.
336      *
337      * @see #getImplementation()
338      */
339     public Instance getInstance( final Model model )
340     {
341         if ( model == null )
342         {
343             throw new NullPointerException( "model" );
344         }
345 
346         Instance i = null;
347 
348         if ( this.getImplementation() != null )
349         {
350             final Modules modules = ModelHelper.getModules( model );
351 
352             if ( modules != null )
353             {
354                 i = modules.getInstance( this.getImplementation() );
355             }
356 
357             if ( i == null )
358             {
359                 this.log( Messages.getMessage( "implementationNotFound", this.getImplementation() ), Project.MSG_WARN );
360             }
361         }
362 
363         return i;
364     }
365 
366     /**
367      * Gets the identifier of a module to write.
368      *
369      * @return The identifier of a module to write or {@code null}.
370      *
371      * @see #setModule(java.lang.String)
372      */
373     public String getModule()
374     {
375         return this.module;
376     }
377 
378     /**
379      * Sets the identifier of a module to write.
380      *
381      * @param value The new identifier of a module to write or {@code null}.
382      *
383      * @see #getModule()
384      */
385     public void setModule( final String value )
386     {
387         this.module = value;
388     }
389 
390     /**
391      * Gets the module to write from a given model.
392      *
393      * @param model The model to get the module to write from.
394      *
395      * @return The module to write or {@code null}.
396      *
397      * @throws NullPointerException if {@code model} is {@code null}.
398      *
399      * @see #getModule()
400      */
401     public Module getModule( final Model model )
402     {
403         if ( model == null )
404         {
405             throw new NullPointerException( "model" );
406         }
407 
408         Module m = null;
409 
410         if ( this.getModule() != null )
411         {
412             final Modules modules = ModelHelper.getModules( model );
413 
414             if ( modules != null )
415             {
416                 m = modules.getModule( this.getModule() );
417             }
418 
419             if ( m == null )
420             {
421                 this.log( Messages.getMessage( "moduleNotFound", this.getModule() ), Project.MSG_WARN );
422             }
423         }
424 
425         return m;
426     }
427 
428     /** {@inheritDoc} */
429     @Override
430     public void executeTask() throws BuildException
431     {
432         BufferedReader reader = null;
433         ProjectClassLoader classLoader = null;
434         boolean suppressExceptionOnClose = true;
435 
436         try
437         {
438             classLoader = this.newProjectClassLoader();
439             final ModelContext modelContext = this.newModelContext( classLoader );
440             final Model model = this.getModel( modelContext );
441             final Marshaller marshaller = modelContext.createMarshaller( this.getModel() );
442             final ModelValidationReport validationReport = modelContext.validateModel(
443                 this.getModel(), new JAXBSource( marshaller, new ObjectFactory().createModel( model ) ) );
444 
445             this.logValidationReport( modelContext, validationReport );
446             marshaller.setProperty( Marshaller.JAXB_ENCODING, this.getModelEncoding() );
447             marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
448 
449             Model displayModel = new Model();
450             displayModel.setIdentifier( this.getModel() );
451 
452             final Specification s = this.getSpecification( model );
453             if ( s != null )
454             {
455                 displayModel.getAny().add( new org.jomc.model.ObjectFactory().createSpecification( s ) );
456 
457                 if ( this.getSpecificationModelFile() != null )
458                 {
459                     this.log( Messages.getMessage( "writingSpecification", s.getIdentifier(),
460                                                    this.getSpecificationModelFile().getAbsolutePath() ),
461                               Project.MSG_INFO );
462 
463                     marshaller.marshal( new org.jomc.model.ObjectFactory().createSpecification( s ),
464                                         this.getSpecificationModelFile() );
465 
466                 }
467             }
468 
469             final Instance i = this.getInstance( model );
470             if ( i != null )
471             {
472                 displayModel.getAny().add( new org.jomc.model.ObjectFactory().createInstance( i ) );
473 
474                 if ( this.getInstanceModelFile() != null )
475                 {
476                     this.log( Messages.getMessage( "writingInstance", i.getIdentifier(),
477                                                    this.getInstanceModelFile().getAbsolutePath() ),
478                               Project.MSG_INFO );
479 
480                     marshaller.marshal( new org.jomc.model.ObjectFactory().createInstance( i ),
481                                         this.getInstanceModelFile() );
482 
483                 }
484             }
485 
486             final Module m = this.getModule( model );
487             if ( m != null )
488             {
489                 displayModel.getAny().add( new org.jomc.model.ObjectFactory().createModule( m ) );
490 
491                 if ( this.getModuleModelFile() != null )
492                 {
493                     this.log( Messages.getMessage( "writingModule", m.getName(),
494                                                    this.getModuleModelFile().getAbsolutePath() ),
495                               Project.MSG_INFO );
496 
497                     marshaller.marshal( new org.jomc.model.ObjectFactory().createModule( m ),
498                                         this.getModuleModelFile() );
499 
500                 }
501             }
502 
503             if ( displayModel.getAny().isEmpty() )
504             {
505                 displayModel = model;
506             }
507 
508             if ( this.getModelFile() != null )
509             {
510                 this.log( Messages.getMessage( "writingModelObjects", this.getModel(),
511                                                this.getModelFile().getAbsolutePath() ), Project.MSG_INFO );
512 
513                 marshaller.marshal( new ObjectFactory().createModel( displayModel ), this.getModelFile() );
514             }
515             else
516             {
517                 this.log( Messages.getMessage( "showingModelObjects", this.getModel() ), Project.MSG_INFO );
518 
519                 final StringWriter writer = new StringWriter();
520                 marshaller.marshal( new ObjectFactory().createModel( displayModel ), writer );
521 
522                 reader = new BufferedReader( new StringReader( writer.toString() ) );
523                 String line;
524 
525                 while ( ( line = reader.readLine() ) != null )
526                 {
527                     this.log( line, Project.MSG_INFO );
528                 }
529             }
530 
531             suppressExceptionOnClose = false;
532         }
533         catch ( final IOException e )
534         {
535             throw new BuildException( Messages.getMessage( e ), e, this.getLocation() );
536         }
537         catch ( final JAXBException e )
538         {
539             String message = Messages.getMessage( e );
540             if ( message == null )
541             {
542                 message = Messages.getMessage( e.getLinkedException() );
543             }
544 
545             throw new BuildException( message, e, this.getLocation() );
546         }
547         catch ( final ModelException e )
548         {
549             throw new BuildException( Messages.getMessage( e ), e, this.getLocation() );
550         }
551         finally
552         {
553             try
554             {
555                 if ( reader != null )
556                 {
557                     reader.close();
558                 }
559             }
560             catch ( final IOException e )
561             {
562                 if ( suppressExceptionOnClose )
563                 {
564                     this.logMessage( Level.SEVERE, Messages.getMessage( e ), e );
565                 }
566                 else
567                 {
568                     throw new BuildException( Messages.getMessage( e ), e, this.getLocation() );
569                 }
570             }
571             finally
572             {
573                 try
574                 {
575                     if ( classLoader != null )
576                     {
577                         classLoader.close();
578                     }
579                 }
580                 catch ( final IOException e )
581                 {
582                     if ( suppressExceptionOnClose )
583                     {
584                         this.logMessage( Level.SEVERE, Messages.getMessage( e ), e );
585                     }
586                     else
587                     {
588                         throw new BuildException( Messages.getMessage( e ), e, this.getLocation() );
589                     }
590                 }
591             }
592         }
593     }
594 
595     /** {@inheritDoc} */
596     @Override
597     public WriteModelTask clone()
598     {
599         return (WriteModelTask) super.clone();
600     }
601 
602 }