1 18 19 package org.apache.tools.ant.taskdefs; 20 21 import java.io.File ; 22 23 import java.util.HashSet ; 24 import java.util.Iterator ; 25 import java.util.Map ; 26 import java.util.Set ; 27 28 import org.apache.tools.ant.BuildException; 29 import org.apache.tools.ant.DirectoryScanner; 30 import org.apache.tools.ant.Project; 31 import org.apache.tools.ant.Task; 32 import org.apache.tools.ant.types.AbstractFileSet; 33 import org.apache.tools.ant.types.FileSet; 34 import org.apache.tools.ant.types.PatternSet; 35 import org.apache.tools.ant.types.Resource; 36 import org.apache.tools.ant.types.ResourceCollection; 37 import org.apache.tools.ant.types.selectors.FileSelector; 38 import org.apache.tools.ant.types.selectors.NoneSelector; 39 40 55 public class Sync extends Task { 56 57 private MyCopy myCopy; 59 60 private SyncTarget syncTarget; 62 63 69 public void init() 70 throws BuildException { 71 myCopy = new MyCopy(); 73 configureTask(myCopy); 74 75 myCopy.setFiltering(false); 77 myCopy.setIncludeEmptyDirs(false); 78 myCopy.setPreserveLastModified(true); 79 } 80 81 private void configureTask(Task helper) { 82 helper.setProject(getProject()); 83 helper.setTaskName(getTaskName()); 84 helper.setOwningTarget(getOwningTarget()); 85 helper.init(); 86 } 87 88 94 public void execute() 95 throws BuildException { 96 File toDir = myCopy.getToDir(); 98 99 Set allFiles = myCopy.nonOrphans; 101 102 boolean noRemovalNecessary = !toDir.exists() || toDir.list().length < 1; 105 106 log("PASS#1: Copying files to " + toDir, Project.MSG_DEBUG); 108 myCopy.execute(); 109 110 if (noRemovalNecessary) { 112 log("NO removing necessary in " + toDir, Project.MSG_DEBUG); 113 return; } 115 116 log("PASS#2: Removing orphan files from " + toDir, Project.MSG_DEBUG); 118 int[] removedFileCount = removeOrphanFiles(allFiles, toDir); 119 logRemovedCount(removedFileCount[0], "dangling director", "y", "ies"); 120 logRemovedCount(removedFileCount[1], "dangling file", "", "s"); 121 122 if (!myCopy.getIncludeEmptyDirs()) { 124 log("PASS#3: Removing empty directories from " + toDir, 125 Project.MSG_DEBUG); 126 int removedDirCount = removeEmptyDirectories(toDir, false); 127 logRemovedCount(removedDirCount, "empty director", "y", "ies"); 128 } 129 } 130 131 private void logRemovedCount(int count, String prefix, 132 String singularSuffix, String pluralSuffix) { 133 File toDir = myCopy.getToDir(); 134 135 String what = (prefix == null) ? "" : prefix; 136 what += (count < 2) ? singularSuffix : pluralSuffix; 137 138 if (count > 0) { 139 log("Removed " + count + " " + what + " from " + toDir, 140 Project.MSG_INFO); 141 } else { 142 log("NO " + what + " to remove from " + toDir, 143 Project.MSG_VERBOSE); 144 } 145 } 146 147 162 private int[] removeOrphanFiles(Set nonOrphans, File toDir) { 163 int[] removedCount = new int[] {0, 0}; 164 String [] excls = 165 (String []) nonOrphans.toArray(new String [nonOrphans.size() + 1]); 166 excls[nonOrphans.size()] = ""; 168 169 DirectoryScanner ds = null; 170 if (syncTarget != null) { 171 FileSet fs = new FileSet(); 172 fs.setDir(toDir); 173 fs.setCaseSensitive(syncTarget.isCaseSensitive()); 174 fs.setFollowSymlinks(syncTarget.isFollowSymlinks()); 175 176 PatternSet ps = syncTarget.mergePatterns(getProject()); 180 fs.appendExcludes(ps.getIncludePatterns(getProject())); 181 fs.appendIncludes(ps.getExcludePatterns(getProject())); 182 fs.setDefaultexcludes(!syncTarget.getDefaultexcludes()); 183 184 FileSelector[] s = syncTarget.getSelectors(getProject()); 188 if (s.length > 0) { 189 NoneSelector ns = new NoneSelector(); 190 for (int i = 0; i < s.length; i++) { 191 ns.appendSelector(s[i]); 192 } 193 fs.appendSelector(ns); 194 } 195 ds = fs.getDirectoryScanner(getProject()); 196 } else { 197 ds = new DirectoryScanner(); 198 ds.setBasedir(toDir); 199 } 200 ds.addExcludes(excls); 201 202 ds.scan(); 203 String [] files = ds.getIncludedFiles(); 204 for (int i = 0; i < files.length; i++) { 205 File f = new File (toDir, files[i]); 206 log("Removing orphan file: " + f, Project.MSG_DEBUG); 207 f.delete(); 208 ++removedCount[1]; 209 } 210 String [] dirs = ds.getIncludedDirectories(); 211 for (int i = dirs.length - 1; i >= 0; --i) { 217 File f = new File (toDir, dirs[i]); 218 if (f.list().length < 1) { 219 log("Removing orphan directory: " + f, Project.MSG_DEBUG); 220 f.delete(); 221 ++removedCount[0]; 222 } 223 } 224 return removedCount; 225 } 226 227 243 private int removeEmptyDirectories(File dir, boolean removeIfEmpty) { 244 int removedCount = 0; 245 if (dir.isDirectory()) { 246 File [] children = dir.listFiles(); 247 for (int i = 0; i < children.length; ++i) { 248 File file = children[i]; 249 if (file.isDirectory()) { 251 removedCount += removeEmptyDirectories(file, true); 252 } 253 } 254 if (children.length > 0) { 255 children = dir.listFiles(); 258 } 259 if (children.length < 1 && removeIfEmpty) { 260 log("Removing empty directory: " + dir, Project.MSG_DEBUG); 261 dir.delete(); 262 ++removedCount; 263 } 264 } 265 return removedCount; 266 } 267 268 269 273 277 public void setTodir(File destDir) { 278 myCopy.setTodir(destDir); 279 } 280 281 285 public void setVerbose(boolean verbose) { 286 myCopy.setVerbose(verbose); 287 } 288 289 293 public void setOverwrite(boolean overwrite) { 294 myCopy.setOverwrite(overwrite); 295 } 296 297 301 public void setIncludeEmptyDirs(boolean includeEmpty) { 302 myCopy.setIncludeEmptyDirs(includeEmpty); 303 } 304 305 309 public void setFailOnError(boolean failonerror) { 310 myCopy.setFailOnError(failonerror); 311 } 312 313 317 public void addFileset(FileSet set) { 318 add(set); 319 } 320 321 326 public void add(ResourceCollection rc) { 327 myCopy.add(rc); 328 } 329 330 338 public void setGranularity(long granularity) { 339 myCopy.setGranularity(granularity); 340 } 341 342 351 public void addPreserveInTarget(SyncTarget s) { 352 if (syncTarget != null) { 353 throw new BuildException("you must not specify multiple " 354 + "preserveintarget elements."); 355 } 356 syncTarget = s; 357 } 358 359 362 public static class MyCopy extends Copy { 363 364 private Set nonOrphans = new HashSet (); 367 368 369 public MyCopy() { 370 } 371 372 375 376 protected void scan(File fromDir, File toDir, String [] files, 377 String [] dirs) { 378 assertTrue("No mapper", mapperElement == null); 379 380 super.scan(fromDir, toDir, files, dirs); 381 382 for (int i = 0; i < files.length; ++i) { 383 nonOrphans.add(files[i]); 384 } 385 for (int i = 0; i < dirs.length; ++i) { 386 nonOrphans.add(dirs[i]); 387 } 388 } 389 390 393 394 protected Map scan(Resource[] resources, File toDir) { 395 assertTrue("No mapper", mapperElement == null); 396 397 Map m = super.scan(resources, toDir); 398 399 Iterator iter = m.keySet().iterator(); 400 while (iter.hasNext()) { 401 nonOrphans.add(((Resource) iter.next()).getName()); 402 } 403 return m; 404 } 405 406 410 public File getToDir() { 411 return destDir; 412 } 413 414 418 public boolean getIncludeEmptyDirs() { 419 return includeEmpty; 420 } 421 422 427 protected boolean supportsNonFileResources() { 428 return true; 429 } 430 } 431 432 439 public static class SyncTarget extends AbstractFileSet { 440 441 446 public SyncTarget() { 447 super(); 448 } 449 450 456 public void setDir(File dir) throws BuildException { 457 throw new BuildException("preserveintarget doesn't support the dir " 458 + "attribute"); 459 } 460 461 } 462 463 466 private static void assertTrue(String message, boolean condition) { 467 if (!condition) { 468 throw new BuildException("Assertion Error: " + message); 469 } 470 } 471 472 } 473 | Popular Tags |