1 package org.apache.maven.plugin.clean; 2 3 /* 4 * Licensed to the Apache Software Foundation (ASF) under one 5 * or more contributor license agreements. See the NOTICE file 6 * distributed with this work for additional information 7 * regarding copyright ownership. The ASF licenses this file 8 * to you under the Apache License, Version 2.0 (the 9 * "License"); you may not use this file except in compliance 10 * with the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, 15 * software distributed under the License is distributed on an 16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17 * KIND, either express or implied. See the License for the 18 * specific language governing permissions and limitations 19 * under the License. 20 */ 21 22 import org.apache.maven.plugin.AbstractMojo; 23 import org.apache.maven.plugin.MojoExecutionException; 24 import org.apache.maven.plugins.annotations.Mojo; 25 import org.apache.maven.plugins.annotations.Parameter; 26 27 import java.io.File; 28 import java.io.IOException; 29 30 /** 31 * Goal which cleans the build. 32 * <p/> 33 * <P>This attempts to clean a project's working directory of the files that 34 * were generated at build-time. By default, it discovers and deletes the 35 * directories configured in <code>project.build.directory</code>, 36 * <code>project.build.outputDirectory</code>, 37 * <code>project.build.testOutputDirectory</code>, and 38 * <code>project.reporting.outputDirectory</code>. </P> 39 * <p/> 40 * <P>Files outside the default may also be included in the deletion by 41 * configuring the <code>filesets</code> tag.</P> 42 * 43 * @author <a href="mailto:evenisse@maven.org">Emmanuel Venisse</a> 44 * @version $Id: CleanMojo.java 1517354 2013-08-25 18:02:43Z krosenvold $ 45 * @see org.apache.maven.plugin.clean.Fileset 46 * @since 2.0 47 */ 48 @Mojo( name = "clean", threadSafe = true ) 49 public class CleanMojo 50 extends AbstractMojo 51 { 52 53 /** 54 * This is where build results go. 55 */ 56 @Parameter( defaultValue = "${project.build.directory}", readonly = true, required = true ) 57 private File directory; 58 59 /** 60 * This is where compiled classes go. 61 */ 62 @Parameter( defaultValue = "${project.build.outputDirectory}", readonly = true, required = true ) 63 private File outputDirectory; 64 65 /** 66 * This is where compiled test classes go. 67 */ 68 @Parameter( defaultValue = "${project.build.testOutputDirectory}", readonly = true, required = true ) 69 private File testOutputDirectory; 70 71 /** 72 * This is where the site plugin generates its pages. 73 * 74 * @since 2.1.1 75 */ 76 @Parameter( defaultValue = "${project.build.outputDirectory}", readonly = true, required = true ) 77 private File reportDirectory; 78 79 /** 80 * Sets whether the plugin runs in verbose mode. As of plugin version 2.3, the default value is derived from Maven's 81 * global debug flag (compare command line switch <code>-X</code>). 82 * 83 * @since 2.1 84 */ 85 @Parameter( property = "clean.verbose" ) 86 private Boolean verbose; 87 88 /** 89 * The list of file sets to delete, in addition to the default directories. For example: 90 * <pre> 91 * <filesets> 92 * <fileset> 93 * <directory>src/main/generated</directory> 94 * <followSymlinks>false</followSymlinks> 95 * <useDefaultExcludes>true</useDefaultExcludes> 96 * <includes> 97 * <include>*.java</include> 98 * </includes> 99 * <excludes> 100 * <exclude>Template*</exclude> 101 * </excludes> 102 * </fileset> 103 * </filesets> 104 * </pre> 105 * 106 * @since 2.1 107 */ 108 @Parameter 109 private Fileset[] filesets; 110 111 /** 112 * Sets whether the plugin should follow symbolic links while deleting files from the default output directories of 113 * the project. Not following symlinks requires more IO operations and heap memory, regardless whether symlinks are 114 * actually present. So projects with a huge output directory that knowingly does not contain symlinks can improve 115 * performance by setting this parameter to <code>true</code>. 116 * 117 * @since 2.1 118 */ 119 @Parameter( property = "clean.followSymLinks", defaultValue = "false" ) 120 private boolean followSymLinks; 121 122 /** 123 * Disables the plugin execution. 124 * 125 * @since 2.2 126 */ 127 @Parameter( property = "clean.skip", defaultValue = "false" ) 128 private boolean skip; 129 130 /** 131 * Indicates whether the build will continue even if there are clean errors. 132 * 133 * @since 2.2 134 */ 135 @Parameter( property = "maven.clean.failOnError", defaultValue = "true" ) 136 private boolean failOnError; 137 138 /** 139 * Indicates whether the plugin should undertake additional attempts (after a short delay) to delete a file if the 140 * first attempt failed. This is meant to help deleting files that are temporarily locked by third-party tools like 141 * virus scanners or search indexing. 142 * 143 * @since 2.4.2 144 */ 145 @Parameter( property = "maven.clean.retryOnError", defaultValue = "true" ) 146 private boolean retryOnError; 147 148 /** 149 * Disables the deletion of the default output directories configured for a project. If set to <code>true</code>, 150 * only the files/directories selected via the parameter {@link #filesets} will be deleted. 151 * 152 * @since 2.3 153 */ 154 @Parameter( property = "clean.excludeDefaultDirectories", defaultValue = "false" ) 155 private boolean excludeDefaultDirectories; 156 157 /** 158 * Deletes file-sets in the following project build directory order: (source) directory, output directory, test 159 * directory, report directory, and then the additional file-sets. 160 * 161 * @throws MojoExecutionException When a directory failed to get deleted. 162 * @see org.apache.maven.plugin.Mojo#execute() 163 */ 164 public void execute() 165 throws MojoExecutionException 166 { 167 if ( skip ) 168 { 169 getLog().info( "Clean is skipped." ); 170 return; 171 } 172 173 Cleaner cleaner = new Cleaner( getLog(), isVerbose() ); 174 175 try 176 { 177 for ( File directory : getDirectories() ) 178 { 179 if ( directory != null ) 180 { 181 cleaner.delete( directory, null, followSymLinks, failOnError, retryOnError ); 182 } 183 } 184 185 if ( filesets != null ) 186 { 187 for ( Fileset fileset : filesets ) 188 { 189 if ( fileset.getDirectory() == null ) 190 { 191 throw new MojoExecutionException( "Missing base directory for " + fileset ); 192 } 193 GlobSelector selector = new GlobSelector( fileset.getIncludes(), fileset.getExcludes(), 194 fileset.isUseDefaultExcludes() ); 195 cleaner.delete( fileset.getDirectory(), selector, fileset.isFollowSymlinks(), failOnError, 196 retryOnError ); 197 } 198 } 199 } 200 catch ( IOException e ) 201 { 202 throw new MojoExecutionException( "Failed to clean project: " + e.getMessage(), e ); 203 } 204 } 205 206 /** 207 * Indicates whether verbose output is enabled. 208 * 209 * @return <code>true</code> if verbose output is enabled, <code>false</code> otherwise. 210 */ 211 private boolean isVerbose() 212 { 213 return ( verbose != null ) ? verbose : getLog().isDebugEnabled(); 214 } 215 216 /** 217 * Gets the directories to clean (if any). The returned array may contain null entries. 218 * 219 * @return The directories to clean or an empty array if none, never <code>null</code>. 220 */ 221 private File[] getDirectories() 222 { 223 File[] directories; 224 if ( excludeDefaultDirectories ) 225 { 226 directories = new File[0]; 227 } 228 else 229 { 230 directories = new File[]{ directory, outputDirectory, testOutputDirectory, reportDirectory }; 231 } 232 return directories; 233 } 234 235 }