/* * #%L * License Maven Plugin * * $Id$ * $HeadURL$ * %% * Copyright (C) 2008 - 2011 CodeLutin, Codehaus, Tony Chemit * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Lesser Public License for more details. * * You should have received a copy of the GNU General Lesser Public * License along with this program. If not, see * <http://www.gnu.org/licenses/lgpl-3.0.html>. * #L% */ package org.codehaus.mojo.license; import org.apache.commons.lang.StringUtils; import org.apache.maven.execution.MavenSession; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.util.ReaderFactory; import java.io.File; import java.util.Arrays; /** * Abstract license mojo. * * @author tchemit <chemit@codelutin.com> * @since 1.0 */ public abstract class AbstractLicenseMojo extends AbstractMojo { /** * Current maven session. (used to launch certain mojo once by build). * * @parameter expression="${session}" * @required * @readonly * @since 1.0 */ private MavenSession session; /** * The reacted project. * * @parameter default-value="${project}" * @required * @since 1.0 */ private MavenProject project; /** * Flag to activate verbose mode. * <p/> * <b>Note:</b> Verbose mode is always on if you starts a debug maven instance * (says via {@code -X}). * * @parameter expression="${license.verbose}" default-value="${maven.verbose}" * @since 1.0 */ private boolean verbose; /** * Encoding used to read and writes files. * <p/> * <b>Note:</b> If nothing is filled here, we will use the system * property {@code file.encoding}. * * @parameter expression="${license.encoding}" default-value="${project.build.sourceEncoding}" * @since 1.0 */ private String encoding; public final String getEncoding() { return encoding; } public final void setEncoding( String encoding ) { this.encoding = encoding; } /** * Method to initialize the mojo before doing any concrete actions. * <p/> * <b>Note:</b> The method is invoked before the {@link #doAction()} method. * * @throws Exception if any */ protected abstract void init() throws Exception; /** * Do plugin action. * <p/> * The method {@link #execute()} invoke this method only and only if : * <ul> * <li>{@link #checkPackaging()} returns {@code true}.</li> * <li>method {@link #init()} returns {@code true}.</li> * </ul> * * @throws Exception if any */ protected abstract void doAction() throws Exception; public final void execute() throws MojoExecutionException, MojoFailureException { try { if ( getLog().isDebugEnabled() ) { // always be verbose in debug mode setVerbose( true ); } // check if project packaging is compatible with the mojo boolean canContinue = checkPackaging(); if ( !canContinue ) { getLog().warn( "The goal is skip due to packaging '" + getProject().getPackaging() + "'" ); return; } // init the mojo try { checkEncoding(); init(); } catch ( MojoFailureException e ) { throw e; } catch ( MojoExecutionException e ) { throw e; } catch ( Exception e ) { throw new MojoExecutionException( "could not init goal " + getClass().getSimpleName() + " for reason : " + e.getMessage(), e ); } // check if mojo can be skipped canContinue = checkSkip(); if ( !canContinue ) { if ( isVerbose() ) { getLog().info( "Goal will not be executed." ); } return; } // can really execute the mojo try { doAction(); } catch ( MojoFailureException e ) { throw e; } catch ( MojoExecutionException e ) { throw e; } catch ( Exception e ) { throw new MojoExecutionException( "could not execute goal " + getClass().getSimpleName() + " for reason : " + e.getMessage(), e ); } } finally { afterExecute(); } } /** * A call back to execute after the {@link #execute()} is done */ protected void afterExecute() { // by default do nothing } /** * Check if the project packaging is acceptable for the mojo. * <p/> * By default, accept all packaging types. * <p/> * <b>Note:</b> This method is the first instruction to be executed in * the {@link #execute()}. * <p/> * <b>Tip:</b> There is two method to simplify the packaging check : * <p/> * {@link #acceptPackaging(String...)} * <p/> * and * <p/> * {@link #rejectPackaging(String...)} * * @return {@code true} if can execute the goal for the packaging of the * project, {@code false} otherwise. */ protected boolean checkPackaging() { // by default, accept every type of packaging return true; } /** * Checks if the mojo execution should be skipped. * * @return {@code false} if the mojo should not be executed. */ protected boolean checkSkip() { // by default, never skip goal return true; } /** * Accept the project's packaging between some given. * * @param packages the accepted packaging * @return {@code true} if the project's packaging is one of the given ones. */ protected boolean acceptPackaging( String... packages ) { String projectPackaging = getProject().getPackaging(); for ( String p : packages ) { if ( p.equals( projectPackaging ) ) { // accept packaging return true; } } // reject packaging return false; } /** * Accept the project's packaging if not in given one. * * @param packages the rejecting packagings * @return {@code true} if the project's packaging is not in the given ones. */ protected boolean rejectPackaging( String... packages ) { String projectPackaging = getProject().getPackaging(); for ( String p : packages ) { if ( p.equals( projectPackaging ) ) { // reject this packaging return false; } } // accept packaging return true; } /** * Method to be invoked in init phase to check sanity of {@link #getEncoding()}. * <p/> * If no encoding was filled, then use the default for system * (via {@code file.encoding} environement property). */ protected void checkEncoding() { if ( isVerbose() ) { getLog().info( "Will check encoding : " + getEncoding() ); } if ( StringUtils.isEmpty( getEncoding() ) ) { getLog().warn( "File encoding has not been set, using platform encoding " + ReaderFactory.FILE_ENCODING + ", i.e. build is platform dependent!" ); setEncoding( ReaderFactory.FILE_ENCODING ); } } public final MavenProject getProject() { return project; } public final void setProject( MavenProject project ) { this.project = project; } public final boolean isVerbose() { return verbose; } public final void setVerbose( boolean verbose ) { this.verbose = verbose; } public final MavenSession getSession() { return session; } public final void setSession( MavenSession session ) { this.session = session; } public final long getBuildTimestamp() { return session.getStartTime().getTime(); } /** * Add a new resource location to the maven project * (in not already present). * * @param dir the new resource location to add * @param includes files to include */ protected void addResourceDir( File dir, String... includes ) { boolean added = MojoHelper.addResourceDir( dir, getProject(), includes ); if ( added && isVerbose() ) { getLog().info( "add resource " + dir + " with includes " + Arrays.toString( includes ) ); } } /** * @return {@code true} if project is not a pom, {@code false} otherwise. */ protected boolean hasClassPath() { return rejectPackaging( "pom" ); } }