001: /* JFox, the OpenSource J2EE Application Server
002: *
003: * Copyright (C) 2002 huihoo.org
004: * Distributable under GNU LGPL license
005: * See the GNU Lesser General Public License for more details.
006: */
007:
008: package javax.management.openmbean;
009:
010: import java.io.Serializable;
011: import java.util.Arrays;
012: import javax.management.MBeanOperationInfo;
013: import javax.management.MBeanParameterInfo;
014:
015: /**
016: * Describes an operation of an Open MBean.
017: *
018: * @author <a href="mailto:young_yy@hotmail.org">Young Yang</a>
019: */
020:
021: public class OpenMBeanOperationInfoSupport extends MBeanOperationInfo
022: implements OpenMBeanOperationInfo, Serializable {
023:
024: /**
025: * @serial The <i>open type</i> of the values returned by the operation
026: * described by this {@link OpenMBeanOperationInfo} instance
027: *
028: */
029: private OpenType returnOpenType;
030:
031: private transient Integer myHashCode = null; // As this instance is immutable, these two values
032: private transient String myToString = null; // need only be calculated once.
033:
034: /**
035: * Constructs an <tt>OpenMBeanOperationInfoSupport</tt> instance, which describes the operation
036: * of a class of open MBeans, with the specified
037: * <var>name</var>, <var>description</var>, <var>signature</var>, <var>returnOpenType</var> and <var>impact</var>.
038: * <p>
039: * The <var>signature</var> array parameter is internally copied, so that subsequent changes
040: * to the array referenced by <var>signature</var> have no effect on this instance.
041: * <p>
042: *
043: * @param name cannot be a null or empty string.
044: *
045: * @param description cannot be a null or empty string.
046: *
047: * @param signature can be null or empty if there are no parameters to describe.
048: *
049: * @param returnOpenType cannot be null: use <tt>SimpleType.VOID</tt> for operations that return nothing.
050: *
051: * @param impact can be only one of <tt>ACTION</tt>, <tt>ACTION_INFO</tt> or <tt>INFO</tt>.
052: *
053: * @throws IllegalArgumentException if <var>name</var> or <var>description</var> are null or empty string,
054: * or <var>returnOpenType</var> is null,
055: * or <var>impact</var> is not one of <tt>ACTION</tt>, <tt>ACTION_INFO</tt> or <tt>INFO</tt>.
056: *
057: * @throws ArrayStoreException If <var>signature</var> is not an array of instances of a subclass of <tt>MBeanParameterInfo</tt>.
058: */
059: public OpenMBeanOperationInfoSupport(String name,
060: String description, OpenMBeanParameterInfo[] signature,
061: OpenType returnOpenType, int impact) {
062:
063: super (name, description, (signature == null ? null
064: : arrayCopyCast(signature)), // may throw an ArrayStoreException
065: (returnOpenType == null ? null : returnOpenType
066: .getClassName()), impact);
067:
068: // check parameters that should not be null or empty (unfortunately it is not done in superclass :-( ! )
069: //
070: if ((name == null) || (name.trim().equals(""))) {
071: throw new IllegalArgumentException(
072: "Argument name cannot be null or empty.");
073: }
074: if ((description == null) || (description.trim().equals(""))) {
075: throw new IllegalArgumentException(
076: "Argument description cannot be null or empty.");
077: }
078: if (returnOpenType == null) {
079: throw new IllegalArgumentException(
080: "Argument returnOpenType cannot be null.");
081: }
082:
083: // check impact's value is only one of the 3 allowed (UNKNOWN not allowed)
084: //
085: if ((impact != super .ACTION) && (impact != super .ACTION_INFO)
086: && (impact != super .INFO)) {
087: throw new IllegalArgumentException(
088: "Argument impact can be only one of ACTION, ACTION_INFO or INFO.");
089: }
090:
091: this .returnOpenType = returnOpenType;
092: }
093:
094: private static MBeanParameterInfo[] arrayCopyCast(
095: OpenMBeanParameterInfo[] src) throws ArrayStoreException {
096:
097: MBeanParameterInfo[] dst = new MBeanParameterInfo[src.length];
098: System.arraycopy(src, 0, dst, 0, src.length); // may throw an ArrayStoreException
099: return dst;
100: }
101:
102: // [JF]: should we add constructor with java.lang.reflect.Method method parameter ?
103: // would need to add consistency check between OpenType returnOpenType and mehtod.getReturnType().
104:
105: /**
106: * Returns the <i>open type</i> of the values returned by the operation described by this <tt>OpenMBeanOperationInfo</tt> instance.
107: */
108: public OpenType getReturnOpenType() {
109:
110: return returnOpenType;
111: }
112:
113: /* *** Commodity methods from java.lang.Object *** */
114:
115: /**
116: * Compares the specified <var>obj</var> parameter with this <code>OpenMBeanOperationInfoSupport</code> instance for equality.
117: * <p>
118: * Returns <tt>true</tt> if and only if all of the following statements are true:
119: * <ul>
120: * <li><var>obj</var> is non null,</li>
121: * <li><var>obj</var> also implements the <code>OpenMBeanOperationInfo</code> interface,</li>
122: * <li>their names are equal</li>
123: * <li>their signatures are equal</li>
124: * <li>their return open types are equal</li>
125: * <li>their impacts are equal</li>
126: * </ul>
127: * This ensures that this <tt>equals</tt> method works properly for <var>obj</var> parameters which are
128: * different implementations of the <code>OpenMBeanOperationInfo</code> interface.
129: * <br>
130: * @param obj the object to be compared for equality with this <code>OpenMBeanOperationInfoSupport</code> instance;
131: *
132: * @return <code>true</code> if the specified object is equal to this <code>OpenMBeanOperationInfoSupport</code> instance.
133: */
134: public boolean equals(Object obj) {
135:
136: // if obj is null, return false
137: //
138: if (obj == null) {
139: return false;
140: }
141:
142: // if obj is not a OpenMBeanOperationInfo, return false
143: //
144: OpenMBeanOperationInfo other;
145: try {
146: other = (OpenMBeanOperationInfo) obj;
147: } catch (ClassCastException e) {
148: return false;
149: }
150:
151: // Now, really test for equality between this OpenMBeanOperationInfo implementation and the other:
152: //
153:
154: // their Name should be equal
155: if (!this .getName().equals(other.getName())) {
156: return false;
157: }
158:
159: // their Signatures should be equal
160: if (!Arrays.equals(this .getSignature(), other.getSignature())) {
161: return false;
162: }
163:
164: // their return open types should be equal
165: if (!this .getReturnOpenType().equals(other.getReturnOpenType())) {
166: return false;
167: }
168:
169: // their impacts should be equal
170: if (this .getImpact() != other.getImpact()) {
171: return false;
172: }
173:
174: // All tests for equality were successfull
175: //
176: return true;
177: }
178:
179: /**
180: * Returns the hash code value for this <code>OpenMBeanOperationInfoSupport</code> instance.
181: * <p>
182: * The hash code of an <code>OpenMBeanOperationInfoSupport</code> instance is the sum of the hash codes
183: * of all elements of information used in <code>equals</code> comparisons
184: * (ie: its name, return open type, impact and signature, where the signature hashCode is calculated by a call to
185: * <tt>java.util.Arrays.asList(this.getSignature).hashCode()</tt>).
186: * <p>
187: * This ensures that <code> t1.equals(t2) </code> implies that <code> t1.hashCode()==t2.hashCode() </code>
188: * for any two <code>OpenMBeanOperationInfoSupport</code> instances <code>t1</code> and <code>t2</code>,
189: * as required by the general contract of the method
190: * {@link <a href="http://java.sun.com/j2se/1.3/docs/api/java/lang/Object.html#hashCode()">
191: * <code>Object.hashCode</code> </a>}.
192: * <p>
193: * However, note that another instance of a class implementing the <code>OpenMBeanOperationInfo</code> interface
194: * may be equal to this <code>OpenMBeanOperationInfoSupport</code> instance as defined by {@link #equals(java.lang.Object)},
195: * but may have a different hash code if it is calculated differently.
196: * <p>
197: * As <code>OpenMBeanOperationInfoSupport</code> instances are immutable, the hash code for this instance is calculated once,
198: * on the first call to <code>hashCode</code>, and then the same value is returned for subsequent calls.
199: *
200: * @return the hash code value for this <code>OpenMBeanOperationInfoSupport</code> instance
201: */
202: public int hashCode() {
203:
204: // Calculate the hash code value if it has not yet been done (ie 1st call to hashCode())
205: //
206: if (myHashCode == null) {
207: int value = 0;
208: value += this .getName().hashCode();
209: value += Arrays.asList(this .getSignature()).hashCode();
210: value += this .getReturnOpenType().hashCode();
211: value += this .getImpact();
212: myHashCode = new Integer(value);
213: }
214:
215: // return always the same hash code for this instance (immutable)
216: //
217: return myHashCode.intValue();
218: }
219:
220: /**
221: * Returns a string representation of this <code>OpenMBeanOperationInfoSupport</code> instance.
222: * <p>
223: * The string representation consists of the name of this class (ie <code>javax.management.openmbean.OpenMBeanOperationInfoSupport</code>),
224: * and the name, signature, return open type and impact of the described operation.
225: * <p>
226: * As <code>OpenMBeanOperationInfoSupport</code> instances are immutable,
227: * the string representation for this instance is calculated once,
228: * on the first call to <code>toString</code>, and then the same value is returned for subsequent calls.
229: *
230: * @return a string representation of this <code>OpenMBeanOperationInfoSupport</code> instance
231: */
232: public String toString() {
233:
234: // Calculate the hash code value if it has not yet been done (ie 1st call to toString())
235: //
236: if (myToString == null) {
237: myToString = new StringBuffer().append(
238: this .getClass().getName()).append("(name=").append(
239: this .getName()).append(",signature=").append(
240: Arrays.asList(this .getSignature()).toString())
241: .append(",return=").append(
242: this .getReturnOpenType().toString())
243: .append(",impact=").append(this .getImpact())
244: .append(")").toString();
245: }
246:
247: // return always the same string representation for this instance (immutable)
248: //
249: return myToString;
250: }
251:
252: }
|