1 29 30 package com.caucho.server.deploy; 31 32 import com.caucho.config.ConfigException; 33 import com.caucho.config.types.Period; 34 import com.caucho.lifecycle.Lifecycle; 35 import com.caucho.lifecycle.LifecycleListener; 36 import com.caucho.loader.DynamicClassLoader; 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.Dependency; 42 43 import java.io.IOException ; 44 import java.util.logging.Level ; 45 import java.util.logging.Logger ; 46 47 50 abstract public class DeployController<I extends DeployInstance> 51 implements Dependency, AlarmListener 52 { 53 private static final Logger log 54 = Logger.getLogger(DeployController.class.getName()); 55 private static final L10N L = new L10N(DeployController.class); 56 57 public static final String STARTUP_DEFAULT = "default"; 58 public static final String STARTUP_AUTOMATIC = "automatic"; 59 public static final String STARTUP_LAZY = "lazy"; 60 public static final String STARTUP_MANUAL = "manual"; 61 62 public static final String REDEPLOY_DEFAULT = "default"; 63 public static final String REDEPLOY_AUTOMATIC = "automatic"; 64 public static final String REDEPLOY_LAZY = "lazy"; 65 public static final String REDEPLOY_MANUAL = "manual"; 66 67 public static final long REDEPLOY_CHECK_INTERVAL = 60000; 68 69 private ClassLoader _parentLoader; 70 71 private String _id; 72 73 private String _startupMode = STARTUP_DEFAULT; 74 private String _redeployMode = REDEPLOY_DEFAULT; 75 76 private DeployControllerStrategy _strategy; 77 78 protected final Lifecycle _lifecycle; 79 80 private Alarm _alarm = new WeakAlarm(this); 81 private long _redeployCheckInterval = REDEPLOY_CHECK_INTERVAL; 82 83 private long _startTime; 84 private I _deployInstance; 85 86 protected DeployController(String id) 87 { 88 this(id, null); 89 } 90 91 protected DeployController(String id, ClassLoader parentLoader) 92 { 93 _id = id; 94 95 if (parentLoader == null) 96 parentLoader = Thread.currentThread().getContextClassLoader(); 97 98 _parentLoader = parentLoader; 99 100 _lifecycle = new Lifecycle(getLog(), toString()); 101 } 102 103 public void addLifecycleListener(LifecycleListener listener) 104 { 105 _lifecycle.addListener(listener); 106 } 107 108 111 public final String getId() 112 { 113 return _id; 114 } 115 116 119 public ClassLoader getParentClassLoader() 120 { 121 return _parentLoader; 122 } 123 124 127 public void setStartupMode(String mode) 128 { 129 try { 130 _startupMode = toStartupCode(mode); 131 } catch (Exception e) { 132 throw new RuntimeException (e); 133 } 134 } 135 136 139 protected void mergeController(DeployController newController) 140 { 141 newController._parentLoader = _parentLoader; 142 } 143 144 147 public void mergeStartupMode(String mode) 148 { 149 if (mode == null || STARTUP_DEFAULT.equals(mode)) 150 return; 151 152 _startupMode = mode; 153 } 154 155 158 public String getStartupMode() 159 { 160 return _startupMode; 161 } 162 163 166 public static String toStartupCode(String mode) 167 throws ConfigException 168 { 169 if ("automatic".equals(mode)) 170 return STARTUP_AUTOMATIC; 171 else if ("lazy".equals(mode)) 172 return STARTUP_LAZY; 173 else if ("manual".equals(mode)) 174 return STARTUP_MANUAL; 175 else { 176 throw new ConfigException(L.l("'{0}' is an unknown startup-mode. 'automatic', 'lazy', and 'manual' are the acceptable values.", 177 mode)); 178 } 179 } 180 181 184 public void setRedeployMode(String mode) 185 { 186 try { 187 _redeployMode = toRedeployCode(mode); 188 } catch (Exception e) { 189 throw new RuntimeException (e); 190 } 191 } 192 193 196 public void mergeRedeployMode(String mode) 197 { 198 if (mode == null || REDEPLOY_DEFAULT.equals(mode)) 199 return; 200 201 _redeployMode = mode; 202 } 203 204 207 public String getRedeployMode() 208 { 209 return _redeployMode; 210 } 211 212 215 public static String toRedeployCode(String mode) 216 throws ConfigException 217 { 218 if ("automatic".equals(mode)) 219 return REDEPLOY_AUTOMATIC; 220 else if ("lazy".equals(mode)) 221 return REDEPLOY_LAZY; 222 else if ("manual".equals(mode)) 223 return REDEPLOY_MANUAL; 224 else 225 throw new ConfigException(L.l("'{0}' is an unknown redeploy-mode. 'automatic', 'lazy', and 'manual' are the acceptable values.", 226 mode)); 227 } 228 229 232 public void mergeRedeployCheckInterval(long interval) 233 { 234 if (interval != REDEPLOY_CHECK_INTERVAL) 235 _redeployCheckInterval = interval; 236 } 237 238 241 public void setRedeployCheckInterval(Period period) 242 { 243 _redeployCheckInterval = period.getPeriod(); 244 245 if (_redeployCheckInterval < 0) 246 _redeployCheckInterval = Period.INFINITE; 247 248 if (_redeployCheckInterval < 5000) 249 _redeployCheckInterval = 5000; 250 } 251 252 255 public long getRedeployCheckInterval() 256 { 257 return _redeployCheckInterval; 258 } 259 260 263 public boolean isNameMatch(String name) 264 { 265 return getId().equals(name); 266 } 267 268 271 public long getStartTime() 272 { 273 return _startTime; 274 } 275 276 279 protected DeployControllerAdmin getDeployAdmin() 280 { 281 return null; 282 } 283 284 287 public final boolean init() 288 { 289 if (! _lifecycle.toInitializing()) 290 return false; 291 292 Thread thread = Thread.currentThread(); 293 ClassLoader oldLoader = thread.getContextClassLoader(); 294 295 try { 296 thread.setContextClassLoader(getParentClassLoader()); 297 298 initBegin(); 299 300 if (_startupMode == STARTUP_MANUAL) { 301 if (_redeployMode == REDEPLOY_AUTOMATIC) { 302 throw new IllegalStateException (L.l("startup='manual' and redeploy='automatic' is an unsupported combination.")); 303 } 304 else 305 _strategy = StartManualRedeployManualStrategy.create(); 306 } 307 else if (_startupMode == STARTUP_LAZY) { 308 if (_redeployMode == REDEPLOY_MANUAL) 309 _strategy = StartLazyRedeployManualStrategy.create(); 310 else 311 _strategy = StartLazyRedeployAutomaticStrategy.create(); 312 } 313 else { 314 if (_redeployMode == STARTUP_MANUAL) 315 _strategy = StartAutoRedeployManualStrategy.create(); 316 else 317 _strategy = StartAutoRedeployAutoStrategy.create(); 318 } 319 320 initEnd(); 321 322 return _lifecycle.toInit(); 323 } finally { 324 thread.setContextClassLoader(oldLoader); 325 } 326 } 327 328 331 protected void initBegin() 332 { 333 } 334 335 338 protected void initEnd() 339 { 340 } 341 342 protected String getMBeanTypeName() 343 { 344 String className = getDeployInstance().getClass().getName(); 345 int p = className.lastIndexOf('.'); 346 if (p > 0) 347 className = className.substring(p + 1); 348 349 return className; 350 } 351 352 protected String getMBeanId() 353 { 354 String name = getId(); 355 if (name == null || name.equals("")) 356 name = "default"; 357 358 return name; 359 } 360 361 364 public String getState() 365 { 366 if (isDestroyed()) 367 return "destroyed"; 368 else if (isStoppedLazy()) 369 return "stopped-lazy"; 370 else if (isStopped()) 371 return "stopped"; 372 else if (isError()) 373 return "error"; 374 else if (isModified()) 375 return "active-modified"; 376 else 377 return "active"; 378 } 379 380 383 public boolean isActive() 384 { 385 return _lifecycle.isActive(); 386 } 387 388 393 public boolean isStopped() 394 { 395 return _lifecycle.isStopped() || _lifecycle.isInit(); 396 } 397 398 401 public boolean isStoppedLazy() 402 { 403 return _lifecycle.isInit(); 404 } 405 406 411 public boolean isActiveIdle() 412 { 413 DeployInstance instance = getDeployInstance(); 414 415 if (! _lifecycle.isActive()) 416 return false; 417 else if (instance == null) 418 return false; 419 else 420 return instance.isDeployIdle(); 421 } 422 423 428 public boolean isError() 429 { 430 if (_lifecycle.isError()) 431 return true; 432 433 DeployInstance instance = getDeployInstance(); 434 435 return (instance != null && 436 instance.getConfigException() != null); 437 } 438 439 442 public boolean isErrorNow() 443 { 444 if (_lifecycle.isError()) 445 return true; 446 447 DeployInstance instance = getDeployInstance(); 448 449 return (instance != null && 450 instance.getConfigException() != null); 451 } 452 453 456 public boolean isModified() 457 { 458 DeployInstance instance = getDeployInstance(); 459 460 return instance == null || instance.isModified(); 461 } 462 463 466 public boolean isModifiedNow() 467 { 468 DeployInstance instance = getDeployInstance(); 469 470 return instance == null || instance.isModifiedNow(); 471 } 472 473 476 public final I getDeployInstance() 477 { 478 synchronized (this) { 479 if (_deployInstance == null) { 480 Thread thread = Thread.currentThread(); 481 ClassLoader oldLoader = thread.getContextClassLoader(); 482 483 try { 484 thread.setContextClassLoader(_parentLoader); 485 486 _deployInstance = instantiateDeployInstance(); 487 } finally { 488 thread.setContextClassLoader(oldLoader); 489 } 490 } 491 492 return _deployInstance; 493 } 494 } 495 496 499 public void startOnInit() 500 { 501 if (! _lifecycle.isAfterInit()) 502 throw new IllegalStateException (L.l("startOnInit must be called after init (in '{0}')", 503 _lifecycle.getStateName())); 504 505 _strategy.startOnInit(this); 506 } 507 508 511 public final void start() 512 { 513 _strategy.start(this); 514 } 515 516 517 public Throwable getConfigException() 518 { 519 return null; 520 } 521 522 525 public final void stop() 526 { 527 _strategy.stop(this); 528 } 529 530 533 public final void restart() 534 { 535 _strategy.stop(this); 536 _strategy.start(this); 537 } 538 539 542 public final void update() 543 { 544 _strategy.update(this); 545 } 546 547 551 public I request() 552 { 553 if (_lifecycle.isDestroyed()) 554 return null; 555 else if (_strategy != null) 556 return _strategy.request(this); 557 else 558 return null; 559 } 560 561 566 public I subrequest() 567 { 568 if (_lifecycle.isDestroyed()) 569 return null; 570 else if (_strategy != null) 571 return _strategy.subrequest(this); 572 else 573 return null; 574 } 575 576 581 I restartImpl() 582 { 583 if (! _lifecycle.isStopped() && ! _lifecycle.isInit()) 584 stopImpl(); 585 586 return startImpl(); 587 } 588 589 592 protected I startImpl() 593 { 594 assert(_lifecycle.isAfterInit()); 595 596 if (DynamicClassLoader.isModified(_parentLoader)) { 597 _deployInstance = null; 598 return null; 599 } 600 601 I deployInstance = getDeployInstance(); 602 603 Thread thread = Thread.currentThread(); 604 ClassLoader oldLoader = thread.getContextClassLoader(); 605 ClassLoader loader = null; 606 boolean isStarting = false; 607 608 try { 609 loader = deployInstance.getClassLoader(); 610 thread.setContextClassLoader(loader); 611 612 isStarting = _lifecycle.toStarting(); 613 614 if (! isStarting) 615 return deployInstance; 616 617 expandArchive(); 618 619 addManifestClassPath(); 620 621 configureInstance(deployInstance); 622 623 deployInstance.start(); 624 625 _startTime = Alarm.getCurrentTime(); 626 } catch (ConfigException e) { 627 log.severe(e.toString()); 628 log.log(Level.FINE, e.toString(), e); 629 630 _lifecycle.toError(); 631 632 if (deployInstance != null) 633 deployInstance.setConfigException(e); 634 } catch (Throwable e) { 635 log.log(Level.SEVERE, e.toString(), e); 636 637 _lifecycle.toError(); 638 639 if (deployInstance != null) 640 deployInstance.setConfigException(e); 641 } finally { 642 if (isStarting) 643 _lifecycle.toActive(); 644 645 if (loader instanceof DynamicClassLoader) 647 ((DynamicClassLoader) loader).clearModified(); 648 649 if (_alarm != null) 650 _alarm.queue(_redeployCheckInterval); 652 thread.setContextClassLoader(oldLoader); 653 } 654 655 return deployInstance; 656 } 657 658 661 protected void expandArchive() 662 throws Exception 663 { 664 } 665 666 669 void stopLazyImpl() 670 { 671 if (_lifecycle.isInit()) 672 return; 673 674 stopImpl(); 675 676 _lifecycle.toPostInit(); 677 } 678 679 682 void stopImpl() 683 { 684 Thread thread = Thread.currentThread(); 685 ClassLoader oldLoader = thread.getContextClassLoader(); 686 687 DeployInstance oldInstance = _deployInstance; 688 boolean isStopping = false; 689 690 if (oldInstance != null) 691 thread.setContextClassLoader(oldInstance.getClassLoader()); 692 693 try { 694 isStopping = _lifecycle.toStopping(); 695 696 if (! isStopping) 697 return; 698 699 synchronized (this) { 700 oldInstance = _deployInstance; 701 _deployInstance = null; 702 } 703 704 if (oldInstance != null) { 705 oldInstance.destroy(); 706 } 707 } finally { 708 if (isStopping) 709 _lifecycle.toStop(); 710 711 thread.setContextClassLoader(oldLoader); 712 } 713 714 return; 715 } 716 717 720 abstract protected I instantiateDeployInstance(); 721 722 725 protected void addManifestClassPath() 726 throws IOException 727 { 728 } 729 730 733 protected void configureInstance(I deployInstance) 734 throws Throwable 735 { 736 } 737 738 741 public void handleAlarm(Alarm alarm) 742 { 743 try { 744 _strategy.alarm(this); 745 } finally { 746 if (! _lifecycle.isDestroyed()) 747 alarm.queue(_redeployCheckInterval); 748 } 749 } 750 751 754 public boolean isDestroyed() 755 { 756 return _lifecycle.isDestroyed(); 757 } 758 759 762 protected boolean destroy() 763 { 764 if (_lifecycle.isAfterInit()) 765 stop(); 766 767 if (! _lifecycle.toDestroy()) 768 return false; 769 770 Alarm alarm = _alarm; 771 _alarm = null; 772 773 if (alarm != null) { 774 alarm.dequeue(); 775 } 776 777 return true; 778 } 779 780 783 protected Logger getLog() 784 { 785 return log; 786 } 787 788 791 public String toString() 792 { 793 String className = getClass().getName(); 794 int p = className.lastIndexOf('.'); 795 796 return className.substring(p + 1) + "[" + getId() + "]"; 797 } 798 } 799 | Popular Tags |