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