KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > test > system > controller > legacy > OldServiceController


1 /*
2  * JBoss, Home of Professional Open Source
3  * Copyright 2005, JBoss Inc., and individual contributors as indicated
4  * by the @authors tag. See the copyright.txt in the distribution for a
5  * full listing of individual contributors.
6  *
7  * This is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * This software is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this software; if not, write to the Free
19  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21  */

22 package org.jboss.test.system.controller.legacy;
23
24 import java.lang.reflect.InvocationHandler JavaDoc;
25 import java.lang.reflect.Method JavaDoc;
26 import java.lang.reflect.Proxy JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.Collection JavaDoc;
29 import java.util.Collections JavaDoc;
30 import java.util.HashMap JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.LinkedList JavaDoc;
33 import java.util.List JavaDoc;
34 import java.util.ListIterator JavaDoc;
35 import java.util.Map JavaDoc;
36
37 import javax.management.JMException JavaDoc;
38 import javax.management.MBeanInfo JavaDoc;
39 import javax.management.MBeanOperationInfo JavaDoc;
40 import javax.management.MBeanRegistration JavaDoc;
41 import javax.management.MBeanServer JavaDoc;
42 import javax.management.Notification JavaDoc;
43 import javax.management.ObjectName JavaDoc;
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 JavaDoc;
59
60 /**
61  * This is the main Service Controller. A controller can deploy a service to a
62  * jboss.system It installs by delegating, it configures by delegating
63  *
64  * @see org.jboss.system.Service
65  *
66  * @author <a HREF="mailto:marc.fleury@jboss.org">Marc Fleury</a>
67  * @author <a HREF="mailto:d_jencks@users.sourceforge.net">David Jencks</a>
68  * @author <a HREF="mailto:scott.stark@jboss.org">Scott Stark</a>
69  * @author <a HREF="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
70  * @version $Revision: 1.61 $
71  */

