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