1 22 package org.jboss.system; 23 24 import java.util.ArrayList ; 25 import java.util.Collection ; 26 import java.util.List ; 27 import java.util.ListIterator ; 28 import java.util.Map ; 29 import java.util.concurrent.ConcurrentHashMap ; 30 import java.util.concurrent.CopyOnWriteArrayList ; 31 32 import javax.management.MBeanRegistration ; 33 import javax.management.MBeanServer ; 34 import javax.management.Notification ; 35 import javax.management.ObjectName ; 36 37 import org.jboss.dependency.spi.Controller; 38 import org.jboss.dependency.spi.ControllerContext; 39 import org.jboss.dependency.spi.ControllerMode; 40 import org.jboss.dependency.spi.ControllerState; 41 import org.jboss.dependency.spi.DependencyInfo; 42 import org.jboss.dependency.spi.DependencyItem; 43 import org.jboss.deployment.DeploymentException; 44 import org.jboss.deployment.DeploymentInfo; 45 import org.jboss.deployment.DeploymentState; 46 import org.jboss.kernel.Kernel; 47 import org.jboss.kernel.plugins.bootstrap.basic.BasicBootstrap; 48 import org.jboss.kernel.spi.dependency.KernelController; 49 import org.jboss.logging.Logger; 50 import org.jboss.mx.server.ServerConstants; 51 import org.jboss.mx.util.JBossNotificationBroadcasterSupport; 52 import org.jboss.mx.util.ObjectNameFactory; 53 import org.jboss.system.metadata.ServiceMetaData; 54 import org.jboss.system.metadata.ServiceMetaDataParser; 55 import org.jboss.system.microcontainer.LifecycleDependencyItem; 56 import org.jboss.system.microcontainer.ServiceControllerContext; 57 import org.w3c.dom.Element ; 58 59 78 public class ServiceController extends JBossNotificationBroadcasterSupport 79 implements ServiceControllerMBean, MBeanRegistration 80 { 81 82 public static final ObjectName DEFAULT_LOADER_REPOSITORY = ObjectNameFactory.create(ServerConstants.DEFAULT_LOADER_NAME); 83 84 85 public static final String JBOSS_INTERNAL_LIFECYCLE = "jbossInternalLifecycle"; 86 87 88 public static final String [] JBOSS_INTERNAL_LIFECYCLE_SIG = new String [] { String .class.getName() }; 89 90 91 private static final Logger log = Logger.getLogger(ServiceController.class); 92 93 94 protected Kernel kernel; 95 96 97 protected MBeanServer server; 98 99 100 protected ServiceBinding serviceBinding; 101 102 103 protected Map <ObjectName , ServiceControllerContext> installed = new ConcurrentHashMap <ObjectName , ServiceControllerContext>(); 104 105 106 protected CopyOnWriteArrayList <ServiceControllerContext> installedOrder = new CopyOnWriteArrayList <ServiceControllerContext>(); 107 108 113 public MBeanServer getMBeanServer() 114 { 115 return server; 116 } 117 118 123 public void setMBeanServer(MBeanServer server) 124 { 125 this.server = server; 126 } 127 128 133 public Kernel getKernel() 134 { 135 return kernel; 136 } 137 138 143 public void setKernel(Kernel kernel) 144 { 145 this.kernel = kernel; 146 } 147 148 153 public ServiceBinding getServiceBinding() 154 { 155 return serviceBinding; 156 } 157 158 163 public void setServiceBinding(ServiceBinding serviceBinding) 164 { 165 this.serviceBinding = serviceBinding; 166 } 167 168 public List <ServiceContext> listDeployed() 169 { 170 ArrayList <ServiceContext> result = new ArrayList <ServiceContext>(installedOrder.size()); 172 for (ServiceControllerContext context : installedOrder) 173 result.add(context.getServiceContext()); 174 return result; 175 } 176 177 public List <ServiceContext> listIncompletelyDeployed() 178 { 179 ArrayList <ServiceContext> result = new ArrayList <ServiceContext>(); 181 for (ServiceControllerContext context : installedOrder) 182 { 183 ServiceContext sc = context.getServiceContext(); 184 if (sc.state != ServiceContext.CREATED && 185 sc.state != ServiceContext.RUNNING && 186 sc.state != ServiceContext.STOPPED && 187 sc.state != ServiceContext.DESTROYED) 188 { 189 result.add(sc); 190 } 191 } 192 return result; 193 } 194 195 public List <ObjectName > listDeployedNames() 196 { 197 ArrayList <ObjectName > result = new ArrayList <ObjectName >(installed.size()); 199 for (ObjectName name : installed.keySet()) 200 result.add(name); 201 return result; 202 } 203 204 public String listConfiguration(ObjectName [] objectNames) throws Exception 205 { 206 return ServiceConfigurator.getConfiguration(server, this, objectNames); 207 } 208 209 public void validateDeploymentState(DeploymentInfo di, DeploymentState state) 210 { 211 ArrayList <ObjectName > mbeans = new ArrayList <ObjectName >(di.mbeans); 212 if (di.deployedObject != null) 213 mbeans.add(di.deployedObject); 214 boolean mbeansStateIsValid = true; 215 for (int m = 0; m < mbeans.size(); ++m) 216 { 217 ObjectName serviceName = mbeans.get(m); 218 ServiceContext ctx = getServiceContext(serviceName); 219 if (ctx != null && state == DeploymentState.STARTED) 220 mbeansStateIsValid &= ctx.state == ServiceContext.RUNNING; 221 } 222 if (mbeansStateIsValid == true) 223 di.state = state; 224 } 225 226 public List <ObjectName > install(List <ServiceMetaData> metaDatas, ObjectName loaderName) throws DeploymentException 227 { 228 KernelController controller = kernel.getController(); 229 230 List <ObjectName > result = new ArrayList <ObjectName >(metaDatas.size()); 233 List <ServiceControllerContext> contexts = new ArrayList <ServiceControllerContext>(metaDatas.size()); 234 235 for (ServiceMetaData metaData : metaDatas) 237 { 238 metaData.setClassLoaderName(loaderName); 239 240 ServiceControllerContext context = new ServiceControllerContext(this, metaData); 242 try 243 { 244 doInstall(controller, context); 245 contexts.add(context); 246 doChange(controller, context, ControllerState.CONFIGURED, "configure"); 247 result.add(context.getObjectName()); 248 } 249 catch (Throwable t) 250 { 251 for (ServiceControllerContext ctx : contexts) 253 safelyRemoveAnyRegisteredContext(ctx); 254 255 DeploymentException.rethrowAsDeploymentException("Error during install", t); 256 } 257 } 258 return result; 259 } 260 261 public ObjectName install(ServiceMetaData metaData, ObjectName loaderName) throws DeploymentException 262 { 263 KernelController controller = kernel.getController(); 264 metaData.setClassLoaderName(loaderName); 265 ObjectName name = metaData.getObjectName(); 266 267 ServiceControllerContext context = new ServiceControllerContext(this, metaData); 269 try 270 { 271 doInstall(controller, context); 272 doChange(controller, context, ControllerState.CONFIGURED, "configure"); 273 return context.getObjectName(); 274 } 275 catch (Throwable t) 276 { 277 throw DeploymentException.rethrowAsDeploymentException("Error during install " + name, t); 278 } 279 } 280 281 public List <ObjectName > install(Element config, ObjectName loaderName) throws DeploymentException 282 { 283 ServiceMetaDataParser parser = new ServiceMetaDataParser(config); 285 List <ServiceMetaData> metaDatas = parser.parse(); 286 return install(metaDatas, loaderName); 287 } 288 289 296 public void install(ObjectName name, Object object) throws DeploymentException 297 { 298 if (name == null) 299 throw new IllegalArgumentException ("Null name"); 300 if (object == null) 301 throw new IllegalArgumentException ("Null object"); 302 303 KernelController controller = kernel.getController(); 304 305 ServiceControllerContext context = new ServiceControllerContext(this, name, object); 306 try 307 { 308 doInstall(controller, context); 309 doChange(controller, context, ControllerState.CONFIGURED, "configure"); 310 } 311 catch (Throwable t) 312 { 313 safelyRemoveAnyRegisteredContext(context); 315 316 DeploymentException.rethrowAsDeploymentException("Error during install", t); 317 } 318 } 319 320 public void register(ObjectName serviceName) throws Exception 321 { 322 register(serviceName, null); 323 } 324 325 public void register(ObjectName serviceName, Collection <ObjectName > depends) throws Exception 326 { 327 if (serviceName == null) 328 { 329 log.warn("Ignoring request to register null service: ", new Exception ("STACKTRACE")); 330 return; 331 } 332 333 log.debug("Registering service " + serviceName); 334 335 KernelController controller = kernel.getController(); 337 ServiceControllerContext context = new ServiceControllerContext(this, serviceName); 338 if (depends != null) 339 addDependencies(context, depends); 340 341 try 343 { 344 doInstall(controller, context); 345 doChange(controller, context, ControllerState.CONFIGURED, "configure"); 346 } 347 catch (Throwable t) 348 { 349 safelyRemoveAnyRegisteredContext(context); 351 352 DeploymentException.rethrowAsDeploymentException("Error during register: " + serviceName, t); 353 } 354 } 355 356 public void create(ObjectName serviceName) throws Exception 357 { 358 create(serviceName, null); 359 } 360 361 public void create(ObjectName serviceName, Collection <ObjectName > depends) throws Exception 362 { 363 if (serviceName == null) 364 { 365 log.warn("Ignoring request to create null service: ", new Exception ("STACKTRACE")); 366 return; 367 } 368 369 log.debug("Creating service " + serviceName); 370 371 ServiceControllerContext context = installed.get(serviceName); 373 if (context == null) 374 { 375 register(serviceName, depends); 376 context = installed.get(serviceName); 377 } 378 ServiceContext ctx = context.getServiceContext(); 379 380 if (ctx.state == ServiceContext.CREATED 382 || ctx.state == ServiceContext.RUNNING 383 || ctx.state == ServiceContext.FAILED) 384 { 385 log.debug("Ignoring create request for service: " + ctx.objectName + " at state " + ctx.getStateString()); 386 return; 387 } 388 389 KernelController controller = kernel.getController(); 391 try 392 { 393 doChange(controller, context, ControllerState.CREATE, "create"); 394 } 395 catch (Throwable t) 396 { 397 log.warn("Problem creating service " + serviceName, t); 398 } 399 } 400 401 public void start(ObjectName serviceName) throws Exception 402 { 403 if (serviceName == null) 404 { 405 log.warn("Ignoring request to start null service: ", new Exception ("STACKTRACE")); 406 return; 407 } 408 409 log.debug("starting service " + serviceName); 410 411 ServiceControllerContext context = installed.get(serviceName); 413 if (context == null) 414 { 415 register(serviceName, null); 416 context = installed.get(serviceName); 417 } 418 ServiceContext ctx = context.getServiceContext(); 419 420 if (ctx.state == ServiceContext.RUNNING || ctx.state == ServiceContext.FAILED) 422 { 423 log.debug("Ignoring start request for service: " + ctx.objectName + " at state " + ctx.getStateString()); 424 return; 425 } 426 427 KernelController controller = kernel.getController(); 429 try 430 { 431 doChange(controller, context, ControllerState.INSTALLED, "start"); 432 } 433 catch (Throwable t) 434 { 435 log.warn("Problem starting service " + serviceName, t); 436 } 437 } 438 439 public void restart(ObjectName serviceName) throws Exception 440 { 441 if (serviceName == null) 442 { 443 log.warn("Ignoring request to restart null service: ", new Exception ("STACKTRACE")); 444 return; 445 } 446 447 log.debug("restarting service " + serviceName); 448 stop(serviceName); 449 start(serviceName); 450 } 451 452 public void stop(ObjectName serviceName) throws Exception 453 { 454 if (serviceName == null) 455 { 456 log.warn("Ignoring request to stop null service: ", new Exception ("STACKTRACE")); 457 return; 458 } 459 460 log.debug("stopping service: " + serviceName); 461 462 ServiceControllerContext context = installed.get(serviceName); 463 if (context == null) 464 { 465 log.warn("Ignoring request to stop nonexistent service: " + serviceName); 466 return; 467 } 468 469 ServiceContext ctx = context.getServiceContext(); 471 if (ctx.state != ServiceContext.RUNNING) 472 { 473 log.debug("Ignoring stop request for service: " + ctx.objectName + " at state " + ctx.getStateString()); 474 return; 475 } 476 477 KernelController controller = kernel.getController(); 479 try 480 { 481 doChange(controller, context, ControllerState.CREATE, null); 482 } 483 catch (Throwable t) 484 { 485 log.warn("Problem stopping service " + serviceName, t); 486 } 487 } 488 489 public void destroy(ObjectName serviceName) throws Exception 490 { 491 if (serviceName == null) 492 { 493 log.warn("Ignoring request to destroy null service: ", new Exception ("STACKTRACE")); 494 return; 495 } 496 497 log.debug("destroying service: " + serviceName); 498 499 ServiceControllerContext context = installed.get(serviceName); 500 if (context == null) 501 { 502 log.warn("Ignoring request to destroy nonexistent service: " + serviceName); 503 return; 504 } 505 506 ServiceContext ctx = context.getServiceContext(); 508 if (ctx.state == ServiceContext.DESTROYED || ctx.state == ServiceContext.NOTYETINSTALLED || ctx.state == ServiceContext.FAILED) 509 { 510 log.debug("Ignoring destroy request for service: " + ctx.objectName + " at state " + ctx.getStateString()); 511 return; 512 } 513 514 KernelController controller = kernel.getController(); 516 try 517 { 518 doChange(controller, context, ControllerState.CONFIGURED, null); 519 } 520 catch (Throwable t) 521 { 522 log.warn("Problem stopping service " + serviceName, t); 523 } 524 } 525 526 public void remove(ObjectName objectName) throws Exception 527 { 528 if (objectName == null) 529 { 530 log.warn("Ignoring request to remove null service: ", new Exception ("STACKTRACE")); 531 return; 532 } 533 534 ServiceControllerContext context = installed.remove(objectName); 540 if (context == null) 541 { 542 log.trace("Ignoring request to remove nonexistent service: " + objectName); 543 return; 544 } 545 installedOrder.remove(context); 546 log.debug("removing service: " + objectName); 547 548 safelyRemoveAnyRegisteredContext(context); 550 } 551 552 public ServiceContext getServiceContext(ObjectName serviceName) 553 { 554 ServiceControllerContext context = installed.get(serviceName); 555 if (context != null) 556 return context.getServiceContext(); 557 return null; 558 } 559 560 public void shutdown() 561 { 562 log.debug("Stopping " + installedOrder.size() + " services"); 563 564 KernelController controller = kernel.getController(); 565 566 int serviceCounter = 0; 567 568 ListIterator <ServiceControllerContext> iterator = installedOrder.listIterator(installedOrder.size()); 570 while (iterator.hasPrevious()) 571 { 572 ServiceControllerContext context = iterator.previous(); 573 controller.uninstall(context.getName()); 574 ++serviceCounter; 575 } 576 log.debug("Stopped " + serviceCounter + " services"); 577 } 578 579 public ObjectName preRegister(MBeanServer server, ObjectName name) 580 throws Exception 581 { 582 this.server = server; 583 584 if( kernel == null ) 585 { 586 BasicBootstrap bootstrap = new BasicBootstrap(); 588 bootstrap.run(); 589 kernel = bootstrap.getKernel(); 590 } 591 592 log.debug("Controller MBean online"); 593 return name == null ? OBJECT_NAME : name; 594 } 595 596 public void postRegister(Boolean registrationDone) 597 { 598 if (registrationDone.booleanValue() == false) 599 log.fatal("Registration of ServiceController failed"); 600 else 601 { 602 KernelController controller = kernel.getController(); 604 ServiceControllerContext context = new ServiceControllerContext(this, ServiceControllerMBean.OBJECT_NAME); 605 context.setMode(ControllerMode.AUTOMATIC); 606 try 607 { 608 controller.install(context); 609 } 610 catch (Throwable t) 611 { 612 log.fatal("Error registering service controller", t); 613 } 614 } 615 } 616 617 public void preDeregister() 618 throws Exception 619 { 620 } 621 622 public void postDeregister() 623 { 624 installed.clear(); 625 installedOrder.clear(); 626 server = null; 627 } 628 629 636 private void doInstall(KernelController controller, ServiceControllerContext context) throws Throwable 637 { 638 controller.install(context); 639 installed.put(context.getObjectName(), context); 640 installedOrder.add(context); 641 } 642 643 652 private void doChange(KernelController controller, ServiceControllerContext context, ControllerState requiredState, String logWait) throws Throwable 653 { 654 if (ControllerMode.ON_DEMAND.equals(context.getMode()) == false) 655 { 656 controller.change(context, requiredState); 657 ControllerState state = context.getState(); 658 if (logWait != null && requiredState.equals(state) == false && state != ControllerState.ERROR) 659 log.debug("Waiting in " + logWait + " of " + context.getObjectName() + " on " + getUnresolvedDependencies(context, requiredState)); 660 } 661 } 662 663 669 public void sendControllerNotification(String type, ObjectName serviceName) 670 { 671 Notification notification = new Notification (type, this, super.nextNotificationSequenceNumber()); 672 notification.setUserData(serviceName); 673 sendNotification(notification); 674 } 675 676 682 private void addDependencies(ServiceControllerContext context, Collection <ObjectName > depends) 683 { 684 DependencyInfo info = context.getDependencyInfo(); 685 for (ObjectName other : depends) 686 { 687 info.addIDependOn(new LifecycleDependencyItem(context.getName(), other.getCanonicalName(), ControllerState.CREATE)); 688 info.addIDependOn(new LifecycleDependencyItem(context.getName(), other.getCanonicalName(), ControllerState.START)); 689 } 690 } 691 692 699 private String getUnresolvedDependencies(ServiceControllerContext context, ControllerState state) 700 { 701 boolean first = true; 702 703 StringBuilder builder = new StringBuilder (); 704 for (DependencyItem item : context.getDependencyInfo().getUnresolvedDependencies()) 705 { 706 if (item.isResolved() == false && item.getWhenRequired() == state) 707 { 708 if (first) 709 first = false; 710 else 711 builder.append(' '); 712 builder.append(item.getIDependOn()); 713 } 714 } 715 return builder.toString(); 716 } 717 718 723 private void safelyRemoveAnyRegisteredContext(ServiceControllerContext ctx) 724 { 725 Controller controller = ctx.getController(); 727 if (controller != null) 728 { 729 Object name = ctx.getName(); 731 ControllerContext registered = controller.getContext(name, null); 732 if (registered == ctx) 733 controller.uninstall(name); 734 } 735 } 736 } 737 | Popular Tags |