Source code: org/mobicents/slee/container/service/ServiceComponent.java
1 /*
2 * ServiceComponent.java
3 *
4 * Created on Jun 7, 2005
5 *
6 * Created by: M. Ranganathan
7 *
8 * The Mobicents Open SLEE project
9 *
10 * A SLEE for the people!
11 *
12 * The source code contained in this file is in in the public domain.
13 * It can be used in any project or product without prior permission,
14 * license or royalty payments. There is NO WARRANTY OF ANY KIND,
15 * EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION,
16 * THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
17 * AND DATA ACCURACY. We do not warrant or make any representations
18 * regarding the use of the software or the results thereof, including
19 * but not limited to the correctness, accuracy, reliability or
20 * usefulness of the software.
21 */
22
23 package org.mobicents.slee.container.service;
24
25 import java.io.Serializable;
26 import java.lang.reflect.Constructor;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.Iterator;
30 import java.util.Map;
31
32 import javax.management.InstanceNotFoundException;
33 import javax.management.MBeanRegistrationException;
34 import javax.management.MalformedObjectNameException;
35 import javax.management.ObjectName;
36 import javax.slee.InvalidArgumentException;
37 import javax.slee.SbbID;
38 import javax.slee.ServiceID;
39 import javax.slee.UnrecognizedSbbException;
40 import javax.slee.UnrecognizedServiceException;
41 import javax.slee.management.DeployableUnitID;
42 import javax.slee.management.DeploymentException;
43 import javax.slee.management.ManagementException;
44 import javax.slee.management.SbbDescriptor;
45 import javax.slee.management.ServiceState;
46 import javax.slee.management.UsageParameterSetNameAlreadyExistsException;
47 import javax.slee.usage.UnrecognizedUsageParameterSetNameException;
48 import javax.transaction.SystemException;
49
50 import org.jboss.logging.Logger;
51 import org.mobicents.slee.container.SleeContainer;
52 import org.mobicents.slee.container.deployment.ConcreteUsageParameterMBeanInterfaceGenerator;
53 import org.mobicents.slee.container.management.DeployableUnitIDImpl;
54 import org.mobicents.slee.container.management.DeployedComponent;
55 import org.mobicents.slee.container.management.InstalledUsageParameterSet;
56 import org.mobicents.slee.container.management.SbbDescriptorImpl;
57 import org.mobicents.slee.container.management.SbbIDImpl;
58 import org.mobicents.slee.container.management.ServiceDescriptorImpl;
59 import org.mobicents.slee.container.management.ServiceIDImpl;
60 import org.mobicents.slee.container.management.jmx.SbbUsageMBeanImpl;
61 import org.mobicents.slee.runtime.Cacheable;
62 import org.mobicents.slee.runtime.transaction.TransactionManagerImpl;
63 import org.mobicents.slee.runtime.transaction.TransactionalAction;
64
65 /**
66 * This represents the service component - the static part of a service
67 * including the descriptor and service state. This resides in the deployment
68 * cache. The state in this object is persisted to disk and must survive SLEE
69 * restarts. This structure includes the UsageMBeans and pointer to the Service
70 * Descriptor.
71 *
72 * @see Service
73 *
74 *
75 */
76 public class ServiceComponent implements DeployedComponent, Serializable {
77
78
79 private ServiceIDImpl serviceID;
80
81 private ServiceState serviceState;
82 private static Logger logger = Logger.getLogger(ServiceComponent.class);
83 private DeployableUnitID deployableUnitID;
84 private ObjectName usageMBean;
85 private boolean pendingRemove;
86 private transient ServiceDescriptorImpl serviceDescriptor;
87
88
89
90 // A set of usage parameter names. Index into the hash map is
91 // the sbbid.
92
93 private HashMap usageParameterNames;
94
95 // A set of usage parameter object names.
96
97 private HashMap usageParameterObjectNames;
98
99 private HashSet sbbComponents;
100
101 public ServiceComponent(ServiceDescriptorImpl serviceDescriptor) {
102
103 this.serviceID = (ServiceIDImpl) serviceDescriptor.getID();
104
105 this.serviceState = ServiceState.INACTIVE;
106
107 this.usageParameterNames = new HashMap();
108 this.usageParameterObjectNames = new HashMap();
109 this.deployableUnitID = serviceDescriptor.getDeployableUnit();
110 this.serviceDescriptor = serviceDescriptor;
111 this.sbbComponents = new HashSet();
112 SbbID sbbid = this.serviceDescriptor.getRootSbb();
113 this.enumerateSbbs(sbbid);
114
115 }
116
117 private void enumerateSbbs(SbbID sbbId) {
118 this.sbbComponents.add(sbbId);
119 SbbDescriptor sbbDesc = SleeContainer.lookupFromJndi().getSbbComponent(sbbId);
120 SbbID[] sbbIds = sbbDesc.getSbbs();
121 if ( sbbIds != null ) {
122 for ( int i = 0; i < sbbIds.length; i ++ ) {
123 enumerateSbbs(sbbIds[i]);
124 }
125 }
126 }
127
128 /**
129 * Get the names of all usage parameters.
130 *
131 * @return
132 */
133 public HashSet getAllUsageParameterNames() {
134 HashSet retval = new HashSet();
135 for (Iterator it = this.usageParameterNames.values().iterator(); it
136 .hasNext();) {
137 HashSet names = (HashSet) it.next();
138 retval.addAll(names);
139 }
140 return retval;
141 }
142
143
144
145
146
147
148 protected void registerSbbUsageParameter(ServiceID serviceId, SbbID sbbId,
149 ObjectName sbbUsageParameter) {
150 String key = Service.getUsageParametersPathName(serviceId,sbbId);
151 if ( logger.isDebugEnabled()) {
152 logger.debug("registerSbbUsageParameter: serviceId = " + serviceId + " sbbId = " + sbbId + " key = " + key);
153 }
154 this.usageParameterObjectNames.put( key, sbbUsageParameter);
155
156 }
157 private void registerSbbUsageParameter(ServiceID serviceId, SbbID sbbId, String name,
158 ObjectName sbbUsageParameter) {
159 if ( logger.isDebugEnabled() ) {
160 logger.debug("registerSbbUsageParameter: serviceId = " + serviceId +
161 " sbbId = "+ sbbId +
162 " name = " + name +
163 " sbbUsageParameter = " + sbbUsageParameter);
164 }
165 this.usageParameterObjectNames.put( Service.getUsageParametersPathName(serviceId,sbbId,name), sbbUsageParameter);
166 }
167
168 public ObjectName getUsageParameterObjectName( SbbID sbbId) {
169 String key = Service.getUsageParametersPathName(serviceID,sbbId);
170 logger.debug("getUsageParameterObjectName: " + sbbId + " key = " + key);
171 return (ObjectName) this.usageParameterObjectNames.get(key);
172 }
173
174 public ObjectName getUsageParameterObjectName( SbbID sbbId, String name)
175 throws UnrecognizedUsageParameterSetNameException, InvalidArgumentException {
176
177 String key = Service.getUsageParametersPathName(serviceID,sbbId,name);
178
179 if ( ! this.getAllUsageParameterNames().contains(name)) {
180 //logger.debug("usageParamNames = " + usageParameterNames);
181 throw new UnrecognizedUsageParameterSetNameException
182 ("Illegal arg - param name not found for this service " + name);
183 }
184
185 if (this.usageParameterNames.get(sbbId.toString()) == null ) {
186 throw new InvalidArgumentException ("no usage parameter found for this sbb");
187 }
188
189 logger.debug("getUsageParameterObjectName: " + sbbId
190 + " name = " + name + " key = " + key);
191
192 return (ObjectName) this.usageParameterObjectNames.get(key);
193 }
194 /**
195 * Install a usage parameter set.
196 *
197 * @param service
198 * @param sbbId
199 * @param name
200 * @throws Exception
201 */
202 public void installUsageParameter(SbbID sbbId, String name)
203 throws Exception {
204 boolean b = SleeContainer.getTransactionManager().requireTransaction();
205
206 if ( logger.isDebugEnabled() ) {
207 logger.debug("installUsageParameter: sbbId = " + sbbId + " name = " + name);
208 }
209 try {
210 if (sbbId == null || name == null)
211 throw new NullPointerException(" Null arg! ");
212 ServiceID serviceID = this.getServiceID();
213
214 SbbDescriptorImpl sbbDescriptor = (SbbDescriptorImpl) SleeContainer
215 .lookupFromJndi().getSbbComponent(sbbId);
216
217 if (sbbDescriptor == null)
218 throw new UnrecognizedSbbException("Unrecognized Sbb");
219
220
221
222 if (this.usageParameterNames.get(sbbId.toString()) != null
223 && ((HashSet) this.usageParameterNames.get(sbbId.toString()))
224 .contains(name))
225 throw new UsageParameterSetNameAlreadyExistsException(
226 "Usage Parameter already exists " + name);
227
228 // Create the actual usage parameter instance.
229 Class usageParameterClass = sbbDescriptor.getUsageParameterClass();
230 if (usageParameterClass == null)
231 throw new RuntimeException("Usage parameter class not found !");
232 Constructor cons = usageParameterClass.getConstructor(new Class[] {
233 ServiceIDImpl.class, SbbIDImpl.class });
234 Object usageParm = cons
235 .newInstance(new Object[] { serviceID, sbbId });
236 String pathName = Service.getUsageParametersPathName(this.getServiceID(),
237 (SbbIDImpl) sbbDescriptor.getID(), name);
238
239 // The service instance houses the actual usage parameter.
240 try {
241 Service service = SleeContainer.lookupFromJndi().getService(this.serviceID);
242 service.addUsageParameter(pathName, usageParm);
243 } catch ( Exception ex ) {
244 throw new ManagementException ("Service not found " + serviceID);
245 }
246
247 HashSet hset = (HashSet) this.usageParameterNames.get(sbbId.toString());
248 if (hset == null) {
249 hset = new HashSet();
250 this.usageParameterNames.put(sbbId.toString(), hset);
251 }
252 hset.add(name);
253
254 // TODO: The following code creating the SbbUsageMBean instance is
255 // the same
256 // as in installDefaultUsageParameters. Should be extracted.
257 String usageParameterMBeanClassName = sbbDescriptor
258 .getUsageParametersInterface()
259 + "MBeanImpl";
260 Class[] args = { ServiceID.class, SbbID.class,
261 String.class, String.class, usageParameterClass };
262 Class usageParameterMBeanClass = sbbDescriptor.getClassLoader()
263 .loadClass(usageParameterMBeanClassName);
264 Constructor constructor = usageParameterMBeanClass
265 .getConstructor(args);
266 Object[] objs = { this.serviceID, sbbId,
267 name,
268 sbbDescriptor.getUsageParametersInterface() + "MBean",
269 usageParm };
270 SbbUsageMBeanImpl usageMbean = (SbbUsageMBeanImpl) constructor
271 .newInstance(objs);
272 String mbeanName = "slee:SbbUsageMBean=" + pathName;
273 ObjectName oname = new ObjectName(mbeanName);
274 SleeContainer.lookupFromJndi().getMBeanServer().registerMBean(
275 usageMbean, oname);
276
277 registerSbbUsageParameter(this.serviceID, sbbId, name, oname);
278
279 InstalledUsageParameterSet usageParam = (InstalledUsageParameterSet) usageParm;
280 usageParam.setName(name);
281 usageParam.setSbbUsageMBean(usageMbean);
282 usageMbean.setUsageParameter(usageParam);
283
284 } catch (Exception e) {
285 String s = "Unexpected exception !";
286 logger.error(s, e);
287 try {
288 SleeContainer.getTransactionManager().setRollbackOnly();
289 } catch (SystemException ex) {
290 s = "Tx manager Failure!";
291 }
292 throw e;
293 } finally {
294 try {
295 if (b)
296 SleeContainer.getTransactionManager().commit();
297 } catch (Exception ex) {
298 throw new RuntimeException("Unexpected error in tx manager", ex);
299 }
300 }
301 }
302
303 /**
304 * Installs the default usage parameter set.
305 *
306 * @param descriptor --
307 * the sbb descriptor of the root sbb of the service.
308 *
309 * @throws Exception
310 */
311 public void installDefaultUsageParameters(SbbDescriptorImpl descriptor)
312 throws Exception {
313
314 logger.debug("Installing default usage parameter for "
315 + descriptor.getID());
316 ClassLoader currentClassLoader = Thread.currentThread()
317 .getContextClassLoader();
318 Thread.currentThread().setContextClassLoader(
319 descriptor.getClassLoader());
320 try {
321 if (descriptor.getUsageParametersInterface() != null) {
322 Class usageParameterClass = descriptor.getUsageParameterClass();
323
324 Constructor cons = usageParameterClass
325 .getConstructor(new Class[] { ServiceIDImpl.class,
326 SbbIDImpl.class });
327 Object usageParm = cons.newInstance(new Object[] {
328 this.getServiceID(), descriptor.getID() });
329 InstalledUsageParameterSet usageParam = (InstalledUsageParameterSet) usageParm;
330 String pathName = Service.getUsageParametersPathName(this.getServiceID(),(SbbID) descriptor
331 .getID());
332
333 if ( logger.isDebugEnabled()) {
334 logger.debug(" Putting usage parameter into table " + pathName);
335 }
336
337 Service service = SleeContainer.lookupFromJndi().getService(this.serviceID);
338 service.addUsageParameter(pathName, usageParam);
339
340 // Creating the custom MBean Interface
341 ConcreteUsageParameterMBeanInterfaceGenerator mbeanInterfaceGenerator = new ConcreteUsageParameterMBeanInterfaceGenerator(
342 descriptor);
343 mbeanInterfaceGenerator
344 .generateConcreteUsageParameterMBeanInterface();
345 String usageParameterMBeanClassName = descriptor
346 .getUsageParametersInterface()
347 + "MBeanImpl";
348 Class usageParameterMBeanClass = Thread.currentThread()
349 .getContextClassLoader().loadClass(
350 usageParameterMBeanClassName);
351 Class[] args = { ServiceID.class,
352 SbbID.class, String.class, String.class,
353 usageParameterClass };
354 Constructor constructor = usageParameterMBeanClass
355 .getConstructor(args);
356
357 Object[] objs = { this.serviceID,
358 (SbbID) descriptor.getID(), null,
359 descriptor.getUsageParametersInterface() + "MBean",
360 usageParam };
361 Object usageMbean = constructor.newInstance(objs);
362 usageParam.setSbbUsageMBean((SbbUsageMBeanImpl) usageMbean);
363 ((SbbUsageMBeanImpl) usageMbean).setUsageParameter(usageParam);
364
365 String mbeanName = "slee:SbbUsageMBean=" + pathName;
366 ObjectName oname = new ObjectName(mbeanName);
367 SleeContainer.lookupFromJndi().getMBeanServer().registerMBean(
368 usageMbean, oname);
369
370
371 registerSbbUsageParameter(this.serviceID, (SbbID) descriptor
372 .getID(), oname);
373
374
375 }
376 } finally {
377 Thread.currentThread().setContextClassLoader(currentClassLoader);
378 }
379 SbbID[] sbbs = descriptor.getSbbs();
380 if (sbbs == null)
381 return;
382 for (int i = 0; i < sbbs.length; i++) {
383 SbbDescriptorImpl desc = (SbbDescriptorImpl) SleeContainer
384 .lookupFromJndi().getSbbComponent(sbbs[i]);
385
386
387 this.installDefaultUsageParameters(desc);
388 }
389
390 }
391
392
393 /**
394 * Remove the usage parameter object and unregister the mbean for the usage
395 * parameter object.
396 *
397 * @param sbbId
398 * @param name
399 * @throws ManagementException
400 * @throws UnrecognizedUsageParameterSetNameException
401 */
402 public void removeUsageParameter(SbbID sbbId, String name)
403 throws ManagementException,
404 UnrecognizedUsageParameterSetNameException, UnrecognizedSbbException ,
405 InvalidArgumentException {
406
407
408 if ( ! this.sbbComponents.contains(sbbId))
409 throw new UnrecognizedSbbException ("SBB does not belong to this service " + sbbId);
410
411 HashSet names = (HashSet) this.usageParameterNames
412 .get(sbbId.toString());
413
414
415 if ( names == null )
416 throw new InvalidArgumentException ("UsageParameter name " + name + " not found ");
417
418 if ( !names.contains(name)) {
419 throw new UnrecognizedUsageParameterSetNameException(
420 "usage parameter name not found " + name);
421 }
422 names.remove(name);
423 String pathName = Service.getUsageParametersPathName(this.getServiceID(),
424 sbbId, name);
425
426 try {
427 Service service = SleeContainer.lookupFromJndi().getService(this.serviceID);
428 service.removeUsageParameter(pathName);
429 } catch ( Exception ex ) {
430 throw new ManagementException ("Unexpected exception!", ex);
431 }
432 String mbeanName = "slee:SbbUsageMBean=" + pathName;
433 ObjectName oname = null;
434 try {
435 oname = new ObjectName(mbeanName);
436
437 } catch (MalformedObjectNameException e) {
438 logger.fatal(" malformed url! " + mbeanName, e);
439 throw new ManagementException("error unregistering mbean ", e);
440 }
441 // Remove this from our set of usage parameer object names.
442 this.usageParameterObjectNames.remove(pathName);
443
444 try {
445 SleeContainer.lookupFromJndi().getMBeanServer().unregisterMBean(
446 oname);
447 } catch (InstanceNotFoundException e1) {
448 throw new ManagementException("Instance not found ! " + oname);
449 } catch (MBeanRegistrationException e1) {
450 logger.fatal("unexpected exception ", e1);
451 throw new ManagementException("Instance not registered! " + oname);
452 }
453 }
454
455 /**
456 * Return the set of named usage parameter names as an array.
457 *
458 * @param sbbId --
459 * sbb id for which to get the usage parameter set.
460 * @return
461 */
462 public String[] getNamedUsageParameterSets(SbbID sbbId) throws InvalidArgumentException {
463
464 HashSet paramSet = (HashSet) this.usageParameterNames.get(sbbId.toString());
465 String[] retval = null;
466 if (paramSet != null) {
467
468 retval = new String[paramSet.size()];
469 paramSet.toArray(retval);
470 return retval;
471 } else
472 throw new InvalidArgumentException ( "No named usage parameters for this sbb " + sbbId);
473
474
475
476 }
477 /**
478 * Returns an iterator with all the usage parameter names.
479 *
480 * @return
481 */
482 public Iterator getSbbUsageMBeans() {
483
484 return this.usageParameterObjectNames.values().iterator();
485 }
486
487
488
489
490 /**
491 * Return the deployable unit id for this service
492 *
493 * @return
494 */
495 public DeployableUnitID getDeployableUnit() {
496
497 return this.deployableUnitID;
498 }
499
500 public void setDeployableUnit(DeployableUnitID deployableUnitID) {
501 this.deployableUnitID = deployableUnitID;
502 }
503
504 /**
505 * Set the service state.
506 *
507 * @param serviceState --
508 * service state to set.
509 */
510 public void setState(ServiceState serviceState) {
511 this.serviceState = serviceState;
512
513 }
514
515 /**
516 * Returns the service state.
517 *
518 * @return
519 */
520 public ServiceState getState() {
521
522 return this.serviceState;
523 }
524
525 /**
526 * Get the service id for this service component.
527 *
528 * @return serviceID
529 */
530 public ServiceID getServiceID() {
531
532 return this.serviceID;
533 }
534
535 /**
536 * @return
537 */
538 public ServiceDescriptorImpl getServiceDescriptor() {
539
540 return this.serviceDescriptor;
541 }
542
543 /**
544 * Get the root sbb component for the service
545 *
546 * @return the root sbb component for the service.
547 */
548 public SbbDescriptorImpl getRootSbbComponent() {
549 return (SbbDescriptorImpl) SleeContainer.lookupFromJndi()
550 .getSbbComponent(serviceDescriptor.getRootSbb());
551 }
552
553 public void setUsageMBeanName(ObjectName usageMBean) {
554 this.usageMBean = usageMBean;
555
556 }
557
558
559
560 public ObjectName getUsageMBean() {
561 return this.usageMBean;
562 }
563
564
565 /**
566 * Mark for garbage collection.
567 *
568 */
569 public void markForRemove() {
570 this.pendingRemove = true;
571 }
572
573 /**
574 * Return true if marked for GC.
575 */
576 public boolean isMarkedForRemove() {
577 return this.pendingRemove;
578 }
579
580
581
582
583 /* (non-Javadoc)
584 * @see org.mobicents.slee.container.management.DeployedComponent#checkDeployment()
585 */
586 public void checkDeployment() throws DeploymentException {
587
588
589 }
590
591 /**
592 * @param sbbId
593 * @return
594 */
595 public boolean isComponent(SbbID sbbId) {
596 // TODO Auto-generated method stub
597 return this.sbbComponents.contains(sbbId);
598 }
599
600
601
602
603
604
605 }
606