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