WriteModelTask.java

  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. import java.io.BufferedReader;
  33. import java.io.ByteArrayOutputStream;
  34. import java.io.File;
  35. import java.io.IOException;
  36. import java.io.OutputStreamWriter;
  37. import java.io.StringReader;
  38. import java.io.StringWriter;
  39. import java.util.logging.Level;
  40. import javax.xml.bind.JAXBException;
  41. import javax.xml.bind.Marshaller;
  42. import javax.xml.bind.util.JAXBSource;
  43. import org.apache.tools.ant.BuildException;
  44. import org.apache.tools.ant.Project;
  45. import org.jomc.model.Instance;
  46. import org.jomc.model.Module;
  47. import org.jomc.model.Modules;
  48. import org.jomc.model.Specification;
  49. import org.jomc.model.modlet.ModelHelper;
  50. import org.jomc.modlet.Model;
  51. import org.jomc.modlet.ModelContext;
  52. import org.jomc.modlet.ModelException;
  53. import org.jomc.modlet.ModelValidationReport;
  54. import org.jomc.modlet.ObjectFactory;

  55. /**
  56.  * Task for writing model objects.
  57.  *
  58.  * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
  59.  * @version $JOMC: WriteModelTask.java 5043 2015-05-27 07:03:39Z schulte $
  60.  */
  61. public final class WriteModelTask extends JomcModelTask
  62. {

  63.     /**
  64.      * The identifier of a specification to write.
  65.      */
  66.     private String specification;

  67.     /**
  68.      * The identifier of an implementation to write.
  69.      */
  70.     private String implementation;

  71.     /**
  72.      * The name of a module to write.
  73.      */
  74.     private String module;

  75.     /**
  76.      * The encoding to use when writing the model.
  77.      */
  78.     private String modelEncoding;

  79.     /**
  80.      * File to write the model to.
  81.      */
  82.     private File modelFile;

  83.     /**
  84.      * File to write the specification to.
  85.      *
  86.      * @since 1.6
  87.      */
  88.     private File specificationModelFile;

  89.     /**
  90.      * File to write the instance to.
  91.      *
  92.      * @since 1.6
  93.      */
  94.     private File instanceModelFile;

  95.     /**
  96.      * File to write the module to.
  97.      *
  98.      * @since 1.6
  99.      */
  100.     private File moduleModelFile;

  101.     /**
  102.      * Creates a new {@code WriteModelTask} instance.
  103.      */
  104.     public WriteModelTask()
  105.     {
  106.         super();
  107.     }

  108.     /**
  109.      * Gets the encoding of the model resource.
  110.      *
  111.      * @return The encoding of the model resource.
  112.      *
  113.      * @see #setModelEncoding(java.lang.String)
  114.      */
  115.     public String getModelEncoding()
  116.     {
  117.         if ( this.modelEncoding == null )
  118.         {
  119.             this.modelEncoding = new OutputStreamWriter( new ByteArrayOutputStream() ).getEncoding();
  120.         }

  121.         return this.modelEncoding;
  122.     }

  123.     /**
  124.      * Sets the encoding of the model resource.
  125.      *
  126.      * @param value The new encoding of the model resource or {@code null}.
  127.      *
  128.      * @see #getModelEncoding()
  129.      */
  130.     public void setModelEncoding( final String value )
  131.     {
  132.         this.modelEncoding = value;
  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.      * Sets the file to write the model to.
  147.      *
  148.      * @param value The new file to write the model to or {@code null}.
  149.      *
  150.      * @see #getModelFile()
  151.      */
  152.     public void setModelFile( final File value )
  153.     {
  154.         this.modelFile = value;
  155.     }

  156.     /**
  157.      * Gets the file to write the specification to.
  158.      *
  159.      * @return The file to write the specification to or {@code null}.
  160.      *
  161.      * @see #setSpecificationModelFile(java.io.File)
  162.      *
  163.      * @since 1.6
  164.      */
  165.     public File getSpecificationModelFile()
  166.     {
  167.         return this.specificationModelFile;
  168.     }

  169.     /**
  170.      * Sets the file to write the specification to.
  171.      *
  172.      * @param value The new file to write the specification to or {@code null}.
  173.      *
  174.      * @see #getSpecificationModelFile()
  175.      *
  176.      * @since 1.6
  177.      */
  178.     public void setSpecificationModelFile( final File value )
  179.     {
  180.         this.specificationModelFile = value;
  181.     }

  182.     /**
  183.      * Gets the file to write the instance to.
  184.      *
  185.      * @return The file to write the instance to or {@code null}.
  186.      *
  187.      * @see #setInstanceModelFile(java.io.File)
  188.      *
  189.      * @since 1.6
  190.      */
  191.     public File getInstanceModelFile()
  192.     {
  193.         return this.instanceModelFile;
  194.     }

  195.     /**
  196.      * Sets the file to write the instance to.
  197.      *
  198.      * @param value The new file to write the instance to or {@code null}.
  199.      *
  200.      * @see #getInstanceModelFile()
  201.      *
  202.      * @since 1.6
  203.      */
  204.     public void setInstanceModelFile( final File value )
  205.     {
  206.         this.instanceModelFile = value;
  207.     }

  208.     /**
  209.      * Gets the file to write the module to.
  210.      *
  211.      * @return The file to write the module to or {@code null}.
  212.      *
  213.      * @see #setModuleModelFile(java.io.File)
  214.      *
  215.      * @since 1.6
  216.      */
  217.     public File getModuleModelFile()
  218.     {
  219.         return this.moduleModelFile;
  220.     }

  221.     /**
  222.      * Sets the file to write the module to.
  223.      *
  224.      * @param value The new file to write the module to or {@code null}.
  225.      *
  226.      * @see #getModuleModelFile()
  227.      *
  228.      * @since 1.6
  229.      */
  230.     public void setModuleModelFile( final File value )
  231.     {
  232.         this.moduleModelFile = value;
  233.     }

  234.     /**
  235.      * Gets the identifier of a specification to write.
  236.      *
  237.      * @return The identifier of a specification to write or {@code null}.
  238.      *
  239.      * @see #setSpecification(java.lang.String)
  240.      */
  241.     public String getSpecification()
  242.     {
  243.         return this.specification;
  244.     }

  245.     /**
  246.      * Sets the identifier of a specification to write.
  247.      *
  248.      * @param value The new identifier of a specification to write or {@code null}.
  249.      *
  250.      * @see #getSpecification()
  251.      */
  252.     public void setSpecification( final String value )
  253.     {
  254.         this.specification = value;
  255.     }

  256.     /**
  257.      * Gets the specification to write from a given model.
  258.      *
  259.      * @param model The model to get the specification to write from.
  260.      *
  261.      * @return The specification to write or {@code null}.
  262.      *
  263.      * @throws NullPointerException if {@code model} is {@code null}.
  264.      *
  265.      * @see #getSpecification()
  266.      */
  267.     public Specification getSpecification( final Model model )
  268.     {
  269.         if ( model == null )
  270.         {
  271.             throw new NullPointerException( "model" );
  272.         }

  273.         Specification s = null;

  274.         if ( this.getSpecification() != null )
  275.         {
  276.             final Modules modules = ModelHelper.getModules( model );

  277.             if ( modules != null )
  278.             {
  279.                 s = modules.getSpecification( this.getSpecification() );
  280.             }

  281.             if ( s == null )
  282.             {
  283.                 this.log( Messages.getMessage( "specificationNotFound", this.getSpecification() ), Project.MSG_WARN );
  284.             }
  285.         }

  286.         return s;
  287.     }

  288.     /**
  289.      * Gets the identifier of an implementation to write.
  290.      *
  291.      * @return The identifier of an implementation to write or {@code null}.
  292.      *
  293.      * @see #setImplementation(java.lang.String)
  294.      */
  295.     public String getImplementation()
  296.     {
  297.         return this.implementation;
  298.     }

  299.     /**
  300.      * Sets the identifier of an implementation to write.
  301.      *
  302.      * @param value The new identifier of an implementation to write or {@code null}.
  303.      *
  304.      * @see #getImplementation()
  305.      */
  306.     public void setImplementation( final String value )
  307.     {
  308.         this.implementation = value;
  309.     }

  310.     /**
  311.      * Gets the instance to write from a given model.
  312.      *
  313.      * @param model The model to get the instance to write from.
  314.      *
  315.      * @return The instance to write or {@code null}.
  316.      *
  317.      * @throws NullPointerException if {@code model} is {@code null}.
  318.      *
  319.      * @see #getImplementation()
  320.      */
  321.     public Instance getInstance( final Model model )
  322.     {
  323.         if ( model == null )
  324.         {
  325.             throw new NullPointerException( "model" );
  326.         }

  327.         Instance i = null;

  328.         if ( this.getImplementation() != null )
  329.         {
  330.             final Modules modules = ModelHelper.getModules( model );

  331.             if ( modules != null )
  332.             {
  333.                 i = modules.getInstance( this.getImplementation() );
  334.             }

  335.             if ( i == null )
  336.             {
  337.                 this.log( Messages.getMessage( "implementationNotFound", this.getImplementation() ), Project.MSG_WARN );
  338.             }
  339.         }

  340.         return i;
  341.     }

  342.     /**
  343.      * Gets the identifier of a module to write.
  344.      *
  345.      * @return The identifier of a module to write or {@code null}.
  346.      *
  347.      * @see #setModule(java.lang.String)
  348.      */
  349.     public String getModule()
  350.     {
  351.         return this.module;
  352.     }

  353.     /**
  354.      * Sets the identifier of a module to write.
  355.      *
  356.      * @param value The new identifier of a module to write or {@code null}.
  357.      *
  358.      * @see #getModule()
  359.      */
  360.     public void setModule( final String value )
  361.     {
  362.         this.module = value;
  363.     }

  364.     /**
  365.      * Gets the module to write from a given model.
  366.      *
  367.      * @param model The model to get the module to write from.
  368.      *
  369.      * @return The module to write or {@code null}.
  370.      *
  371.      * @throws NullPointerException if {@code model} is {@code null}.
  372.      *
  373.      * @see #getModule()
  374.      */
  375.     public Module getModule( final Model model )
  376.     {
  377.         if ( model == null )
  378.         {
  379.             throw new NullPointerException( "model" );
  380.         }

  381.         Module m = null;

  382.         if ( this.getModule() != null )
  383.         {
  384.             final Modules modules = ModelHelper.getModules( model );

  385.             if ( modules != null )
  386.             {
  387.                 m = modules.getModule( this.getModule() );
  388.             }

  389.             if ( m == null )
  390.             {
  391.                 this.log( Messages.getMessage( "moduleNotFound", this.getModule() ), Project.MSG_WARN );
  392.             }
  393.         }

  394.         return m;
  395.     }

  396.     /**
  397.      * {@inheritDoc}
  398.      */
  399.     @Override
  400.     public void executeTask() throws BuildException
  401.     {
  402.         BufferedReader reader = null;
  403.         ProjectClassLoader classLoader = null;
  404.         boolean suppressExceptionOnClose = true;

  405.         try
  406.         {
  407.             classLoader = this.newProjectClassLoader();
  408.             final ModelContext modelContext = this.newModelContext( classLoader );
  409.             final Model model = this.getModel( modelContext );
  410.             final Marshaller marshaller = modelContext.createMarshaller( this.getModel() );
  411.             final ModelValidationReport validationReport = modelContext.validateModel(
  412.                 this.getModel(), new JAXBSource( marshaller, new ObjectFactory().createModel( model ) ) );

  413.             this.logValidationReport( modelContext, validationReport );
  414.             marshaller.setProperty( Marshaller.JAXB_ENCODING, this.getModelEncoding() );
  415.             marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );

  416.             Model displayModel = new Model();
  417.             displayModel.setIdentifier( this.getModel() );

  418.             final Specification s = this.getSpecification( model );
  419.             if ( s != null )
  420.             {
  421.                 displayModel.getAny().add( new org.jomc.model.ObjectFactory().createSpecification( s ) );

  422.                 if ( this.getSpecificationModelFile() != null )
  423.                 {
  424.                     this.log( Messages.getMessage( "writingSpecification", s.getIdentifier(),
  425.                                                    this.getSpecificationModelFile().getAbsolutePath() ),
  426.                               Project.MSG_INFO );

  427.                     marshaller.marshal( new org.jomc.model.ObjectFactory().createSpecification( s ),
  428.                                         this.getSpecificationModelFile() );

  429.                 }
  430.             }

  431.             final Instance i = this.getInstance( model );
  432.             if ( i != null )
  433.             {
  434.                 displayModel.getAny().add( new org.jomc.model.ObjectFactory().createInstance( i ) );

  435.                 if ( this.getInstanceModelFile() != null )
  436.                 {
  437.                     this.log( Messages.getMessage( "writingInstance", i.getIdentifier(),
  438.                                                    this.getInstanceModelFile().getAbsolutePath() ),
  439.                               Project.MSG_INFO );

  440.                     marshaller.marshal( new org.jomc.model.ObjectFactory().createInstance( i ),
  441.                                         this.getInstanceModelFile() );

  442.                 }
  443.             }

  444.             final Module m = this.getModule( model );
  445.             if ( m != null )
  446.             {
  447.                 displayModel.getAny().add( new org.jomc.model.ObjectFactory().createModule( m ) );

  448.                 if ( this.getModuleModelFile() != null )
  449.                 {
  450.                     this.log( Messages.getMessage( "writingModule", m.getName(),
  451.                                                    this.getModuleModelFile().getAbsolutePath() ),
  452.                               Project.MSG_INFO );

  453.                     marshaller.marshal( new org.jomc.model.ObjectFactory().createModule( m ),
  454.                                         this.getModuleModelFile() );

  455.                 }
  456.             }

  457.             if ( displayModel.getAny().isEmpty() )
  458.             {
  459.                 displayModel = model;
  460.             }

  461.             if ( this.getModelFile() != null )
  462.             {
  463.                 this.log( Messages.getMessage( "writingModelObjects", this.getModel(),
  464.                                                this.getModelFile().getAbsolutePath() ), Project.MSG_INFO );

  465.                 marshaller.marshal( new ObjectFactory().createModel( displayModel ), this.getModelFile() );
  466.             }
  467.             else
  468.             {
  469.                 this.log( Messages.getMessage( "showingModelObjects", this.getModel() ), Project.MSG_INFO );

  470.                 final StringWriter writer = new StringWriter();
  471.                 marshaller.marshal( new ObjectFactory().createModel( displayModel ), writer );

  472.                 reader = new BufferedReader( new StringReader( writer.toString() ) );
  473.                 String line;

  474.                 while ( ( line = reader.readLine() ) != null )
  475.                 {
  476.                     this.log( line, Project.MSG_INFO );
  477.                 }
  478.             }

  479.             suppressExceptionOnClose = false;
  480.         }
  481.         catch ( final IOException e )
  482.         {
  483.             throw new BuildException( Messages.getMessage( e ), e, this.getLocation() );
  484.         }
  485.         catch ( final JAXBException e )
  486.         {
  487.             String message = Messages.getMessage( e );
  488.             if ( message == null )
  489.             {
  490.                 message = Messages.getMessage( e.getLinkedException() );
  491.             }

  492.             throw new BuildException( message, e, this.getLocation() );
  493.         }
  494.         catch ( final ModelException e )
  495.         {
  496.             throw new BuildException( Messages.getMessage( e ), e, this.getLocation() );
  497.         }
  498.         finally
  499.         {
  500.             try
  501.             {
  502.                 if ( reader != null )
  503.                 {
  504.                     reader.close();
  505.                 }
  506.             }
  507.             catch ( final IOException e )
  508.             {
  509.                 if ( suppressExceptionOnClose )
  510.                 {
  511.                     this.logMessage( Level.SEVERE, Messages.getMessage( e ), e );
  512.                 }
  513.                 else
  514.                 {
  515.                     throw new BuildException( Messages.getMessage( e ), e, this.getLocation() );
  516.                 }
  517.             }
  518.             finally
  519.             {
  520.                 try
  521.                 {
  522.                     if ( classLoader != null )
  523.                     {
  524.                         classLoader.close();
  525.                     }
  526.                 }
  527.                 catch ( final IOException e )
  528.                 {
  529.                     if ( suppressExceptionOnClose )
  530.                     {
  531.                         this.logMessage( Level.SEVERE, Messages.getMessage( e ), e );
  532.                     }
  533.                     else
  534.                     {
  535.                         throw new BuildException( Messages.getMessage( e ), e, this.getLocation() );
  536.                     }
  537.                 }
  538.             }
  539.         }
  540.     }

  541.     /**
  542.      * {@inheritDoc}
  543.      */
  544.     @Override
  545.     public WriteModelTask clone()
  546.     {
  547.         return (WriteModelTask) super.clone();
  548.     }

  549. }