1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.vfs2.tasks;
18
19 import java.util.ArrayList;
20 import java.util.HashSet;
21 import java.util.Set;
22 import java.util.StringTokenizer;
23
24 import org.apache.commons.vfs2.FileName;
25 import org.apache.commons.vfs2.FileObject;
26 import org.apache.commons.vfs2.NameScope;
27 import org.apache.commons.vfs2.Selectors;
28 import org.apache.commons.vfs2.util.FileObjectUtils;
29 import org.apache.commons.vfs2.util.Messages;
30 import org.apache.tools.ant.BuildException;
31 import org.apache.tools.ant.Project;
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 public abstract class AbstractSyncTask extends VfsTask {
54 private final ArrayList<SourceInfo> srcFiles = new ArrayList<>();
55 private String destFileUrl;
56 private String destDirUrl;
57 private String srcDirUrl;
58 private boolean srcDirIsBase;
59 private boolean failonerror = true;
60 private String filesList;
61
62
63
64
65
66
67 public void setDestFile(final String destFile) {
68 this.destFileUrl = destFile;
69 }
70
71
72
73
74
75
76 public void setDestDir(final String destDir) {
77 this.destDirUrl = destDir;
78 }
79
80
81
82
83
84
85 public void setSrc(final String srcFile) {
86 final SourceInfo src = new SourceInfo();
87 src.setFile(srcFile);
88 addConfiguredSrc(src);
89 }
90
91
92
93
94
95
96 public void setSrcDir(final String srcDir) {
97 this.srcDirUrl = srcDir;
98 }
99
100
101
102
103
104
105 public void setSrcDirIsBase(final boolean srcDirIsBase) {
106 this.srcDirIsBase = srcDirIsBase;
107 }
108
109
110
111
112
113
114 public void setFailonerror(final boolean failonerror) {
115 this.failonerror = failonerror;
116 }
117
118
119
120
121
122
123 public boolean isFailonerror() {
124 return failonerror;
125 }
126
127
128
129
130
131
132 public void setIncludes(final String filesList) {
133 this.filesList = filesList;
134 }
135
136
137
138
139
140
141
142 public void addConfiguredSrc(final SourceInfo srcInfo) throws BuildException {
143 if (srcInfo.file == null) {
144 final String message = Messages.getString("vfs.tasks/sync.no-source-file.error");
145 throw new BuildException(message);
146 }
147 srcFiles.add(srcInfo);
148 }
149
150
151
152
153
154
155 @Override
156 public void execute() throws BuildException {
157
158 if (destFileUrl == null && destDirUrl == null) {
159 final String message = Messages.getString("vfs.tasks/sync.no-destination.error");
160 logOrDie(message, Project.MSG_WARN);
161 return;
162 }
163
164 if (destFileUrl != null && destDirUrl != null) {
165 final String message = Messages.getString("vfs.tasks/sync.too-many-destinations.error");
166 logOrDie(message, Project.MSG_WARN);
167 return;
168 }
169
170
171 if (srcDirUrl != null && !srcDirUrl.equals(destDirUrl) && filesList != null && filesList.length() > 0) {
172 if (!srcDirUrl.endsWith("/")) {
173 srcDirUrl += "/";
174 }
175 final StringTokenizer tok = new StringTokenizer(filesList, ", \t\n\r\f", false);
176 while (tok.hasMoreTokens()) {
177 String nextFile = tok.nextToken();
178
179
180 if (nextFile.endsWith("/**")) {
181 nextFile = nextFile.substring(0, nextFile.length() - 2);
182 }
183
184 final SourceInfo src = new SourceInfo();
185 src.setFile(srcDirUrl + nextFile);
186 addConfiguredSrc(src);
187 }
188 }
189
190 if (srcFiles.isEmpty()) {
191 final String message = Messages.getString("vfs.tasks/sync.no-source-files.warn");
192 logOrDie(message, Project.MSG_WARN);
193 return;
194 }
195
196
197 try {
198 if (destFileUrl != null) {
199 handleSingleFile();
200 } else {
201 handleFiles();
202 }
203 } catch (final BuildException e) {
204 throw e;
205 } catch (final Exception e) {
206 throw new BuildException(e.getMessage(), e);
207 }
208 }
209
210 protected void logOrDie(final String message, final int level) {
211 if (!isFailonerror()) {
212 log(message, level);
213 return;
214 }
215 throw new BuildException(message);
216 }
217
218
219
220
221 private void handleFiles() throws Exception {
222
223 final FileObject destFolder = resolveFile(destDirUrl);
224 destFolder.createFolder();
225
226
227 FileName srcDirName = null;
228 if (srcDirUrl != null) {
229 srcDirName = resolveFile(srcDirUrl).getName();
230 }
231 final ArrayList<FileObject> srcs = new ArrayList<>();
232 for (final SourceInfo src : srcFiles) {
233 final FileObject srcFile = resolveFile(src.file);
234 if (!srcFile.exists()) {
235 final String message = Messages.getString("vfs.tasks/sync.src-file-no-exist.warn", srcFile);
236
237 logOrDie(message, Project.MSG_WARN);
238 } else {
239 srcs.add(srcFile);
240 }
241 }
242
243
244 final Set<FileObject> destFiles = new HashSet<>();
245 for (final FileObject rootFile : srcs) {
246 final FileName rootName = rootFile.getName();
247
248 if (rootFile.isFile()) {
249
250 final String relName;
251 if (srcDirName == null || !srcDirIsBase) {
252 relName = rootName.getBaseName();
253 } else {
254 relName = srcDirName.getRelativeName(rootName);
255 }
256 final FileObject destFile = destFolder.resolveFile(relName, NameScope.DESCENDENT);
257
258
259 handleFile(destFiles, rootFile, destFile);
260 } else {
261
262
263 final FileObject[] files = rootFile
264 .findFiles(srcDirIsBase ? Selectors.SELECT_ALL : Selectors.SELECT_FILES);
265
266 for (final FileObject srcFile : files) {
267
268 final String relName;
269 if (srcDirName == null || !srcDirIsBase) {
270 relName = rootName.getRelativeName(srcFile.getName());
271 } else {
272 relName = srcDirName.getRelativeName(srcFile.getName());
273 }
274
275 final FileObject destFile = destFolder.resolveFile(relName, NameScope.DESCENDENT);
276
277
278 handleFile(destFiles, srcFile, destFile);
279 }
280 }
281 }
282
283
284 if (detectMissingSourceFiles()) {
285 final FileObject[] allDestFiles = destFolder.findFiles(Selectors.SELECT_FILES);
286 for (final FileObject destFile : allDestFiles) {
287 if (!destFiles.contains(destFile)) {
288 handleMissingSourceFile(destFile);
289 }
290 }
291 }
292 }
293
294
295
296
297 private void handleFile(final Set<FileObject> destFiles, final FileObjectect.html#FileObject">FileObject srcFile, final FileObject destFile)
298 throws Exception
299
300 {
301
302 if (destFiles.contains(destFile)) {
303 final String message = Messages.getString("vfs.tasks/sync.duplicate-source-files.warn", destFile);
304 logOrDie(message, Project.MSG_WARN);
305 } else {
306 destFiles.add(destFile);
307 }
308
309
310 handleFile(srcFile, destFile);
311 }
312
313
314
315
316 private void handleSingleFile() throws Exception {
317
318
319 if (srcFiles.size() > 1) {
320 final String message = Messages.getString("vfs.tasks/sync.too-many-source-files.error");
321 logOrDie(message, Project.MSG_WARN);
322 return;
323 }
324 final SourceInfo src = srcFiles.get(0);
325 final FileObject srcFile = resolveFile(src.file);
326 if (!srcFile.isFile()) {
327 final String message = Messages.getString("vfs.tasks/sync.source-not-file.error", srcFile);
328 logOrDie(message, Project.MSG_WARN);
329 return;
330 }
331
332
333 final FileObject destFile = resolveFile(destFileUrl);
334
335
336 handleFile(srcFile, destFile);
337 }
338
339
340
341
342 private void handleFile(final FileObjectect.html#FileObject">FileObject srcFile, final FileObject destFile) throws Exception {
343 if (!FileObjectUtils.exists(destFile)
344 || srcFile.getContent().getLastModifiedTime() > destFile.getContent().getLastModifiedTime()) {
345
346 handleOutOfDateFile(srcFile, destFile);
347 } else {
348
349 handleUpToDateFile(srcFile, destFile);
350 }
351 }
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366 protected void handleOutOfDateFile(final FileObjectect.html#FileObject">FileObject srcFile, final FileObject destFile) throws Exception {
367
368 }
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383 protected void handleUpToDateFile(final FileObjectect.html#FileObject">FileObject srcFile, final FileObject destFile) throws Exception {
384
385 }
386
387
388
389
390
391
392
393
394
395
396 protected void handleMissingSourceFile(final FileObject destFile) throws Exception {
397
398 }
399
400
401
402
403
404
405
406
407
408 protected boolean detectMissingSourceFiles() {
409 return false;
410 }
411
412
413
414
415 public static class SourceInfo {
416 private String file;
417
418 public void setFile(final String file) {
419 this.file = file;
420 }
421 }
422
423 }