1 /*
   2  * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javax.management;
  27 
  28 import java.util.Arrays;
  29 import java.util.Objects;
  30 
  31 /**
  32  * <p>The <CODE>MBeanNotificationInfo</CODE> class is used to describe the
  33  * characteristics of the different notification instances
  34  * emitted by an MBean, for a given Java class of notification.
  35  * If an MBean emits notifications that can be instances of different Java classes,
  36  * then the metadata for that MBean should provide an <CODE>MBeanNotificationInfo</CODE>
  37  * object for each of these notification Java classes.</p>
  38  *
  39  * <p>Instances of this class are immutable.  Subclasses may be
  40  * mutable but this is not recommended.</p>
  41  *
  42  * <p>This class extends <CODE>javax.management.MBeanFeatureInfo</CODE>
  43  * and thus provides <CODE>name</CODE> and <CODE>description</CODE> fields.
  44  * The <CODE>name</CODE> field should be the fully qualified Java class name of
  45  * the notification objects described by this class.</p>
  46  *
  47  * <p>The <CODE>getNotifTypes</CODE> method returns an array of
  48  * strings containing the notification types that the MBean may
  49  * emit. The notification type is a dot-notation string which
  50  * describes what the emitted notification is about, not the Java
  51  * class of the notification.  A single generic notification class can
  52  * be used to send notifications of several types.  All of these types
  53  * are returned in the string array result of the
  54  * <CODE>getNotifTypes</CODE> method.
  55  *
  56  * @since 1.5
  57  */
  58 public class MBeanNotificationInfo extends MBeanFeatureInfo implements Cloneable {
  59 
  60     /* Serial version */
  61     static final long serialVersionUID = -3888371564530107064L;
  62 
  63     private static final String[] NO_TYPES = new String[0];
  64 
  65     static final MBeanNotificationInfo[] NO_NOTIFICATIONS =
  66         new MBeanNotificationInfo[0];
  67 
  68     /**
  69      * @serial The different types of the notification.
  70      */
  71     private final String[] types;
  72 
  73     /** @see MBeanInfo#arrayGettersSafe */
  74     private final transient boolean arrayGettersSafe;
  75 
  76     /**
  77      * Constructs an <CODE>MBeanNotificationInfo</CODE> object.
  78      *
  79      * @param notifTypes The array of strings (in dot notation)
  80      * containing the notification types that the MBean may emit.
  81      * This may be null with the same effect as a zero-length array.
  82      * @param name The fully qualified Java class name of the
  83      * described notifications.
  84      * @param description A human readable description of the data.
  85      */
  86     public MBeanNotificationInfo(String[] notifTypes,
  87                                  String name,
  88                                  String description) {
  89         this(notifTypes, name, description, null);
  90     }
  91 
  92     /**
  93      * Constructs an <CODE>MBeanNotificationInfo</CODE> object.
  94      *
  95      * @param notifTypes The array of strings (in dot notation)
  96      * containing the notification types that the MBean may emit.
  97      * This may be null with the same effect as a zero-length array.
  98      * @param name The fully qualified Java class name of the
  99      * described notifications.
 100      * @param description A human readable description of the data.
 101      * @param descriptor The descriptor for the notifications.  This may be null
 102      * which is equivalent to an empty descriptor.
 103      *
 104      * @since 1.6
 105      */
 106     public MBeanNotificationInfo(String[] notifTypes,
 107                                  String name,
 108                                  String description,
 109                                  Descriptor descriptor) {
 110         super(name, description, descriptor);
 111 
 112         /* We do not validate the notifTypes, since the spec just says
 113            they are dot-separated, not that they must look like Java
 114            classes.  E.g. the spec doesn't forbid "sun.prob.25" as a
 115            notifType, though it doesn't explicitly allow it
 116            either.  */
 117 
 118         if (notifTypes == null)
 119             notifTypes = NO_TYPES;
 120         this.types = notifTypes;
 121         this.arrayGettersSafe =
 122             MBeanInfo.arrayGettersSafe(this.getClass(),
 123                                        MBeanNotificationInfo.class);
 124     }
 125 
 126 
 127     /**
 128      * Returns a shallow clone of this instance.
 129      * The clone is obtained by simply calling <tt>super.clone()</tt>,
 130      * thus calling the default native shallow cloning mechanism
 131      * implemented by <tt>Object.clone()</tt>.
 132      * No deeper cloning of any internal field is made.
 133      */
 134      public Object clone () {
 135          try {
 136              return super.clone() ;
 137          } catch (CloneNotSupportedException e) {
 138              // should not happen as this class is cloneable
 139              return null;
 140          }
 141      }
 142 
 143 
 144     /**
 145      * Returns the array of strings (in dot notation) containing the
 146      * notification types that the MBean may emit.
 147      *
 148      * @return the array of strings.  Changing the returned array has no
 149      * effect on this MBeanNotificationInfo.
 150      */
 151     public String[] getNotifTypes() {
 152         if (types.length == 0)
 153             return NO_TYPES;
 154         else
 155             return types.clone();
 156     }
 157 
 158     private String[] fastGetNotifTypes() {
 159         if (arrayGettersSafe)
 160             return types;
 161         else
 162             return getNotifTypes();
 163     }
 164 
 165     public String toString() {
 166         return
 167             getClass().getName() + "[" +
 168             "description=" + getDescription() + ", " +
 169             "name=" + getName() + ", " +
 170             "notifTypes=" + Arrays.asList(fastGetNotifTypes()) + ", " +
 171             "descriptor=" + getDescriptor() +
 172             "]";
 173     }
 174 
 175     /**
 176      * Compare this MBeanNotificationInfo to another.
 177      *
 178      * @param o the object to compare to.
 179      *
 180      * @return true if and only if <code>o</code> is an MBeanNotificationInfo
 181      * such that its {@link #getName()}, {@link #getDescription()},
 182      * {@link #getDescriptor()},
 183      * and {@link #getNotifTypes()} values are equal (not necessarily
 184      * identical) to those of this MBeanNotificationInfo.  Two
 185      * notification type arrays are equal if their corresponding
 186      * elements are equal.  They are not equal if they have the same
 187      * elements but in a different order.
 188      */
 189     public boolean equals(Object o) {
 190         if (o == this)
 191             return true;
 192         if (!(o instanceof MBeanNotificationInfo))
 193             return false;
 194         MBeanNotificationInfo p = (MBeanNotificationInfo) o;
 195         return (Objects.equals(p.getName(), getName()) &&
 196                 Objects.equals(p.getDescription(), getDescription()) &&
 197                 Objects.equals(p.getDescriptor(), getDescriptor()) &&
 198                 Arrays.equals(p.fastGetNotifTypes(), fastGetNotifTypes()));
 199     }
 200 
 201     public int hashCode() {
 202         int hash = getName().hashCode();
 203         for (int i = 0; i < types.length; i++)
 204             hash ^= types[i].hashCode();
 205         return hash;
 206     }
 207 }