1 29 30 package com.caucho.server.deploy; 31 32 import com.caucho.config.ConfigException; 33 import com.caucho.config.types.FileSetType; 34 import com.caucho.config.types.Period; 35 import com.caucho.loader.Environment; 36 import com.caucho.log.Log; 37 import com.caucho.util.Alarm; 38 import com.caucho.util.AlarmListener; 39 import com.caucho.util.L10N; 40 import com.caucho.util.WeakAlarm; 41 import com.caucho.vfs.Path; 42 43 import java.io.IOException ; 44 import java.util.ArrayList ; 45 import java.util.Set ; 46 import java.util.TreeSet ; 47 import java.util.logging.Level ; 48 import java.util.logging.Logger ; 49 50 53 abstract public class ExpandDeployGenerator<E extends ExpandDeployController> 54 extends DeployGenerator<E> 55 implements AlarmListener 56 { 57 private static final Logger log = Log.open(ExpandDeployGenerator.class); 58 private static final L10N L = new L10N(ExpandDeployGenerator.class); 59 60 private static final long MIN_CRON_INTERVAL = 5000L; 61 62 private Path _path; 64 private Path _containerRootDirectory; 65 private Path _archiveDirectory; 66 private Path _expandDirectory; 67 68 private String _extension = ".jar"; 69 70 private String _expandPrefix = ""; 71 private String _expandSuffix = ""; 72 73 private ArrayList <String > _requireFiles = new ArrayList <String >(); 74 75 private TreeSet <String > _controllerNames = new TreeSet <String >(); 76 77 private FileSetType _expandCleanupFileSet; 78 79 private Alarm _alarm; 80 private long _cronInterval; 81 82 private volatile long _lastCheckTime; 83 private volatile boolean _isChecking; 84 private long _checkInterval = 1000L; 85 private long _digest; 86 private volatile boolean _isModified; 87 private volatile boolean _isDeploying; 88 89 92 public ExpandDeployGenerator(DeployContainer<E> container, Path containerRootDirectory) 93 { 94 super(container); 95 96 _containerRootDirectory = containerRootDirectory; 97 98 _alarm = new WeakAlarm(this); 99 100 _cronInterval = Environment.getDependencyCheckInterval(); 101 if (_cronInterval < MIN_CRON_INTERVAL) 102 _cronInterval = MIN_CRON_INTERVAL; 103 } 104 105 Path getContainerRootDirectory() 106 { 107 return _containerRootDirectory; 108 } 109 110 113 public Path getPath() 114 { 115 return _path; 116 } 117 118 121 public void setPath(Path path) 122 { 123 _path = path; 124 } 125 126 129 public void setExpandPath(Path path) 130 { 131 log.config("Use <expand-directory> instead of <expand-path>. <expand-path> is deprecated."); 132 133 setExpandDirectory(path); 134 } 135 136 139 public void setExpandDirectory(Path path) 140 { 141 _expandDirectory = path; 142 } 143 144 147 public Path getExpandDirectory() 148 { 149 if (_expandDirectory != null) 150 return _expandDirectory; 151 else 152 return _path; 153 } 154 155 161 public Path getExpandPath(String name) 162 { 163 if (!isDeployedKey(nameToEntryName(name))) 164 return null; 165 166 return getExpandDirectory().lookup(getExpandName(name)); 167 } 168 169 175 protected String getExpandName(String name) 176 { 177 return getExpandPrefix() + name + getExpandSuffix(); 178 } 179 180 183 public void setArchiveDirectory(Path path) 184 { 185 _archiveDirectory = path; 186 } 187 188 191 public Path getArchiveDirectory() 192 { 193 if (_archiveDirectory != null) 194 return _archiveDirectory; 195 else 196 return _path; 197 } 198 199 204 public Path getArchivePath(String name) 205 { 206 return getArchiveDirectory().lookup(name + getExtension()); 207 } 208 209 212 public void setDependencyCheckInterval(Period period) 213 { 214 _cronInterval = period.getPeriod(); 215 216 if (_cronInterval < 0) 217 _cronInterval = Period.INFINITE; 218 else if (_cronInterval < MIN_CRON_INTERVAL) 219 _cronInterval = MIN_CRON_INTERVAL; 220 } 221 222 public long getDependencyCheckInterval() 223 { 224 return _cronInterval; 225 } 226 227 230 public void setExpandCleanupFileset(FileSetType fileSet) 231 { 232 _expandCleanupFileSet = fileSet; 233 } 234 235 238 public void setExtension(String extension) 239 throws ConfigException 240 { 241 if (! extension.startsWith(".")) 242 throw new ConfigException(L.l("deployment extension '{0}' must begin with '.'", 243 extension)); 244 245 _extension = extension; 246 } 247 248 251 public String getExtension() 252 { 253 return _extension; 254 } 255 256 259 public void setExpandPrefix(String prefix) 260 throws ConfigException 261 { 262 if (! prefix.equals("") && 263 ! prefix.startsWith("_") && 264 ! prefix.startsWith(".")) 265 throw new ConfigException(L.l("expand-prefix '{0}' must start with '.' or '_'.", 266 prefix)); 267 268 _expandPrefix = prefix; 269 } 270 271 274 public String getExpandPrefix() 275 { 276 return _expandPrefix; 277 } 278 279 282 public void setExpandSuffix(String suffix) 283 throws ConfigException 284 { 285 _expandSuffix = suffix; 286 } 287 288 291 public String getExpandSuffix() 292 { 293 return _expandSuffix; 294 } 295 296 299 public void addRequireFile(String file) 300 throws ConfigException 301 { 302 _requireFiles.add(file); 303 } 304 305 308 protected Logger getLog() 309 { 310 return log; 311 } 312 313 316 public boolean isModified() 317 { 318 synchronized (this) { 319 long now = Alarm.getCurrentTime(); 320 321 if (now < _lastCheckTime + _checkInterval || _isChecking) { 322 return _isModified; 323 } 324 325 _isChecking = true; 326 _lastCheckTime = Alarm.getCurrentTime(); 327 } 328 329 try { 330 long digest = getDigest(); 331 332 _isModified = _digest != digest; 333 334 return _isModified; 335 } catch (Exception e) { 336 log.log(Level.FINE, e.toString(), e); 337 338 return false; 339 } finally { 340 _isChecking = false; 341 } 342 } 343 344 347 @Override 348 protected void initImpl() 349 throws ConfigException 350 { 351 super.initImpl(); 352 353 if (getExpandDirectory() == null) 354 throw new ConfigException(L.l("<expand-directory> must be specified for deployment of archive expansion.")); 355 356 if (getArchiveDirectory() == null) 357 throw new ConfigException(L.l("<archive-directory> must be specified for deployment of archive expansion.")); 358 } 359 360 363 @Override 364 protected void startImpl() 365 { 366 super.startImpl(); 367 368 handleAlarm(_alarm); 369 } 370 371 374 protected void fillDeployedKeys(Set <String > keys) 375 { 376 if (isModified()) { 377 try { 378 deploy(); 379 } catch (Throwable e) { 380 log.log(Level.WARNING, e.toString(), e); 381 } 382 } 383 384 for (String name : _controllerNames) { 385 keys.add(name); 386 } 387 } 388 389 392 protected boolean isDeployedKey(String key) 393 { 394 return _controllerNames.contains(key); 395 } 396 397 400 public void update() 401 { 402 _lastCheckTime = 0; 404 405 request(); 406 } 407 408 409 412 public void request() 413 { 414 if (isModified()) { 415 try { 416 deploy(); 417 } catch (Throwable e) { 418 log.log(Level.WARNING, e.toString(), e); 419 } 420 } 421 } 422 423 426 private void deploy() 427 throws Exception 428 { 429 boolean isDeploying = false; 430 431 log.finer(this + " redeploy " + _isDeploying); 432 433 try { 434 ArrayList <String > updatedNames = null; 435 436 synchronized (this) { 437 if (_isDeploying) 438 return; 439 else { 440 _isDeploying = true; 441 isDeploying = true; 442 } 443 444 TreeSet <String > entryNames = findEntryNames(); 445 446 _digest = getDigest(); 447 448 if (! _controllerNames.equals(entryNames)) { 449 updatedNames = new ArrayList <String >(); 450 451 for (String name : _controllerNames) { 452 if (! entryNames.contains(name)) 453 updatedNames.add(name); 454 } 455 456 for (String name : entryNames) { 457 if (! _controllerNames.contains(name)) 458 updatedNames.add(name); 459 } 460 461 _controllerNames = entryNames; 462 } 463 } 464 465 for (int i = 0; updatedNames != null && i < updatedNames.size(); i++) { 466 String name = updatedNames.get(i); 467 468 getDeployContainer().update(name); 469 } 470 } finally { 471 if (isDeploying) { 472 _isModified = false; 473 _isDeploying = false; 474 } 475 } 476 } 477 478 481 public E generateController(String name) 482 { 483 request(); 484 485 Thread thread = Thread.currentThread(); 486 ClassLoader oldLoader = thread.getContextClassLoader(); 487 try { 488 thread.setContextClassLoader(getParentClassLoader()); 489 490 E controller = createController(name); 491 492 if (controller != null) { 493 controller.setExpandCleanupFileSet(_expandCleanupFileSet); 494 495 _controllerNames.add(name); } 497 498 return controller; 499 } finally { 500 thread.setContextClassLoader(oldLoader); 501 } 502 } 503 504 507 private long getDigest() 508 { 509 long archiveDigest = 0; 510 511 Path archiveDirectory = getArchiveDirectory(); 512 if (archiveDirectory != null) 513 archiveDigest = archiveDirectory.getCrc64(); 514 515 long expandDigest = 0; 516 517 Path expandDirectory = getExpandDirectory(); 518 if (expandDirectory != null) 519 expandDigest = expandDirectory.getCrc64(); 520 521 return archiveDigest * 65521 + expandDigest; 522 } 523 524 527 private TreeSet <String > findEntryNames() 528 throws IOException 529 { 530 TreeSet <String > entryNames = new TreeSet <String >(); 531 532 Path archiveDirectory = getArchiveDirectory(); 533 Path expandDirectory = getExpandDirectory(); 534 535 if (archiveDirectory == null || expandDirectory == null) 536 return entryNames; 537 538 String []entryList = archiveDirectory.list(); 539 540 loop: 542 for (int i = 0; i < entryList.length; i++) { 543 String archiveName = entryList[i]; 544 545 Path archivePath = archiveDirectory.lookup(archiveName); 546 547 String entryName = null; 548 549 if (! archivePath.canRead()) 550 continue; 551 else 552 entryName = archiveNameToEntryName(archiveName); 553 554 if (entryName != null) 555 entryNames.add(entryName); 556 } 557 558 String []entryExpandList = expandDirectory.list(); 559 560 loop: 562 for (int i = 0; i < entryExpandList.length; i++) { 563 String pathName = entryExpandList[i]; 564 565 569 570 Path rootDirectory = expandDirectory.lookup(pathName); 571 572 String entryName = pathNameToEntryName(pathName); 573 574 if (entryName == null) 575 continue; 576 else if (entryName.endsWith(getExtension())) 577 continue; 578 579 if (! isValidDirectory(rootDirectory, pathName)) 580 continue; 581 582 if (! entryNames.contains(entryName)) 583 entryNames.add(entryName); 584 } 585 586 return entryNames; 587 } 588 589 protected boolean isValidDirectory(Path rootDirectory, String pathName) 590 { 591 592 if (! rootDirectory.isDirectory() || pathName.startsWith(".")) { 593 return false; 594 } 595 596 if (pathName.equalsIgnoreCase("web-inf") || 597 pathName.equalsIgnoreCase("meta-inf")) 598 return false; 599 600 for (int j = 0; j < _requireFiles.size(); j++) { 601 String file = _requireFiles.get(j); 602 603 if (! rootDirectory.lookup(file).canRead()) 604 return false; 605 } 606 607 return true; 608 } 609 610 614 protected String pathNameToEntryName(String name) 615 { 616 if (_expandPrefix == null) { 617 } 618 else if (_expandPrefix.equals("") && 619 (name.startsWith("_") || 620 name.startsWith(".") || 621 name.equalsIgnoreCase("META-INF") || 622 name.equalsIgnoreCase("WEB-INF"))) { 623 return null; 624 } 625 else if (name.startsWith(_expandPrefix)) { 626 name = name.substring(_expandPrefix.length()); 627 } 628 else 629 return null; 630 631 if (_expandSuffix == null) 632 return name; 633 else if (name.endsWith(_expandSuffix)) 634 return name.substring(0, name.length() - _expandSuffix.length()); 635 else 636 return null; 637 } 638 639 643 protected String entryNameToArchiveName(String entryName) 644 { 645 return entryName + getExtension(); 646 } 647 648 652 protected String archiveNameToEntryName(String archiveName) 653 { 654 if (! archiveName.endsWith(_extension)) 655 return null; 656 else { 657 int sublen = archiveName.length() - _extension.length(); 658 return pathNameToEntryName(archiveName.substring(0, sublen)); 659 } 660 } 661 662 665 abstract protected E createController(String name); 666 667 private String nameToEntryName(String name) 668 { 669 return archiveNameToEntryName(name + getExtension()); 670 } 671 672 private String entryNameToName(String name) 673 { 674 String archiveName = entryNameToArchiveName(name); 675 676 if (archiveName == null) 677 return null; 678 else 679 return archiveName.substring(0, archiveName.length() - getExtension().length()); 680 } 681 682 public String [] getNames() 683 { 684 String [] names = new String [_controllerNames.size()]; 685 686 int i = 0; 687 688 for (String controllerName : _controllerNames) { 689 names[i++] = entryNameToName(controllerName); 690 } 691 692 return names; 693 } 694 695 private String getNamesAsString() 696 { 697 StringBuilder builder = new StringBuilder (); 698 699 for (String name : getNames()) { 700 if (builder.length() > 0) 701 builder.append(", "); 702 703 builder.append(name); 704 } 705 706 builder.insert(0, '['); 707 builder.append(']'); 708 709 return builder.toString(); 710 } 711 712 715 public boolean start(String name) 716 { 717 DeployController controller = getDeployContainer().findController(nameToEntryName(name)); 718 719 if (controller == null) { 720 if (log.isLoggable(Level.FINE)) 721 log.log(Level.FINE, L.l("unknown name `{0}'", name)); 722 723 if (log.isLoggable(Level.FINER)) 724 log.log(Level.FINER, L.l("known names are {0}", getNamesAsString())); 725 726 return false; 727 } 728 729 controller.start(); 730 return true; 731 } 732 733 736 public Throwable getConfigException(String name) 737 { 738 DeployController controller = getDeployContainer().findController(nameToEntryName(name)); 739 740 if (controller == null) { 741 if (log.isLoggable(Level.FINE)) 742 log.log(Level.FINE, L.l("unknown name `{0}'", name)); 743 744 if (log.isLoggable(Level.FINER)) 745 log.log(Level.FINER, L.l("known names are {0}", getNamesAsString())); 746 747 return new ConfigException(L.l("unknown name `{0}'", name)); 748 } 749 750 return controller.getConfigException(); 751 } 752 755 public boolean stop(String name) 756 { 757 DeployController controller = getDeployContainer().findController(nameToEntryName(name)); 758 759 if (controller == null) { 760 if (log.isLoggable(Level.FINE)) 761 log.log(Level.FINE, L.l("unknown name `{0}'", name)); 762 763 if (log.isLoggable(Level.FINER)) 764 log.log(Level.FINER, L.l("known names are {0}", getNamesAsString())); 765 766 return false; 767 } 768 769 controller.stop(); 770 return true; 771 } 772 773 776 public boolean undeploy(String name) 777 { 778 DeployController controller = getDeployContainer().findController(nameToEntryName(name)); 779 780 if (controller == null) { 781 if (log.isLoggable(Level.FINE)) 782 log.log(Level.FINE, L.l("unknown name `{0}'", name)); 783 784 if (log.isLoggable(Level.FINER)) 785 log.log(Level.FINER, L.l("known names are {0}", getNamesAsString())); 786 787 return false; 788 } 789 790 Path archivePath = getArchivePath(name); 791 Path expandPath = getExpandPath(name); 792 793 controller.stop(); 794 795 try { 796 if (log.isLoggable(Level.FINEST)) 797 log.log(Level.FINEST, L.l("deleting {0}", archivePath)); 798 799 archivePath.removeAll(); 800 } 801 catch (IOException ex) { 802 if (log.isLoggable(Level.FINE)) 803 log.log(Level.FINE, ex.toString(), ex); 804 } 805 806 try { 807 if (expandPath != null) { 808 if (log.isLoggable(Level.FINEST)) 809 log.log(Level.FINEST, L.l("deleting {0}", expandPath)); 810 811 expandPath.removeAll(); 812 } 813 } 814 catch (IOException ex) { 815 if (log.isLoggable(Level.FINE)) 816 log.log(Level.FINE, ex.toString(), ex); 817 } 818 819 getDeployContainer().update(nameToEntryName(name)); 820 821 return true; 822 } 823 824 825 828 public void handleAlarm(Alarm alarm) 829 { 830 if (! isActive()) 831 return; 832 833 try { 834 request(); 835 } catch (Exception e) { 836 log.log(Level.WARNING, e.toString(), e); 837 } finally { 838 _alarm.queue(_cronInterval); 839 } 840 } 841 842 845 @Override 846 protected void stopImpl() 847 { 848 _alarm.dequeue(); 849 850 super.stopImpl(); 851 } 852 853 856 public boolean equals(Object o) 857 { 858 if (o == null || ! getClass().equals(o.getClass())) 859 return false; 860 861 ExpandDeployGenerator deploy = (ExpandDeployGenerator) o; 862 863 Path expandDirectory = getExpandDirectory(); 864 Path deployExpandDirectory = deploy.getExpandDirectory(); 865 866 if (expandDirectory != deployExpandDirectory && 867 (expandDirectory == null || 868 ! expandDirectory.equals(deployExpandDirectory))) 869 return false; 870 871 return true; 872 } 873 874 public String toString() 875 { 876 String name = getClass().getName(); 877 int p = name.lastIndexOf('.'); 878 if (p > 0) 879 name = name.substring(p + 1); 880 881 return name + "[" + getExpandDirectory() + "]"; 882 } 883 884 } 885 | Popular Tags |