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: CommitClassesTask.java 4613 2012-09-22 10:07:08Z schulte $
29   *
30   */
31  package org.jomc.ant;
32  
33  import java.io.File;
34  import java.io.IOException;
35  import java.util.ArrayList;
36  import java.util.LinkedList;
37  import java.util.List;
38  import java.util.logging.Level;
39  import javax.xml.bind.JAXBContext;
40  import javax.xml.bind.JAXBException;
41  import javax.xml.bind.util.JAXBSource;
42  import javax.xml.transform.Source;
43  import javax.xml.transform.Transformer;
44  import javax.xml.transform.TransformerConfigurationException;
45  import org.apache.tools.ant.BuildException;
46  import org.jomc.ant.types.TransformerResourceType;
47  import org.jomc.model.Implementation;
48  import org.jomc.model.Module;
49  import org.jomc.model.Specification;
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  import org.jomc.tools.ClassFileProcessor;
56  
57  /**
58   * Task for committing model objects to class files.
59   *
60   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
61   * @version $JOMC: CommitClassesTask.java 4613 2012-09-22 10:07:08Z schulte $
62   */
63  public final class CommitClassesTask extends ClassFileProcessorTask
64  {
65  
66      /** The directory holding the class files to commit model objects to. */
67      private File classesDirectory;
68  
69      /** XSLT documents to use for transforming model objects. */
70      private List<TransformerResourceType> modelObjectStylesheetResources;
71  
72      /** Creates a new {@code CommitClassesTask} instance. */
73      public CommitClassesTask()
74      {
75          super();
76      }
77  
78      /**
79       * Gets the directory holding the class files to commit model objects to.
80       *
81       * @return The directory holding the class files to commit model objects to or {@code null}.
82       *
83       * @see #setClassesDirectory(java.io.File)
84       */
85      public File getClassesDirectory()
86      {
87          return this.classesDirectory;
88      }
89  
90      /**
91       * Sets the directory holding the class files to commit model objects to.
92       *
93       * @param value The new directory holding the class files to commit model objects to or {@code null}.
94       *
95       * @see #getClassesDirectory()
96       */
97      public void setClassesDirectory( final File value )
98      {
99          this.classesDirectory = value;
100     }
101 
102     /**
103      * Gets the XSLT documents to use for transforming model objects.
104      * <p>This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you make
105      * to the returned list will be present inside the object. This is why there is no {@code set} method for the
106      * model object stylesheet resources property.</p>
107      *
108      * @return The XSLT documents to use for transforming model objects.
109      *
110      * @see #createModelObjectStylesheetResource()
111      */
112     public List<TransformerResourceType> getModelObjectStylesheetResources()
113     {
114         if ( this.modelObjectStylesheetResources == null )
115         {
116             this.modelObjectStylesheetResources = new LinkedList<TransformerResourceType>();
117         }
118 
119         return this.modelObjectStylesheetResources;
120     }
121 
122     /**
123      * Creates a new {@code modelObjectStylesheetResource} element instance.
124      *
125      * @return A new {@code modelObjectStylesheetResource} element instance.
126      *
127      * @see #getModelObjectStylesheetResources()
128      */
129     public TransformerResourceType createModelObjectStylesheetResource()
130     {
131         final TransformerResourceType modelObjectStylesheetResource = new TransformerResourceType();
132         this.getModelObjectStylesheetResources().add( modelObjectStylesheetResource );
133         return modelObjectStylesheetResource;
134     }
135 
136     /** {@inheritDoc} */
137     @Override
138     public void preExecuteTask() throws BuildException
139     {
140         super.preExecuteTask();
141 
142         this.assertNotNull( "classesDirectory", this.getClassesDirectory() );
143         this.assertLocationsNotNull( this.getModelObjectStylesheetResources() );
144     }
145 
146     /**
147      * Commits model objects to class files.
148      *
149      * @throws BuildException if committing model objects fails.
150      */
151     @Override
152     public void processClassFiles() throws BuildException
153     {
154         ProjectClassLoader classLoader = null;
155         boolean suppressExceptionOnClose = true;
156 
157         try
158         {
159             this.log( Messages.getMessage( "committingModelObjects", this.getModel() ) );
160 
161             classLoader = this.newProjectClassLoader();
162             final ModelContext context = this.newModelContext( classLoader );
163             final ClassFileProcessor tool = this.newClassFileProcessor();
164             final JAXBContext jaxbContext = context.createContext( this.getModel() );
165             final Model model = this.getModel( context );
166             final Source source = new JAXBSource( jaxbContext, new ObjectFactory().createModel( model ) );
167             final ModelValidationReport validationReport = context.validateModel( this.getModel(), source );
168 
169             this.logValidationReport( context, validationReport );
170             tool.setModel( model );
171 
172             final List<Transformer> transformers =
173                 new ArrayList<Transformer>( this.getModelObjectStylesheetResources().size() );
174 
175             for ( int i = 0, s0 = this.getModelObjectStylesheetResources().size(); i < s0; i++ )
176             {
177                 final Transformer transformer =
178                     this.getTransformer( this.getModelObjectStylesheetResources().get( i ) );
179 
180                 if ( transformer != null )
181                 {
182                     transformers.add( transformer );
183                 }
184             }
185 
186             if ( validationReport.isModelValid() )
187             {
188                 final Specification s = this.getSpecification( model );
189                 final Implementation i = this.getImplementation( model );
190                 final Module m = this.getModule( model );
191 
192                 if ( s != null )
193                 {
194                     tool.commitModelObjects( s, context, this.getClassesDirectory() );
195 
196                     if ( !transformers.isEmpty() )
197                     {
198                         tool.transformModelObjects( s, context, this.getClassesDirectory(), transformers );
199                     }
200                 }
201 
202 
203                 if ( i != null )
204                 {
205                     tool.commitModelObjects( i, context, this.getClassesDirectory() );
206 
207                     if ( !transformers.isEmpty() )
208                     {
209                         tool.transformModelObjects( i, context, this.getClassesDirectory(), transformers );
210                     }
211                 }
212 
213                 if ( m != null )
214                 {
215                     tool.commitModelObjects( m, context, this.getClassesDirectory() );
216 
217                     if ( !transformers.isEmpty() )
218                     {
219                         tool.transformModelObjects( m, context, this.getClassesDirectory(), transformers );
220                     }
221                 }
222 
223                 if ( this.isModulesProcessingRequested() )
224                 {
225                     tool.commitModelObjects( context, this.getClassesDirectory() );
226 
227                     if ( !transformers.isEmpty() )
228                     {
229                         tool.transformModelObjects( context, this.getClassesDirectory(), transformers );
230                     }
231                 }
232 
233                 suppressExceptionOnClose = false;
234             }
235             else
236             {
237                 throw new ModelException( Messages.getMessage( "invalidModel", this.getModel() ) );
238             }
239         }
240         catch ( final IOException e )
241         {
242             throw new ClassProcessingException( Messages.getMessage( e ), e, this.getLocation() );
243         }
244         catch ( final JAXBException e )
245         {
246             throw new ClassProcessingException( Messages.getMessage( e ), e, this.getLocation() );
247         }
248         catch ( final TransformerConfigurationException e )
249         {
250             throw new ClassProcessingException( Messages.getMessage( e ), e, this.getLocation() );
251         }
252         catch ( final ModelException e )
253         {
254             throw new ClassProcessingException( Messages.getMessage( e ), e, this.getLocation() );
255         }
256         finally
257         {
258             try
259             {
260                 if ( classLoader != null )
261                 {
262                     classLoader.close();
263                 }
264             }
265             catch ( final IOException e )
266             {
267                 if ( suppressExceptionOnClose )
268                 {
269                     this.logMessage( Level.SEVERE, Messages.getMessage( e ), e );
270                 }
271                 else
272                 {
273                     throw new ClassProcessingException( Messages.getMessage( e ), e, this.getLocation() );
274                 }
275             }
276         }
277     }
278 
279     /** {@inheritDoc} */
280     @Override
281     public CommitClassesTask clone()
282     {
283         final CommitClassesTask clone = (CommitClassesTask) super.clone();
284         clone.classesDirectory =
285             this.classesDirectory != null ? new File( this.classesDirectory.getAbsolutePath() ) : null;
286 
287         if ( this.modelObjectStylesheetResources != null )
288         {
289             clone.modelObjectStylesheetResources =
290                 new ArrayList<TransformerResourceType>( this.modelObjectStylesheetResources.size() );
291 
292             for ( TransformerResourceType e : this.modelObjectStylesheetResources )
293             {
294                 clone.modelObjectStylesheetResources.add( e.clone() );
295             }
296         }
297 
298         return clone;
299     }
300 
301 }