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 org.jboss.mx.metadata;
023:
024: import java.util.ArrayList;
025: import java.util.HashMap;
026: import java.util.Iterator;
027: import java.util.List;
028: import javax.management.Descriptor;
029: import javax.management.MBeanAttributeInfo;
030: import javax.management.MBeanConstructorInfo;
031: import javax.management.MBeanException;
032: import javax.management.MBeanInfo;
033: import javax.management.MBeanNotificationInfo;
034: import javax.management.MBeanOperationInfo;
035: import javax.management.MBeanParameterInfo;
036: import javax.management.modelmbean.DescriptorSupport;
037: import javax.management.modelmbean.ModelMBeanAttributeInfo;
038: import javax.management.modelmbean.ModelMBeanConstructorInfo;
039: import javax.management.modelmbean.ModelMBeanInfo;
040: import javax.management.modelmbean.ModelMBeanInfoSupport;
041: import javax.management.modelmbean.ModelMBeanNotificationInfo;
042: import javax.management.modelmbean.ModelMBeanOperationInfo;
043: import org.jboss.mx.modelmbean.ModelMBeanConstants;
044: import org.jboss.mx.server.MethodMapper;
045:
046: /**
047: * Routines for converting MBeanInfo to ModelMBeanInfoSupport and stripping
048: * ModelMBeanOperationInfos that are referred to in ModelMBeanAttributeInfos.
049: *
050: * @author <a href="mailto:juha@jboss.org">Juha Lindfors</a>.
051: * @version $Revision: 57200 $
052: */
053: public class MBeanInfoConversion implements ModelMBeanConstants {
054: /**
055: * Convert regular MBeanInfo into ModelMBeanInfo.
056: *
057: * @param info MBeanInfo to convert (such as the Standard MBean info)
058: */
059: public static ModelMBeanInfoSupport toModelMBeanInfo(MBeanInfo info) {
060: return toModelMBeanInfo(info, true);
061: }
062:
063: /**
064: * Convert regular MBeanInfo to ModelMBeanInfo.
065: *
066: * @param info MBeanInfo to convert (such a the Standard MBean info)
067: * @param createAttributeOperationMapping setting this boolean to
068: * <tt>true</tt> will automatically create the attribute operation
069: * mapping for Model MBean managemenet attributes. Based on the
070: * Standard MBean attribute naming conventions, the Model MBean
071: * attribute descriptors are mapped to appropriate management
072: * operations with the <tt>getMethod</tt> and <tt>setMethod</tt>
073: * descriptor fields.
074: */
075: public static ModelMBeanInfoSupport toModelMBeanInfo(
076: MBeanInfo info, boolean createAttributeOperationMapping) {
077: if (info instanceof ModelMBeanInfoSupport)
078: return (ModelMBeanInfoSupport) info;
079:
080: if (info instanceof ModelMBeanInfo)
081: return new ModelMBeanInfoSupport((ModelMBeanInfo) info);
082:
083: // create attributes
084: MBeanAttributeInfo[] attributes = info.getAttributes();
085: ModelMBeanAttributeInfo[] mmbAttributes = new ModelMBeanAttributeInfo[attributes.length];
086: List accessorOperations = new ArrayList();
087:
088: for (int i = 0; i < attributes.length; ++i) {
089: // add basic info
090: ModelMBeanAttributeInfo attrInfo = new ModelMBeanAttributeInfo(
091: attributes[i].getName(), attributes[i].getType(),
092: attributes[i].getDescription(), attributes[i]
093: .isReadable(), attributes[i].isWritable(),
094: attributes[i].isIs());
095:
096: // by default, conversion metadata should not try to cache attributes
097: Descriptor d = attrInfo.getDescriptor();
098: d.setField(CURRENCY_TIME_LIMIT, CACHE_NEVER);
099: attrInfo.setDescriptor(d);
100:
101: mmbAttributes[i] = attrInfo;
102:
103: // if we're doing attribute operation mapping, find the accessor methods
104: // from the Standard MBean interface, and create the 'setter' and 'getter'
105: // management operations for them. Map the Model MBean attributes to
106: // these operations.
107: if (createAttributeOperationMapping) {
108: String getterOperationName = null;
109: String setterOperationName = null;
110: Descriptor getterDescriptor = null;
111: Descriptor setterDescriptor = null;
112:
113: // figure out the getter type
114: if (attributes[i].isReadable()) {
115: if (attributes[i].isIs())
116: getterOperationName = "is"
117: + attributes[i].getName();
118: else
119: getterOperationName = "get"
120: + attributes[i].getName();
121:
122: // create a descriptor for 'getter' mgmt operation
123: getterDescriptor = new DescriptorSupport();
124: getterDescriptor
125: .setField(NAME, getterOperationName);
126: getterDescriptor.setField(DESCRIPTOR_TYPE,
127: OPERATION_DESCRIPTOR);
128: getterDescriptor.setField(ROLE, ROLE_GETTER);
129:
130: // create the new management operation
131: ModelMBeanOperationInfo opInfo = new ModelMBeanOperationInfo(
132: getterOperationName,
133: "Read accessor operation for '"
134: + attributes[i].getName()
135: + "' attribute.",
136: new MBeanParameterInfo[0], // void signature
137: attributes[i].getType(), // return type
138: MBeanOperationInfo.INFO, // impact
139: getterDescriptor);
140:
141: // modify the attributes descriptor to map the read operation
142: // to the above created management operation
143: Descriptor attrDescriptor = mmbAttributes[i]
144: .getDescriptor();
145: attrDescriptor.setField(GET_METHOD,
146: getterOperationName);
147: mmbAttributes[i].setDescriptor(attrDescriptor);
148:
149: accessorOperations.add(opInfo);
150: }
151:
152: // figure out the setter
153: if (attributes[i].isWritable()) {
154: setterOperationName = "set"
155: + attributes[i].getName();
156:
157: // create a descriptor for 'setter' mgmt operation
158: setterDescriptor = new DescriptorSupport();
159: setterDescriptor
160: .setField(NAME, setterOperationName);
161: setterDescriptor.setField(DESCRIPTOR_TYPE,
162: OPERATION_DESCRIPTOR);
163: setterDescriptor.setField(ROLE, ROLE_SETTER);
164:
165: // create the new management operation
166: ModelMBeanOperationInfo opInfo = new ModelMBeanOperationInfo(
167: setterOperationName,
168: "Write accessor operation for '"
169: + attributes[i].getName()
170: + "' attribute.",
171:
172: new MBeanParameterInfo[] { new MBeanParameterInfo(
173: "value", attributes[i].getType(),
174: "Attribute's value.") },
175:
176: Void.TYPE.getName(),
177: MBeanOperationInfo.ACTION, setterDescriptor);
178:
179: // modify the attributes descriptor to map the read operation
180: // to the above created management operation
181: Descriptor attrDescriptor = mmbAttributes[i]
182: .getDescriptor();
183: attrDescriptor.setField(SET_METHOD,
184: setterOperationName);
185: mmbAttributes[i].setDescriptor(attrDescriptor);
186:
187: accessorOperations.add(opInfo);
188: }
189: }
190: }
191:
192: // deal with the basic manaement operations (non-getter and setter types)
193: MBeanOperationInfo[] operations = info.getOperations();
194: ModelMBeanOperationInfo[] mmbOperations = new ModelMBeanOperationInfo[operations.length
195: + accessorOperations.size()];
196:
197: for (int i = 0; i < operations.length; ++i) {
198: mmbOperations[i] = new ModelMBeanOperationInfo(
199: operations[i].getName(), operations[i]
200: .getDescription(), operations[i]
201: .getSignature(), operations[i]
202: .getReturnType(), operations[i].getImpact());
203: }
204:
205: for (int i = operations.length; i < mmbOperations.length; ++i)
206: mmbOperations[i] = (ModelMBeanOperationInfo) accessorOperations
207: .get(i - operations.length);
208:
209: // the constructors...
210: MBeanConstructorInfo[] constructors = info.getConstructors();
211: ModelMBeanConstructorInfo[] mmbConstructors = new ModelMBeanConstructorInfo[constructors.length];
212:
213: for (int i = 0; i < constructors.length; ++i) {
214: mmbConstructors[i] = new ModelMBeanConstructorInfo(
215: constructors[i].getName(), constructors[i]
216: .getDescription(), constructors[i]
217: .getSignature());
218: }
219:
220: // and finally the notifications
221:
222: // FIXME: we are assuming here that the Model MBean implementation adds the
223: // default generic and attribute change notifications to the metadata.
224: // I think we could explicitly add them here as well, can't see it
225: // do any harm. [JPL]
226: MBeanNotificationInfo[] notifications = info.getNotifications();
227: ModelMBeanNotificationInfo[] mmbNotifications = new ModelMBeanNotificationInfo[notifications.length];
228:
229: for (int i = 0; i < notifications.length; ++i) {
230: mmbNotifications[i] = new ModelMBeanNotificationInfo(
231: notifications[i].getNotifTypes(), notifications[i]
232: .getName(), notifications[i]
233: .getDescription());
234: }
235:
236: return new ModelMBeanInfoSupport(info.getClassName(), info
237: .getDescription(), mmbAttributes, mmbConstructors,
238: mmbOperations, mmbNotifications);
239: }
240:
241: /**
242: * Returns a ModelMBeanInfoSupport where ModelMBeanOperationInfos that are
243: * referred to by ModelMBeanAttributeInfo getMethod or setMethod descriptor
244: * fields are stripped out. If the stripAllRoles parameter is true
245: * then all the referred-to operations will be stripped. Otherwise only
246: * referred-to operations with a role of "getter" or "setter" will be stripped.
247: */
248: // why mbeanexception?
249: public static ModelMBeanInfoSupport stripAttributeOperations(
250: ModelMBeanInfo info, boolean stripAllRoles)
251: throws MBeanException {
252: HashMap opsMap = new HashMap();
253: ModelMBeanOperationInfo[] operations = (ModelMBeanOperationInfo[]) info
254: .getOperations();
255:
256: for (int i = 0; i < operations.length; i++) {
257: opsMap.put(MethodMapper.operationSignature(operations[i]),
258: operations[i]);
259: }
260:
261: ModelMBeanAttributeInfo[] attributes = (ModelMBeanAttributeInfo[]) info
262: .getAttributes();
263:
264: for (int i = 0; i < attributes.length; i++) {
265: if (attributes[i].isReadable()
266: && (attributes[i].getDescriptor().getFieldValue(
267: "getMethod") != null)) {
268: String key = MethodMapper
269: .getterSignature(attributes[i]);
270: ModelMBeanOperationInfo opinfo = (ModelMBeanOperationInfo) opsMap
271: .get(key);
272: String role = (String) opinfo.getDescriptor()
273: .getFieldValue("role");
274: if ("getter".equals(role) || stripAllRoles) {
275: opsMap.remove(key);
276: }
277: }
278:
279: if (attributes[i].isWritable()
280: && (attributes[i].getDescriptor().getFieldValue(
281: "setMethod") != null)) {
282: String key = MethodMapper
283: .setterSignature(attributes[i]);
284: ModelMBeanOperationInfo opinfo = (ModelMBeanOperationInfo) opsMap
285: .get(key);
286:
287: String role = (String) opinfo.getDescriptor()
288: .getFieldValue("role");
289: if ("setter".equals(role) || stripAllRoles) {
290: opsMap.remove(key);
291: }
292: }
293: }
294:
295: operations = new ModelMBeanOperationInfo[opsMap.size()];
296: int position = 0;
297: for (Iterator iterator = opsMap.values().iterator(); iterator
298: .hasNext(); position++) {
299: operations[position] = (ModelMBeanOperationInfo) iterator
300: .next();
301: }
302:
303: return new ModelMBeanInfoSupport(info.getClassName(), info
304: .getDescription(), (ModelMBeanAttributeInfo[]) info
305: .getAttributes(), (ModelMBeanConstructorInfo[]) info
306: .getConstructors(), operations,
307: (ModelMBeanNotificationInfo[]) info.getNotifications(),
308: info.getMBeanDescriptor());
309: }
310: }
|