001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package javax.management;
023:
024: import java.lang.reflect.Method;
025: import java.io.Serializable;
026:
027: import org.jboss.mx.util.Serialization;
028:
029: /**
030: * Represents a management attribute in an MBeans' management interface.
031: *
032: * @see javax.management.MBeanInfo
033: *
034: * @author <a href="mailto:juha@jboss.org">Juha Lindfors</a>.
035: * @author <a href="mailto:Adrian.Brock@HappeningTimes.com">Adrian Brock</a>
036: * @version $Revision: 57200 $
037: *
038: * <p><b>Revisions:</b>
039: * <p><b>20020711 Adrian Brock:</b>
040: * <ul>
041: * <li> Serialization </li>
042: * </ul>
043: *
044: */
045: public class MBeanAttributeInfo extends MBeanFeatureInfo implements
046: Serializable, Cloneable {
047: // Constants -----------------------------------------------------
048:
049: private static final long serialVersionUID;
050:
051: static {
052: switch (Serialization.version) {
053: case Serialization.V1R0:
054: serialVersionUID = 7043855487133450673L;
055: break;
056: default:
057: serialVersionUID = 8644704819898565848L;
058: }
059: }
060:
061: // Attributes ----------------------------------------------------
062:
063: /**
064: * Attribute type string. This is a fully qualified class name of the type.
065: */
066: private String attributeType = null;
067:
068: /**
069: * Is attribute readable.
070: */
071: private boolean isRead = false;
072:
073: /**
074: * Is attribute writable.
075: */
076: private boolean isWrite = false;
077:
078: /**
079: * Is attribute using the boolean <tt>isAttributeName</tt> naming convention.
080: */
081: private boolean is = false;
082:
083: /**
084: * The cached string
085: */
086: private transient String cacheString;
087:
088: /**
089: * The cached hashCode
090: */
091: private transient int cacheHashCode;
092:
093: // Constructors --------------------------------------------------
094:
095: /**
096: * Creates an MBean attribute info object.
097: *
098: * @param name name of the attribute
099: * @param type the fully qualified class name of the attribute's type
100: * @param description human readable description string of the attribute
101: * @param isReadable if attribute is readable
102: * @param isWritable if attribute is writable
103: * @param isIs if attribute is using the boolean <tt>isAttributeName</tt> naming convention for its getter method
104: * @exception IllegalArgumentException for a true isIs with a non boolean type or the type is not a valid
105: * java type or it is a reserved word
106: */
107: public MBeanAttributeInfo(String name, String type,
108: String description, boolean isReadable, boolean isWritable,
109: boolean isIs) throws IllegalArgumentException {
110: super (name, description);
111:
112: /* Removed as of the 1.2 management release
113: if (MetaDataUtil.isValidJavaType(type) == false)
114: throw new IllegalArgumentException("Type is not a valid java identifier (or is reserved): " + type);
115: */
116: if (isIs && type.equals(Boolean.TYPE.getName()) == false
117: && type.equals(Boolean.class.getName()) == false)
118: throw new IllegalArgumentException(
119: "Cannot have isIs for a non boolean/Boolean type");
120:
121: this .attributeType = type;
122: this .isRead = isReadable;
123: this .isWrite = isWritable;
124: this .is = isIs;
125: }
126:
127: /**
128: * Creates an MBean attribute info object using the given accessor methods.
129: *
130: * @param name Name of the attribute.
131: * @param description Human readable description string of the attribute's type.
132: * @param getter The attribute's read accessor. May be <tt>null</tt> if the attribute is write-only.
133: * @param setter The attribute's write accessor. May be <tt>null</tt> if the attribute is read-only.
134: *
135: * @throws IntrospectionException if the accessor methods are not valid for the attribute
136: */
137: public MBeanAttributeInfo(String name, String description,
138: Method getter, Method setter) throws IntrospectionException {
139: super (name, description);
140:
141: if (getter != null) {
142: // getter must always be no args method, return type cannot be void
143: if (getter.getParameterTypes().length != 0)
144: throw new IntrospectionException(
145: "Expecting getter method to be of the form 'AttributeType getAttributeName()': found getter with "
146: + getter.getParameterTypes().length
147: + " parameters.");
148: if (getter.getReturnType() == Void.TYPE)
149: throw new IntrospectionException(
150: "Expecting getter method to be of the form 'AttributeType getAttributeName()': found getter with void return type.");
151:
152: this .isRead = true;
153:
154: if (getter.getName().startsWith("is"))
155: this .is = true;
156:
157: this .attributeType = getter.getReturnType().getName();
158: }
159:
160: if (setter != null) {
161: // setter must have one argument, no less, no more. Return type must be void.
162: if (setter.getParameterTypes().length != 1)
163: throw new IntrospectionException(
164: "Expecting the setter method to be of the form 'void setAttributeName(AttributeType value)': found setter with "
165: + setter.getParameterTypes().length
166: + " parameters.");
167: if (setter.getReturnType() != Void.TYPE)
168: throw new IntrospectionException(
169: "Expecting the setter method to be of the form 'void setAttributeName(AttributeType value)': found setter with "
170: + setter.getReturnType()
171: + " return type.");
172:
173: this .isWrite = true;
174:
175: if (attributeType == null) {
176: try {
177: attributeType = setter.getParameterTypes()[0]
178: .getName();
179: } catch (ArrayIndexOutOfBoundsException e) {
180: throw new IntrospectionException(
181: "Attribute setter is lacking type: " + name);
182: }
183: }
184:
185: if (!(attributeType.equals(setter.getParameterTypes()[0]
186: .getName())))
187: throw new IntrospectionException(
188: "Attribute type mismatch: " + name);
189: }
190: }
191:
192: // Public --------------------------------------------------------
193:
194: /**
195: * Creates a copy of this object.
196: *
197: * @return clone of this object
198: */
199: public synchronized Object clone() {
200: MBeanAttributeInfo clone = null;
201: try {
202: clone = (MBeanAttributeInfo) super .clone();
203: clone.attributeType = this .attributeType;
204: clone.isRead = this .isRead;
205: clone.isWrite = this .isWrite;
206: clone.is = this .is;
207: } catch (CloneNotSupportedException e) {
208: }
209:
210: return clone;
211: }
212:
213: /**
214: * Returns the type string of this attribute.
215: *
216: * @return fully qualified class name of the attribute's type
217: */
218: public String getType() {
219: return attributeType;
220: }
221:
222: /**
223: * If the attribute is readable.
224: *
225: * @return true if attribute is readable; false otherwise
226: */
227: public boolean isReadable() {
228: return isRead;
229: }
230:
231: /**
232: * If the attribute is writable.
233: *
234: * @return true if attribute is writable; false otherwise
235: */
236: public boolean isWritable() {
237: return isWrite;
238: }
239:
240: /**
241: * If the attribute is using the boolean <tt>isAttributeName</tt> naming convention
242: * for its read accessor.
243: *
244: * @return true if using <tt>isAttributeName</tt> getter; false otherwise
245: */
246: public boolean isIs() {
247: return is;
248: }
249:
250: public boolean equals(Object object) {
251: if (this == object)
252: return true;
253: if (object == null
254: || (object instanceof MBeanAttributeInfo) == false)
255: return false;
256:
257: MBeanAttributeInfo other = (MBeanAttributeInfo) object;
258:
259: if (super .equals(other) == false)
260: return false;
261: if (this .getType().equals(other.getType()) == false)
262: return false;
263: if (this .isReadable() != other.isReadable())
264: return false;
265: if (this .isWritable() != other.isWritable())
266: return false;
267: if (this .isIs() != other.isIs())
268: return false;
269:
270: return true;
271: }
272:
273: public int hashCode() {
274: if (cacheHashCode == 0) {
275: cacheHashCode = super .hashCode();
276: cacheHashCode += getType().hashCode();
277: }
278: return cacheHashCode;
279: }
280:
281: public String toString() {
282: if (cacheString == null) {
283: StringBuffer buffer = new StringBuffer(100);
284: buffer.append(getClass().getName()).append(":");
285: buffer.append(" name=").append(getName());
286: buffer.append(" description=").append(getDescription());
287: buffer.append(" type=").append(getType());
288: buffer.append(" Readable=").append(isReadable());
289: buffer.append(" Writable=").append(isWritable());
290: buffer.append(" isIs=").append(isIs());
291: cacheString = buffer.toString();
292: }
293: return cacheString;
294: }
295:
296: }
|