72 public class OldServiceController extends JBossNotificationBroadcasterSupport
73    implements OldServiceControllerMBean, MBeanRegistration JavaDoc
74 {
75    /** The ObjectName of the default loader repository */
76    public static final ObjectName JavaDoc DEFAULT_LOADER_REPOSITORY = ObjectNameFactory.create(ServerConstants.DEFAULT_LOADER_NAME);
77
78    /** The operation name for lifecycle */
79    public static final String JavaDoc JBOSS_INTERNAL_LIFECYCLE = "jbossInternalLifecycle";
80
81    /** The signature for lifecycle operations */
82    public static final String JavaDoc[] JBOSS_INTERNAL_LIFECYCLE_SIG = new String JavaDoc[] { String JavaDoc.class.getName() };
83
84    /** Class logger. */
85    private static final Logger log = Logger.getLogger(OldServiceController.class);
86
87    /** A callback to the JMX MBeanServer */
88    protected MBeanServer JavaDoc server;
89
90    /** Creator, helper class to instantiate MBeans **/
91    protected OldServiceCreator creator;
92
93    /** Configurator, helper class to configure MBeans **/
94    protected OldServiceConfigurator configurator;
95
96    /** ObjectName to ServiceContext map **/
97    protected Map JavaDoc<ObjectName JavaDoc, ServiceContext> nameToServiceMap = Collections.synchronizedMap(new HashMap JavaDoc<ObjectName JavaDoc, ServiceContext>());
98
99    /** A linked list of services in the order they were created **/
100    protected List JavaDoc<ServiceContext> installedServices = new LinkedList JavaDoc<ServiceContext>();
101
102    /**
103     * Plugin a ServiceBinding policy
104     *
105     * @param serviceBinding policy
106     */

107    public void setServiceBinding(ServiceBinding serviceBinding)
108    {
109       if (configurator != null)
110       {
111          configurator.setServiceBinding(serviceBinding);
112       }
113    }
114    
115    public List JavaDoc<ServiceContext> listDeployed()
116    {
117       return new ArrayList JavaDoc<ServiceContext>(installedServices);
118    }
119
120    public List JavaDoc<ServiceContext> listIncompletelyDeployed()
121    {
122       List JavaDoc<ServiceContext> id = new ArrayList JavaDoc<ServiceContext>();
123       for (Iterator JavaDoc<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 JavaDoc<ObjectName JavaDoc> listDeployedNames()
138    {
139       List JavaDoc<ObjectName JavaDoc> names = new ArrayList JavaDoc<ObjectName JavaDoc>(installedServices.size());
140       for (Iterator JavaDoc<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 JavaDoc listConfiguration(ObjectName JavaDoc[] objectNames) throws Exception JavaDoc
150    {
151       return configurator.getConfiguration(objectNames);
152    }
153
154    public void validateDeploymentState(DeploymentInfo di, DeploymentState state)
155    {
156       ArrayList JavaDoc<ObjectName JavaDoc> mbeans = new ArrayList JavaDoc<ObjectName JavaDoc>(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 JavaDoc 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 JavaDoc<ObjectName JavaDoc> install(Element JavaDoc config, ObjectName JavaDoc loaderName) throws DeploymentException
172    {
173       List JavaDoc<ObjectName JavaDoc> mbeans = configurator.install(config, loaderName);
174       for (Iterator JavaDoc<ObjectName JavaDoc> i = mbeans.iterator(); i.hasNext();)
175       {
176          ObjectName JavaDoc mbean = i.next();
177          installedServices.add(createServiceContext(mbean));
178       }
179       return mbeans;
180    }
181
182    public synchronized void register(ObjectName JavaDoc serviceName) throws Exception JavaDoc
183    {
184       register(serviceName, null);
185    }
186
187    public synchronized void register(ObjectName JavaDoc serviceName, Collection JavaDoc<ObjectName JavaDoc> depends)
188          throws Exception JavaDoc
189    {
190       if (serviceName == null)
191       {
192          log.warn("Ignoring request to register null service: ", new Exception JavaDoc("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 JavaDoc serviceName) throws Exception JavaDoc
203    {
204       create(serviceName, null);
205    }
206
207    public synchronized void create(ObjectName JavaDoc serviceName, Collection JavaDoc<ObjectName JavaDoc> depends)
208          throws Exception JavaDoc
209    {
210       if (serviceName == null)
211       {
212          log.warn("Ignoring request to create null service: ", new Exception JavaDoc("STACKTRACE"));
213          return;
214       }
215       
216       log.debug("Creating service " + serviceName);
217       ServiceContext ctx = createServiceContext(serviceName);
218
219       // Register the context and its dependencies if necessary
220
register(ctx, depends);
221
222       // If we are already created (can happen in dependencies) or failed just return
223
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       // JSR 77, and to avoid circular dependencies
232
int oldState = ctx.state;
233       ctx.state = ServiceContext.CREATED;
234
235       // Are all the mbeans I depend on created? if not just return
236
for (Iterator JavaDoc iterator = ctx.iDependOn.iterator(); iterator.hasNext();)
237       {
238          ServiceContext sc = (ServiceContext) iterator.next();
239          int state = sc.state;
240
241          // A dependent is not created or running
242
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       // Call create on the service Proxy
252
try
253       {
254          ctx.proxy.create();
255          sendControllerNotification(ServiceMBean.CREATE_EVENT, serviceName);
256       }
257       catch (Throwable JavaDoc e)
258       {
259          ctx.state = ServiceContext.FAILED;
260          ctx.problem = e;
261          log.warn("Problem creating service " + serviceName, e);
262          return;
263       }
264
265       // Those that depend on me are waiting for my creation, recursively create them
266
log.debug("Creating dependent components for: " + serviceName
267             + " dependents are: " + ctx.dependsOnMe);
268       ArrayList JavaDoc<ServiceContext> tmp = new ArrayList JavaDoc<ServiceContext>(ctx.dependsOnMe);
269       for (int n = 0; n < tmp.size(); n++)
270       {
271          // marcf fixme circular dependencies?
272
ServiceContext ctx2 = tmp.get(n);
273          create(ctx2.objectName);
274       }
275       tmp.clear();
276    }
277
278    public synchronized void start(ObjectName JavaDoc serviceName) throws Exception JavaDoc
279    {
280       if (serviceName == null)
281       {
282          log.warn("Ignoring request to start null service: ", new Exception JavaDoc("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 we are already started (can happen in dependencies) just return
294
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       // Start() is called before create(), so call create() to compensate
301
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       // Get the fancy service proxy (for the lifecycle API)
308
if (ctx.proxy == null)
309          ctx.proxy = getServiceProxy(ctx.objectName, null);
310
311       // JSR 77, and to avoid circular dependencies
312
int oldState = ctx.state;
313       ctx.state = ServiceContext.RUNNING;
314
315       // Are all the mbeans I depend on started? if not just return
316
for (Iterator JavaDoc iterator = ctx.iDependOn.iterator(); iterator.hasNext();)
317       {
318          ServiceContext sctx = (ServiceContext) iterator.next();
319
320          int state = sctx.state;
321
322          // A dependent is not running
323
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       // Call start on the service Proxy
332
try
333       {
334          ctx.proxy.start();
335          sendControllerNotification(ServiceMBean.START_EVENT, serviceName);
336       }
337       catch (Throwable JavaDoc e)
338       {
339          ctx.state = ServiceContext.FAILED;
340          ctx.problem = e;
341          log.warn("Problem starting service " + serviceName, e);
342          return;
343       }
344       // Those that depend on me are waiting for my start, recursively start them
345
log.debug("Starting dependent components for: " + serviceName
346             + " dependent components: " + ctx.dependsOnMe);
347       ArrayList JavaDoc<ServiceContext> tmp = new ArrayList JavaDoc<ServiceContext>(ctx.dependsOnMe);
348       for (int n = 0; n < tmp.size(); n++)
349       {
350          // marcf fixme circular dependencies?
351
ServiceContext ctx2 = tmp.get(n);
352          start(ctx2.objectName);
353       }
354       tmp.clear();
355    }
356
357    public void restart(ObjectName JavaDoc serviceName) throws Exception JavaDoc
358    {
359       if (serviceName == null)
360       {
361          log.warn("Ignoring request to restart null service: ", new Exception JavaDoc("STACKTRACE"));
362          return;
363       }
364
365       log.debug("restarting service " + serviceName);
366       stop(serviceName);
367       start(serviceName);
368    }
369
370    public void stop(ObjectName JavaDoc serviceName) throws Exception JavaDoc
371    {
372       if (serviceName == null)
373       {
374          log.warn("Ignoring request to stop null service: ", new Exception JavaDoc("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 we are already stopped (can happen in dependencies) just return
388
if (ctx.state != ServiceContext.RUNNING) return;
389
390       // JSR 77 and to avoid circular dependencies
391
ctx.state = ServiceContext.STOPPED;
392
393       log.debug("stopping dependent services for: " + serviceName
394             + " dependent services are: " + ctx.dependsOnMe);
395       
396       ArrayList JavaDoc<ServiceContext> tmp = new ArrayList JavaDoc<ServiceContext>(ctx.dependsOnMe);
397       for (int n = 0; n < tmp.size(); n++)
398       {
399          // stop all the mbeans that depend on me
400
ServiceContext ctx2 = tmp.get(n);
401          ObjectName JavaDoc other = ctx2.objectName;
402          stop(other);
403       }
404       tmp.clear();
405
406       // Call stop on the service Proxy
407
if (ctx.proxy != null)
408       {
409          try
410          {
411             ctx.proxy.stop();
412             sendControllerNotification(ServiceMBean.STOP_EVENT, serviceName);
413          }
414          catch (Throwable JavaDoc 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 JavaDoc serviceName) throws Exception JavaDoc
424    {
425       if (serviceName == null)
426       {
427          log.warn("Ignoring request to destroy null service: ", new Exception JavaDoc("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 we are already destroyed (can happen in dependencies) just return
441
if (ctx.state == ServiceContext.DESTROYED ||
442           ctx.state == ServiceContext.NOTYETINSTALLED)
443          return;
444       
445       // If we are still running, stop service first
446
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       // JSR 77, and to avoid circular dependencies
453
ctx.state = ServiceContext.DESTROYED;
454
455       log.debug("destroying dependent services for: " + serviceName
456             + " dependent services are: " + ctx.dependsOnMe);
457       
458       ArrayList JavaDoc<ServiceContext> tmp = new ArrayList JavaDoc<ServiceContext>(ctx.dependsOnMe);
459       for (int n = 0; n < tmp.size(); n++)
460       {
461          // destroy all the mbeans that depend on me
462
ServiceContext ctx2 = tmp.get(n);
463          ObjectName JavaDoc other = ctx2.objectName;
464          destroy(other);
465       }
466       tmp.clear();
467
468       // Call destroy on the service Proxy
469
if (ctx.proxy != null)
470       {
471          try
472          {
473             ctx.proxy.destroy();
474             sendControllerNotification(ServiceMBean.DESTROY_EVENT, serviceName);
475          }
476          catch (Throwable JavaDoc 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 JavaDoc objectName) throws Exception JavaDoc
486    {
487       if (objectName == null)
488       {
489          log.warn("Ignoring request to remove null service: ", new Exception JavaDoc("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       // Notify those that think I depend on them
502
Iterator JavaDoc iterator = ctx.iDependOn.iterator();
503       while (iterator.hasNext())
504       {
505          ServiceContext iDependOnContext = (ServiceContext) iterator.next();
506          iDependOnContext.dependsOnMe.remove(ctx);
507
508          // Remove any context whose only reason for existence is that
509
// we depend on it, i.e. it otherwise unknown to the system
510
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       //We remove all traces of our dependency configuration, since we
519
//don't know what will show up the next time we are deployed.
520
ctx.iDependOn.clear();
521
522       // Do we have a deployed MBean?
523
if (server.isRegistered(objectName))
524       {
525          log.debug("removing " + objectName + " from server");
526
527          // Remove the context, unless it is still recording dependencies
528
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          // remove the mbean from the instaled ones
538
installedServices.remove(ctx);
539          creator.remove(objectName);
540       }
541       else
542       {
543          // Remove the context, unless it is still recording dependencies
544
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       // This context is no longer installed, but it may still exist
557
// to record dependent services
558
ctx.state = ServiceContext.NOTYETINSTALLED;
559    }
560
561    /**
562     * Lookup the ServiceContext for the given serviceName
563     *
564     * @jmx.managed-operation
565     */

566    public ServiceContext getServiceContext(ObjectName JavaDoc 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 JavaDoc<ServiceContext> servicesCopy = new ArrayList JavaDoc<ServiceContext>(installedServices);
577
578       int serviceCounter = 0;
579       ObjectName JavaDoc name = null;
580
581       ListIterator JavaDoc i = servicesCopy.listIterator(servicesCopy.size());
582       while (i.hasPrevious())
583       {
584          ServiceContext ctx = (ServiceContext) i.previous();
585          name = ctx.objectName;
586
587          // Go through the full stop/destroy cycle
588
try
589          {
590             stop(name);
591          }
592          catch (Throwable JavaDoc e)
593          {
594             log.error("Could not stop mbean: " + name, e);
595          }
596          try
597          {
598             destroy(name);
599          }
600          catch (Throwable JavaDoc e)
601          {
602             log.error("Could not destroy mbean: " + name, e);
603          }
604          try
605          {
606             remove(name);
607             serviceCounter++;
608          }
609          catch (Throwable JavaDoc e)
610          {
611             log.error("Could not remove mbean: " + name, e);
612          }
613       }
614       log.debug("Stopped " + serviceCounter + " services");
615    }
616    
617    // MBeanRegistration implementation ----------------------------------------
618

619    /**
620     * #Description of the Method
621     *
622     * @param server Description of Parameter
623     * @param name Description of Parameter
624     * @return Description of the Returned Value
625     * @exception Exception Description of Exception
626     */

627    public ObjectName JavaDoc preRegister(MBeanServer JavaDoc server, ObjectName JavaDoc name)
628          throws Exception JavaDoc
629    {
630       this.server = server;
631
632       creator = new OldServiceCreator(server);
633       configurator = new OldServiceConfigurator(server, this, creator);
634
635       // Register the ServiceController as a running service
636
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 JavaDoc registrationDone)
644    {
645       if (!registrationDone.booleanValue())
646       {
647          log.info("Registration of ServiceController failed");
648       }
649    }
650
651    public void preDeregister()
652          throws Exception JavaDoc
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    // Package Protected ---------------------------------------------
667

668    // Create a Service Context for the service, or get one if it exists
669
synchronized ServiceContext createServiceContext(ObjectName JavaDoc objectName)
670    {
671       // If it is already there just return it
672
if (nameToServiceMap.containsKey(objectName))
673          return nameToServiceMap.get(objectName);
674
675       // If not create it, add it and return it
676
ServiceContext ctx = new ServiceContext();
677       ctx.objectName = objectName;
678
679       // we keep track of these here
680
nameToServiceMap.put(objectName, ctx);
681
682       return ctx;
683    }
684
685    void registerDependency(ObjectName JavaDoc needs, ObjectName JavaDoc 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 depends on usedCtx
695
needsCtx.iDependOn.add(usedCtx);
696          // UsedCtx needs to know I depend on him
697
usedCtx.dependsOnMe.add(needsCtx);
698       }
699    }
700
701    // Private -------------------------------------------------------
702

703    /**
704     * Register the service context and its dependencies against the microkernel.
705     * If the context is already registered it does nothing.
706     *
707     * @param ctx the ServiceContext to register
708     * @param depends a collection of ObjectNames of services the registered service depends on
709     */

710    private void register(ServiceContext ctx, Collection JavaDoc depends) throws Exception JavaDoc
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 JavaDoc i = depends.iterator(); i.hasNext();)
719          {
720             registerDependency(ctx.objectName, (ObjectName JavaDoc) i.next());
721          }
722       }
723
724       // Get the fancy service proxy (for the lifecycle API), if needed
725
if (ctx.proxy == null)
726          ctx.proxy = getServiceProxy(ctx.objectName, null);
727    }
728    
729    /**
730     * Get the Service interface through which the mbean given by objectName
731     * will be managed.
732     *
733     * @param objectName
734     * @param serviceFactory
735     * @return The Service value
736     *
737     * @throws ClassNotFoundException
738     * @throws InstantiationException
739     * @throws IllegalAccessException
740     */

741    private Service getServiceProxy(ObjectName JavaDoc objectName, String JavaDoc serviceFactory)
742          throws ClassNotFoundException JavaDoc, InstantiationException JavaDoc,
743          IllegalAccessException JavaDoc, JMException JavaDoc
744    {
745       Service service = null;
746       ClassLoader JavaDoc loader = Thread.currentThread().getContextClassLoader();
747       if (serviceFactory != null && serviceFactory.length() > 0)
748       {
749          Class JavaDoc clazz = loader.loadClass(serviceFactory);
750          ServiceFactory factory = (ServiceFactory) clazz.newInstance();
751          service = factory.createService(server, objectName);
752       }
753       else
754       {
755          MBeanInfo JavaDoc info = server.getMBeanInfo(objectName);
756          MBeanOperationInfo JavaDoc[] opInfo = info.getOperations();
757          Class JavaDoc[] interfaces = {Service.class};
758          InvocationHandler JavaDoc handler = new ServiceProxy(objectName, opInfo);
759          service = (Service) Proxy.newProxyInstance(Service.class.getClassLoader(), interfaces, handler);
760       }
761
762       return service;
763    }
764
765    /**
766     * Sends outs controller notifications about service lifecycle events
767     */

768    private void sendControllerNotification(String JavaDoc type, ObjectName JavaDoc serviceName)
769    {
770       Notification JavaDoc notification = new Notification JavaDoc(type, this, super.nextNotificationSequenceNumber());
771       notification.setUserData(serviceName);
772       sendNotification(notification);
773    }
774    
775    // Inner classes -------------------------------------------------
776

777    /**
778     * A mapping from the Service interface method names to the corresponding
779     * index into the ServiceProxy.hasOp array.
780     */

781    private static HashMap JavaDoc<String JavaDoc, Integer JavaDoc> serviceOpMap = new HashMap JavaDoc<String JavaDoc, Integer JavaDoc>();
782
783    /**
784     * An implementation of InvocationHandler used to proxy of the Service
785     * interface for mbeans. It determines which of the start/stop
786     * methods of the Service interface an mbean implements by inspecting its
787     * MBeanOperationInfo values. Each Service interface method that has a
788     * matching operation is forwarded to the mbean by invoking the method
789     * through the MBeanServer object.
790     */

791    public class ServiceProxy implements InvocationHandler JavaDoc
792    {
793       private boolean[] hasOp = {false, false, false, false};
794       private ObjectName JavaDoc objectName;
795
796       /** Whether we have the lifecycle method */
797       private boolean hasJBossInternalLifecycle;
798
799       /**
800        * Go through the opInfo array and for each operation that matches on of
801        * the Service interface methods set the corresponding hasOp array value
802        * to true.
803        *
804        * @param objectName
805        * @param opInfo
806        */

807       public ServiceProxy(ObjectName JavaDoc objectName, MBeanOperationInfo JavaDoc[] opInfo)
808       {
809          this.objectName = objectName;
810
811          for (int op = 0; op < opInfo.length; op++)
812          {
813             MBeanOperationInfo JavaDoc info = opInfo[op];
814             String JavaDoc name = info.getName();
815
816             if (name.equals(JBOSS_INTERNAL_LIFECYCLE))
817             {
818                hasJBossInternalLifecycle = true;
819                continue;
820             }
821
822             Integer JavaDoc opID = serviceOpMap.get(name);
823             if (opID == null)
824             {
825                continue;
826             }
827
828             // Validate that is a no-arg void return type method
829
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       /**
843        * Map the method name to a Service interface method index and if the
844        * corresponding hasOp array element is true, dispatch the method to the
845        * mbean we are proxying.
846        *
847        * @param proxy
848        * @param method
849        * @param args
850        * @return Always null.
851        * @throws Throwable
852        */

853       public Object JavaDoc invoke(Object JavaDoc proxy, Method JavaDoc method, Object JavaDoc[] args)
854             throws Throwable JavaDoc
855       {
856          String JavaDoc name = method.getName();
857
858          if (hasJBossInternalLifecycle)
859          {
860             try
861             {
862                server.invoke(objectName, JBOSS_INTERNAL_LIFECYCLE, new Object JavaDoc[] { name }, JBOSS_INTERNAL_LIFECYCLE_SIG);
863                return null;
864             }
865             catch (Exception JavaDoc e)
866             {
867                throw JMXExceptionDecoder.decode(e);
868             }
869          }
870
871          Integer JavaDoc opID = serviceOpMap.get(name);
872
873          if (opID != null && hasOp[opID.intValue()] == true)
874          {
875             // deal with those pesky JMX exceptions
876
try
877             {
878                String JavaDoc[] sig = {};
879                server.invoke(objectName, name, args, sig);
880             }
881             catch (Exception JavaDoc e)
882             {
883                throw JMXExceptionDecoder.decode(e);
884             }
885          }
886
887          return null;
888       }
889    }
890
891    /**
892     * Initialize the service operation map.
893     */

894    static
895    {
896       serviceOpMap.put("create", new Integer JavaDoc(0));
897       serviceOpMap.put("start", new Integer JavaDoc(1));
898       serviceOpMap.put("destroy", new Integer JavaDoc(2));
899       serviceOpMap.put("stop", new Integer JavaDoc(3));
900    }
901 }
902
Popular Tags