J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright 1999-2006 Sun Microsystems, Inc. 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. Sun designates this |
| 8 | * particular file as subject to the "Classpath" exception as provided |
| 9 | * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| 22 | * CA 95054 USA or visit www.sun.com if you need additional information or |
| 23 | * have any questions. |
| 24 | */ |
| 25 | |
| 26 | package javax.management; |
| 27 | |
| 28 | import com.sun.jmx.mbeanserver.Introspector; |
| 29 | import java.lang.annotation.Annotation; |
| 30 | import java.lang.reflect.Method; |
| 31 | import java.util.Arrays; |
| 32 | |
| 33 | /** |
| 34 | * Describes a management operation exposed by an MBean. Instances of |
| 35 | * this class are immutable. Subclasses may be mutable but this is |
| 36 | * not recommended. |
| 37 | * |
| 38 | * @since 1.5 |
| 39 | */ |
| 40 | public class MBeanOperationInfo extends MBeanFeatureInfo implements Cloneable { |
| 41 | |
| 42 | /* Serial version */ |
| 43 | static final long serialVersionUID = -6178860474881375330L; |
| 44 | |
| 45 | static final MBeanOperationInfo[] NO_OPERATIONS = |
| 46 | new MBeanOperationInfo[0]; |
| 47 | |
| 48 | /** |
| 49 | * Indicates that the operation is read-like, |
| 50 | * it basically returns information. |
| 51 | */ |
| 52 | public static final int INFO = 0; |
| 53 | |
| 54 | /** |
| 55 | * Indicates that the operation is a write-like, |
| 56 | * and would modify the MBean in some way, typically by writing some value |
| 57 | * or changing a configuration. |
| 58 | */ |
| 59 | public static final int ACTION = 1; |
| 60 | |
| 61 | /** |
| 62 | * Indicates that the operation is both read-like and write-like. |
| 63 | */ |
| 64 | public static final int ACTION_INFO = 2; |
| 65 | |
| 66 | /** |
| 67 | * Indicates that the operation has an "unknown" nature. |
| 68 | */ |
| 69 | public static final int UNKNOWN = 3; |
| 70 | |
| 71 | /** |
| 72 | * @serial The method's return value. |
| 73 | */ |
| 74 | private final String type; |
| 75 | |
| 76 | /** |
| 77 | * @serial The signature of the method, that is, the class names |
| 78 | * of the arguments. |
| 79 | */ |
| 80 | private final MBeanParameterInfo[] signature; |
| 81 | |
| 82 | /** |
| 83 | * @serial The impact of the method, one of |
| 84 | * <CODE>INFO</CODE>, |
| 85 | * <CODE>ACTION</CODE>, |
| 86 | * <CODE>ACTION_INFO</CODE>, |
| 87 | * <CODE>UNKNOWN</CODE> |
| 88 | */ |
| 89 | private final int impact; |
| 90 | |
| 91 | /** @see MBeanInfo#arrayGettersSafe */ |
| 92 | private final transient boolean arrayGettersSafe; |
| 93 | |
| 94 | |
| 95 | /** |
| 96 | * Constructs an <CODE>MBeanOperationInfo</CODE> object. The |
| 97 | * {@link Descriptor} of the constructed object will include |
| 98 | * fields contributed by any annotations on the {@code Method} |
| 99 | * object that contain the {@link DescriptorKey} meta-annotation. |
| 100 | * |
| 101 | * @param method The <CODE>java.lang.reflect.Method</CODE> object |
| 102 | * describing the MBean operation. |
| 103 | * @param description A human readable description of the operation. |
| 104 | */ |
| 105 | public MBeanOperationInfo(String description, Method method) { |
| 106 | this(method.getName(), |
| 107 | description, |
| 108 | methodSignature(method), |
| 109 | method.getReturnType().getName(), |
| 110 | UNKNOWN, |
| 111 | Introspector.descriptorForElement(method)); |
| 112 | } |
| 113 | |
| 114 | /** |
| 115 | * Constructs an <CODE>MBeanOperationInfo</CODE> object. |
| 116 | * |
| 117 | * @param name The name of the method. |
| 118 | * @param description A human readable description of the operation. |
| 119 | * @param signature <CODE>MBeanParameterInfo</CODE> objects |
| 120 | * describing the parameters(arguments) of the method. This may be |
| 121 | * null with the same effect as a zero-length array. |
| 122 | * @param type The type of the method's return value. |
| 123 | * @param impact The impact of the method, one of <CODE>INFO, |
| 124 | * ACTION, ACTION_INFO, UNKNOWN</CODE>. |
| 125 | */ |
| 126 | public MBeanOperationInfo(String name, |
| 127 | String description, |
| 128 | MBeanParameterInfo[] signature, |
| 129 | String type, |
| 130 | int impact) { |
| 131 | this(name, description, signature, type, impact, (Descriptor) null); |
| 132 | } |
| 133 | |
| 134 | /** |
| 135 | * Constructs an <CODE>MBeanOperationInfo</CODE> object. |
| 136 | * |
| 137 | * @param name The name of the method. |
| 138 | * @param description A human readable description of the operation. |
| 139 | * @param signature <CODE>MBeanParameterInfo</CODE> objects |
| 140 | * describing the parameters(arguments) of the method. This may be |
| 141 | * null with the same effect as a zero-length array. |
| 142 | * @param type The type of the method's return value. |
| 143 | * @param impact The impact of the method, one of <CODE>INFO, |
| 144 | * ACTION, ACTION_INFO, UNKNOWN</CODE>. |
| 145 | * @param descriptor The descriptor for the operation. This may be null |
| 146 | * which is equivalent to an empty descriptor. |
| 147 | * |
| 148 | * @since 1.6 |
| 149 | */ |
| 150 | public MBeanOperationInfo(String name, |
| 151 | String description, |
| 152 | MBeanParameterInfo[] signature, |
| 153 | String type, |
| 154 | int impact, |
| 155 | Descriptor descriptor) { |
| 156 | |
| 157 | super(name, description, descriptor); |
| 158 | |
| 159 | if (signature == null || signature.length == 0) |
| 160 | signature = MBeanParameterInfo.NO_PARAMS; |
| 161 | else |
| 162 | signature = signature.clone(); |
| 163 | this.signature = signature; |
| 164 | this.type = type; |
| 165 | this.impact = impact; |
| 166 | this.arrayGettersSafe = |
| 167 | MBeanInfo.arrayGettersSafe(this.getClass(), |
| 168 | MBeanOperationInfo.class); |
| 169 | } |
| 170 | |
| 171 | /** |
| 172 | * <p>Returns a shallow clone of this instance. |
| 173 | * The clone is obtained by simply calling <tt>super.clone()</tt>, |
| 174 | * thus calling the default native shallow cloning mechanism |
| 175 | * implemented by <tt>Object.clone()</tt>. |
| 176 | * No deeper cloning of any internal field is made.</p> |
| 177 | * |
| 178 | * <p>Since this class is immutable, cloning is chiefly of interest |
| 179 | * to subclasses.</p> |
| 180 | */ |
| 181 | public Object clone () { |
| 182 | try { |
| 183 | return super.clone() ; |
| 184 | } catch (CloneNotSupportedException e) { |
| 185 | // should not happen as this class is cloneable |
| 186 | return null; |
| 187 | } |
| 188 | } |
| 189 | |
| 190 | /** |
| 191 | * Returns the type of the method's return value. |
| 192 | * |
| 193 | * @return the return type. |
| 194 | */ |
| 195 | public String getReturnType() { |
| 196 | return type; |
| 197 | } |
| 198 | |
| 199 | /** |
| 200 | * <p>Returns the list of parameters for this operation. Each |
| 201 | * parameter is described by an <CODE>MBeanParameterInfo</CODE> |
| 202 | * object.</p> |
| 203 | * |
| 204 | * <p>The returned array is a shallow copy of the internal array, |
| 205 | * which means that it is a copy of the internal array of |
| 206 | * references to the <CODE>MBeanParameterInfo</CODE> objects but |
| 207 | * that each referenced <CODE>MBeanParameterInfo</CODE> object is |
| 208 | * not copied.</p> |
| 209 | * |
| 210 | * @return An array of <CODE>MBeanParameterInfo</CODE> objects. |
| 211 | */ |
| 212 | public MBeanParameterInfo[] getSignature() { |
| 213 | // If MBeanOperationInfo was created in our implementation, |
| 214 | // signature cannot be null - because our constructors replace |
| 215 | // null with MBeanParameterInfo.NO_PARAMS; |
| 216 | // |
| 217 | // However, signature could be null if an MBeanOperationInfo is |
| 218 | // deserialized from a byte array produced by another implementation. |
| 219 | // This is not very likely but possible, since the serial form says |
| 220 | // nothing against it. (see 6373150) |
| 221 | // |
| 222 | if (signature == null) |
| 223 | // if signature is null simply return an empty array . |
| 224 | // |
| 225 | return MBeanParameterInfo.NO_PARAMS; |
| 226 | else if (signature.length == 0) |
| 227 | return signature; |
| 228 | else |
| 229 | return signature.clone(); |
| 230 | } |
| 231 | |
| 232 | private MBeanParameterInfo[] fastGetSignature() { |
| 233 | if (arrayGettersSafe) { |
| 234 | // if signature is null simply return an empty array . |
| 235 | // see getSignature() above. |
| 236 | // |
| 237 | if (signature == null) |
| 238 | return MBeanParameterInfo.NO_PARAMS; |
| 239 | else return signature; |
| 240 | } else return getSignature(); |
| 241 | } |
| 242 | |
| 243 | /** |
| 244 | * Returns the impact of the method, one of |
| 245 | * <CODE>INFO</CODE>, <CODE>ACTION</CODE>, <CODE>ACTION_INFO</CODE>, <CODE>UNKNOWN</CODE>. |
| 246 | * |
| 247 | * @return the impact code. |
| 248 | */ |
| 249 | public int getImpact() { |
| 250 | return impact; |
| 251 | } |
| 252 | |
| 253 | public String toString() { |
| 254 | String impactString; |
| 255 | switch (getImpact()) { |
| 256 | case ACTION: impactString = "action"; break; |
| 257 | case ACTION_INFO: impactString = "action/info"; break; |
| 258 | case INFO: impactString = "info"; break; |
| 259 | case UNKNOWN: impactString = "unknown"; break; |
| 260 | default: impactString = "(" + getImpact() + ")"; |
| 261 | } |
| 262 | return getClass().getName() + "[" + |
| 263 | "description=" + getDescription() + ", " + |
| 264 | "name=" + getName() + ", " + |
| 265 | "returnType=" + getReturnType() + ", " + |
| 266 | "signature=" + Arrays.asList(fastGetSignature()) + ", " + |
| 267 | "impact=" + impactString + ", " + |
| 268 | "descriptor=" + getDescriptor() + |
| 269 | "]"; |
| 270 | } |
| 271 | |
| 272 | /** |
| 273 | * Compare this MBeanOperationInfo to another. |
| 274 | * |
| 275 | * @param o the object to compare to. |
| 276 | * |
| 277 | * @return true if and only if <code>o</code> is an MBeanOperationInfo such |
| 278 | * that its {@link #getName()}, {@link #getReturnType()}, {@link |
| 279 | * #getDescription()}, {@link #getImpact()}, {@link #getDescriptor()} |
| 280 | * and {@link #getSignature()} values are equal (not necessarily identical) |
| 281 | * to those of this MBeanConstructorInfo. Two signature arrays |
| 282 | * are equal if their elements are pairwise equal. |
| 283 | */ |
| 284 | public boolean equals(Object o) { |
| 285 | if (o == this) |
| 286 | return true; |
| 287 | if (!(o instanceof MBeanOperationInfo)) |
| 288 | return false; |
| 289 | MBeanOperationInfo p = (MBeanOperationInfo) o; |
| 290 | return (p.getName().equals(getName()) && |
| 291 | p.getReturnType().equals(getReturnType()) && |
| 292 | p.getDescription().equals(getDescription()) && |
| 293 | p.getImpact() == getImpact() && |
| 294 | Arrays.equals(p.fastGetSignature(), fastGetSignature()) && |
| 295 | p.getDescriptor().equals(getDescriptor())); |
| 296 | } |
| 297 | |
| 298 | /* We do not include everything in the hashcode. We assume that |
| 299 | if two operations are different they'll probably have different |
| 300 | names or types. The penalty we pay when this assumption is |
| 301 | wrong should be less than the penalty we would pay if it were |
| 302 | right and we needlessly hashed in the description and the |
| 303 | parameter array. */ |
| 304 | public int hashCode() { |
| 305 | return getName().hashCode() ^ getReturnType().hashCode(); |
| 306 | } |
| 307 | |
| 308 | private static MBeanParameterInfo[] methodSignature(Method method) { |
| 309 | final Class[] classes = method.getParameterTypes(); |
| 310 | final Annotation[][] annots = method.getParameterAnnotations(); |
| 311 | return parameters(classes, annots); |
| 312 | } |
| 313 | |
| 314 | static MBeanParameterInfo[] parameters(Class[] classes, |
| 315 | Annotation[][] annots) { |
| 316 | final MBeanParameterInfo[] params = |
| 317 | new MBeanParameterInfo[classes.length]; |
| 318 | assert(classes.length == annots.length); |
| 319 | |
| 320 | for (int i = 0; i < classes.length; i++) { |
| 321 | Descriptor d = Introspector.descriptorForAnnotations(annots[i]); |
| 322 | final String pn = "p" + (i + 1); |
| 323 | params[i] = |
| 324 | new MBeanParameterInfo(pn, classes[i].getName(), "", d); |
| 325 | } |
| 326 | |
| 327 | return params; |
| 328 | } |
| 329 | } |