001/*
002 *   Copyright (C) Christian Schulte, 2005-206
003 *   All rights reserved.
004 *
005 *   Redistribution and use in source and binary forms, with or without
006 *   modification, are permitted provided that the following conditions
007 *   are met:
008 *
009 *     o Redistributions of source code must retain the above copyright
010 *       notice, this list of conditions and the following disclaimer.
011 *
012 *     o Redistributions in binary form must reproduce the above copyright
013 *       notice, this list of conditions and the following disclaimer in
014 *       the documentation and/or other materials provided with the
015 *       distribution.
016 *
017 *   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
018 *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
019 *   AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
020 *   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
021 *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
022 *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
023 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
024 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
026 *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027 *
028 *   $JOMC: AbstractAttachMojo.java 4613 2012-09-22 10:07:08Z schulte $
029 *
030 */
031package org.jomc.mojo;
032
033import java.io.File;
034import java.io.IOException;
035import org.apache.commons.io.FileUtils;
036import org.apache.maven.artifact.ArtifactUtils;
037import org.apache.maven.execution.MavenSession;
038import org.apache.maven.plugin.AbstractMojo;
039import org.apache.maven.plugin.MojoExecutionException;
040import org.apache.maven.plugin.MojoFailureException;
041import org.apache.maven.plugin.descriptor.MojoDescriptor;
042import org.apache.maven.project.MavenProject;
043import org.apache.maven.project.MavenProjectHelper;
044
045/**
046 * Base class for attaching artifacts to a project.
047 *
048 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
049 * @version $JOMC: AbstractAttachMojo.java 4613 2012-09-22 10:07:08Z schulte $
050 */
051public abstract class AbstractAttachMojo extends AbstractMojo
052{
053
054    /** Constant for the name of the tool backing the mojo. */
055    private static final String TOOLNAME = "MavenProjectHelper";
056
057    /** Prefix prepended to log messages. */
058    private static final String LOG_PREFIX = "[JOMC] ";
059
060    /**
061     * The Maven project of the instance.
062     *
063     * @parameter expression="${project}"
064     * @required
065     * @readonly
066     */
067    private MavenProject mavenProject;
068
069    /**
070     * The Maven ProjectHelper of the instance.
071     *
072     * @component
073     * @required
074     * @readonly
075     */
076    private MavenProjectHelper mavenProjectHelper;
077
078    /**
079     * The Maven session of the instance.
080     *
081     * @parameter expression="${session}"
082     * @required
083     * @readonly
084     * @since 1.1
085     */
086    private MavenSession mavenSession;
087
088    /**
089     * Directory holding the session related files of the project.
090     *
091     * @parameter default-value="${project.build.directory}/jomc-sessions" expression="${jomc.sessionDirectory}"
092     * @since 1.1
093     */
094    private String sessionDirectory;
095
096    /**
097     * Controls verbosity of the plugin.
098     *
099     * @parameter expression="${jomc.verbose}" default-value="false"
100     * @since 1.1
101     */
102    private boolean verbose;
103
104    /** Creates a new {@code AbstractAttachMojo} instance. */
105    public AbstractAttachMojo()
106    {
107        super();
108    }
109
110    /**
111     * Gets the Maven project of the instance.
112     *
113     * @return The Maven project of the instance.
114     *
115     * @throws MojoExecutionException if getting the Maven project of the instance fails.
116     *
117     * @since 1.1
118     */
119    protected MavenProject getMavenProject() throws MojoExecutionException
120    {
121        return this.mavenProject;
122    }
123
124    /**
125     * Gets the Maven session of the instance.
126     *
127     * @return The Maven session of the instance.
128     *
129     * @throws MojoExecutionException if getting the Maven session of the instance fails.
130     *
131     * @since 1.1
132     */
133    protected MavenSession getMavenSession() throws MojoExecutionException
134    {
135        return this.mavenSession;
136    }
137
138    /**
139     * Gets the Maven project helper of the instance.
140     *
141     * @return The Maven project helper of the instance.
142     *
143     * @throws MojoExecutionException if getting the Maven project helper of the instance fails.
144     *
145     * @since 1.1
146     */
147    protected MavenProjectHelper getMavenProjectHelper() throws MojoExecutionException
148    {
149        return this.mavenProjectHelper;
150    }
151
152    /**
153     * Gets the directory holding the session related files of the project.
154     *
155     * @return The directory holding the session related files of the project.
156     *
157     * @throws MojoExecutionException if getting the directory fails.
158     *
159     * @since 1.1
160     */
161    protected File getSessionDirectory() throws MojoExecutionException
162    {
163        File directory = new File( this.sessionDirectory );
164
165        if ( !directory.isAbsolute() )
166        {
167            directory = new File( this.getMavenProject().getBasedir(), this.sessionDirectory );
168        }
169
170        return directory;
171    }
172
173    /**
174     * Gets a flag indicating verbose output is enabled.
175     *
176     * @return {@code true}, if verbose output is enabled; {@code false}, if information messages are suppressed.
177     *
178     * @throws MojoExecutionException if getting the flag fails.
179     *
180     * @since 1.1
181     */
182    protected final boolean isVerbose() throws MojoExecutionException
183    {
184        return this.verbose;
185    }
186
187    /**
188     * Sets the flag indicating verbose output is enabled.
189     *
190     * @param value {@code true}, to enable verbose output; {@code false}, to suppress information messages.
191     *
192     * @throws MojoExecutionException if setting the flag fails.
193     *
194     * @since 1.1
195     */
196    protected final void setVerbose( final boolean value ) throws MojoExecutionException
197    {
198        this.verbose = value;
199    }
200
201    /**
202     * Gets the file of the artifact to attach.
203     *
204     * @return The file of the artifact to attach.
205     */
206    protected abstract File getArtifactFile();
207
208    /**
209     * Gets the classifier of the artifact to attach.
210     *
211     * @return The classifier of the artifact to attach.
212     */
213    protected abstract String getArtifactClassifier();
214
215    /**
216     * Gets the type of the artifact to attach.
217     *
218     * @return The type of the artifact to attach.
219     */
220    protected abstract String getArtifactType();
221
222    /**
223     * Gets the execution strategy of the instance.
224     *
225     * @return The execution strategy of the instance.
226     *
227     * @since 1.1
228     */
229    protected abstract String getExecutionStrategy();
230
231    public final void execute() throws MojoExecutionException, MojoFailureException
232    {
233        final File attachment =
234            new File( this.getSessionDirectory(),
235                      ArtifactUtils.versionlessKey( this.getMavenProject().getArtifact() ).hashCode()
236                      + "-" + this.getArtifactClassifier()
237                      + "-" + this.getMavenSession().getStartTime().getTime()
238                      + "." + this.getArtifactType() );
239
240        try
241        {
242            if ( this.isVerbose() && this.getLog().isInfoEnabled() )
243            {
244                this.getLog().info( LOG_PREFIX + Messages.getMessage( "separator" ) );
245                this.getLog().info( LOG_PREFIX + Messages.getMessage( "title" ) );
246            }
247
248            if ( MojoDescriptor.MULTI_PASS_EXEC_STRATEGY.equals( this.getExecutionStrategy() )
249                 || !attachment.exists() )
250            {
251                if ( this.isVerbose() && this.getLog().isInfoEnabled() )
252                {
253                    this.getLog().info( LOG_PREFIX + Messages.getMessage( "separator" ) );
254                    this.getLog().info( LOG_PREFIX + Messages.getMessage(
255                        "processingProject", TOOLNAME, this.getMavenProject().getName() == null
256                                                       ? this.getMavenProject().getArtifactId()
257                                                       : this.getMavenProject().getName() ) );
258
259                }
260
261                if ( this.getArtifactFile().isFile() )
262                {
263                    if ( attachment.exists() && !attachment.delete() )
264                    {
265                        this.getLog().warn( LOG_PREFIX + Messages.getMessage(
266                            "failedDeletingFile", attachment.getAbsolutePath() ) );
267
268                    }
269                    if ( !attachment.getParentFile().exists() && !attachment.getParentFile().mkdirs() )
270                    {
271                        throw new MojoExecutionException( Messages.getMessage(
272                            "failedCreatingDirectory", attachment.getParentFile().getAbsolutePath() ) );
273
274                    }
275
276                    FileUtils.copyFile( this.getArtifactFile(), attachment );
277                    this.getMavenProjectHelper().attachArtifact( this.getMavenProject(), this.getArtifactType(),
278                                                                 this.getArtifactClassifier(), attachment );
279
280                    if ( this.isVerbose() && this.getLog().isInfoEnabled() )
281                    {
282                        this.getLog().info( LOG_PREFIX + Messages.getMessage(
283                            "creatingAttachment", this.getArtifactFile().getAbsolutePath(),
284                            this.getArtifactClassifier(), this.getArtifactType() ) );
285
286                        this.getLog().info( LOG_PREFIX + Messages.getMessage( "toolSuccess", TOOLNAME ) );
287                    }
288                }
289                else if ( this.getLog().isWarnEnabled() )
290                {
291                    this.getLog().warn( LOG_PREFIX + Messages.getMessage(
292                        "artifactFileNotFound", this.getArtifactFile().getAbsolutePath() ) );
293
294                }
295            }
296            else if ( this.isVerbose() && this.getLog().isInfoEnabled() )
297            {
298                this.getLog().info( LOG_PREFIX + Messages.getMessage( "executionSuppressed",
299                                                                      this.getExecutionStrategy() ) );
300
301            }
302        }
303        catch ( final IOException e )
304        {
305            final String message = Messages.getMessage( e );
306            throw new MojoExecutionException( Messages.getMessage(
307                "failedCopying", this.getArtifactFile().getAbsolutePath(), attachment.getAbsolutePath(),
308                message != null ? message : "" ), e );
309
310        }
311        finally
312        {
313            if ( this.isVerbose() && this.getLog().isInfoEnabled() )
314            {
315                this.getLog().info( LOG_PREFIX + Messages.getMessage( "separator" ) );
316            }
317        }
318    }
319
320}