1 22 package org.objectweb.petals.jbi.component.lifecycle; 23 24 import java.lang.reflect.InvocationTargetException ; 25 import java.lang.reflect.Method ; 26 import java.net.MalformedURLException ; 27 import java.net.URI ; 28 import java.net.URL ; 29 import java.util.ArrayList ; 30 import java.util.Iterator ; 31 import java.util.List ; 32 33 import javax.jbi.JBIException; 34 import javax.jbi.component.Bootstrap; 35 import javax.jbi.component.Component; 36 import javax.jbi.component.InstallationContext; 37 import javax.jbi.management.LifeCycleMBean; 38 import javax.management.AttributeChangeNotification ; 39 import javax.management.ListenerNotFoundException ; 40 import javax.management.MBeanNotificationInfo ; 41 import javax.management.Notification ; 42 import javax.management.NotificationBroadcaster ; 43 import javax.management.NotificationBroadcasterSupport ; 44 import javax.management.NotificationFilter ; 45 import javax.management.NotificationListener ; 46 import javax.management.ObjectName ; 47 48 import org.objectweb.petals.PetalsException; 49 import org.objectweb.petals.classloader.LoaderManager; 50 import org.objectweb.petals.classloader.PetalsClassLoader; 51 import org.objectweb.petals.jbi.component.context.ComponentContextImpl; 52 import org.objectweb.petals.jbi.component.context.InstallationContextImpl; 53 import org.objectweb.petals.jbi.component.event.StateChangeFailedEvent; 54 import org.objectweb.petals.jbi.component.event.StateChangedEvent; 55 import org.objectweb.petals.jbi.component.thread.BootstrapThread; 56 import org.objectweb.petals.jbi.component.thread.ComponentLifeCycleThread; 57 import org.objectweb.petals.jbi.management.service.LifeCycleManagerService; 58 import org.objectweb.petals.jbi.management.service.MBeanNamesImpl; 59 import org.objectweb.petals.jbi.management.service.ManagementException; 60 import org.objectweb.petals.jbi.management.systemstate.SystemState; 61 import org.objectweb.petals.tools.jbicommon.descriptor.ComponentDescription; 62 import org.objectweb.petals.tools.jbicommon.descriptor.JBIDescriptor; 63 import org.objectweb.petals.tools.jbicommon.descriptor.SharedLibraryList; 64 import org.objectweb.petals.util.ConvertSpecialCharactersUtil; 65 import org.objectweb.petals.util.LoggingUtil; 66 import org.objectweb.petals.util.SystemUtil; 67 import org.objectweb.util.monolog.api.Logger; 68 69 75 public class Installer implements InstallerMBean, NotificationBroadcaster { 76 77 80 public static final String BS_PREFIX = "BS"; 81 82 85 public static final String COMP_PREFIX = "COMP"; 86 87 public static final String INSTALLED = "Installed"; 88 89 public static final String INSTALLING = "Installing"; 90 91 public static final String UNINSTALLED = "Uninstalled"; 92 93 public static final String UNINSTALLING = "Uninstalling"; 94 95 public static final String UNKNOWN = "Unknown"; 96 97 private static final String BINDING_COMPONENT = "binding-component"; 98 99 private static final String SERVICE_ENGINE = "service-engine"; 100 101 protected Object activitySynchronizer; 105 106 protected String state; 107 108 NotificationBroadcasterSupport notifSupport = new NotificationBroadcasterSupport (); 109 110 protected ComponentContextImpl componentContext; 111 112 protected ComponentDescription componentDescription; 113 114 protected ObjectName componentJmxName; 115 116 protected URI installationRoot; 117 118 protected Bootstrap jbiBootstrap; 119 120 protected LifeCycleManagerService jmxAdmin; 121 122 protected LoaderManager loadSrv; 123 124 protected BootstrapThread bootstrapThread; 125 126 protected LoggingUtil log; 127 128 131 protected ObjectName mBeanName; 132 133 protected SystemState recoverySrv; 134 135 138 protected long sequenceNumber; 139 140 152 public Installer(URI installationRoot, LoaderManager loadSrv, 153 ComponentContextImpl componentContext, 154 ComponentDescription componentDescription, 155 LifeCycleManagerService jmxAdmin, SystemState recoverySrv, 156 ObjectName mbeanName, Logger logger) { 157 super(); 158 log = new LoggingUtil(logger); 159 160 log.start(); 161 162 this.jmxAdmin = jmxAdmin; 163 164 this.recoverySrv = recoverySrv; 165 166 this.componentDescription = componentDescription; 167 168 this.installationRoot = installationRoot; 169 170 this.componentContext = componentContext; 171 172 this.loadSrv = loadSrv; 173 174 this.mBeanName = mbeanName; 175 176 this.state = UNINSTALLED; 177 178 activitySynchronizer = new Object (); 179 180 log.end(); 181 } 182 183 189 public void addNotificationListener(NotificationListener arg0, 190 NotificationFilter arg1, Object arg2) throws IllegalArgumentException { 191 notifSupport.addNotificationListener(arg0, arg1, arg2); 192 } 193 194 200 public String getComponentName() { 201 return componentContext.getComponentName(); 202 } 203 204 210 public String getCurrentState() { 211 if (!(LifeCycleMBean.SHUTDOWN.equals(state) 212 || LifeCycleMBean.STARTED.equals(state) || LifeCycleMBean.STOPPED 213 .equals(state))) { 214 return LifeCycleMBean.UNKNOWN; 215 } 216 return state; 217 } 218 219 224 public ObjectName getInstallerConfigurationMBean() throws JBIException { 225 LifeCycleAbstract lifeCycle = jmxAdmin 226 .getComponentByName(componentContext.getComponentName()); 227 if (!INSTALLED.equals(state) 228 || (lifeCycle != null && !lifeCycle.getCurrentState().equals( 229 LifeCycleMBean.SHUTDOWN))) { 230 throw new JBIException("Component is not in the SHUTDOWN state"); 231 } 232 233 if (jbiBootstrap == null) { 234 throw new JBIException("Bootstrap should not be null"); 235 } 236 237 return bootstrapThread.getExtensionMBeanName(); 238 } 239 240 245 public String getInstallRoot() { 246 return componentContext.getInstallRoot(); 247 } 248 249 253 public ObjectName getMBeanName() { 254 return mBeanName; 255 } 256 257 262 public MBeanNotificationInfo [] getNotificationInfo() { 263 String [] types = new String [] {AttributeChangeNotification.ATTRIBUTE_CHANGE}; 264 265 String name = AttributeChangeNotification .class.getName(); 266 267 String description = "Notification about a change of the lifeCycle state or a state change failure."; 268 269 MBeanNotificationInfo info = new MBeanNotificationInfo (types, name, 270 description); 271 272 return new MBeanNotificationInfo [] {info}; 273 } 274 275 282 public ObjectName install() throws JBIException { 283 log.start(); 284 if (UNINSTALLED.equals(state)) { 285 synchronized (activitySynchronizer) { 286 try { 287 setState(INSTALLING); 288 289 doInstall(); 290 291 setState(INSTALLED); 292 } catch (Throwable re) { 293 setState(UNKNOWN); 294 295 String msg = "An exception occured during the installation."; 296 297 JBIException e = new JBIException(msg, re); 298 299 log.error(msg, e); 300 301 stateChangeFailed(new StateChangeFailedEvent(this, e)); 302 303 throw e; 304 } 305 } 306 } else { 307 String msg = "The Object can not be installed in this state."; 308 309 JBIException e = new JBIException(msg); 310 311 log.error(msg, e); 312 313 stateChangeFailed(new StateChangeFailedEvent(this, e)); 314 315 throw e; 316 } 317 log.end(); 318 319 return componentJmxName; 320 } 321 322 327 public boolean isInstalled() { 328 boolean result = false; 329 if (INSTALLED.equals(state)) { 330 result = true; 331 } 332 return result; 333 } 334 335 340 public void removeNotificationListener(NotificationListener arg0) 341 throws ListenerNotFoundException { 342 notifSupport.removeNotificationListener(arg0); 343 } 344 345 352 public synchronized void setState(String state) throws JBIException { 353 stateChanged(new StateChangedEvent(this, this.state, state)); 354 355 this.state = state; 356 357 try { 358 recoverySrv.updateComponentInstallationState(getComponentName(), 359 state); 360 } catch (Exception e) { 361 String msg = "Component state can't be persisted for recovery"; 362 log.error(msg, e); 363 throw new JBIException(msg, e); 364 } 365 } 366 367 373 public synchronized void stateChanged(StateChangedEvent event) { 374 log.call(); 375 Notification n = new AttributeChangeNotification (mBeanName, 376 sequenceNumber++, System.currentTimeMillis(), "State of '" 377 + mBeanName.toString() + "' changed : " + event.getOldState() 378 + " -> " + event.getNewState(), "state", "String", event 379 .getOldState(), event.getNewState()); 380 381 notifSupport.sendNotification(n); 382 } 383 384 391 public synchronized void stateChangeFailed(StateChangeFailedEvent event) { 392 log.call(); 393 Notification n = new AttributeChangeNotification (mBeanName, 394 sequenceNumber++, System.currentTimeMillis(), "State change of '" 395 + mBeanName.toString() + "' failed : " 396 + event.getException().getMessage(), "exception", "String", 397 null, event.getException().toString()); 398 399 notifSupport.sendNotification(n); 400 } 401 402 409 public void uninstall() throws JBIException { 410 log.start(); 411 if (INSTALLED.equals(state)) { 412 synchronized (activitySynchronizer) { 413 try { 414 415 ComponentLifeCycle componentLifeCycle = getComponentLifeCycle(); 416 String compState = componentLifeCycle.getCurrentState(); 417 418 if (ComponentLifeCycle.STARTED.equals(compState)) { 419 componentLifeCycle.stop(); 420 componentLifeCycle.shutDown(); 421 } else if (ComponentLifeCycle.STOPPED.equals(compState)) { 422 componentLifeCycle.shutDown(); 423 } 424 425 compState = componentLifeCycle.getCurrentState(); 426 427 if (ComponentLifeCycle.SHUTDOWN.equals(compState)) { 428 setState(UNINSTALLING); 429 doUninstall(); 430 setState(UNINSTALLED); 431 } 432 } catch (Throwable re) { 433 setState(UNKNOWN); 434 435 String msg = "An exception occured during the uninstallation."; 436 437 JBIException e = new JBIException(msg, re); 438 439 log.error(msg, e); 440 441 stateChangeFailed(new StateChangeFailedEvent(this, e)); 442 443 throw e; 444 } 445 } 446 } else { 447 String msg = "The Object can not be uninstalled in this state."; 448 449 JBIException e = new JBIException(msg); 450 451 log.error(msg, e); 452 453 stateChangeFailed(new StateChangeFailedEvent(this, e)); 454 455 throw e; 456 } 457 log.end(); 458 } 459 460 465 protected PetalsClassLoader createBootstrapClassloader() { 466 log.call(); 467 468 List <String > classpath = componentDescription.getBootstrapClassPath(); 469 470 boolean parentFirst = JBIDescriptor.isParentFirst(componentDescription 471 .getBootstrapClassLoaderDelegation()); 472 473 return createClassLoader(BS_PREFIX, classpath, parentFirst, null); 474 } 475 476 489 protected PetalsClassLoader createClassLoader(String prefix, 490 List <String > classpath, boolean parentFirst, List <String > slNameList) { 491 log.call(); 492 493 List <URL > urls = new ArrayList <URL >(); 495 496 try { 497 String installRootPath; 499 if (installationRoot.toURL().getPath().startsWith("/")) { 500 installRootPath = "file://" 501 + installationRoot.toURL().getPath(); 502 } else { 503 installRootPath = "file:///" 504 + installationRoot.toURL().getPath(); 505 } 506 507 installRootPath = ConvertSpecialCharactersUtil 508 .convertPath(installRootPath); 509 510 urls.add(new URL (installRootPath)); 511 } catch (MalformedURLException e) { 512 String msg = "Unexpected error. " + e.getMessage(); 516 log.info(msg, e); 517 } 518 URL [] baseUrls = urls.toArray(new URL [] {}); 519 520 PetalsClassLoader classLoader = null; 521 522 try { 523 classLoader = (PetalsClassLoader) loadSrv 524 .createComponentClassLoader(prefix 525 + componentDescription.getIdentification().getName(), 526 baseUrls, classpath, parentFirst, slNameList); 527 } catch (PetalsException pe) { 528 log.error("Error creating bootstrap class loader. " 530 + pe.getMessage(), pe); 531 532 log.end(); 533 return null; 534 } 535 return classLoader; 536 } 537 538 546 @SuppressWarnings ("unchecked") 547 protected PetalsClassLoader createComponentClassloader() { 548 log.call(); 549 550 InstallationContext installContext = new InstallationContextImpl( 551 componentDescription, componentContext, true); 552 553 List <String > classpath = (List <String >) installContext 554 .getClassPathElements(); 555 556 boolean parentFirst = JBIDescriptor.isParentFirst(componentDescription 558 .getComponentClassLoaderDelegation()); 559 560 List <SharedLibraryList> slList = componentDescription 562 .getSharedLibraryList(); 563 564 List slNameList = new ArrayList (); 565 566 if (slList != null) { 567 for (Iterator iter = slList.iterator(); iter.hasNext();) { 568 SharedLibraryList element = (SharedLibraryList) iter.next(); 569 slNameList.add(element.getName()); 570 } 571 } 572 573 return createClassLoader(COMP_PREFIX, classpath, parentFirst, 574 slNameList); 575 } 576 577 582 protected void doInstall() throws JBIException { 583 584 if (jbiBootstrap != null) { 586 throw new JBIException( 587 "Bootstrap should be null, the installer has already been initialized"); 588 } 589 590 PetalsClassLoader classloader = createComponentClassloader(); 592 593 jbiBootstrap = loadBootstrap(classloader); 595 596 bootstrapThread = createBootstrapThread(classloader); 598 599 InstallationContextImpl installContext = new InstallationContextImpl( 601 componentDescription, componentContext, true); 602 603 bootstrapThread.init(installContext); 605 bootstrapThread.onInstall(); 606 607 componentJmxName = createComponentLifeCycleMBean(); 609 610 bootstrapThread.cleanUp(); 611 } 612 613 620 protected BootstrapThread createBootstrapThread(PetalsClassLoader classloader) { 621 BootstrapThread it = new BootstrapThread(this, jbiBootstrap); 622 it.setContextClassLoader(classloader); 623 it.start(); 624 return it; 625 } 626 627 634 protected ComponentLifeCycleThread createComponentLifeCycleThread( 635 Component component, PetalsClassLoader classloader) { 636 ComponentLifeCycleThread clt = new ComponentLifeCycleThread(component); 637 clt.setContextClassLoader(classloader); 638 clt.start(); 639 return clt; 640 } 641 642 648 protected ObjectName createComponentLifeCycleMBean() throws JBIException { 649 ObjectName objectName = null; 650 651 PetalsClassLoader cl = createComponentClassloader(); 653 654 Component jbiComponent = loadComponent(cl); 656 657 ComponentLifeCycleThread lifeCycleThread = createComponentLifeCycleThread( 659 jbiComponent, cl); 660 661 MBeanNamesImpl mbeanNames = jmxAdmin.getMBeanNames(); 663 if (BINDING_COMPONENT.equals(componentDescription.getType())) { 664 objectName = mbeanNames 665 .createBindingComponentMBeanName(componentDescription 666 .getIdentification().getName()); 667 } else if (SERVICE_ENGINE.equals(componentDescription.getType())){ 668 objectName = mbeanNames 669 .createEngineComponentMBeanName(componentDescription 670 .getIdentification().getName()); 671 } 672 673 ComponentLifeCycle lifecycle = new ComponentLifeCycle( 675 componentDescription, jbiComponent, componentContext, recoverySrv, 676 objectName, lifeCycleThread, log); 677 678 if (BINDING_COMPONENT.equals(componentDescription.getType())) { 680 objectName = jmxAdmin.registerBindingComponent(lifecycle); 681 } else if (SERVICE_ENGINE.equals(componentDescription.getType())) { 682 objectName = jmxAdmin.registerEngineComponent(lifecycle); 683 } 684 685 return objectName; 686 } 687 688 693 protected void unregisterComponentLifeCycleMBean() throws ManagementException { 694 if (BINDING_COMPONENT.equals(componentDescription.getType())) { 695 jmxAdmin.unregisterBindingComponent(componentJmxName); 696 } else if (SERVICE_ENGINE.equals(componentDescription.getType())) { 697 jmxAdmin.unregisterEngineComponent(componentJmxName); 698 } 699 } 700 701 706 protected void doUninstall() throws JBIException { 707 708 if (jbiBootstrap == null) { 709 throw new JBIException("Bootstrap should not be null"); 710 } 711 712 InstallationContextImpl uninstallContext = new InstallationContextImpl( 715 componentDescription, componentContext, false); 716 717 bootstrapThread.init(uninstallContext); 718 719 bootstrapThread.onUninstall(); 720 721 unregisterComponentLifeCycleMBean(); 723 724 if (componentContext.getComponent().getLifeCycle() != null) { 726 ObjectName extName = componentContext.getComponent().getLifeCycle() 727 .getExtensionMBeanName(); 728 try { 729 jmxAdmin.getMBeanServer().unregisterMBean(extName); 730 } catch (Exception e) { 731 } 733 } 734 735 bootstrapThread.cleanUp(); 736 737 bootstrapThread.shutdownThread(); 740 741 744 String componentName = componentDescription.getIdentification() 745 .getName(); 746 747 loadSrv.deleteClassLoader(Installer.COMP_PREFIX + componentName); 748 loadSrv.deleteClassLoader(Installer.BS_PREFIX + componentName); 749 750 jbiBootstrap = null; 752 753 } 754 755 760 protected ComponentLifeCycle getComponentLifeCycle() { 761 String compName = componentDescription.getIdentification().getName(); 762 return jmxAdmin.getComponentByName(compName); 763 } 764 765 770 protected Bootstrap loadBootstrap(PetalsClassLoader classloader) 771 throws JBIException { 772 log.call(); 773 Class bootstrapClass; 774 Bootstrap jbiBootstrapTmp = null; 775 try { 776 779 bootstrapClass = classloader.loadClass(componentDescription 780 .getBootstrapClassName()); 781 782 if (bootstrapClass == null) { 783 throw new JBIException("Could not find bootstrap class: " 784 + componentDescription.getBootstrapClassName()); 785 } 786 jbiBootstrapTmp = (Bootstrap) bootstrapClass.newInstance(); 787 788 794 } catch (ClassNotFoundException e) { 795 throw new JBIException("Class not found: " 796 + componentDescription.getBootstrapClassName(), e); 797 } catch (InstantiationException e) { 798 throw new JBIException("Could not instantiate : " 799 + componentDescription.getBootstrapClassName(), e); 800 } catch (IllegalAccessException e) { 801 throw new JBIException("Illegal access on: " 802 + componentDescription.getBootstrapClassName(), e); 803 } 804 return jbiBootstrapTmp; 805 } 806 807 812 protected javax.jbi.component.Component loadComponent(PetalsClassLoader classloader) throws JBIException { 813 log.call(); 814 815 Class componentClass; 816 javax.jbi.component.Component jbiComponent = null; 817 818 try { 819 componentClass = classloader.loadClass(componentDescription 820 .getComponentClassName()); 821 822 if (componentClass == null) { 823 throw new JBIException("Could not find component class: " 824 + componentDescription.getComponentClassName()); 825 } 826 827 jbiComponent = (javax.jbi.component.Component) componentClass 828 .newInstance(); 829 830 Class clazz = classloader.loadClass("java.util.logging.Logger"); 832 Method method = clazz.getMethod("getLogger", new Class [] { 833 Class.forName("java.lang.String"), 834 Class.forName("java.lang.String")}); 835 java.util.logging.Logger logger = (java.util.logging.Logger ) method 836 .invoke(null, new Object [] { 837 "root0.Petals" + ".components.container-" 838 + SystemUtil.getContainerName() + "." 839 + componentDescription.getIdentification().getName(), 840 null}); 841 componentContext.setRootLogger(logger); 842 843 } catch (ClassNotFoundException e) { 844 throw new JBIException("Class not found: " 845 + componentDescription.getComponentClassName(), e); 846 } catch (InstantiationException e) { 847 throw new JBIException("Could not instantiate : " 848 + componentDescription.getComponentClassName(), e); 849 } catch (IllegalAccessException e) { 850 throw new JBIException("Illegal access on: " 851 + componentDescription.getComponentClassName(), e); 852 } catch (SecurityException e) { 853 throw new JBIException( 854 "Security exception for java.util.logging.Logger", e); 855 } catch (NoSuchMethodException e) { 856 throw new JBIException(e); 857 } catch (IllegalArgumentException e) { 858 throw new JBIException(e); 859 } catch (InvocationTargetException e) { 860 throw new JBIException(e); 861 } 862 return jbiComponent; 863 } 864 } 865 | Popular Tags |