1 18 19 package org.apache.tools.ant.taskdefs; 20 21 import java.io.File ; 22 import java.io.IOException ; 23 import java.util.Hashtable ; 24 import java.util.Iterator ; 25 import java.util.Vector ; 26 import org.apache.tools.ant.BuildException; 27 import org.apache.tools.ant.DirectoryScanner; 28 import org.apache.tools.ant.Project; 29 import org.apache.tools.ant.types.Commandline; 30 import org.apache.tools.ant.types.AbstractFileSet; 31 import org.apache.tools.ant.types.DirSet; 32 import org.apache.tools.ant.types.EnumeratedAttribute; 33 import org.apache.tools.ant.types.FileList; 34 import org.apache.tools.ant.types.FileSet; 35 import org.apache.tools.ant.types.Mapper; 36 import org.apache.tools.ant.types.Resource; 37 import org.apache.tools.ant.types.ResourceCollection; 38 import org.apache.tools.ant.types.resources.FileResource; 39 import org.apache.tools.ant.types.resources.Union; 40 import org.apache.tools.ant.util.FileNameMapper; 41 import org.apache.tools.ant.util.SourceFileScanner; 42 43 50 public class ExecuteOn extends ExecTask { 51 52 54 61 protected Vector filesets = new Vector (); private Union resources = null; 64 private boolean relative = false; 65 private boolean parallel = false; 66 private boolean forwardSlash = false; 67 protected String type = FileDirBoth.FILE; 68 protected Commandline.Marker srcFilePos = null; 69 private boolean skipEmpty = false; 70 protected Commandline.Marker targetFilePos = null; 71 protected Mapper mapperElement = null; 72 protected FileNameMapper mapper = null; 73 protected File destDir = null; 74 private int maxParallel = -1; 75 private boolean addSourceFile = true; 76 private boolean verbose = false; 77 private boolean ignoreMissing = true; 78 private boolean force = false; 79 80 83 protected boolean srcIsFirst = true; 84 85 90 public void addFileset(FileSet set) { 91 filesets.addElement(set); 92 } 93 94 101 public void addDirset(DirSet set) { 102 filesets.addElement(set); 103 } 104 105 109 public void addFilelist(FileList list) { 110 add(list); 111 } 112 113 118 public void add(ResourceCollection rc) { 119 if (resources == null) { 120 resources = new Union(); 121 } 122 resources.add(rc); 123 } 124 125 132 public void setRelative(boolean relative) { 133 this.relative = relative; 134 } 135 136 137 143 public void setParallel(boolean parallel) { 144 this.parallel = parallel; 145 } 146 147 151 public void setType(FileDirBoth type) { 152 this.type = type.getValue(); 153 } 154 155 161 public void setSkipEmptyFilesets(boolean skip) { 162 skipEmpty = skip; 163 } 164 165 169 public void setDest(File destDir) { 170 this.destDir = destDir; 171 } 172 173 178 public void setForwardslash(boolean forwardSlash) { 179 this.forwardSlash = forwardSlash; 180 } 181 182 193 public void setMaxParallel(int max) { 194 maxParallel = max; 195 } 196 197 206 public void setAddsourcefile(boolean b) { 207 addSourceFile = b; 208 } 209 210 217 public void setVerbose(boolean b) { 218 verbose = b; 219 } 220 221 227 public void setIgnoremissing(boolean b) { 228 ignoreMissing = b; 229 } 230 231 237 public void setForce(boolean b) { 238 force = b; 239 } 240 241 246 public Commandline.Marker createSrcfile() { 247 if (srcFilePos != null) { 248 throw new BuildException(getTaskType() + " doesn\'t support multiple " 249 + "srcfile elements.", getLocation()); 250 } 251 srcFilePos = cmdl.createMarker(); 252 return srcFilePos; 253 } 254 255 260 public Commandline.Marker createTargetfile() { 261 if (targetFilePos != null) { 262 throw new BuildException(getTaskType() + " doesn\'t support multiple " 263 + "targetfile elements.", getLocation()); 264 } 265 targetFilePos = cmdl.createMarker(); 266 srcIsFirst = (srcFilePos != null); 267 return targetFilePos; 268 } 269 270 276 public Mapper createMapper() throws BuildException { 277 if (mapperElement != null) { 278 throw new BuildException("Cannot define more than one mapper", 279 getLocation()); 280 } 281 mapperElement = new Mapper(getProject()); 282 return mapperElement; 283 } 284 285 290 public void add(FileNameMapper fileNameMapper) { 291 createMapper().add(fileNameMapper); 292 } 293 294 297 protected void checkConfiguration() { 298 if ("execon".equals(getTaskName())) { 301 log("!! execon is deprecated. Use apply instead. !!"); 302 } 303 super.checkConfiguration(); 304 if (filesets.size() == 0 && resources == null) { 305 throw new BuildException("no resources specified", 306 getLocation()); 307 } 308 if (targetFilePos != null && mapperElement == null) { 309 throw new BuildException("targetfile specified without mapper", 310 getLocation()); 311 } 312 if (destDir != null && mapperElement == null) { 313 throw new BuildException("dest specified without mapper", 314 getLocation()); 315 } 316 if (mapperElement != null) { 317 mapper = mapperElement.getImplementation(); 318 } 319 } 320 321 327 protected ExecuteStreamHandler createHandler() throws BuildException { 328 return (redirectorElement == null) 330 ? super.createHandler() : new PumpStreamHandler(); 331 } 332 333 336 protected void setupRedirector() { 337 super.setupRedirector(); 338 redirector.setAppendProperties(true); 339 } 340 341 346 protected void runExec(Execute exe) throws BuildException { 347 int totalFiles = 0; 348 int totalDirs = 0; 349 boolean haveExecuted = false; 350 try { 351 Vector fileNames = new Vector (); 352 Vector baseDirs = new Vector (); 353 for (int i = 0; i < filesets.size(); i++) { 354 String currentType = type; 355 AbstractFileSet fs = (AbstractFileSet) filesets.elementAt(i); 356 if (fs instanceof DirSet) { 357 if (!FileDirBoth.DIR.equals(type)) { 358 log("Found a nested dirset but type is " + type + ". " 359 + "Temporarily switching to type=\"dir\" on the" 360 + " assumption that you really did mean" 361 + " <dirset> not <fileset>.", Project.MSG_DEBUG); 362 currentType = FileDirBoth.DIR; 363 } 364 } 365 File base = fs.getDir(getProject()); 366 367 DirectoryScanner ds = fs.getDirectoryScanner(getProject()); 368 369 if (!FileDirBoth.DIR.equals(currentType)) { 370 String [] s = getFiles(base, ds); 371 for (int j = 0; j < s.length; j++) { 372 totalFiles++; 373 fileNames.addElement(s[j]); 374 baseDirs.addElement(base); 375 } 376 } 377 if (!FileDirBoth.FILE.equals(currentType)) { 378 String [] s = getDirs(base, ds); 379 for (int j = 0; j < s.length; j++) { 380 totalDirs++; 381 fileNames.addElement(s[j]); 382 baseDirs.addElement(base); 383 } 384 } 385 if (fileNames.size() == 0 && skipEmpty) { 386 int includedCount 387 = ((!FileDirBoth.DIR.equals(currentType)) 388 ? ds.getIncludedFilesCount() : 0) 389 + ((!FileDirBoth.FILE.equals(currentType)) 390 ? ds.getIncludedDirsCount() : 0); 391 392 log("Skipping fileset for directory " + base + ". It is " 393 + ((includedCount > 0) ? "up to date." : "empty."), 394 Project.MSG_INFO); 395 continue; 396 } 397 if (!parallel) { 398 String [] s = new String [fileNames.size()]; 399 fileNames.copyInto(s); 400 for (int j = 0; j < s.length; j++) { 401 String [] command = getCommandline(s[j], base); 402 log(Commandline.describeCommand(command), 403 Project.MSG_VERBOSE); 404 exe.setCommandline(command); 405 406 if (redirectorElement != null) { 407 setupRedirector(); 408 redirectorElement.configure(redirector, s[j]); 409 } 410 if (redirectorElement != null || haveExecuted) { 411 exe.setStreamHandler(redirector.createHandler()); 415 } 416 runExecute(exe); 417 haveExecuted = true; 418 } 419 fileNames.removeAllElements(); 420 baseDirs.removeAllElements(); 421 } 422 } 423 424 if (resources != null) { 425 Iterator iter = resources.iterator(); 426 while (iter.hasNext()) { 427 Resource res = (Resource) iter.next(); 428 429 if (!res.isExists() && ignoreMissing) { 430 continue; 431 } 432 433 File base = null; 434 String name = res.getName(); 435 if (res instanceof FileResource) { 436 FileResource fr = (FileResource) res; 437 base = fr.getBaseDir(); 438 if (base == null) { 439 name = fr.getFile().getAbsolutePath(); 440 } 441 } 442 443 if (restrict(new String [] {name}, base).length == 0) { 444 continue; 445 } 446 447 if ((!res.isDirectory() || !res.isExists()) 448 && !FileDirBoth.DIR.equals(type)) { 449 totalFiles++; 450 } else if (res.isDirectory() 451 && !FileDirBoth.FILE.equals(type)) { 452 totalDirs++; 453 } else { 454 continue; 455 } 456 457 baseDirs.add(base); 458 fileNames.add(name); 459 460 if (!parallel) { 461 String [] command = getCommandline(name, base); 462 log(Commandline.describeCommand(command), 463 Project.MSG_VERBOSE); 464 exe.setCommandline(command); 465 466 if (redirectorElement != null) { 467 setupRedirector(); 468 redirectorElement.configure(redirector, name); 469 } 470 if (redirectorElement != null || haveExecuted) { 471 exe.setStreamHandler(redirector.createHandler()); 475 } 476 runExecute(exe); 477 haveExecuted = true; 478 fileNames.removeAllElements(); 479 baseDirs.removeAllElements(); 480 } 481 } 482 } 483 if (parallel && (fileNames.size() > 0 || !skipEmpty)) { 484 runParallel(exe, fileNames, baseDirs); 485 haveExecuted = true; 486 } 487 if (haveExecuted) { 488 log("Applied " + cmdl.getExecutable() + " to " 489 + totalFiles + " file" 490 + (totalFiles != 1 ? "s" : "") + " and " 491 + totalDirs + " director" 492 + (totalDirs != 1 ? "ies" : "y") + ".", 493 verbose ? Project.MSG_INFO : Project.MSG_VERBOSE); 494 } 495 } catch (IOException e) { 496 throw new BuildException("Execute failed: " + e, e, getLocation()); 497 } finally { 498 logFlush(); 500 redirector.setAppendProperties(false); 501 redirector.setProperties(); 502 } 503 } 504 505 512 protected String [] getCommandline(String [] srcFiles, File [] baseDirs) { 513 final char fileSeparator = File.separatorChar; 514 Vector targets = new Vector (); 515 if (targetFilePos != null) { 516 Hashtable addedFiles = new Hashtable (); 517 for (int i = 0; i < srcFiles.length; i++) { 518 String [] subTargets = mapper.mapFileName(srcFiles[i]); 519 if (subTargets != null) { 520 for (int j = 0; j < subTargets.length; j++) { 521 String name = null; 522 if (!relative) { 523 name = (new File (destDir, subTargets[j])).getAbsolutePath(); 524 } else { 525 name = subTargets[j]; 526 } 527 if (forwardSlash && fileSeparator != '/') { 528 name = name.replace(fileSeparator, '/'); 529 } 530 if (!addedFiles.contains(name)) { 531 targets.addElement(name); 532 addedFiles.put(name, name); 533 } 534 } 535 } 536 } 537 } 538 String [] targetFiles = new String [targets.size()]; 539 targets.copyInto(targetFiles); 540 541 if (!addSourceFile) { 542 srcFiles = new String [0]; 543 } 544 String [] orig = cmdl.getCommandline(); 545 String [] result 546 = new String [orig.length + srcFiles.length + targetFiles.length]; 547 548 int srcIndex = orig.length; 549 if (srcFilePos != null) { 550 srcIndex = srcFilePos.getPosition(); 551 } 552 if (targetFilePos != null) { 553 int targetIndex = targetFilePos.getPosition(); 554 555 if (srcIndex < targetIndex 556 || (srcIndex == targetIndex && srcIsFirst)) { 557 558 System.arraycopy(orig, 0, result, 0, srcIndex); 560 561 System.arraycopy(orig, srcIndex, result, 563 srcIndex + srcFiles.length, 564 targetIndex - srcIndex); 565 566 System.arraycopy(targetFiles, 0, result, 568 targetIndex + srcFiles.length, 569 targetFiles.length); 570 571 System.arraycopy(orig, targetIndex, result, 573 targetIndex + srcFiles.length + targetFiles.length, 574 orig.length - targetIndex); 575 } else { 576 System.arraycopy(orig, 0, result, 0, targetIndex); 578 579 System.arraycopy(targetFiles, 0, result, 581 targetIndex, 582 targetFiles.length); 583 584 System.arraycopy(orig, targetIndex, result, 586 targetIndex + targetFiles.length, 587 srcIndex - targetIndex); 588 589 System.arraycopy(orig, srcIndex, result, 591 srcIndex + srcFiles.length + targetFiles.length, 592 orig.length - srcIndex); 593 srcIndex += targetFiles.length; 594 } 595 596 } else { 598 System.arraycopy(orig, 0, result, 0, srcIndex); 600 System.arraycopy(orig, srcIndex, result, 602 srcIndex + srcFiles.length, 603 orig.length - srcIndex); 604 } 605 for (int i = 0; i < srcFiles.length; i++) { 607 if (!relative) { 608 result[srcIndex + i] = 609 (new File (baseDirs[i], srcFiles[i])).getAbsolutePath(); 610 } else { 611 result[srcIndex + i] = srcFiles[i]; 612 } 613 if (forwardSlash && fileSeparator != '/') { 614 result[srcIndex + i] = 615 result[srcIndex + i].replace(fileSeparator, '/'); 616 } 617 } 618 return result; 619 } 620 621 628 protected String [] getCommandline(String srcFile, File baseDir) { 629 return getCommandline(new String [] {srcFile}, new File [] {baseDir}); 630 } 631 632 639 protected String [] getFiles(File baseDir, DirectoryScanner ds) { 640 return restrict(ds.getIncludedFiles(), baseDir); 641 } 642 643 650 protected String [] getDirs(File baseDir, DirectoryScanner ds) { 651 return restrict(ds.getIncludedDirectories(), baseDir); 652 } 653 654 662 protected String [] getFilesAndDirs(FileList list) { 663 return restrict(list.getFiles(getProject()), list.getDir(getProject())); 664 } 665 666 private String [] restrict(String [] s, File baseDir) { 667 return (mapper == null || force) ? s 668 : new SourceFileScanner(this).restrict(s, baseDir, destDir, mapper); 669 } 670 671 681 protected void runParallel(Execute exe, Vector fileNames, 682 Vector baseDirs) 683 throws IOException , BuildException { 684 String [] s = new String [fileNames.size()]; 685 fileNames.copyInto(s); 686 File [] b = new File [baseDirs.size()]; 687 baseDirs.copyInto(b); 688 689 if (maxParallel <= 0 690 || s.length == 0 ) { 691 String [] command = getCommandline(s, b); 692 log(Commandline.describeCommand(command), Project.MSG_VERBOSE); 693 exe.setCommandline(command); 694 runExecute(exe); 695 } else { 696 int stillToDo = fileNames.size(); 697 int currentOffset = 0; 698 while (stillToDo > 0) { 699 int currentAmount = Math.min(stillToDo, maxParallel); 700 String [] cs = new String [currentAmount]; 701 System.arraycopy(s, currentOffset, cs, 0, currentAmount); 702 File [] cb = new File [currentAmount]; 703 System.arraycopy(b, currentOffset, cb, 0, currentAmount); 704 String [] command = getCommandline(cs, cb); 705 log(Commandline.describeCommand(command), Project.MSG_VERBOSE); 706 exe.setCommandline(command); 707 if (redirectorElement != null) { 708 setupRedirector(); 709 redirectorElement.configure(redirector, null); 710 } 711 if (redirectorElement != null || currentOffset > 0) { 712 exe.setStreamHandler(redirector.createHandler()); 716 } 717 runExecute(exe); 718 719 stillToDo -= currentAmount; 720 currentOffset += currentAmount; 721 } 722 } 723 } 724 725 729 public static class FileDirBoth extends EnumeratedAttribute { 730 731 public static final String FILE = "file"; 732 733 public static final String DIR = "dir"; 734 737 738 public String [] getValues() { 739 return new String [] {FILE, DIR, "both"}; 740 } 741 } 742 } 743 | Popular Tags |