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.modelmbean;
023:
024: import org.jboss.mx.modelmbean.ModelMBeanConstants;
025: import org.jboss.mx.util.Serialization;
026:
027: import javax.management.Descriptor;
028: import javax.management.DescriptorAccess;
029: import javax.management.MBeanOperationInfo;
030: import javax.management.MBeanParameterInfo;
031: import javax.management.RuntimeOperationsException;
032: import java.io.IOException;
033: import java.io.ObjectInputStream;
034: import java.io.ObjectOutputStream;
035: import java.io.ObjectStreamField;
036: import java.io.StreamCorruptedException;
037: import java.lang.reflect.Method;
038:
039: /**
040: * Represents Model MBean operation.
041: *
042: * @see javax.management.modelmbean.ModelMBeanInfo
043: * @see javax.management.modelmbean.ModelMBeanInfoSupport
044: *
045: * @author <a href="mailto:juha@jboss.org">Juha Lindfors</a>.
046: * @author <a href="mailto:adrian.brock@happeningtimes.com">Adrian Brock</a>.
047: * @author <a href="mailto:thomas.diesler@jboss.com">Thomas Diesler</a>.
048: * @version $Revision: 57200 $
049: *
050: */
051: public class ModelMBeanOperationInfo extends MBeanOperationInfo
052: implements DescriptorAccess {
053:
054: // Attributes ----------------------------------------------------
055:
056: /**
057: * The descriptor associated with this operation.
058: */
059: private Descriptor descriptor = null;
060:
061: /**
062: * The role of this operation
063: * Is constructor, getter, setter, operation
064: */
065: private transient String operationRole;
066:
067: // Static --------------------------------------------------------
068:
069: private static final long serialVersionUID;
070: private static final ObjectStreamField[] serialPersistentFields;
071:
072: static {
073: switch (Serialization.version) {
074: case Serialization.V1R0:
075: serialVersionUID = 9087646304346171239L;
076: serialPersistentFields = new ObjectStreamField[] { new ObjectStreamField(
077: "operDescriptor", Descriptor.class) };
078: break;
079: default:
080: serialVersionUID = 6532732096650090465L;
081: serialPersistentFields = new ObjectStreamField[] { new ObjectStreamField(
082: "operationDescriptor", Descriptor.class) };
083: }
084: }
085:
086: // Constructors --------------------------------------------------
087: /**
088: * Creates a new operation info with a default descriptor.
089: *
090: * @param description human readable description string
091: * @param operationMethod a <tt>Method</tt> instance representing the
092: * management operation
093: */
094: public ModelMBeanOperationInfo(String description,
095: Method operationMethod) {
096: super (description, operationMethod);
097: this .operationRole = getOperationRole();
098: setDescriptor(createDefaultDescriptor());
099: }
100:
101: /**
102: * Creates a new operation info with a given descriptor. If a <tt>null</tt> or
103: * invalid descriptor is passed as a paramter, a default descriptor will be created
104: * for the operation.
105: *
106: * @param description human readable description string
107: * @param operationMethod a <tt>Method</tt> instance representing the management
108: * operation
109: * @param descriptor a descriptor to associate with this operation
110: */
111: public ModelMBeanOperationInfo(String description,
112: Method operationMethod, Descriptor descriptor) {
113: super (description, operationMethod);
114: this .operationRole = getOperationRole();
115: setDescriptor(descriptor);
116: }
117:
118: /**
119: * Creates a new operation info with a default descriptor.
120: *
121: * @param name name of the operation
122: * @param description human readable description string
123: * @param signature operation signature
124: * @param type a fully qualified name of the operations return type
125: * @param impact operation impact: {@link #INFO INFO}, {@link #ACTION ACTION}, {@link #ACTION_INFO ACTION_INFO}, {@link #UNKNOWN UNKNOWN}
126: */
127: public ModelMBeanOperationInfo(String name, String description,
128: MBeanParameterInfo[] signature, String type, int impact) {
129: super (name, description, signature, type, impact);
130: this .operationRole = getOperationRole();
131: setDescriptor(createDefaultDescriptor());
132: }
133:
134: /**
135: * Creates a new operation info with a given descriptor. If a <tt>null</tt> or invalid
136: * descriptor is passed as a parameter, a default descriptor will be created for the operation.
137: *
138: * @param name name of the operation
139: * @param description human readable description string
140: * @param signature operation signature
141: * @param type a fully qualified name of the oeprations return type
142: * @param impact operation impact: {@link #INFO INFO}, {@link #ACTION ACTION}, {@link #ACTION_INFO ACTION_INFO}, {@link #UNKNOWN UNKNOWN}
143: * @param descriptor a descriptor to associate with this operation
144: */
145: public ModelMBeanOperationInfo(String name, String description,
146: MBeanParameterInfo[] signature, String type, int impact,
147: Descriptor descriptor) {
148: super (name, description, signature, type, impact);
149: this .operationRole = getOperationRole();
150: setDescriptor(descriptor);
151: }
152:
153: /**
154: * Copy constructor.
155: *
156: * @param info the operation info to copy
157: */
158: public ModelMBeanOperationInfo(ModelMBeanOperationInfo info) {
159: this (info.getName(), info.getDescription(),
160: info.getSignature(), info.getReturnType(), info
161: .getImpact(), info.getDescriptor());
162: }
163:
164: /**
165: * Get the role of this operation
166: */
167: private String getOperationRole() {
168: if (getName().startsWith("get")
169: && getReturnType().equals("void") == false
170: && getSignature().length == 0)
171: return ModelMBeanConstants.ROLE_GETTER;
172: else if (getName().startsWith("is")
173: && (getReturnType().equals("boolean") || getReturnType()
174: .equals("java.lang.Boolean"))
175: && getSignature().length == 0)
176: return ModelMBeanConstants.ROLE_GETTER;
177: else if (getName().startsWith("set")
178: && getReturnType().equals("void")
179: && getSignature().length == 1)
180: return ModelMBeanConstants.ROLE_SETTER;
181: else
182: return ModelMBeanConstants.ROLE_OPERATION;
183: }
184:
185: // DescriptorAccess implementation -------------------------------
186:
187: /**
188: * Returns a copy of the descriptor associated with this operation.
189: *
190: * @return a copy of this operation's associated descriptor
191: */
192: public Descriptor getDescriptor() {
193: return (Descriptor) descriptor.clone();
194: }
195:
196: /**
197: * Replaces the descriptor associated with this operation. If the <tt>inDescriptor</tt>
198: * argument is <tt>null</tt> then the existing descriptor is replaced with a default
199: * descriptor.
200: *
201: * @param inDescriptor descriptor used for replacing the existing operation descriptor
202: * @throws IllegalArgumentException if the new descriptor is not valid
203: */
204: public void setDescriptor(Descriptor inDescriptor) {
205: if (inDescriptor == null)
206: inDescriptor = createDefaultDescriptor();
207:
208: if (inDescriptor.isValid()
209: && isOperationDescriptorValid(inDescriptor))
210: this .descriptor = inDescriptor;
211: }
212:
213: /**
214: * Validate the descriptor in the context of an attribute
215: */
216: private boolean isOperationDescriptorValid(Descriptor inDescriptor) {
217: String name = (String) inDescriptor
218: .getFieldValue(ModelMBeanConstants.NAME);
219: if (name.equals(getName()) == false)
220: throw new RuntimeOperationsException(
221: new IllegalArgumentException(
222: "Invalid name, expected '" + getName()
223: + "' but got: " + name));
224:
225: String descriptorType = (String) inDescriptor
226: .getFieldValue(ModelMBeanConstants.DESCRIPTOR_TYPE);
227: if (ModelMBeanConstants.OPERATION_DESCRIPTOR
228: .equalsIgnoreCase(descriptorType) == false)
229: throw new RuntimeOperationsException(
230: new IllegalArgumentException(
231: "Invalid descriptorType, for operation '"
232: + name
233: + "' expected 'operation' but got: "
234: + descriptorType));
235:
236: String role = (String) inDescriptor
237: .getFieldValue(ModelMBeanConstants.ROLE);
238: if (role != null && operationRole.equals(role) == false)
239: throw new RuntimeOperationsException(
240: new IllegalArgumentException(
241: "Invalid role, for operation '" + name
242: + "' expected '" + operationRole
243: + "' but got: " + role));
244:
245: return true;
246: }
247:
248: // Cloneable implementation --------------------------------------
249: /**
250: * Creates a copy of this object.
251: *
252: * @return clone of this object
253: */
254: public synchronized Object clone() {
255: ModelMBeanOperationInfo clone = (ModelMBeanOperationInfo) super
256: .clone();
257: clone.descriptor = (Descriptor) this .descriptor.clone();
258: return clone;
259: }
260:
261: // Object overrides ----------------------------------------------
262: /**
263: * Returns a string representation of this Model MBean operation info object.
264: * The returned string is in the form: <pre>
265: *
266: * ModelMBeanOperationInfo[<return type> <operation name>(<signature>),
267: * Impact=ACTION | INFO | ACTION_INFO | UNKNOWN,
268: * Descriptor=(fieldName1=fieldValue1, ... , fieldName<n>=fieldValue<n>)]
269: *
270: * </pre>
271: *
272: * @return string representation of this object
273: */
274: public String toString() {
275: return "ModelMBeanOperationInfo[" + getReturnType() + " "
276: + getName() + getSignatureString() + ",Impact="
277: + getImpactString() + ",Descriptor(" + getDescriptor()
278: + ")]";
279: }
280:
281: // Private -------------------------------------------------------
282: private String getSignatureString() {
283: StringBuffer sbuf = new StringBuffer(400);
284: sbuf.append("(");
285:
286: MBeanParameterInfo[] sign = getSignature();
287:
288: if (sign.length > 0) {
289: for (int i = 0; i < sign.length; ++i) {
290: sbuf.append(sign[i].getType());
291: sbuf.append(" ");
292: sbuf.append(sign[i].getName());
293:
294: sbuf.append(",");
295: }
296:
297: sbuf.delete(sbuf.length() - 1, sbuf.length());
298: }
299: sbuf.append(")");
300:
301: return sbuf.toString();
302: }
303:
304: private String getImpactString() {
305: int impact = getImpact();
306: if (impact == MBeanOperationInfo.ACTION)
307: return "ACTION";
308: else if (impact == MBeanOperationInfo.INFO)
309: return "INFO";
310: else if (impact == MBeanOperationInfo.ACTION_INFO)
311: return "ACTION_INFO";
312: else
313: return "UNKNOWN";
314: }
315:
316: /**
317: * The default descriptor will have name, descriptorType, displayName and role fields set.
318: */
319: private Descriptor createDefaultDescriptor() {
320: DescriptorSupport descr = new DescriptorSupport();
321: descr.setField(ModelMBeanConstants.NAME, super .getName());
322: descr.setField(ModelMBeanConstants.DISPLAY_NAME, super
323: .getName());
324: descr.setField(ModelMBeanConstants.DESCRIPTOR_TYPE,
325: ModelMBeanConstants.OPERATION_DESCRIPTOR);
326: descr.setField(ModelMBeanConstants.ROLE, operationRole);
327: return descr;
328: }
329:
330: private void readObject(ObjectInputStream ois) throws IOException,
331: ClassNotFoundException {
332: ObjectInputStream.GetField getField = ois.readFields();
333: switch (Serialization.version) {
334: case Serialization.V1R0:
335: descriptor = (Descriptor) getField.get("operDescriptor",
336: null);
337: break;
338: default:
339: descriptor = (Descriptor) getField.get(
340: "operationDescriptor", null);
341: }
342: if (descriptor == null)
343: throw new StreamCorruptedException("Null descriptor?");
344: }
345:
346: private void writeObject(ObjectOutputStream oos) throws IOException {
347: ObjectOutputStream.PutField putField = oos.putFields();
348: switch (Serialization.version) {
349: case Serialization.V1R0:
350: putField.put("operDescriptor", descriptor);
351: break;
352: default:
353: putField.put("operationDescriptor", descriptor);
354: }
355: oos.writeFields();
356: }
357: }
|