0001: /**
0002: * Copyright 2004-2005 jManage.org
0003: *
0004: * Licensed under the Apache License, Version 2.0 (the "License");
0005: * you may not use this file except in compliance with the License.
0006: * You may obtain a copy of the License at
0007: *
0008: * http://www.apache.org/licenses/LICENSE-2.0
0009: *
0010: * Unless required by applicable law or agreed to in writing, software
0011: * distributed under the License is distributed on an "AS IS" BASIS,
0012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013: * See the License for the specific language governing permissions and
0014: * limitations under the License.
0015: */package org.jmanage.core.services;
0016:
0017: import org.apache.commons.beanutils.ConvertUtils;
0018: import org.jmanage.core.config.ApplicationConfig;
0019: import org.jmanage.core.config.MBeanConfig;
0020: import org.jmanage.core.data.AttributeListData;
0021: import org.jmanage.core.data.MBeanData;
0022: import org.jmanage.core.data.OperationResultData;
0023: import org.jmanage.core.management.*;
0024: import org.jmanage.core.util.*;
0025: import org.jmanage.util.StringUtils;
0026:
0027: import javax.management.openmbean.CompositeData;
0028: import javax.management.openmbean.CompositeType;
0029: import javax.management.openmbean.OpenType;
0030: import java.lang.reflect.Constructor;
0031: import java.util.*;
0032: import java.util.logging.Level;
0033: import java.util.logging.Logger;
0034:
0035: /**
0036: *
0037: * date: Feb 21, 2005
0038: * @author Rakesh Kalra, Shashank Bellary
0039: */
0040: public class MBeanServiceImpl implements MBeanService {
0041:
0042: private static final Logger logger = Loggers
0043: .getLogger(MBeanService.class);
0044:
0045: private static final String DEFAULT_FILTER = "*:*";
0046: private static final char COMPOSITE_ATTR_SEPARATOR = '.';
0047:
0048: private static final ObjectName DEFAULT_FILTER_OBJECT_NAME = new ObjectName(
0049: DEFAULT_FILTER);
0050:
0051: public List queryMBeans(ServiceContext context, String filter)
0052: throws ServiceException {
0053:
0054: ServerConnection serverConnection = context
0055: .getServerConnection();
0056:
0057: ObjectName filterObjectName = null;
0058: if (filter == null) {
0059: filterObjectName = DEFAULT_FILTER_OBJECT_NAME;
0060: } else {
0061: filterObjectName = new ObjectName(filter);
0062: }
0063:
0064: Set mbeans = serverConnection.queryNames(filterObjectName);
0065: ArrayList mbeanDataList = new ArrayList(mbeans.size());
0066: for (Iterator it = mbeans.iterator(); it.hasNext();) {
0067: ObjectName objName = (ObjectName) it.next();
0068: mbeanDataList.add(new MBeanData(objName.getDisplayName()));
0069: }
0070: return mbeanDataList;
0071: }
0072:
0073: public Map queryMBeansOutputMap(ServiceContext context,
0074: String filter, String[] dataTypes, String applyAttribFilter) {
0075: List mbeanDataList = null;
0076: if ("false".equals(applyAttribFilter)) {
0077: mbeanDataList = queryMBeans(context, filter);
0078: } else {
0079: mbeanDataList = queryMBeansWithAttributes(context, filter,
0080: dataTypes);
0081: }
0082:
0083: Map domainToObjectNameListMap = new TreeMap();
0084: ObjectNameTuple tuple = new ObjectNameTuple();
0085: for (Iterator it = mbeanDataList.iterator(); it.hasNext();) {
0086: MBeanData mbeanData = (MBeanData) it.next();
0087: tuple.setObjectName(mbeanData.getName());
0088: String domain = tuple.getDomain();
0089: String name = tuple.getName();
0090: Set objectNameList = (Set) domainToObjectNameListMap
0091: .get(domain);
0092: if (objectNameList == null) {
0093: objectNameList = new TreeSet();
0094: domainToObjectNameListMap.put(domain, objectNameList);
0095: }
0096: objectNameList.add(name);
0097: }
0098: return domainToObjectNameListMap;
0099: }
0100:
0101: private List queryMBeansWithAttributes(ServiceContext context,
0102: String filter, String[] dataTypes) throws ServiceException {
0103: ServerConnection serverConnection = context
0104: .getServerConnection();
0105: List mbeans = queryMBeans(context, filter);
0106: List mbeanToAttributesList = new ArrayList();
0107: for (Iterator itr = mbeans.iterator(); itr.hasNext();) {
0108: MBeanData mbeanData = (MBeanData) itr.next();
0109: ObjectName objName = new ObjectName(mbeanData.getName());
0110: try {
0111: ObjectInfo objInfo = serverConnection
0112: .getObjectInfo(objName);
0113: ObjectAttributeInfo[] objAttrInfo = objInfo
0114: .getAttributes();
0115: if (objAttrInfo != null && objAttrInfo.length > 0) {
0116: if (dataTypes != null && dataTypes.length > 0) {
0117: if (checkAttributeDataType(serverConnection,
0118: objName, objAttrInfo, dataTypes,
0119: context.getApplicationConfig(), null)) {
0120: mbeanToAttributesList.add(mbeanData);
0121: }
0122: } else {
0123: mbeanToAttributesList.add(mbeanData);
0124: }
0125: }
0126: } catch (Exception e) {
0127: /* if there is an error while getting MBean Info, continue
0128: looking further */
0129: String errorMessage = "Error getting ObjectInfo for: "
0130: + objName + ", error=" + e.getMessage();
0131: logger.log(Level.WARNING, errorMessage);
0132: logger.log(Level.FINE, errorMessage, e);
0133: }
0134: }
0135: return mbeanToAttributesList;
0136: }
0137:
0138: /**
0139: *
0140: * @param objAttrInfo
0141: * @param dataTypes
0142: * @param appConfig
0143: * @param attributesList (optional) if specified, it will be populated
0144: * with ObjectAttributeInfo objects that match the dataTypes
0145: * specified
0146: * @return
0147: */
0148: private boolean checkAttributeDataType(ServerConnection connection,
0149: ObjectName objectName, ObjectAttributeInfo[] objAttrInfo,
0150: String[] dataTypes, ApplicationConfig appConfig,
0151: List attributesList) {
0152:
0153: boolean result = false;
0154: outerloop: for (int i = 0; i < objAttrInfo.length; i++) {
0155: ObjectAttributeInfo attrInfo = objAttrInfo[i];
0156: for (int j = 0; j < dataTypes.length; j++) {
0157: Class attrInfoType = getClass(attrInfo.getType(),
0158: appConfig.getApplicationClassLoader());
0159: Class dataType = getClass(dataTypes[j], this .getClass()
0160: .getClassLoader());
0161: if (attrInfoType != null
0162: && dataType.isAssignableFrom(attrInfoType)) {
0163: result = true;
0164: if (attributesList != null) {
0165: /* special handling for CompositeData */
0166: if (attrInfoType
0167: .getName()
0168: .equals(
0169: "javax.management.openmbean.CompositeData")) {
0170: handleCompositeData(connection, objectName,
0171: attrInfo, dataTypes, attributesList);
0172: } else {
0173: attributesList.add(attrInfo);
0174: }
0175: } else {
0176: // we found one. return true
0177: break outerloop;
0178: }
0179: }
0180: }
0181: }
0182: return result;
0183: }
0184:
0185: /**
0186: * Expands a CompositeData object into individual attributes with the
0187: * naming convention:
0188: * <p>
0189: * attributeName.itemName
0190: * <p>
0191: * The items should conform to given "dataType" array. These individual
0192: * attributes are added to the <code>attributeList</code>
0193: * @param attributesList ObjectAttributeInfo instances are added to this
0194: * list
0195: */
0196: private void handleCompositeData(ServerConnection connection,
0197: ObjectName objectName, ObjectAttributeInfo attrInfo,
0198: String[] dataTypes, List attributesList) {
0199:
0200: CompositeType type = getCompositeType(connection, objectName,
0201: attrInfo);
0202: for (Iterator it = type.keySet().iterator(); it.hasNext();) {
0203: String itemName = (String) it.next();
0204: OpenType itemType = type.getType(itemName);
0205: Class itemTypeClass = getClass(itemType.getClassName(),
0206: this .getClass().getClassLoader());
0207: for (int j = 0; j < dataTypes.length; j++) {
0208:
0209: Class dataType = getClass(dataTypes[j], this .getClass()
0210: .getClassLoader());
0211: if (dataType.isAssignableFrom(itemTypeClass)) {
0212: attributesList.add(new ObjectAttributeInfo(attrInfo
0213: .getName()
0214: + COMPOSITE_ATTR_SEPARATOR + itemName, type
0215: .getDescription(itemName), itemType
0216: .getClassName(), false, true, false));
0217: }
0218: }
0219: }
0220: }
0221:
0222: // todo: is there a simpler way to get CompositeType (without getting the value)
0223: private CompositeType getCompositeType(ServerConnection connection,
0224: ObjectName objectName, ObjectAttributeInfo attrInfo) {
0225: CompositeData compositeData = (CompositeData) connection
0226: .getAttribute(objectName, attrInfo.getName());
0227: return compositeData.getCompositeType();
0228: }
0229:
0230: private Class getClass(String type, ClassLoader classLoader) {
0231: if (type.equals("boolean"))
0232: return Boolean.class;
0233: if (type.equals("byte"))
0234: return Byte.TYPE;
0235: if (type.equals("char"))
0236: return Character.class;
0237: if (type.equals("double"))
0238: return Double.class;
0239: if (type.equals("float"))
0240: return Float.class;
0241: if (type.equals("int"))
0242: return Integer.class;
0243: if (type.equals("long"))
0244: return Long.class;
0245: if (type.equals("short"))
0246: return Short.class;
0247: if (type.equals("void"))
0248: return Void.class;
0249: Class clazz = null;
0250: try {
0251: clazz = Class.forName(type, true, classLoader);
0252:
0253: } catch (ClassNotFoundException e) {
0254: logger.fine("Error finding class of type=" + type
0255: + ", error=" + e.getMessage());
0256: }
0257: return clazz;
0258: }
0259:
0260: private static class ObjectNameTuple {
0261: String domain;
0262: String name;
0263:
0264: void setObjectName(String canonicalName) {
0265: int index = canonicalName.indexOf(":");
0266: domain = canonicalName.substring(0, index);
0267: name = canonicalName.substring(index + 1);
0268: }
0269:
0270: String getName() {
0271: return name;
0272: }
0273:
0274: String getDomain() {
0275: return domain;
0276: }
0277: }
0278:
0279: public ObjectInfo getMBeanInfo(ServiceContext context)
0280: throws ServiceException {
0281: canAccessThisMBean(context);
0282: ServerConnection serverConnection = ServiceUtils
0283: .getServerConnectionEvenIfCluster(context
0284: .getApplicationConfig());
0285: ObjectInfo objectInfo = serverConnection.getObjectInfo(context
0286: .getObjectName());
0287: return objectInfo;
0288: }
0289:
0290: /**
0291: * @return list of all attribute values
0292: */
0293: public AttributeListData[] getAttributes(ServiceContext context)
0294: throws ServiceException {
0295: canAccessThisMBean(context);
0296: ServerConnection serverConnection = null;
0297: try {
0298: serverConnection = ServiceUtils
0299: .getServerConnectionEvenIfCluster(context
0300: .getApplicationConfig());
0301: ObjectInfo objInfo = serverConnection.getObjectInfo(context
0302: .getObjectName());
0303: assert objInfo != null;
0304: ObjectAttributeInfo[] attributes = objInfo.getAttributes();
0305: List attributeNames = new LinkedList();
0306: for (int i = 0; i < attributes.length; i++) {
0307: if (attributes[i].isReadable()) {
0308: attributeNames.add(attributes[i].getName());
0309: }
0310: }
0311: String[] attributeArray = StringUtils
0312: .listToStringArray(attributeNames);
0313: return getAttributes(context, attributeArray, true);
0314: } finally {
0315: ServiceUtils.close(serverConnection);
0316: }
0317: }
0318:
0319: /**
0320: *
0321: * @return list of attribute values for given attributes
0322: */
0323: public AttributeListData[] getAttributes(ServiceContext context,
0324: String[] attributes, boolean handleCluster)
0325: throws ServiceException {
0326: canAccessThisMBean(context);
0327: ApplicationConfig appConfig = context.getApplicationConfig();
0328: ObjectName objectName = context.getObjectName();
0329:
0330: AttributeListData[] resultData = null;
0331: if (appConfig.isCluster()) {
0332: if (!handleCluster) {
0333: throw new ServiceException(
0334: ErrorCodes.OPERATION_NOT_SUPPORTED_FOR_CLUSTER);
0335: }
0336: /* we need to perform this operation for all servers
0337: in this cluster */
0338: resultData = new AttributeListData[appConfig
0339: .getApplications().size()];
0340: int index = 0;
0341: for (Iterator it = appConfig.getApplications().iterator(); it
0342: .hasNext(); index++) {
0343: ApplicationConfig childAppConfig = (ApplicationConfig) it
0344: .next();
0345: try {
0346: resultData[index] = getAttributes(context,
0347: childAppConfig, objectName, attributes);
0348: } catch (ConnectionFailedException e) {
0349: resultData[index] = new AttributeListData(
0350: childAppConfig.getName());
0351: }
0352: }
0353: } else {
0354: resultData = new AttributeListData[1];
0355: resultData[0] = getAttributes(context, appConfig,
0356: objectName, attributes);
0357: }
0358: return resultData;
0359: }
0360:
0361: /**
0362: * Returns ObjectAttribute instance containing the value of the given
0363: * attribute. This method also handles CompositeData item with the
0364: * attribute naming convention:
0365: * <p>
0366: * Building.NumberOfFloors
0367: * <p>
0368: * where "Building" is the composite attribute name and "NumberOfFloors"
0369: * is the item name in the "Building" composite type.
0370: *
0371: * @param context
0372: * @param attribute
0373: * @return
0374: * @throws ServiceException
0375: */
0376: public ObjectAttribute getObjectAttribute(ServiceContext context,
0377: String attribute) throws ServiceException {
0378: assert context.getObjectName() != null;
0379: assert context.getApplicationConfig() != null;
0380: canAccessThisMBean(context);
0381: AccessController.checkAccess(context,
0382: ACLConstants.ACL_VIEW_MBEAN_ATTRIBUTES, attribute);
0383: // we don't support clustering here
0384: assert !context.getApplicationConfig().isCluster();
0385:
0386: ServerConnection connection = context.getServerConnection();
0387: List attrList = connection.getAttributes(context
0388: .getObjectName(), new String[] { attribute });
0389: ObjectAttribute attrValue = (ObjectAttribute) attrList.get(0);
0390: if (attrValue.getStatus() != ObjectAttribute.STATUS_NOT_FOUND) {
0391: return attrValue;
0392: }
0393:
0394: /* see if this is a composite attribute */
0395: String attributeName = null;
0396: String itemName = null;
0397: int index = attribute.indexOf(COMPOSITE_ATTR_SEPARATOR);
0398: if (index == -1)
0399: return attrValue;
0400:
0401: // composite data attribute
0402: itemName = attribute.substring(index + 1);
0403: attributeName = attribute.substring(0, index);
0404:
0405: attrList = connection.getAttributes(context.getObjectName(),
0406: new String[] { attributeName });
0407: attrValue = (ObjectAttribute) attrList.get(0);
0408: if (attrValue.getStatus() == ObjectAttribute.STATUS_OK) {
0409: CompositeData compositeData = (CompositeData) attrValue
0410: .getValue();
0411: attrValue = new ObjectAttribute(attribute, compositeData
0412: .get(itemName));
0413: }
0414: return attrValue;
0415: }
0416:
0417: /**
0418: * @return list of attribute values for given attributes
0419: */
0420: private AttributeListData getAttributes(ServiceContext context,
0421: ApplicationConfig appConfig, ObjectName objectName,
0422: String[] attributes) throws ConnectionFailedException {
0423:
0424: // TODO: we should hide the attributes in the jsp
0425: for (int attrCount = 0; attrCount < attributes.length; attrCount++) {
0426: AccessController.checkAccess(context,
0427: ACLConstants.ACL_VIEW_MBEAN_ATTRIBUTES,
0428: attributes[attrCount]);
0429: }
0430: ServerConnection connection = null;
0431:
0432: try {
0433: connection = ServerConnector.getServerConnection(appConfig);
0434: List attrList = connection.getAttributes(objectName,
0435: attributes);
0436: return new AttributeListData(appConfig.getName(), attrList);
0437: } finally {
0438: ServiceUtils.close(connection);
0439: }
0440: }
0441:
0442: public List filterAttributes(ServiceContext context,
0443: ObjectName objectName, ObjectAttributeInfo[] objAttrInfo,
0444: String[] dataTypes) {
0445: List objAttrInfoList = new LinkedList();
0446: checkAttributeDataType(context.getServerConnection(),
0447: objectName, objAttrInfo, dataTypes, context
0448: .getApplicationConfig(), objAttrInfoList);
0449: return objAttrInfoList;
0450: }
0451:
0452: public OperationResultData[] invoke(ServiceContext context,
0453: String operationName, String[] params)
0454: throws ServiceException {
0455: canAccessThisMBean(context);
0456: AccessController.checkAccess(context,
0457: ACLConstants.ACL_EXECUTE_MBEAN_OPERATIONS,
0458: operationName);
0459:
0460: /* try to determine the method, based on params */
0461: ObjectOperationInfo operationInfo = findOperation(context,
0462: operationName, params != null ? params.length : 0);
0463: return invoke(context, operationName, params, operationInfo
0464: .getParameters());
0465: }
0466:
0467: /**
0468: * Invokes MBean operation
0469: * @return
0470: * @throws ServiceException
0471: */
0472: public OperationResultData[] invoke(ServiceContext context,
0473: String operationName, String[] params, String[] signature)
0474: throws ServiceException {
0475: canAccessThisMBean(context);
0476: AccessController.checkAccess(context,
0477: ACLConstants.ACL_EXECUTE_MBEAN_OPERATIONS,
0478: operationName);
0479:
0480: ApplicationConfig appConfig = context.getApplicationConfig();
0481: ObjectName objectName = context.getObjectName();
0482:
0483: OperationResultData[] resultData = null;
0484: if (appConfig.isCluster()) {
0485: /* we need to perform this operation for all servers
0486: in this cluster */
0487: resultData = new OperationResultData[appConfig
0488: .getApplications().size()];
0489: int index = 0;
0490: for (Iterator it = appConfig.getApplications().iterator(); it
0491: .hasNext(); index++) {
0492: ApplicationConfig childAppConfig = (ApplicationConfig) it
0493: .next();
0494: resultData[index] = executeMBeanOperation(context,
0495: childAppConfig, objectName, operationName,
0496: params, signature);
0497: }
0498: } else {
0499: resultData = new OperationResultData[1];
0500: resultData[0] = executeMBeanOperation(context, appConfig,
0501: objectName, operationName, params, signature);
0502: }
0503: return resultData;
0504: }
0505:
0506: private static OperationResultData executeMBeanOperation(
0507: ServiceContext context, ApplicationConfig appConfig,
0508: ObjectName objectName, String operationName,
0509: String[] params, String[] signature) {
0510:
0511: OperationResultData resultData = new OperationResultData(
0512: appConfig.getName());
0513: ServerConnection serverConnection = null;
0514: try {
0515: serverConnection = ServerConnector
0516: .getServerConnection(appConfig);
0517: Object[] typedParams = getTypedArray(appConfig, params,
0518: signature);
0519: final Object result = serverConnection.invoke(objectName,
0520: operationName, typedParams, signature);
0521:
0522: resultData.setOutput(result);
0523: UserActivityLogger.getInstance().logActivity(
0524: context.getUser().getUsername(),
0525: "Performed " + operationName + " on "
0526: + objectName.getCanonicalName()
0527: + " in application " + appConfig.getName());
0528: } catch (ConnectionFailedException e) {
0529: logger.log(Level.INFO, "Error executing operation "
0530: + operationName + " on " + objectName, e);
0531: resultData.setResult(OperationResultData.RESULT_ERROR);
0532: resultData.setErrorString(ErrorCatalog
0533: .getMessage(ErrorCodes.CONNECTION_FAILED));
0534: } catch (RuntimeException e) {
0535: logger.log(Level.SEVERE, "Error executing operation "
0536: + operationName + " on " + objectName, e);
0537: resultData.setResult(OperationResultData.RESULT_ERROR);
0538: if (e.getCause() != null) {
0539: if (e.getCause().getClass().getName().equals(
0540: "javax.management.RuntimeMBeanException")
0541: && e.getCause().getCause() != null) {
0542: resultData.setException(e.getCause().getCause());
0543: } else {
0544: resultData.setException(e.getCause());
0545: }
0546: } else {
0547: resultData.setException(e);
0548: }
0549: } catch (Exception e) {
0550: logger.log(Level.SEVERE, "Error executing operation "
0551: + operationName + " on " + objectName, e);
0552: resultData.setResult(OperationResultData.RESULT_ERROR);
0553: resultData.setException(e);
0554: } finally {
0555: ServiceUtils.close(serverConnection);
0556: }
0557: return resultData;
0558: }
0559:
0560: private ObjectOperationInfo findOperation(ServiceContext context,
0561: String operationName, int paramCount) {
0562:
0563: ObjectName objectName = context.getObjectName();
0564: ServerConnection connection = null;
0565: try {
0566: connection = ServiceUtils
0567: .getServerConnectionEvenIfCluster(context
0568: .getApplicationConfig());
0569: ObjectInfo objectInfo = connection
0570: .getObjectInfo(objectName);
0571: ObjectOperationInfo[] operationInfo = objectInfo
0572: .getOperations();
0573: for (int i = 0; i < operationInfo.length; i++) {
0574: if (operationInfo[i].getName().equals(operationName)
0575: && operationInfo[i].getSignature().length == paramCount) {
0576: return operationInfo[i];
0577: }
0578: }
0579: throw new ServiceException(
0580: ErrorCodes.INVALID_MBEAN_OPERATION, operationName,
0581: objectName);
0582: } finally {
0583: ServiceUtils.close(connection);
0584: }
0585: }
0586:
0587: //TODO: should we first check that all apps in a cluster are up,
0588: // before updating? - rk
0589: public AttributeListData[] setAttributes(ServiceContext context,
0590: String[][] attributes) throws ServiceException {
0591: canAccessThisMBean(context);
0592: List applications = getApplications(context
0593: .getApplicationConfig());
0594: ObjectName objectName = context.getObjectName();
0595: List attributeList = buildAttributeList(context, attributes);
0596: AttributeListData[] attrListData = new AttributeListData[applications
0597: .size()];
0598: int index = 0;
0599: for (Iterator it = applications.iterator(); it.hasNext(); index++) {
0600: final ApplicationConfig childAppConfig = (ApplicationConfig) it
0601: .next();
0602: attrListData[index] = updateAttributes(context,
0603: childAppConfig, objectName, attributeList);
0604: }
0605: return attrListData;
0606: }
0607:
0608: /**
0609: * Updates MBean attributes at a stand alone application level or at a
0610: * cluster level.
0611: * <p>
0612: * The attributes element contains the keys in the format:
0613: * attr+<applicationId>+<attrName>+<attrType>
0614: * <p>
0615: * todo: improve this interface (currently written for webui)
0616: *
0617: *
0618: * @param context
0619: * @param attributes Map containing
0620: * @throws ServiceException
0621: */
0622: public AttributeListData[] setAttributes(ServiceContext context,
0623: Map attributes) throws ServiceException {
0624: canAccessThisMBean(context);
0625: List applications = getApplications(context
0626: .getApplicationConfig());
0627: ObjectName objectName = context.getObjectName();
0628: AttributeListData[] attrListData = new AttributeListData[applications
0629: .size()];
0630: int index = 0;
0631:
0632: ServerConnection connection = ServiceUtils
0633: .getServerConnectionEvenIfCluster(context
0634: .getApplicationConfig());
0635: try {
0636: ObjectInfo objInfo = connection.getObjectInfo(objectName);
0637: for (Iterator it = applications.iterator(); it.hasNext(); index++) {
0638: final ApplicationConfig childAppConfig = (ApplicationConfig) it
0639: .next();
0640: List attributeList = buildAttributeList(attributes,
0641: childAppConfig, objInfo.getAttributes(),
0642: connection, objectName);
0643: attrListData[index] = updateAttributes(context,
0644: childAppConfig, objectName, attributeList);
0645: }
0646: } finally {
0647: ServiceUtils.close(connection);
0648: }
0649: return attrListData;
0650: }
0651:
0652: public Map queryMBeansWithNotifications(ServiceContext context)
0653: throws ServiceException {
0654:
0655: ServerConnection serverConnection = context
0656: .getServerConnection();
0657: Set mbeans = serverConnection
0658: .queryNames(DEFAULT_FILTER_OBJECT_NAME);
0659: Map mbeanToNoficationsMap = new TreeMap();
0660: for (Iterator it = mbeans.iterator(); it.hasNext();) {
0661: ObjectName objName = (ObjectName) it.next();
0662:
0663: try {
0664: ObjectInfo objInfo = serverConnection
0665: .getObjectInfo(objName);
0666: ObjectNotificationInfo[] notifications = objInfo
0667: .getNotifications();
0668: if (notifications != null && notifications.length > 0) {
0669: mbeanToNoficationsMap.put(objName.getDisplayName(),
0670: notifications);
0671: }
0672: } catch (Exception e) {
0673: /* if there is an error while getting MBean Info, continue
0674: looking further */
0675: String errorMessage = "Error getting ObjectInfo for: "
0676: + objName + ", error=" + e.getMessage();
0677: logger.log(Level.WARNING, errorMessage);
0678: logger.log(Level.FINE, errorMessage, e);
0679: }
0680: }
0681: return mbeanToNoficationsMap;
0682: }
0683:
0684: private AttributeListData updateAttributes(ServiceContext context,
0685: ApplicationConfig appConfig, ObjectName objectName,
0686: List attributeList) {
0687: for (Iterator attrIterator = attributeList.iterator(); attrIterator
0688: .hasNext();) {
0689: ObjectAttribute objAttr = (ObjectAttribute) attrIterator
0690: .next();
0691: AccessController.checkAccess(context,
0692: ACLConstants.ACL_UPDATE_MBEAN_ATTRIBUTES, objAttr
0693: .getName());
0694: }
0695: AttributeListData attrListData = null;
0696: ServerConnection serverConnection = null;
0697: try {
0698: serverConnection = ServerConnector
0699: .getServerConnection(appConfig);
0700: attributeList = serverConnection.setAttributes(objectName,
0701: attributeList);
0702: attrListData = new AttributeListData(appConfig.getName(),
0703: attributeList);
0704: String logString = getLogString(attributeList);
0705: UserActivityLogger.getInstance()
0706: .logActivity(
0707: context.getUser().getUsername(),
0708: "Updated the attributes of application:"
0709: + appConfig.getName()
0710: + ", object name:"
0711: + objectName.getCanonicalName()
0712: + logString);
0713: } catch (ConnectionFailedException e) {
0714: logger.log(Level.FINE, "Error connecting to :"
0715: + appConfig.getName(), e);
0716: attrListData = new AttributeListData(appConfig.getName());
0717: } finally {
0718: ServiceUtils.close(serverConnection);
0719: }
0720: return attrListData;
0721: }
0722:
0723: /**
0724: * Converts a two dimentional String array containing attribute name and
0725: * value to a list of ObjectAttribute objects.
0726: *
0727: * @return list containing ObjectAttribute objects
0728: */
0729: private List buildAttributeList(ServiceContext context,
0730: String[][] attributes) {
0731: ObjectName objectName;
0732: ObjectInfo objInfo;
0733: ServerConnection connection = null;
0734: try {
0735: connection = ServiceUtils
0736: .getServerConnectionEvenIfCluster(context
0737: .getApplicationConfig());
0738: objectName = context.getObjectName();
0739: objInfo = connection.getObjectInfo(objectName);
0740: } finally {
0741: ServiceUtils.close(connection);
0742: }
0743:
0744: ObjectAttributeInfo[] objAttributes = objInfo.getAttributes();
0745: List attributeList = new LinkedList();
0746: for (int i = 0; i < attributes.length; i++) {
0747: String attribute = attributes[i][0];
0748: String type = getAttributeType(connection, objAttributes,
0749: attribute, objectName);
0750: /* ensure that this attribute is writable */
0751: ensureAttributeIsWritable(objAttributes, attribute,
0752: objectName);
0753:
0754: Object value = getTypedValue(
0755: context.getApplicationConfig(), attributes[i][1],
0756: type);
0757: ObjectAttribute objAttribute = new ObjectAttribute(
0758: attribute, value);
0759: attributeList.add(objAttribute);
0760: }
0761: return attributeList;
0762: }
0763:
0764: // handles composite attribute type
0765: private String getAttributeType(ServerConnection connection,
0766: ObjectAttributeInfo[] objAttributes, String attribute,
0767: ObjectName objectName) {
0768:
0769: /* first look for normal attribute */
0770: for (int i = 0; i < objAttributes.length; i++) {
0771: if (objAttributes[i].getName().equals(attribute)) {
0772: return objAttributes[i].getType();
0773: }
0774: }
0775:
0776: /* now look for CompositeData */
0777: String itemName = null;
0778: final int index = attribute.indexOf(COMPOSITE_ATTR_SEPARATOR);
0779: if (index != -1) {
0780: itemName = attribute.substring(index + 1);
0781: attribute = attribute.substring(0, index);
0782: for (int i = 0; i < objAttributes.length; i++) {
0783: if (objAttributes[i].getName().equals(attribute)) {
0784: // it is a CompositeData type
0785: CompositeType type = getCompositeType(connection,
0786: objectName, objAttributes[i]);
0787: return type.getType(itemName).getClassName();
0788: }
0789: }
0790: }
0791: throw new ServiceException(ErrorCodes.INVALID_MBEAN_ATTRIBUTE,
0792: attribute, objectName);
0793: }
0794:
0795: private void ensureAttributeIsWritable(
0796: ObjectAttributeInfo[] objAttributes, String attribute,
0797: ObjectName objectName) {
0798: ObjectAttributeInfo attributeInfo = null;
0799: for (int i = 0; i < objAttributes.length; i++) {
0800: if (objAttributes[i].getName().equals(attribute)) {
0801: attributeInfo = objAttributes[i];
0802: break;
0803: }
0804: }
0805: assert attributeInfo != null : "attribute not found:"
0806: + attribute;
0807: if (!attributeInfo.isWritable()) {
0808: throw new ServiceException(
0809: ErrorCodes.READ_ONLY_MBEAN_ATTRIBUTE, attribute,
0810: objectName);
0811: }
0812: }
0813:
0814: private List getApplications(ApplicationConfig appConfig) {
0815: List applications = null;
0816: if (appConfig.isCluster()) {
0817: applications = appConfig.getApplications();
0818: } else {
0819: applications = new ArrayList(1);
0820: applications.add(appConfig);
0821: }
0822: return applications;
0823: }
0824:
0825: /**
0826: * Map keys are of the format:
0827: * attr+<applicationId>+<attrName>
0828: *
0829: */
0830: private List buildAttributeList(Map attributes,
0831: ApplicationConfig appConfig,
0832: ObjectAttributeInfo[] objAttributes,
0833: ServerConnection connection, ObjectName objectName) {
0834:
0835: String applicationId = appConfig.getApplicationId();
0836: Iterator it = attributes.keySet().iterator();
0837: List attributeList = new LinkedList();
0838: while (it.hasNext()) {
0839: String param = (String) it.next();
0840: // look for keys which only start with "attr+"
0841: if (param.startsWith("attr+")) {
0842: StringTokenizer tokenizer = new StringTokenizer(param,
0843: "+");
0844: if (tokenizer.countTokens() != 3) {
0845: throw new RuntimeException("Invalid param name: "
0846: + param);
0847: }
0848: tokenizer.nextToken(); // equals to "attr"
0849: if (applicationId.equals(tokenizer.nextToken())) { // applicationId
0850: String attrName = tokenizer.nextToken();
0851: String attrType = getAttributeType(connection,
0852: objAttributes, attrName, objectName);
0853:
0854: String[] attrValues = (String[]) attributes
0855: .get(param);
0856: Object typedValue = null;
0857: if (attrType.startsWith("[")) {
0858: // it is an array
0859: // the first elements in the array is dummy to allow
0860: // empty string to be saved
0861: String[] actualValue = new String[attrValues.length - 1];
0862: for (int i = 0; i < actualValue.length; i++) {
0863: actualValue[i] = attrValues[i + 1];
0864: }
0865: try {
0866: typedValue = ConvertUtils.convert(
0867: actualValue, Class
0868: .forName(attrType));
0869: } catch (ClassNotFoundException e) {
0870: throw new RuntimeException(e);
0871: }
0872: } else {
0873: typedValue = getTypedValue(appConfig,
0874: attrValues[0], attrType);
0875: }
0876: attributeList.add(new ObjectAttribute(attrName,
0877: typedValue));
0878: }
0879: }
0880: }
0881: return attributeList;
0882: }
0883:
0884: /**
0885: *
0886: * @param attributes
0887: * @return
0888: */
0889: private String getLogString(List attributes) {
0890: StringBuffer logString = new StringBuffer("");
0891: for (Iterator iterator = attributes.iterator(); iterator
0892: .hasNext();) {
0893: ObjectAttribute attribute = (ObjectAttribute) iterator
0894: .next();
0895: logString.append(" [");
0896: logString.append(attribute.getName());
0897: logString.append("=");
0898: logString.append(attribute.getValue());
0899: logString.append("]");
0900: }
0901: return logString.toString();
0902: }
0903:
0904: private void canAccessThisMBean(ServiceContext context) {
0905: final ApplicationConfig config = context.getApplicationConfig();
0906: final MBeanConfig configuredMBean = config
0907: .findMBeanByObjectName(context.getObjectName()
0908: .getCanonicalName());
0909: AccessController.checkAccess(context,
0910: ACLConstants.ACL_VIEW_APPLICATIONS);
0911: if (configuredMBean != null)
0912: AccessController.checkAccess(context,
0913: ACLConstants.ACL_VIEW_MBEANS);
0914: }
0915:
0916: public static Object getTypedValue(ApplicationConfig appConfig,
0917: String value, String type) {
0918:
0919: if (type.equals("int")) {
0920: type = "java.lang.Integer";
0921: } else if (type.equals("long")) {
0922: type = "java.lang.Long";
0923: } else if (type.equals("short")) {
0924: type = "java.lang.Short";
0925: } else if (type.equals("float")) {
0926: type = "java.lang.Float";
0927: } else if (type.equals("double")) {
0928: type = "java.lang.Double";
0929: } else if (type.equals("char")) {
0930: type = "java.lang.Character";
0931: } else if (type.equals("boolean")) {
0932: type = "java.lang.Boolean";
0933: } else if (type.equals("byte")) {
0934: type = "java.lang.Byte";
0935: }
0936:
0937: try {
0938: /* handle ObjectName as a special type */
0939: if (type.equals("javax.management.ObjectName")) {
0940: Class clazz = Class.forName(type, true, appConfig
0941: .getApplicationClassLoader());
0942: try {
0943: Constructor ctor = clazz
0944: .getConstructor(new Class[] { String.class });
0945: return ctor.newInstance(new Object[] { value });
0946: } catch (Exception e) {
0947: throw new RuntimeException(e);
0948: }
0949: }
0950:
0951: /* other types */
0952: return ConvertUtils.convert(value, Class.forName(type));
0953: } catch (ClassNotFoundException e) {
0954: throw new RuntimeException(e);
0955: }
0956: }
0957:
0958: public static Object[] getTypedArray(ApplicationConfig appConfig,
0959: String[] values, String[] type) {
0960: Object[] obj = new Object[values.length];
0961: for (int i = 0; i < values.length; i++) {
0962: obj[i] = getTypedValue(appConfig, values[i], type[i]);
0963: }
0964: return obj;
0965: }
0966:
0967: public ObjectOperationInfo getOperationInfo(ServiceContext context,
0968: String operationName, String[] signature)
0969: throws ServiceException {
0970:
0971: ObjectOperationInfo operationInfo = null;
0972: ObjectInfo objectInfo = getMBeanInfo(context);
0973: ObjectOperationInfo[] operations = objectInfo.getOperations();
0974:
0975: for (int index = 0; index < operations.length; index++) {
0976: operationInfo = operations[index];
0977:
0978: if (operationName.equals(operationInfo.getName())) {
0979: int matchCounter = 0;
0980: ObjectParameterInfo[] objectSignature = operationInfo
0981: .getSignature();
0982:
0983: if (signature.length == objectSignature.length) {
0984: for (int paramIndex = 0; paramIndex < objectSignature.length; paramIndex++) {
0985: if (signature[paramIndex]
0986: .equals(objectSignature[paramIndex]
0987: .getType())) {
0988: matchCounter++;
0989: }
0990: }
0991:
0992: if (matchCounter == signature.length) {
0993: break;
0994: }
0995: }
0996: }
0997: }
0998: return operationInfo;
0999: }
1000:
1001: public String getAttributeDataType(ServiceContext context,
1002: String attributeName, String objectName) {
1003: ServerConnection connection = context.getServerConnection();
1004: ObjectName objName = new ObjectName(objectName);
1005: ObjectInfo objectInfo = connection.getObjectInfo(objName);
1006: ObjectAttributeInfo[] objAttrInfo = objectInfo.getAttributes();
1007: return getAttributeType(connection, objAttrInfo, attributeName,
1008: objName);
1009: }
1010: }
|