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: AbstractAttachMojo.java 5325 2016-09-01 00:33:38Z schulte $
29   *
30   */
31  package org.jomc.mojo;
32  
33  import java.io.File;
34  import java.io.FileInputStream;
35  import java.io.FileOutputStream;
36  import java.io.IOException;
37  import java.io.InputStream;
38  import java.io.OutputStream;
39  import org.apache.maven.artifact.ArtifactUtils;
40  import org.apache.maven.execution.MavenSession;
41  import org.apache.maven.plugin.AbstractMojo;
42  import org.apache.maven.plugin.MojoExecutionException;
43  import org.apache.maven.plugin.MojoFailureException;
44  import org.apache.maven.plugin.descriptor.MojoDescriptor;
45  import org.apache.maven.plugins.annotations.Component;
46  import org.apache.maven.plugins.annotations.Parameter;
47  import org.apache.maven.project.MavenProject;
48  import org.apache.maven.project.MavenProjectHelper;
49  
50  /**
51   * Base class for attaching artifacts to a project.
52   *
53   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
54   * @version $JOMC: AbstractAttachMojo.java 5325 2016-09-01 00:33:38Z schulte $
55   */
56  public abstract class AbstractAttachMojo extends AbstractMojo
57  {
58  
59      /**
60       * Constant for the name of the tool backing the mojo.
61       */
62      private static final String TOOLNAME = "MavenProjectHelper";
63  
64      /**
65       * Prefix prepended to log messages.
66       */
67      private static final String LOG_PREFIX = "[JOMC] ";
68  
69      /**
70       * The Maven project of the instance.
71       */
72      @Parameter( name = "mavenProject",
73                  defaultValue = "${project}",
74                  readonly = true,
75                  required = true )
76      private MavenProject mavenProject;
77  
78      /**
79       * The Maven ProjectHelper of the instance.
80       */
81      @Component
82      private MavenProjectHelper mavenProjectHelper;
83  
84      /**
85       * The Maven session of the instance.
86       *
87       * @since 1.1
88       */
89      @Parameter( name = "mavenSession",
90                  defaultValue = "${session}",
91                  readonly = true,
92                  required = true )
93      private MavenSession mavenSession;
94  
95      /**
96       * Directory holding the session related files of the project.
97       *
98       * @since 1.1
99       */
100     @Parameter( name = "sessionDirectory",
101                 property = "jomc.sessionDirectory",
102                 defaultValue = "${project.build.directory}/jomc-sessions" )
103     private String sessionDirectory;
104 
105     /**
106      * Controls verbosity of the plugin.
107      *
108      * @since 1.1
109      */
110     @Parameter( name = "verbose",
111                 property = "jomc.verbose",
112                 defaultValue = "false" )
113     private boolean verbose;
114 
115     /**
116      * Creates a new {@code AbstractAttachMojo} instance.
117      */
118     public AbstractAttachMojo()
119     {
120         super();
121     }
122 
123     /**
124      * Gets the Maven project of the instance.
125      *
126      * @return The Maven project of the instance.
127      *
128      * @throws MojoExecutionException if getting the Maven project of the instance fails.
129      *
130      * @since 1.1
131      */
132     protected MavenProject getMavenProject() throws MojoExecutionException
133     {
134         return this.mavenProject;
135     }
136 
137     /**
138      * Gets the Maven session of the instance.
139      *
140      * @return The Maven session of the instance.
141      *
142      * @throws MojoExecutionException if getting the Maven session of the instance fails.
143      *
144      * @since 1.1
145      */
146     protected MavenSession getMavenSession() throws MojoExecutionException
147     {
148         return this.mavenSession;
149     }
150 
151     /**
152      * Gets the Maven project helper of the instance.
153      *
154      * @return The Maven project helper of the instance.
155      *
156      * @throws MojoExecutionException if getting the Maven project helper of the instance fails.
157      *
158      * @since 1.1
159      */
160     protected MavenProjectHelper getMavenProjectHelper() throws MojoExecutionException
161     {
162         return this.mavenProjectHelper;
163     }
164 
165     /**
166      * Gets the directory holding the session related files of the project.
167      *
168      * @return The directory holding the session related files of the project.
169      *
170      * @throws MojoExecutionException if getting the directory fails.
171      *
172      * @since 1.1
173      */
174     protected File getSessionDirectory() throws MojoExecutionException
175     {
176         File directory = new File( this.sessionDirectory );
177 
178         if ( !directory.isAbsolute() )
179         {
180             directory = new File( this.getMavenProject().getBasedir(), this.sessionDirectory );
181         }
182 
183         return directory;
184     }
185 
186     /**
187      * Gets a flag indicating verbose output is enabled.
188      *
189      * @return {@code true}, if verbose output is enabled; {@code false}, if information messages are suppressed.
190      *
191      * @throws MojoExecutionException if getting the flag fails.
192      *
193      * @since 1.1
194      */
195     protected final boolean isVerbose() throws MojoExecutionException
196     {
197         return this.verbose;
198     }
199 
200     /**
201      * Sets the flag indicating verbose output is enabled.
202      *
203      * @param value {@code true}, to enable verbose output; {@code false}, to suppress information messages.
204      *
205      * @throws MojoExecutionException if setting the flag fails.
206      *
207      * @since 1.1
208      */
209     protected final void setVerbose( final boolean value ) throws MojoExecutionException
210     {
211         this.verbose = value;
212     }
213 
214     /**
215      * Gets the file of the artifact to attach.
216      *
217      * @return The file of the artifact to attach.
218      */
219     protected abstract File getArtifactFile();
220 
221     /**
222      * Gets the classifier of the artifact to attach.
223      *
224      * @return The classifier of the artifact to attach.
225      */
226     protected abstract String getArtifactClassifier();
227 
228     /**
229      * Gets the type of the artifact to attach.
230      *
231      * @return The type of the artifact to attach.
232      */
233     protected abstract String getArtifactType();
234 
235     /**
236      * Gets the execution strategy of the instance.
237      *
238      * @return The execution strategy of the instance.
239      *
240      * @since 1.1
241      */
242     protected abstract String getExecutionStrategy();
243 
244     public final void execute() throws MojoExecutionException, MojoFailureException
245     {
246         final File attachment =
247             new File( this.getSessionDirectory(),
248                       ArtifactUtils.versionlessKey( this.getMavenProject().getArtifact() ).hashCode()
249                           + "-" + this.getArtifactClassifier()
250                           + "-" + this.getMavenSession().getStartTime().getTime()
251                           + "." + this.getArtifactType() );
252 
253         try
254         {
255             if ( this.isVerbose() && this.getLog().isInfoEnabled() )
256             {
257                 this.getLog().info( LOG_PREFIX + Messages.getMessage( "separator" ) );
258                 this.getLog().info( LOG_PREFIX + Messages.getMessage( "title" ) );
259             }
260 
261             if ( MojoDescriptor.MULTI_PASS_EXEC_STRATEGY.equals( this.getExecutionStrategy() )
262                      || !attachment.exists() )
263             {
264                 if ( this.isVerbose() && this.getLog().isInfoEnabled() )
265                 {
266                     this.getLog().info( LOG_PREFIX + Messages.getMessage( "separator" ) );
267                     this.getLog().info( LOG_PREFIX + Messages.getMessage(
268                         "processingProject", TOOLNAME, this.getMavenProject().getName() == null
269                                                            ? this.getMavenProject().getArtifactId()
270                                                            : this.getMavenProject().getName() ) );
271 
272                 }
273 
274                 if ( this.getArtifactFile().isFile() )
275                 {
276                     if ( attachment.exists() && !attachment.delete() )
277                     {
278                         this.getLog().warn( LOG_PREFIX + Messages.getMessage(
279                             "failedDeletingFile", attachment.getAbsolutePath() ) );
280 
281                     }
282                     if ( !attachment.getParentFile().exists() && !attachment.getParentFile().mkdirs() )
283                     {
284                         throw new MojoExecutionException( Messages.getMessage(
285                             "failedCreatingDirectory", attachment.getParentFile().getAbsolutePath() ) );
286 
287                     }
288 
289                     this.copyFile( this.getArtifactFile(), attachment );
290                     this.getMavenProjectHelper().attachArtifact( this.getMavenProject(), this.getArtifactType(),
291                                                                  this.getArtifactClassifier(), attachment );
292 
293                     if ( this.isVerbose() && this.getLog().isInfoEnabled() )
294                     {
295                         this.getLog().info( LOG_PREFIX + Messages.getMessage(
296                             "creatingAttachment", this.getArtifactFile().getAbsolutePath(),
297                             this.getArtifactClassifier(), this.getArtifactType() ) );
298 
299                         this.getLog().info( LOG_PREFIX + Messages.getMessage( "toolSuccess", TOOLNAME ) );
300                     }
301                 }
302                 else if ( this.getLog().isWarnEnabled() )
303                 {
304                     this.getLog().warn( LOG_PREFIX + Messages.getMessage(
305                         "artifactFileNotFound", this.getArtifactFile().getAbsolutePath() ) );
306 
307                 }
308             }
309             else if ( this.isVerbose() && this.getLog().isInfoEnabled() )
310             {
311                 this.getLog().info( LOG_PREFIX + Messages.getMessage( "executionSuppressed",
312                                                                       this.getExecutionStrategy() ) );
313 
314             }
315         }
316         catch ( final IOException e )
317         {
318             final String message = Messages.getMessage( e );
319             throw new MojoExecutionException( Messages.getMessage(
320                 "failedCopying", this.getArtifactFile().getAbsolutePath(), attachment.getAbsolutePath(),
321                 message != null ? message : "" ), e );
322 
323         }
324         finally
325         {
326             if ( this.isVerbose() && this.getLog().isInfoEnabled() )
327             {
328                 this.getLog().info( LOG_PREFIX + Messages.getMessage( "separator" ) );
329             }
330         }
331     }
332 
333     /**
334      * Copies a file.
335      *
336      * @param source The file to copy.
337      * @param target The file to copy the source file to.
338      *
339      * @throws IOException if copying fails.
340      *
341      * @since 1.10
342      */
343     protected final void copyFile( final File source, final File target ) throws IOException
344     {
345         InputStream in = null;
346         OutputStream out = null;
347         try
348         {
349             if ( !source.equals( target ) )
350             {
351                 in = new FileInputStream( source );
352                 out = new FileOutputStream( target );
353 
354                 final byte[] buffer = new byte[ 65536 ];
355 
356                 for ( int read = in.read( buffer );
357                       read >= 0;
358                       out.write( buffer, 0, read ), read = in.read( buffer ) );
359 
360                 out.close();
361                 out = null;
362 
363                 in.close();
364                 in = null;
365             }
366         }
367         finally
368         {
369             try
370             {
371                 if ( out != null )
372                 {
373                     out.close();
374                 }
375             }
376             catch ( final IOException e )
377             {
378                 this.getLog().warn( e );
379             }
380             finally
381             {
382                 try
383                 {
384                     if ( in != null )
385                     {
386                         in.close();
387                     }
388                 }
389                 catch ( final IOException e )
390                 {
391                     this.getLog().warn( e );
392                 }
393             }
394         }
395     }
396 
397 }