001/* 002 * Copyright (C) 2005 Christian Schulte <cs@schulte.it> 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 5325 2016-09-01 00:33:38Z schulte $ 029 * 030 */ 031package org.jomc.mojo; 032 033import java.io.File; 034import java.io.FileInputStream; 035import java.io.FileOutputStream; 036import java.io.IOException; 037import java.io.InputStream; 038import java.io.OutputStream; 039import org.apache.maven.artifact.ArtifactUtils; 040import org.apache.maven.execution.MavenSession; 041import org.apache.maven.plugin.AbstractMojo; 042import org.apache.maven.plugin.MojoExecutionException; 043import org.apache.maven.plugin.MojoFailureException; 044import org.apache.maven.plugin.descriptor.MojoDescriptor; 045import org.apache.maven.plugins.annotations.Component; 046import org.apache.maven.plugins.annotations.Parameter; 047import org.apache.maven.project.MavenProject; 048import org.apache.maven.project.MavenProjectHelper; 049 050/** 051 * Base class for attaching artifacts to a project. 052 * 053 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 054 * @version $JOMC: AbstractAttachMojo.java 5325 2016-09-01 00:33:38Z schulte $ 055 */ 056public abstract class AbstractAttachMojo extends AbstractMojo 057{ 058 059 /** 060 * Constant for the name of the tool backing the mojo. 061 */ 062 private static final String TOOLNAME = "MavenProjectHelper"; 063 064 /** 065 * Prefix prepended to log messages. 066 */ 067 private static final String LOG_PREFIX = "[JOMC] "; 068 069 /** 070 * The Maven project of the instance. 071 */ 072 @Parameter( name = "mavenProject", 073 defaultValue = "${project}", 074 readonly = true, 075 required = true ) 076 private MavenProject mavenProject; 077 078 /** 079 * The Maven ProjectHelper of the instance. 080 */ 081 @Component 082 private MavenProjectHelper mavenProjectHelper; 083 084 /** 085 * The Maven session of the instance. 086 * 087 * @since 1.1 088 */ 089 @Parameter( name = "mavenSession", 090 defaultValue = "${session}", 091 readonly = true, 092 required = true ) 093 private MavenSession mavenSession; 094 095 /** 096 * Directory holding the session related files of the project. 097 * 098 * @since 1.1 099 */ 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}