1 22 package org.jboss.test.system.controller.legacy; 23 24 import java.lang.reflect.InvocationHandler ; 25 import java.lang.reflect.Method ; 26 import java.lang.reflect.Proxy ; 27 import java.util.ArrayList ; 28 import java.util.Collection ; 29 import java.util.Collections ; 30 import java.util.HashMap ; 31 import java.util.Iterator ; 32 import java.util.LinkedList ; 33 import java.util.List ; 34 import java.util.ListIterator ; 35 import java.util.Map ; 36 37 import javax.management.JMException ; 38 import javax.management.MBeanInfo ; 39 import javax.management.MBeanOperationInfo ; 40 import javax.management.MBeanRegistration ; 41 import javax.management.MBeanServer ; 42 import javax.management.Notification ; 43 import javax.management.ObjectName ; 44 45 import org.jboss.deployment.DeploymentException; 46 import org.jboss.deployment.DeploymentInfo; 47 import org.jboss.deployment.DeploymentState; 48 import org.jboss.logging.Logger; 49 import org.jboss.mx.server.ServerConstants; 50 import org.jboss.mx.util.JBossNotificationBroadcasterSupport; 51 import org.jboss.mx.util.JMXExceptionDecoder; 52 import org.jboss.mx.util.ObjectNameFactory; 53 import org.jboss.system.Service; 54 import org.jboss.system.ServiceBinding; 55 import org.jboss.system.ServiceContext; 56 import org.jboss.system.ServiceFactory; 57 import org.jboss.system.ServiceMBean; 58 import org.w3c.dom.Element ; 59 60 72 public class OldServiceController extends JBossNotificationBroadcasterSupport 73 implements OldServiceControllerMBean, MBeanRegistration 74 { 75 76 public static final ObjectName DEFAULT_LOADER_REPOSITORY = ObjectNameFactory.create(ServerConstants.DEFAULT_LOADER_NAME); 77 78 79 public static final String JBOSS_INTERNAL_LIFECYCLE = "jbossInternalLifecycle"; 80 81 82 public static final String [] JBOSS_INTERNAL_LIFECYCLE_SIG = new String [] { String .class.getName() }; 83 84 85 private static final Logger log = Logger.getLogger(OldServiceController.class); 86 87 88 protected MBeanServer server; 89 90 91 protected OldServiceCreator creator; 92 93 94 protected OldServiceConfigurator configurator; 95 96 97 protected Map <ObjectName , ServiceContext> nameToServiceMap = Collections.synchronizedMap(new HashMap <ObjectName , ServiceContext>()); 98 99 100 protected List <ServiceContext> installedServices = new LinkedList <ServiceContext>(); 101 102 107 public void setServiceBinding(ServiceBinding serviceBinding) 108 { 109 if (configurator != null) 110 { 111 configurator.setServiceBinding(serviceBinding); 112 } 113 } 114 115 public List <ServiceContext> listDeployed() 116 { 117 return new ArrayList <ServiceContext>(installedServices); 118 } 119 120 public List <ServiceContext> listIncompletelyDeployed() 121 { 122 List <ServiceContext> id = new ArrayList <ServiceContext>(); 123 for (Iterator <ServiceContext> i = installedServices.iterator(); i.hasNext();) 124 { 125 ServiceContext sc = i.next(); 126 if ( sc.state != ServiceContext.CREATED && 127 sc.state != ServiceContext.RUNNING && 128 sc.state != ServiceContext.STOPPED && 129 sc.state != ServiceContext.DESTROYED ) 130 { 131 id.add(sc); 132 } 133 } 134 return id; 135 } 136 137 public List <ObjectName > listDeployedNames() 138 { 139 List <ObjectName > names = new ArrayList <ObjectName >(installedServices.size()); 140 for (Iterator <ServiceContext> i = installedServices.iterator(); i.hasNext();) 141 { 142 ServiceContext ctx = i.next(); 143 names.add(ctx.objectName); 144 } 145 146 return names; 147 } 148 149 public String listConfiguration(ObjectName [] objectNames) throws Exception 150 { 151 return configurator.getConfiguration(objectNames); 152 } 153 154 public void validateDeploymentState(DeploymentInfo di, DeploymentState state) 155 { 156 ArrayList <ObjectName > mbeans = new ArrayList <ObjectName >(di.mbeans); 157 if (di.deployedObject != null) 158 mbeans.add(di.deployedObject); 159 boolean mbeansStateIsValid = true; 160 for (int m = 0; m < mbeans.size(); m++) 161 { 162 ObjectName serviceName = mbeans.get(m); 163 ServiceContext ctx = this.getServiceContext(serviceName); 164 if (ctx != null && state == DeploymentState.STARTED) 165 mbeansStateIsValid &= ctx.state == ServiceContext.RUNNING; 166 } 167 if (mbeansStateIsValid == true) 168 di.state = state; 169 } 170 171 public synchronized List <ObjectName > install(Element config, ObjectName loaderName) throws DeploymentException 172 { 173 List <ObjectName > mbeans = configurator.install(config, loaderName); 174 for (Iterator <ObjectName > i = mbeans.iterator(); i.hasNext();) 175 { 176 ObjectName mbean = i.next(); 177 installedServices.add(createServiceContext(mbean)); 178 } 179 return mbeans; 180 } 181 182 public synchronized void register(ObjectName serviceName) throws Exception 183 { 184 register(serviceName, null); 185 } 186 187 public synchronized void register(ObjectName serviceName, Collection <ObjectName > depends) 188 throws Exception 189 { 190 if (serviceName == null) 191 { 192 log.warn("Ignoring request to register null service: ", new Exception ("STACKTRACE")); 193 return; 194 } 195 196 log.debug("Registering service " + serviceName); 197 ServiceContext ctx = createServiceContext(serviceName); 198 199 register(ctx, depends); 200 } 201 202 public synchronized void create(ObjectName serviceName) throws Exception 203 { 204 create(serviceName, null); 205 } 206 207 public synchronized void create(ObjectName serviceName, Collection <ObjectName > depends) 208 throws Exception 209 { 210 if (serviceName == null) 211 { 212 log.warn("Ignoring request to create null service: ", new Exception ("STACKTRACE")); 213 return; 214 } 215 216 log.debug("Creating service " + serviceName); 217 ServiceContext ctx = createServiceContext(serviceName); 218 219 register(ctx, depends); 221 222 if (ctx.state == ServiceContext.CREATED 224 || ctx.state == ServiceContext.RUNNING 225 || ctx.state == ServiceContext.FAILED) 226 { 227 log.debug("Ignoring create request for service: " + ctx.objectName); 228 return; 229 } 230 231 int oldState = ctx.state; 233 ctx.state = ServiceContext.CREATED; 234 235 for (Iterator iterator = ctx.iDependOn.iterator(); iterator.hasNext();) 237 { 238 ServiceContext sc = (ServiceContext) iterator.next(); 239 int state = sc.state; 240 241 if (!(state == ServiceContext.CREATED || state == ServiceContext.RUNNING)) 243 { 244 log.debug("waiting in create of " + serviceName + 245 " waiting on " + sc.objectName); 246 ctx.state = oldState; 247 return; 248 } 249 } 250 251 try 253 { 254 ctx.proxy.create(); 255 sendControllerNotification(ServiceMBean.CREATE_EVENT, serviceName); 256 } 257 catch (Throwable e) 258 { 259 ctx.state = ServiceContext.FAILED; 260 ctx.problem = e; 261 log.warn("Problem creating service " + serviceName, e); 262 return; 263 } 264 265 log.debug("Creating dependent components for: " + serviceName 267 + " dependents are: " + ctx.dependsOnMe); 268 ArrayList <ServiceContext> tmp = new ArrayList <ServiceContext>(ctx.dependsOnMe); 269 for (int n = 0; n < tmp.size(); n++) 270 { 271 ServiceContext ctx2 = tmp.get(n); 273 create(ctx2.objectName); 274 } 275 tmp.clear(); 276 } 277 278 public synchronized void start(ObjectName serviceName) throws Exception 279 { 280 if (serviceName == null) 281 { 282 log.warn("Ignoring request to start null service: ", new Exception ("STACKTRACE")); 283 return; 284 } 285 286 log.debug("starting service " + serviceName); 287 288 ServiceContext ctx = createServiceContext(serviceName); 289 290 if (!installedServices.contains(ctx)) 291 installedServices.add(ctx); 292 293 if (ctx.state == ServiceContext.RUNNING || ctx.state == ServiceContext.FAILED) 295 { 296 log.debug("Ignoring start request for service: " + ctx.objectName); 297 return; 298 } 299 300 if (ctx.state != ServiceContext.CREATED && ctx.state != ServiceContext.STOPPED) 302 { 303 log.debug("Start requested before create, calling create now for service: " + serviceName); 304 create(serviceName); 305 } 306 307 if (ctx.proxy == null) 309 ctx.proxy = getServiceProxy(ctx.objectName, null); 310 311 int oldState = ctx.state; 313 ctx.state = ServiceContext.RUNNING; 314 315 for (Iterator iterator = ctx.iDependOn.iterator(); iterator.hasNext();) 317 { 318 ServiceContext sctx = (ServiceContext) iterator.next(); 319 320 int state = sctx.state; 321 322 if (!(state == ServiceContext.RUNNING)) 324 { 325 log.debug("waiting in start " + serviceName + " on " + sctx.objectName); 326 ctx.state = oldState; 327 return; 328 } 329 } 330 331 try 333 { 334 ctx.proxy.start(); 335 sendControllerNotification(ServiceMBean.START_EVENT, serviceName); 336 } 337 catch (Throwable e) 338 { 339 ctx.state = ServiceContext.FAILED; 340 ctx.problem = e; 341 log.warn("Problem starting service " + serviceName, e); 342 return; 343 } 344 log.debug("Starting dependent components for: " + serviceName 346 + " dependent components: " + ctx.dependsOnMe); 347 ArrayList <ServiceContext> tmp = new ArrayList <ServiceContext>(ctx.dependsOnMe); 348 for (int n = 0; n < tmp.size(); n++) 349 { 350 ServiceContext ctx2 = tmp.get(n); 352 start(ctx2.objectName); 353 } 354 tmp.clear(); 355 } 356 357 public void restart(ObjectName serviceName) throws Exception 358 { 359 if (serviceName == null) 360 { 361 log.warn("Ignoring request to restart null service: ", new Exception ("STACKTRACE")); 362 return; 363 } 364 365 log.debug("restarting service " + serviceName); 366 stop(serviceName); 367 start(serviceName); 368 } 369 370 public void stop(ObjectName serviceName) throws Exception 371 { 372 if (serviceName == null) 373 { 374 log.warn("Ignoring request to stop null service: ", new Exception ("STACKTRACE")); 375 return; 376 } 377 378 ServiceContext ctx = nameToServiceMap.get(serviceName); 379 log.debug("stopping service: " + serviceName); 380 381 if (ctx == null) 382 { 383 log.warn("Ignoring request to stop nonexistent service: " + serviceName); 384 return; 385 } 386 387 if (ctx.state != ServiceContext.RUNNING) return; 389 390 ctx.state = ServiceContext.STOPPED; 392 393 log.debug("stopping dependent services for: " + serviceName 394 + " dependent services are: " + ctx.dependsOnMe); 395 396 ArrayList <ServiceContext> tmp = new ArrayList <ServiceContext>(ctx.dependsOnMe); 397 for (int n = 0; n < tmp.size(); n++) 398 { 399 ServiceContext ctx2 = tmp.get(n); 401 ObjectName other = ctx2.objectName; 402 stop(other); 403 } 404 tmp.clear(); 405 406 if (ctx.proxy != null) 408 { 409 try 410 { 411 ctx.proxy.stop(); 412 sendControllerNotification(ServiceMBean.STOP_EVENT, serviceName); 413 } 414 catch (Throwable e) 415 { 416 ctx.state = ServiceContext.FAILED; 417 ctx.problem = e; 418 log.warn("Problem stopping service " + serviceName, e); 419 } 420 } 421 } 422 423 public void destroy(ObjectName serviceName) throws Exception 424 { 425 if (serviceName == null) 426 { 427 log.warn("Ignoring request to destroy null service: ", new Exception ("STACKTRACE")); 428 return; 429 } 430 431 ServiceContext ctx = nameToServiceMap.get(serviceName); 432 log.debug("destroying service: " + serviceName); 433 434 if (ctx == null) 435 { 436 log.warn("Ignoring request to destroy nonexistent service: " + serviceName); 437 return; 438 } 439 440 if (ctx.state == ServiceContext.DESTROYED || 442 ctx.state == ServiceContext.NOTYETINSTALLED) 443 return; 444 445 if (ctx.state == ServiceContext.RUNNING) 447 { 448 log.debug("Destroy requested before stop, calling stop now for service: " + serviceName); 449 stop(serviceName); 450 } 451 452 ctx.state = ServiceContext.DESTROYED; 454 455 log.debug("destroying dependent services for: " + serviceName 456 + " dependent services are: " + ctx.dependsOnMe); 457 458 ArrayList <ServiceContext> tmp = new ArrayList <ServiceContext>(ctx.dependsOnMe); 459 for (int n = 0; n < tmp.size(); n++) 460 { 461 ServiceContext ctx2 = tmp.get(n); 463 ObjectName other = ctx2.objectName; 464 destroy(other); 465 } 466 tmp.clear(); 467 468 if (ctx.proxy != null) 470 { 471 try 472 { 473 ctx.proxy.destroy(); 474 sendControllerNotification(ServiceMBean.DESTROY_EVENT, serviceName); 475 } 476 catch (Throwable e) 477 { 478 ctx.state = ServiceContext.FAILED; 479 ctx.problem = e; 480 log.warn("Problem destroying service " + serviceName, e); 481 } 482 } 483 } 484 485 public void remove(ObjectName objectName) throws Exception 486 { 487 if (objectName == null) 488 { 489 log.warn("Ignoring request to remove null service: ", new Exception ("STACKTRACE")); 490 return; 491 } 492 493 ServiceContext ctx = nameToServiceMap.get(objectName); 494 if (ctx == null) 495 { 496 log.debug("Ignoring request to remove nonexistent service: " + objectName); 497 return; 498 } 499 log.debug("removing service: " + objectName); 500 501 Iterator iterator = ctx.iDependOn.iterator(); 503 while (iterator.hasNext()) 504 { 505 ServiceContext iDependOnContext = (ServiceContext) iterator.next(); 506 iDependOnContext.dependsOnMe.remove(ctx); 507 508 if (iDependOnContext.state == ServiceContext.NOTYETINSTALLED 511 && iDependOnContext.dependsOnMe.size() == 0) 512 { 513 nameToServiceMap.remove(iDependOnContext.objectName); 514 log.debug("Removing context for nonexistent service it is " + 515 "no longer recording dependencies: " + iDependOnContext); 516 } 517 } 518 ctx.iDependOn.clear(); 521 522 if (server.isRegistered(objectName)) 524 { 525 log.debug("removing " + objectName + " from server"); 526 527 if (ctx.dependsOnMe.size() == 0) 529 nameToServiceMap.remove(objectName); 530 else 531 { 532 log.debug("Context not removed, it is recording " + 533 "dependencies: " + ctx); 534 ctx.proxy = null; 535 } 536 537 installedServices.remove(ctx); 539 creator.remove(objectName); 540 } 541 else 542 { 543 installedServices.remove(ctx); 545 if (ctx.dependsOnMe.size() == 0) 546 { 547 log.debug("removing already unregistered " + objectName + " from server"); 548 nameToServiceMap.remove(objectName); 549 } 550 else 551 { 552 log.debug("no need to remove " + objectName + " from server"); 553 ctx.proxy = null; 554 } 555 } 556 ctx.state = ServiceContext.NOTYETINSTALLED; 559 } 560 561 566 public ServiceContext getServiceContext(ObjectName serviceName) 567 { 568 ServiceContext ctx = nameToServiceMap.get(serviceName); 569 return ctx; 570 } 571 572 public void shutdown() 573 { 574 log.debug("Stopping " + nameToServiceMap.size() + " services"); 575 576 List <ServiceContext> servicesCopy = new ArrayList <ServiceContext>(installedServices); 577 578 int serviceCounter = 0; 579 ObjectName name = null; 580 581 ListIterator i = servicesCopy.listIterator(servicesCopy.size()); 582 while (i.hasPrevious()) 583 { 584 ServiceContext ctx = (ServiceContext) i.previous(); 585 name = ctx.objectName; 586 587 try 589 { 590 stop(name); 591 } 592 catch (Throwable e) 593 { 594 log.error("Could not stop mbean: " + name, e); 595 } 596 try 597 { 598 destroy(name); 599 } 600 catch (Throwable e) 601 { 602 log.error("Could not destroy mbean: " + name, e); 603 } 604 try 605 { 606 remove(name); 607 serviceCounter++; 608 } 609 catch (Throwable e) 610 { 611 log.error("Could not remove mbean: " + name, e); 612 } 613 } 614 log.debug("Stopped " + serviceCounter + " services"); 615 } 616 617 619 627 public ObjectName preRegister(MBeanServer server, ObjectName name) 628 throws Exception 629 { 630 this.server = server; 631 632 creator = new OldServiceCreator(server); 633 configurator = new OldServiceConfigurator(server, this, creator); 634 635 ServiceContext sc = this.createServiceContext(name); 637 sc.state = ServiceContext.RUNNING; 638 639 log.debug("Controller MBean online"); 640 return name == null ? OBJECT_NAME : name; 641 } 642 643 public void postRegister(Boolean registrationDone) 644 { 645 if (!registrationDone.booleanValue()) 646 { 647 log.info("Registration of ServiceController failed"); 648 } 649 } 650 651 public void preDeregister() 652 throws Exception 653 { 654 } 655 656 public void postDeregister() 657 { 658 nameToServiceMap.clear(); 659 installedServices.clear(); 660 creator.shutdown(); 661 creator = null; 662 configurator = null; 663 server = null; 664 } 665 666 668 synchronized ServiceContext createServiceContext(ObjectName objectName) 670 { 671 if (nameToServiceMap.containsKey(objectName)) 673 return nameToServiceMap.get(objectName); 674 675 ServiceContext ctx = new ServiceContext(); 677 ctx.objectName = objectName; 678 679 nameToServiceMap.put(objectName, ctx); 681 682 return ctx; 683 } 684 685 void registerDependency(ObjectName needs, ObjectName used) 686 { 687 log.debug("recording that " + needs + " depends on " + used); 688 ServiceContext needsCtx = createServiceContext(needs); 689 ServiceContext usedCtx = createServiceContext(used); 690 691 692 if (!needsCtx.iDependOn.contains(usedCtx)) 693 { 694 needsCtx.iDependOn.add(usedCtx); 696 usedCtx.dependsOnMe.add(needsCtx); 698 } 699 } 700 701 703 710 private void register(ServiceContext ctx, Collection depends) throws Exception 711 { 712 if (!installedServices.contains(ctx)) 713 installedServices.add(ctx); 714 715 if (depends != null) 716 { 717 log.debug("adding depends in ServiceController.register: " + depends); 718 for (Iterator i = depends.iterator(); i.hasNext();) 719 { 720 registerDependency(ctx.objectName, (ObjectName ) i.next()); 721 } 722 } 723 724 if (ctx.proxy == null) 726 ctx.proxy = getServiceProxy(ctx.objectName, null); 727 } 728 729 741 private Service getServiceProxy(ObjectName objectName, String serviceFactory) 742 throws ClassNotFoundException , InstantiationException , 743 IllegalAccessException , JMException 744 { 745 Service service = null; 746 ClassLoader loader = Thread.currentThread().getContextClassLoader(); 747 if (serviceFactory != null && serviceFactory.length() > 0) 748 { 749 Class clazz = loader.loadClass(serviceFactory); 750 ServiceFactory factory = (ServiceFactory) clazz.newInstance(); 751 service = factory.createService(server, objectName); 752 } 753 else 754 { 755 MBeanInfo info = server.getMBeanInfo(objectName); 756 MBeanOperationInfo [] opInfo = info.getOperations(); 757 Class [] interfaces = {Service.class}; 758 InvocationHandler handler = new ServiceProxy(objectName, opInfo); 759 service = (Service) Proxy.newProxyInstance(Service.class.getClassLoader(), interfaces, handler); 760 } 761 762 return service; 763 } 764 765 768 private void sendControllerNotification(String type, ObjectName serviceName) 769 { 770 Notification notification = new Notification (type, this, super.nextNotificationSequenceNumber()); 771 notification.setUserData(serviceName); 772 sendNotification(notification); 773 } 774 775 777 781 private static HashMap <String , Integer > serviceOpMap = new HashMap <String , Integer >(); 782 783 791 public class ServiceProxy implements InvocationHandler 792 { 793 private boolean[] hasOp = {false, false, false, false}; 794 private ObjectName objectName; 795 796 797 private boolean hasJBossInternalLifecycle; 798 799 807 public ServiceProxy(ObjectName objectName, MBeanOperationInfo [] opInfo) 808 { 809 this.objectName = objectName; 810 811 for (int op = 0; op < opInfo.length; op++) 812 { 813 MBeanOperationInfo info = opInfo[op]; 814 String name = info.getName(); 815 816 if (name.equals(JBOSS_INTERNAL_LIFECYCLE)) 817 { 818 hasJBossInternalLifecycle = true; 819 continue; 820 } 821 822 Integer opID = serviceOpMap.get(name); 823 if (opID == null) 824 { 825 continue; 826 } 827 828 if (info.getReturnType().equals("void") == false) 830 { 831 continue; 832 } 833 if (info.getSignature().length != 0) 834 { 835 continue; 836 } 837 838 hasOp[opID.intValue()] = true; 839 } 840 } 841 842 853 public Object invoke(Object proxy, Method method, Object [] args) 854 throws Throwable 855 { 856 String name = method.getName(); 857 858 if (hasJBossInternalLifecycle) 859 { 860 try 861 { 862 server.invoke(objectName, JBOSS_INTERNAL_LIFECYCLE, new Object [] { name }, JBOSS_INTERNAL_LIFECYCLE_SIG); 863 return null; 864 } 865 catch (Exception e) 866 { 867 throw JMXExceptionDecoder.decode(e); 868 } 869 } 870 871 Integer opID = serviceOpMap.get(name); 872 873 if (opID != null && hasOp[opID.intValue()] == true) 874 { 875 try 877 { 878 String [] sig = {}; 879 server.invoke(objectName, name, args, sig); 880 } 881 catch (Exception e) 882 { 883 throw JMXExceptionDecoder.decode(e); 884 } 885 } 886 887 return null; 888 } 889 } 890 891 894 static 895 { 896 serviceOpMap.put("create", new Integer (0)); 897 serviceOpMap.put("start", new Integer (1)); 898 serviceOpMap.put("destroy", new Integer (2)); 899 serviceOpMap.put("stop", new Integer (3)); 900 } 901 } 902 | Popular Tags |