1 package org.apache.maven.plugin.clean;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.IOException;
24
25 import org.apache.maven.plugin.logging.Log;
26 import org.codehaus.plexus.util.Os;
27
28
29
30
31
32
33 class Cleaner
34 {
35
36 private static final boolean ON_WINDOWS = Os.isFamily( Os.FAMILY_WINDOWS );
37
38 private final Logger logDebug;
39
40 private final Logger logInfo;
41
42 private final Logger logVerbose;
43
44 private final Logger logWarn;
45
46
47
48
49
50
51
52 public Cleaner( final Log log, boolean verbose )
53 {
54 logDebug = ( log == null || !log.isDebugEnabled() ) ? null : new Logger()
55 {
56 public void log( CharSequence message )
57 {
58 log.debug( message );
59 }
60 };
61
62 logInfo = ( log == null || !log.isInfoEnabled() ) ? null : new Logger()
63 {
64 public void log( CharSequence message )
65 {
66 log.info( message );
67 }
68 };
69
70 logWarn = ( log == null || !log.isWarnEnabled() ) ? null : new Logger()
71 {
72 public void log( CharSequence message )
73 {
74 log.warn( message );
75 }
76 };
77
78 logVerbose = verbose ? logInfo : logDebug;
79 }
80
81
82
83
84
85
86
87
88
89
90
91
92 public void delete( File basedir, Selector selector, boolean followSymlinks, boolean failOnError )
93 throws IOException
94 {
95 if ( !basedir.isDirectory() )
96 {
97 if ( !basedir.exists() )
98 {
99 if ( logDebug != null )
100 {
101 logDebug.log( "Skipping non-existing directory " + basedir );
102 }
103 return;
104 }
105 throw new IOException( "Invalid base directory " + basedir );
106 }
107
108 if ( logInfo != null )
109 {
110 logInfo.log( "Deleting " + basedir + ( selector != null ? " (" + selector + ")" : "" ) );
111 }
112
113 File file = followSymlinks ? basedir : basedir.getCanonicalFile();
114
115 delete( file, "", selector, followSymlinks, failOnError );
116 }
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132 private Result delete( File file, String pathname, Selector selector, boolean followSymlinks, boolean failOnError )
133 throws IOException
134 {
135 Result result = new Result();
136
137 boolean isDirectory = file.isDirectory();
138
139 if ( isDirectory )
140 {
141 if ( selector == null || selector.couldHoldSelected( pathname ) )
142 {
143 File canonical = followSymlinks ? file : file.getCanonicalFile();
144 if ( followSymlinks || file.equals( canonical ) )
145 {
146 String[] filenames = canonical.list();
147 if ( filenames != null )
148 {
149 String prefix = ( pathname.length() > 0 ) ? pathname + File.separatorChar : "";
150 for ( int i = filenames.length - 1; i >= 0; i-- )
151 {
152 String filename = filenames[i];
153 File child = new File( canonical, filename );
154 result.update( delete( child, prefix + filename, selector, followSymlinks, failOnError ) );
155 }
156 }
157 }
158 else if ( logDebug != null )
159 {
160 logDebug.log( "Not recursing into symlink " + file );
161 }
162 }
163 else if ( logDebug != null )
164 {
165 logDebug.log( "Not recursing into directory without included files " + file );
166 }
167 }
168
169 if ( !result.excluded && ( selector == null || selector.isSelected( pathname ) ) )
170 {
171 if ( logVerbose != null )
172 {
173 if ( isDirectory )
174 {
175 logVerbose.log( "Deleting directory " + file );
176 }
177 else if ( file.exists() )
178 {
179 logVerbose.log( "Deleting file " + file );
180 }
181 else
182 {
183 logVerbose.log( "Deleting dangling symlink " + file );
184 }
185 }
186 result.failures += delete( file, failOnError );
187 }
188 else
189 {
190 result.excluded = true;
191 }
192
193 return result;
194 }
195
196
197
198
199
200
201
202
203
204
205 private int delete( File file, boolean failOnError )
206 throws IOException
207 {
208 if ( !file.delete() )
209 {
210 if ( ON_WINDOWS )
211 {
212
213 System.gc();
214 }
215 try
216 {
217 Thread.sleep( 10 );
218 }
219 catch ( InterruptedException e )
220 {
221
222 }
223 if ( !file.delete() )
224 {
225 if ( failOnError )
226 {
227 throw new IOException( "Failed to delete " + file );
228 }
229 else
230 {
231 if ( logWarn != null )
232 {
233 logWarn.log( "Failed to delete " + file );
234 }
235 return 1;
236 }
237 }
238 }
239
240 return 0;
241 }
242
243 private static class Result
244 {
245
246 public int failures;
247
248 public boolean excluded;
249
250 public void update( Result result )
251 {
252 failures += result.failures;
253 excluded |= result.excluded;
254 }
255
256 }
257
258 private static interface Logger
259 {
260
261 public void log( CharSequence message );
262
263 }
264
265 }