001 /*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License"). You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 * Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 * Portions Copyright 2006-2007-2008 Sun Microsystems, Inc.
026 */
027 package org.opends.server.config;
028 import org.opends.messages.Message;
029
030
031
032 import java.util.ArrayList;
033 import java.util.Iterator;
034 import java.util.LinkedHashMap;
035 import java.util.LinkedHashSet;
036 import java.util.Set;
037 import java.util.concurrent.CopyOnWriteArrayList;
038 import javax.management.Attribute;
039 import javax.management.AttributeList;
040 import javax.management.AttributeNotFoundException;
041 import javax.management.DynamicMBean;
042 import javax.management.MBeanAttributeInfo;
043 import javax.management.InvalidAttributeValueException;
044 import javax.management.MBeanConstructorInfo;
045 import javax.management.MBeanException;
046 import javax.management.MBeanInfo;
047 import javax.management.MBeanNotificationInfo;
048 import javax.management.MBeanOperationInfo;
049 import javax.management.MBeanServer;
050 import javax.management.ObjectName;
051
052 import org.opends.server.admin.std.server.MonitorProviderCfg;
053 import org.opends.server.api.AlertGenerator;
054 import org.opends.server.api.ClientConnection;
055 import org.opends.server.api.DirectoryServerMBean;
056 import org.opends.server.api.InvokableComponent;
057 import org.opends.server.api.MonitorProvider;
058 import org.opends.server.core.DirectoryServer;
059 import org.opends.server.protocols.jmx.Credential;
060 import org.opends.server.types.AttributeType;
061 import org.opends.server.types.AttributeValue;
062 import org.opends.server.types.DebugLogLevel;
063 import org.opends.server.types.DirectoryException;
064 import org.opends.server.types.DN;
065 import org.opends.server.types.InvokableMethod;
066 import org.opends.server.types.ResultCode;
067 import org.opends.server.types.SearchScope;
068
069 import static org.opends.server.loggers.debug.DebugLogger.*;
070 import static org.opends.server.loggers.ErrorLogger.*;
071 import org.opends.server.loggers.debug.DebugTracer;
072 import static org.opends.messages.ConfigMessages.*;
073 import static org.opends.server.util.ServerConstants.*;
074 import static org.opends.server.util.StaticUtils.*;
075 import org.opends.server.protocols.jmx.JmxClientConnection;
076 import org.opends.server.protocols.asn1.ASN1OctetString;
077 import org.opends.server.protocols.internal.InternalClientConnection;
078 import org.opends.server.protocols.ldap.LDAPFilter;
079 import org.opends.server.protocols.internal.InternalSearchOperation ;
080 import org.opends.server.types.LDAPException;
081
082
083
084 /**
085 * This class defines a JMX MBean that can be registered with the Directory
086 * Server to provide monitoring and statistical information, provide read and/or
087 * read-write access to the configuration, and provide notifications and alerts
088 * if a significant event or severe/fatal error occurs.
089 */
090 @org.opends.server.types.PublicAPI(
091 stability=org.opends.server.types.StabilityLevel.VOLATILE,
092 mayInstantiate=true,
093 mayExtend=false,
094 mayInvoke=true)
095 public final class JMXMBean
096 implements DynamicMBean, DirectoryServerMBean
097 {
098 /**
099 * The tracer object for the debug logger.
100 */
101 private static final DebugTracer TRACER = getTracer();
102
103 /**
104 * The fully-qualified name of this class.
105 */
106 private static final String CLASS_NAME = "org.opends.server.config.JMXMBean";
107
108
109
110 // The set of alert generators for this MBean.
111 private CopyOnWriteArrayList<AlertGenerator> alertGenerators;
112
113 // The set of invokable components for this MBean.
114 private CopyOnWriteArrayList<InvokableComponent> invokableComponents;
115
116 // The set of monitor providers for this MBean.
117 private CopyOnWriteArrayList<MonitorProvider<? extends MonitorProviderCfg>>
118 monitorProviders;
119
120 // The DN of the configuration entry with which this MBean is associated.
121 private DN configEntryDN;
122
123 // The object name for this MBean.
124 private ObjectName objectName;
125
126
127 /**
128 * Creates a JMX object name string based on a DN.
129 *
130 * @param configEntryDN The DN of the configuration entry with which
131 * this ObjectName is associated.
132 *
133 * @return The string representation of the JMX Object Name
134 * associated with the input DN.
135 */
136 public static String getJmxName (DN configEntryDN)
137 {
138 String typeStr = null;
139 String nameStr = null ;
140 try
141 {
142 String dnString = configEntryDN.toString();
143 if ( ! ((dnString == null) || (dnString.length() == 0)))
144 {
145 StringBuilder buffer = new StringBuilder(dnString.length());
146 String rdns[] = dnString.replace(',', ';').split(";");
147 for (int j = rdns.length - 1; j >= 0; j--)
148 {
149 int rdnIndex = rdns.length - j;
150 buffer.append(",Rdn" + rdnIndex + "=") ;
151 for (int i = 0; i < rdns[j].length(); i++)
152 {
153 char c = rdns[j].charAt(i);
154 if (isAlpha(c) || isDigit(c))
155 {
156 buffer.append(c);
157 } else
158 {
159 switch (c)
160 {
161 case ' ':
162 buffer.append("_");
163 break;
164 case '=':
165 buffer.append("-");
166 }
167 }
168 }
169 }
170
171 typeStr = buffer.toString();
172 }
173
174 nameStr = MBEAN_BASE_DOMAIN + ":" + "Name=rootDSE" + typeStr;
175 } catch (Exception e)
176 {
177 if (debugEnabled())
178 {
179 TRACER.debugCaught(DebugLogLevel.ERROR, e);
180 }
181
182 Message message = ERR_CONFIG_JMX_CANNOT_REGISTER_MBEAN.get(
183 configEntryDN.toString(), String.valueOf(e));
184 logError(message);
185 }
186 return nameStr ;
187 }
188
189 /**
190 * Creates a new dynamic JMX MBean for use with the Directory Server.
191 *
192 * @param configEntryDN The DN of the configuration entry with which this
193 * MBean is associated.
194 */
195 public JMXMBean(DN configEntryDN)
196 {
197
198 this.configEntryDN = configEntryDN;
199
200 alertGenerators = new CopyOnWriteArrayList<AlertGenerator>();
201 invokableComponents = new CopyOnWriteArrayList<InvokableComponent>();
202 monitorProviders =
203 new CopyOnWriteArrayList<MonitorProvider<
204 ? extends MonitorProviderCfg>>();
205
206 MBeanServer mBeanServer = DirectoryServer.getJMXMBeanServer();
207 if (mBeanServer != null)
208 {
209 try
210 {
211 objectName = new ObjectName(getJmxName(configEntryDN)) ;
212
213 try
214 {
215 if(mBeanServer.isRegistered(objectName))
216 {
217 mBeanServer.unregisterMBean(objectName);
218 }
219 } catch(Exception e)
220 {
221 if (debugEnabled())
222 {
223 TRACER.debugCaught(DebugLogLevel.ERROR, e);
224 }
225 }
226
227 mBeanServer.registerMBean(this, objectName);
228
229 } catch (Exception e)
230 {
231 if (debugEnabled())
232 {
233 TRACER.debugCaught(DebugLogLevel.ERROR, e);
234 }
235 e.printStackTrace();
236
237 Message message = ERR_CONFIG_JMX_CANNOT_REGISTER_MBEAN.get(
238 configEntryDN.toString(), String.valueOf(e));
239 logError(message);
240 }
241 }
242 }
243
244
245
246 /**
247 * Retrieves the JMX object name for this JMX MBean.
248 *
249 * @return The JMX object name for this JMX MBean.
250 */
251 public ObjectName getObjectName()
252 {
253 return objectName;
254 }
255
256
257
258 /**
259 * Retrieves the set of alert generators for this JMX MBean.
260 *
261 * @return The set of alert generators for this JMX MBean.
262 */
263 public CopyOnWriteArrayList<AlertGenerator> getAlertGenerators()
264 {
265 return alertGenerators;
266 }
267
268
269
270 /**
271 * Adds the provided alert generator to the set of alert generators associated
272 * with this JMX MBean.
273 *
274 * @param generator The alert generator to add to the set of alert
275 * generators for this JMX MBean.
276 */
277 public void addAlertGenerator(AlertGenerator generator)
278 {
279 synchronized (alertGenerators)
280 {
281 if (! alertGenerators.contains(generator))
282 {
283 alertGenerators.add(generator);
284 }
285 }
286 }
287
288
289
290 /**
291 * Removes the provided alert generator from the set of alert generators
292 * associated with this JMX MBean.
293 *
294 * @param generator The alert generator to remove from the set of alert
295 * generators for this JMX MBean.
296 *
297 * @return <CODE>true</CODE> if the alert generator was removed, or
298 * <CODE>false</CODE> if it was not associated with this MBean.
299 */
300 public boolean removeAlertGenerator(AlertGenerator generator)
301 {
302 synchronized (alertGenerators)
303 {
304 return alertGenerators.remove(generator);
305 }
306 }
307
308
309
310 /**
311 * Retrieves the set of invokable components associated with this JMX MBean.
312 *
313 * @return The set of invokable components associated with this JMX MBean.
314 */
315 public CopyOnWriteArrayList<InvokableComponent> getInvokableComponents()
316 {
317 return invokableComponents;
318 }
319
320
321
322 /**
323 * Adds the provided invokable component to the set of components associated
324 * with this JMX MBean.
325 *
326 * @param component The component to add to the set of invokable components
327 * for this JMX MBean.
328 */
329 public void addInvokableComponent(InvokableComponent component)
330 {
331 synchronized (invokableComponents)
332 {
333 if (! invokableComponents.contains(component))
334 {
335 invokableComponents.add(component);
336 }
337 }
338 }
339
340
341
342 /**
343 * Removes the provided invokable component from the set of components
344 * associated with this JMX MBean.
345 *
346 * @param component The component to remove from the set of invokable
347 * components for this JMX MBean.
348 *
349 * @return <CODE>true</CODE> if the specified component was successfully
350 * removed, or <CODE>false</CODE> if not.
351 */
352 public boolean removeInvokableComponent(InvokableComponent component)
353 {
354 synchronized (invokableComponents)
355 {
356 return invokableComponents.remove(component);
357 }
358 }
359
360
361
362 /**
363 * Retrieves the set of monitor providers associated with this JMX MBean.
364 *
365 * @return The set of monitor providers associated with this JMX MBean.
366 */
367 public CopyOnWriteArrayList<MonitorProvider<? extends MonitorProviderCfg>>
368 getMonitorProviders()
369 {
370 return monitorProviders;
371 }
372
373
374
375 /**
376 * Adds the given monitor provider to the set of components associated with
377 * this JMX MBean.
378 *
379 * @param component The component to add to the set of monitor providers
380 * for this JMX MBean.
381 */
382 public void addMonitorProvider(MonitorProvider<? extends MonitorProviderCfg>
383 component)
384 {
385 synchronized (monitorProviders)
386 {
387 if (! monitorProviders.contains(component))
388 {
389 monitorProviders.add(component);
390 }
391 }
392 }
393
394
395
396 /**
397 * Removes the given monitor provider from the set of components associated
398 * with this JMX MBean.
399 *
400 * @param component The component to remove from the set of monitor
401 * providers for this JMX MBean.
402 *
403 * @return <CODE>true</CODE> if the specified component was successfully
404 * removed, or <CODE>false</CODE> if not.
405 */
406 public boolean removeMonitorProvider(MonitorProvider component)
407 {
408 synchronized (monitorProviders)
409 {
410 return monitorProviders.remove(component);
411 }
412 }
413
414
415
416 /**
417 * Retrieves the specified configuration attribute.
418 *
419 * @param name The name of the configuration attribute to retrieve.
420 *
421 * @return The specified configuration attribute, or <CODE>null</CODE> if
422 * there is no such attribute.
423 */
424 private Attribute getJmxAttribute(String name)
425 {
426 // It's possible that this is a monitor attribute rather than a configurable
427 // one. Check all of those.
428 AttributeType attrType =
429 DirectoryServer.getAttributeType(name.toLowerCase());
430 if (attrType == null)
431 {
432 attrType = DirectoryServer.getDefaultAttributeType(name);
433 }
434 for (MonitorProvider<? extends MonitorProviderCfg> monitor :
435 monitorProviders)
436 {
437 for (org.opends.server.types.Attribute a : monitor.getMonitorData())
438 {
439 if (attrType.equals(a.getAttributeType()))
440 {
441 LinkedHashSet<AttributeValue> values = a.getValues();
442 if (values.isEmpty())
443 {
444 continue;
445 }
446
447 Iterator<AttributeValue> iterator = values.iterator();
448 AttributeValue value = iterator.next();
449
450 if (iterator.hasNext())
451 {
452 ArrayList<String> stringValues = new ArrayList<String>();
453 stringValues.add(value.getStringValue());
454
455 while (iterator.hasNext())
456 {
457 value = iterator.next();
458 stringValues.add(value.getStringValue());
459 }
460
461 String[] valueArray = new String[stringValues.size()];
462 stringValues.toArray(valueArray);
463 return new Attribute(name, valueArray);
464 }
465 else
466 {
467 return new Attribute(name, value.getStringValue());
468 }
469 }
470 }
471 }
472
473 return null;
474 }
475
476
477
478 /**
479 * Obtain the value of a specific attribute of the Dynamic MBean.
480 *
481 * @param attributeName The name of the attribute to be retrieved.
482 *
483 * @return The requested attribute.
484 *
485 * @throws AttributeNotFoundException If the specified attribute is not
486 * associated with this MBean.
487 */
488 public Attribute getAttribute(String attributeName)
489 throws AttributeNotFoundException
490 {
491 //
492 // Get the jmx Client connection
493 ClientConnection clientConnection = getClientConnection();
494 if (clientConnection == null)
495 {
496 return null;
497 }
498
499 //
500 // prepare the ldap search
501
502 LDAPFilter filter;
503 try
504 {
505 filter = LDAPFilter.decode("objectclass=*");
506 }
507 catch (LDAPException e)
508 {
509 if (debugEnabled())
510 {
511 TRACER.debugCaught(DebugLogLevel.ERROR, e);
512 }
513
514 Message message = ERR_CONFIG_JMX_CANNOT_GET_ATTRIBUTE.
515 get(String.valueOf(attributeName), String.valueOf(configEntryDN),
516 getExceptionMessage(e));
517 throw new AttributeNotFoundException(message.toString());
518 }
519
520 //
521 // Perform the Ldap operation for
522 // - ACI Check
523 // - Loggin purpose
524 InternalSearchOperation op=null;
525 if (clientConnection instanceof JmxClientConnection) {
526 op = ((JmxClientConnection)clientConnection).processSearch(
527 new ASN1OctetString(configEntryDN.toString()),
528 SearchScope.BASE_OBJECT, filter);
529 }
530 else if (clientConnection instanceof InternalClientConnection) {
531 op = ((InternalClientConnection)clientConnection).processSearch(
532 new ASN1OctetString(configEntryDN.toString()),
533 SearchScope.BASE_OBJECT, filter);
534 }
535 ResultCode rc = op.getResultCode();
536 if (rc != ResultCode.SUCCESS) {
537 clientConnection = null ;
538
539 Message message = ERR_CONFIG_JMX_CANNOT_GET_ATTRIBUTE.
540 get(String.valueOf(attributeName), String.valueOf(configEntryDN),
541 String.valueOf(op.getErrorMessage()));
542 throw new AttributeNotFoundException(message.toString());
543 }
544
545 try
546 {
547 return getJmxAttribute(attributeName);
548 }
549 catch (Exception e)
550 {
551 if (debugEnabled())
552 {
553 TRACER.debugCaught(DebugLogLevel.ERROR, e);
554 }
555
556 Message message = ERR_CONFIG_JMX_ATTR_NO_ATTR.get(
557 String.valueOf(configEntryDN), attributeName);
558 logError(message);
559 throw new AttributeNotFoundException(message.toString());
560 }
561 }
562
563 /**
564 * Set the value of a specific attribute of the Dynamic MBean. In this case,
565 * it will always throw {@code InvalidAttributeValueException} because setting
566 * attribute values over JMX is currently not allowed.
567 *
568 * @param attribute The identification of the attribute to be set and the
569 * value it is to be set to.
570 *
571 * @throws AttributeNotFoundException If the specified attribute is not
572 * associated with this MBean.
573 *
574 * @throws InvalidAttributeValueException If the provided value is not
575 * acceptable for this MBean.
576 */
577 public void setAttribute(javax.management.Attribute attribute)
578 throws AttributeNotFoundException, InvalidAttributeValueException
579 {
580 throw new InvalidAttributeValueException();
581 }
582
583 /**
584 * Get the values of several attributes of the Dynamic MBean.
585 *
586 * @param attributes A list of the attributes to be retrieved.
587 *
588 * @return The list of attributes retrieved.
589 */
590 public AttributeList getAttributes(String[] attributes)
591 {
592
593 //
594 // Get the jmx Client connection
595 ClientConnection clientConnection = getClientConnection();
596 if (clientConnection == null)
597 {
598 return null;
599 }
600
601 //
602 // prepare the ldap search
603 LDAPFilter filter;
604 try
605 {
606 filter = LDAPFilter.decode("objectclass=*");
607 }
608 catch (LDAPException e)
609 {
610 return null;
611 }
612
613 //
614 // Perform the Ldap operation for
615 // - ACI Check
616 // - Loggin purpose
617 InternalSearchOperation op=null;
618 if (clientConnection instanceof JmxClientConnection) {
619 op = ((JmxClientConnection)clientConnection).processSearch(
620 new ASN1OctetString(configEntryDN.toString()),
621 SearchScope.BASE_OBJECT, filter);
622 }
623 else if (clientConnection instanceof InternalClientConnection) {
624 op = ((InternalClientConnection)clientConnection).processSearch(
625 new ASN1OctetString(configEntryDN.toString()),
626 SearchScope.BASE_OBJECT, filter);
627 }
628 ResultCode rc = op.getResultCode();
629 if (rc != ResultCode.SUCCESS)
630 {
631 clientConnection = null ;
632 return null;
633 }
634
635
636 AttributeList attrList = new AttributeList(attributes.length);
637 Attribute attr;
638 for (String name : attributes)
639 {
640 try
641 {
642 if ((attr = getJmxAttribute(name)) != null)
643 {
644 attrList.add(attr);
645 continue;
646 }
647 }
648 catch (Exception e)
649 {
650 if (debugEnabled())
651 {
652 TRACER.debugCaught(DebugLogLevel.ERROR, e);
653 }
654 }
655
656 // It's possible that this is a monitor attribute rather than a
657 // configurable one. Check all of those.
658 AttributeType attrType =
659 DirectoryServer.getAttributeType(name.toLowerCase());
660 if (attrType == null)
661 {
662 attrType = DirectoryServer.getDefaultAttributeType(name);
663 }
664
665 monitorLoop:
666 for (MonitorProvider<? extends MonitorProviderCfg> monitor :
667 monitorProviders)
668 {
669 for (org.opends.server.types.Attribute a : monitor.getMonitorData())
670 {
671 if (attrType.equals(a.getAttributeType()))
672 {
673 LinkedHashSet<AttributeValue> values = a.getValues();
674 if (values.isEmpty())
675 {
676 continue;
677 }
678
679 Iterator<AttributeValue> iterator = values.iterator();
680 AttributeValue value = iterator.next();
681
682 if (iterator.hasNext())
683 {
684 ArrayList<String> stringValues = new ArrayList<String>();
685 stringValues.add(value.getStringValue());
686
687 while (iterator.hasNext())
688 {
689 value = iterator.next();
690 stringValues.add(value.getStringValue());
691 }
692
693 String[] valueArray = new String[stringValues.size()];
694 stringValues.toArray(valueArray);
695 attrList.add(new Attribute(name, valueArray));
696 break monitorLoop;
697 }
698 else
699 {
700 attrList.add(new Attribute(name, value.getStringValue()));
701 break monitorLoop;
702 }
703 }
704 }
705 }
706 }
707
708 return attrList;
709
710 }
711
712 /**
713 * Sets the values of several attributes of the Dynamic MBean.
714 *
715 * @param attributes A list of attributes: The identification of the
716 * attributes to be set and the values they are to be set
717 * to.
718 *
719 * @return The list of attributes that were set with their new values. In
720 * this case, the list will always be empty because we do not support
721 * setting attribute values over JMX.
722 */
723 public AttributeList setAttributes(AttributeList attributes)
724 {
725 return new AttributeList();
726 }
727
728
729
730 /**
731 * Allows an action to be invoked on the Dynamic MBean.
732 *
733 * @param actionName The name of the action to be invoked.
734 * @param params An array containing the parameters to be set when the
735 * action is invoked.
736 * @param signature An array containing the signature of the action. The
737 * class objects will be loaded through the same class
738 * loader as the one used for loading the MBean on which
739 * action is invoked.
740 *
741 * @return The object returned by the action, which represents the result of
742 * invoking the action on the MBean specified.
743 *
744 * @throws MBeanException If a problem is encountered while invoking the
745 * method.
746 */
747 public Object invoke(String actionName, Object[] params, String[] signature)
748 throws MBeanException
749 {
750 for (InvokableComponent component : invokableComponents)
751 {
752 for (InvokableMethod method : component.getOperationSignatures())
753 {
754 if (method.hasSignature(actionName, signature))
755 {
756 try
757 {
758 method.invoke(component, params);
759 }
760 catch (MBeanException me)
761 {
762 if (debugEnabled())
763 {
764 TRACER.debugCaught(DebugLogLevel.ERROR, me);
765 }
766
767 throw me;
768 }
769 catch (Exception e)
770 {
771 if (debugEnabled())
772 {
773 TRACER.debugCaught(DebugLogLevel.ERROR, e);
774 }
775
776 throw new MBeanException(e);
777 }
778 }
779 }
780 }
781
782
783 // If we've gotten here, then there is no such method so throw an exception.
784 StringBuilder buffer = new StringBuilder();
785 buffer.append(actionName);
786 buffer.append("(");
787
788 if (signature.length > 0)
789 {
790 buffer.append(signature[0]);
791
792 for (int i=1; i < signature.length; i++)
793 {
794 buffer.append(", ");
795 buffer.append(signature[i]);
796 }
797 }
798
799 buffer.append(")");
800
801 Message message = ERR_CONFIG_JMX_NO_METHOD.get(
802 buffer.toString(), configEntryDN.toString());
803 throw new MBeanException(
804 new DirectoryException(ResultCode.NO_SUCH_OPERATION,
805 message));
806 }
807
808
809
810 /**
811 * Provides the exposed attributes and actions of the Dynamic MBean using an
812 * MBeanInfo object.
813 *
814 * @return An instance of <CODE>MBeanInfo</CODE> allowing all attributes and
815 * actions exposed by this Dynamic MBean to be retrieved.
816 */
817 public MBeanInfo getMBeanInfo()
818 {
819 ClientConnection clientConnection = getClientConnection();
820 if (clientConnection == null)
821 {
822 return new MBeanInfo(CLASS_NAME, null, null, null, null, null);
823 }
824
825 ArrayList<MBeanAttributeInfo> attrs = new ArrayList<MBeanAttributeInfo>();
826 for (MonitorProvider<? extends MonitorProviderCfg> monitor :
827 monitorProviders)
828 {
829 for (org.opends.server.types.Attribute a : monitor.getMonitorData())
830 {
831 attrs.add(new MBeanAttributeInfo(a.getName(), String.class.getName(),
832 null, true, false, false));
833 }
834 }
835
836 MBeanAttributeInfo[] mBeanAttributes = new MBeanAttributeInfo[attrs.size()];
837 attrs.toArray(mBeanAttributes);
838
839
840 ArrayList<MBeanNotificationInfo> notifications =
841 new ArrayList<MBeanNotificationInfo>();
842 for (AlertGenerator generator : alertGenerators)
843 {
844 String className = generator.getClassName();
845
846 LinkedHashMap<String,String> alerts = generator.getAlerts();
847 for (String type : alerts.keySet())
848 {
849 String[] types = { type };
850 String description = alerts.get(type);
851 notifications.add(new MBeanNotificationInfo(types, className,
852 description));
853 }
854 }
855
856
857 MBeanNotificationInfo[] mBeanNotifications =
858 new MBeanNotificationInfo[notifications.size()];
859 notifications.toArray(mBeanNotifications);
860
861
862 ArrayList<MBeanOperationInfo> ops = new ArrayList<MBeanOperationInfo>();
863 for (InvokableComponent component : invokableComponents)
864 {
865 for (InvokableMethod method : component.getOperationSignatures())
866 {
867 ops.add(method.toOperationInfo());
868 }
869 }
870
871 MBeanOperationInfo[] mBeanOperations = new MBeanOperationInfo[ops.size()];
872 ops.toArray(mBeanOperations);
873
874
875 MBeanConstructorInfo[] mBeanConstructors = new MBeanConstructorInfo[0];
876 return new MBeanInfo(CLASS_NAME,
877 "Configurable Attributes for " +
878 configEntryDN.toString(),
879 mBeanAttributes, mBeanConstructors, mBeanOperations,
880 mBeanNotifications);
881 }
882
883 /**
884 * Get the client JMX connection to use. Returns null if an Exception is
885 * caught or if the AccessControlContext subject is null.
886 *
887 * @return The JmxClientConnection.
888 */
889 private ClientConnection getClientConnection()
890 {
891 ClientConnection clientConnection=null;
892 java.security.AccessControlContext acc = java.security.AccessController
893 .getContext();
894 try
895 {
896 javax.security.auth.Subject subject = javax.security.auth.Subject
897 .getSubject(acc);
898 if(subject != null) {
899 Set privateCreds = subject.getPrivateCredentials(Credential.class);
900 clientConnection = ((Credential) privateCreds
901 .iterator().next()).getClientConnection();
902 }
903 }
904 catch (Exception e) {}
905 return clientConnection;
906 }
907 }
908
909