// Not in the spec but needed
  private void removeAttributeChangeNotificationListener(
      NotificationListener listener, String attributeName, Object handback)
      throws MBeanException, RuntimeOperationsException, ListenerNotFoundException {
    if (listener == null)
      throw new RuntimeOperationsException(
          new IllegalArgumentException(
              LocalizedStrings.MX4JModelMBean_LISTENER_CANNOT_BE_NULL.toLocalizedString()));
    AttributeChangeNotificationFilter filter = new AttributeChangeNotificationFilter();
    if (attributeName != null) {
      filter.enableAttribute(attributeName);
    } else {
      MBeanAttributeInfo[] ai = m_modelMBeanInfo.getAttributes();
      for (int i = 0; i < ai.length; i++) {
        Descriptor d = ((ModelMBeanAttributeInfo) ai[i]).getDescriptor();
        filter.enableAttribute((String) d.getFieldValue("name"));
      }
    }

    getAttributeChangeBroadcaster().removeNotificationListener(listener, filter, handback);

    Logger logger = getLogger();
    if (logger.isEnabledFor(Logger.DEBUG))
      logger.debug(
          "Listener "
              + listener
              + " for attribute "
              + attributeName
              + " removed successfully, handback is "
              + handback);
  }
  /* Check that all descriptors have been returned */
  private static void checkDescriptors(
      ModelMBeanInfo modelMBeanInfo, Descriptor[] descriptors, String string) {
    int errCount = 0;
    final ArrayList<Descriptor> list = new ArrayList<Descriptor>(descriptors.length);
    list.addAll(Arrays.asList(descriptors));
    System.out.println("Got " + list.size() + " descriptors for " + string);

    // checks that MBean's descriptor is returned.
    //
    final Descriptor mbd = ((MBeanInfo) modelMBeanInfo).getDescriptor();
    if (!mbd.equals(remove(list, mbd))) {
      System.err.println("modelMBeanInfo.getDescriptor(): not found");
      errCount++;
    }

    // checks that MBean's attributes descriptors are returned.
    //
    final MBeanAttributeInfo[] attrs = modelMBeanInfo.getAttributes();
    for (MBeanAttributeInfo att : attrs) {
      final Descriptor ad = att.getDescriptor();
      final String name = att.getName();
      if (!ad.equals(remove(list, ad))) {
        System.err.println("attInfo.getDescriptor(): not found for " + name);
        errCount++;
      }
    }

    // checks that MBean's operations descriptors are returned.
    //
    final MBeanOperationInfo[] ops = modelMBeanInfo.getOperations();
    for (MBeanOperationInfo op : ops) {
      final Descriptor od = op.getDescriptor();
      final String name = op.getName();
      if (!od.equals(remove(list, od))) {
        System.err.println("opInfo.getDescriptor(): not found for " + name);
        errCount++;
      }
    }

    // checks that MBean's notifications descriptors are returned.
    //
    final MBeanNotificationInfo[] ntfs = modelMBeanInfo.getNotifications();
    for (MBeanNotificationInfo ntf : ntfs) {
      final Descriptor nd = ntf.getDescriptor();
      final String name = ntf.getName();
      if (!nd.equals(remove(list, nd))) {
        System.err.println("notifInfo.getDescriptor(): not found for " + name);
        errCount++;
      }
    }
    if (errCount > 0) {
      throw new RuntimeException(string + ": failed with " + errCount + " errors");
    } else if (list.size() != 0) {
      // Check that there are no additional descriptors
      //
      throw new RuntimeException(string + ": Unexpected remaining descriptors: " + list);
    } else System.out.println(string + ": PASSED");
  }
  public void testGetMBeanAttributeInfo() throws Exception {
    ModelMBeanInfo info = getMBeanInfoFromAssembler();
    MBeanAttributeInfo[] inf = info.getAttributes();
    assertEquals("Invalid number of Attributes returned", getExpectedAttributeCount(), inf.length);

    for (int x = 0; x < inf.length; x++) {
      assertNotNull("MBeanAttributeInfo should not be null", inf[x]);
      assertNotNull(
          "Description for MBeanAttributeInfo should not be null", inf[x].getDescription());
    }
  }