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