/* * Copyright 2013 The Generic MBean CLI Project * * The Generic MBean CLI Project licenses this file to you under the Apache License, version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ package com.sohail.alam.generic.mbean.cli.jmx; import com.sohail.alam.generic.mbean.cli.logger.Logger; import javax.management.Attribute; import javax.management.AttributeList; import javax.management.ObjectName; import java.util.HashMap; import java.util.Set; /** * <p/> * The Implementation of {@link AttributeHelper}. This is where most of the 'Magic' happens. * This class is solely responsible for anything and everything that has to do with MBean Attributes * <p/> * * @author Sohail Alam * @version 1.0.0 Date: 19/5/13 * Time: 7:03 PM * @since 1.0.0 */ public class DefaultAttributeHelper implements AttributeHelper { private final JMXInitializer JMX_INITIALIZER; private DataStorage storage; /** * Instantiates a new Attribute helper. */ private DefaultAttributeHelper() { JMX_INITIALIZER = DefaultJMXInitializer.getInstance(); } /** * Gets instance. * * @return the instance */ public static AttributeHelper getInstance() { return SingletonHolder.instance; } /** * Gets attribute info corresponding to a given Attribute Name. * * @param attributeName the attribute name * * @return the attribute info */ @Override public StringBuffer getAttributeHelp(String attributeName) { StringBuffer buffer = new StringBuffer(); for (ObjectName beanObjectName : JMX_INITIALIZER.getMBeanObjectNames()) { buffer.append(getAttributeHelp(beanObjectName.getCanonicalName(), attributeName)); } return buffer; } /** * Gets attribute info corresponding to a given Attribute Name present in a given MBean. * * @param beanName the bean name * @param name the name * * @return the attribute info */ @Override public StringBuffer getAttributeHelp(String beanName, String name) { StringBuffer buffer = new StringBuffer(); String userAttributeName; boolean startsWithWildcard = false; boolean endsWithWildcard = false; if (name.contains("*")) { startsWithWildcard = name.startsWith("*"); endsWithWildcard = name.endsWith("*"); userAttributeName = name.replaceAll("[*]", "").toLowerCase(); if (startsWithWildcard && endsWithWildcard) { buffer = getAttributeHelp(beanName, userAttributeName, 0); } else if (startsWithWildcard) { buffer = getAttributeHelp(beanName, userAttributeName, 1); } else if (endsWithWildcard) { buffer = getAttributeHelp(beanName, userAttributeName, 2); } } else { for (ObjectName beanObjectName : JMX_INITIALIZER.getMBeanObjectNames(beanName)) { storage = DefaultDataStorage.getInstance(beanObjectName); for (String attributeName : storage.getBeanAttributes().keySet()) { } } } if (buffer.length() == 0) { buffer.append("No such attribute => " + name + " found in MBean => " + beanName + ", try using wildcard (*) search\n"); } return buffer; } /** * Gets attribute description. * * @param attributeName the attribute name * * @return the attribute description */ @Override public StringBuffer getAttributeInfo(String attributeName) { StringBuffer buffer = new StringBuffer(); for (ObjectName beanObjectName : JMX_INITIALIZER.getMBeanObjectNames()) { buffer.append(getAttributeInfo(beanObjectName.getCanonicalName(), attributeName)); } return buffer; } /** * Gets attribute description. * * @param beanName the bean name * @param name the name * * @return the attribute description */ @Override public StringBuffer getAttributeInfo(String beanName, String name) { StringBuffer buffer = new StringBuffer(); String userAttributeName; boolean startsWithWildcard = false; boolean endsWithWildcard = false; if (name.contains("*")) { startsWithWildcard = name.startsWith("*"); endsWithWildcard = name.endsWith("*"); userAttributeName = name.replaceAll("[*]", "").toLowerCase(); if (startsWithWildcard && endsWithWildcard) { getAttributeInfo(beanName, buffer, userAttributeName, 0); } else if (startsWithWildcard) { getAttributeInfo(beanName, buffer, userAttributeName, 0); } else if (endsWithWildcard) { getAttributeInfo(beanName, buffer, userAttributeName, 0); } } else { for (ObjectName beanObjectName : JMX_INITIALIZER.getMBeanObjectNames(beanName)) { storage = DefaultDataStorage.getInstance(beanObjectName); for (String attributeName : storage.getBeanAttributes().keySet()) { if (attributeName.equalsIgnoreCase(name.toLowerCase())) { formatAttributeInfo(buffer, beanObjectName, attributeName); } } } } if (buffer.length() == 0) { buffer.append("No such attribute => " + name + " found in MBean => " + beanName + ", try using wildcard (*) search\n"); } return buffer; } /** * Gets all attributes. * * @return the all attributes */ @Override public StringBuffer getAllAttributes() { StringBuffer buffer = new StringBuffer(); for (ObjectName beanObjectName : JMX_INITIALIZER.getMBeanObjectNames()) { buffer.append(getAllAttributes(beanObjectName.getCanonicalName())); } return buffer; } /** * Gets all attributes. * * @param beanName the bean name * * @return the all attributes */ @Override public StringBuffer getAllAttributes(String beanName) { StringBuffer buffer = new StringBuffer(); for (ObjectName beanObjectName : JMX_INITIALIZER.getMBeanObjectNames(beanName)) { storage = DefaultDataStorage.getInstance(beanObjectName); Set<String> allAttributeNames = storage.getBeanAttributes().keySet(); buffer.append("\n==================================================================================================\n"); buffer.append("ALL ATTRIBUTES INFORMATION FOR MBEAN => ") .append(String.format("%-57s", beanObjectName.getCanonicalName())) .append("\n") .append("==================================================================================================\n") .append(String.format("%-60s", "NAME")) .append(String.format("%-15s", "READABLE")) .append(String.format("%-15s", "WRITABLE")) .append(String.format("%-15s", "VALUE")) .append("\n--------------------------------------------------------------------------------------------------\n"); for (String attributeName : allAttributeNames) { buffer.append(String.format("%-60s", attributeName)) .append(String.format("%-15s", storage.getBeanAttributes().get(attributeName).get(storage.READABLE))) .append(String.format("%-15s", storage.getBeanAttributes().get(attributeName).get(storage.WRITEABLE))) .append(String.format("%-15s", getAttributeValue(beanObjectName, attributeName))) .append("\n"); } buffer.append("--------------------------------------------------------------------------------------------------\n"); } return buffer; } /** * TODO: Set all attributes. * * @param attributesMap the attributes map * * @return the boolean */ @Override public boolean SetAllAttributes(HashMap<String, AttributeList> attributesMap) { return false; } /** * TODO: Sets all attributes. * * @param beanObjectName the bean object name * @param attributeList the attribute list * * @return the all attributes */ @Override public boolean setAllAttributes(ObjectName beanObjectName, AttributeList attributeList) { return false; } /** * Gets attribute value. * * @param beanName the bean name * @param name the name * * @return the attribute value */ @Override public StringBuffer getAttributeValue(String beanName, String name) { StringBuffer buffer = new StringBuffer(); String userAttributeName; boolean startsWithWildcard = false; boolean endsWithWildcard = false; if (name.contains("*")) { startsWithWildcard = name.startsWith("*"); endsWithWildcard = name.endsWith("*"); userAttributeName = name.replaceAll("[*]", "").toLowerCase(); if (startsWithWildcard && endsWithWildcard) { getAttributeValue(beanName, buffer, userAttributeName, 0); } else if (startsWithWildcard) { getAttributeValue(beanName, buffer, userAttributeName, 1); } else if (endsWithWildcard) { getAttributeValue(beanName, buffer, userAttributeName, 2); } } else { for (ObjectName beanObjectName : JMX_INITIALIZER.getMBeanObjectNames(beanName)) { storage = DefaultDataStorage.getInstance(beanObjectName); for (String attributeName : storage.getBeanAttributes().keySet()) { if (attributeName.equalsIgnoreCase(name.toLowerCase())) { getAttributeValue(buffer, beanObjectName, attributeName); } } } } if (buffer.length() == 0) { buffer.append("No such attribute => " + name + " found in MBean => " + beanName + ", try using wildcard (*) search\n"); } return buffer; } /** * Gets attribute value. * * @param attributeName the attribute name * * @return the attribute value */ @Override public StringBuffer getAttributeValue(String attributeName) { StringBuffer buffer = new StringBuffer(); for (ObjectName beanObjectName : JMX_INITIALIZER.getMBeanObjectNames()) { buffer.append(getAttributeValue(beanObjectName.getCanonicalName(), attributeName)); } return buffer; } /** * Sets attribute value. * * @param beanName the bean name * @param name the name * @param value the attribute value * * @return the attribute value */ @Override public StringBuffer setAttributeValue(String beanName, String name, String value) { StringBuffer buffer = new StringBuffer(); String userAttributeName; boolean startsWithWildcard = false; boolean endsWithWildcard = false; if (name.contains("*")) { startsWithWildcard = name.startsWith("*"); endsWithWildcard = name.endsWith("*"); userAttributeName = name.replaceAll("[*]", "").toLowerCase(); if (startsWithWildcard && endsWithWildcard) { setAttributeValue(beanName, value, buffer, userAttributeName, 0); } else if (startsWithWildcard) { setAttributeValue(beanName, value, buffer, userAttributeName, 1); } else if (endsWithWildcard) { setAttributeValue(beanName, value, buffer, userAttributeName, 2); } } else { for (ObjectName beanObjectName : JMX_INITIALIZER.getMBeanObjectNames(beanName)) { storage = DefaultDataStorage.getInstance(beanObjectName); for (String attributeName : storage.getBeanAttributes().keySet()) { if (attributeName.equalsIgnoreCase(name.toLowerCase())) { setValue(value, buffer, beanObjectName, attributeName); } } } } if (buffer.length() == 0) { buffer.append("No such attribute => " + name + " found in MBean => " + beanName + ", try using wildcard (*) search\n"); } return buffer; } /** * Sets attribute. * * @param attributeName the attribute name * @param attributeValue the attribute value * * @return the attribute */ @Override public StringBuffer setAttributeValue(String attributeName, String attributeValue) { StringBuffer buffer = new StringBuffer(); for (ObjectName beanObjectName : JMX_INITIALIZER.getMBeanObjectNames()) { buffer.append(setAttributeValue(beanObjectName.getCanonicalName(), attributeName, attributeValue)); } return buffer; } /** * Check conflicts. * * @param name the name * * @return the string buffer */ @Override public StringBuffer checkConflicts(String name) { StringBuffer buffer = new StringBuffer(); for (ObjectName beanObjectName : JMX_INITIALIZER.getMBeanObjectNames()) { buffer.append(checkConflicts(beanObjectName.getCanonicalName(), name)); } return buffer; } /** * Check conflicts. * * @param mbeanName the mbean name * @param name the attribute name * * @return the string buffer */ @Override public StringBuffer checkConflicts(String mbeanName, String name) { StringBuffer buffer = new StringBuffer(); int conflictCounter = 0; for (ObjectName beanObjectName : JMX_INITIALIZER.getMBeanObjectNames()) { storage = DefaultDataStorage.getInstance(beanObjectName); for (String attributeName : storage.getBeanAttributes().keySet()) { if (attributeName.equalsIgnoreCase(name)) { conflictCounter = 1; buffer = new StringBuffer("\nMBean Name: "); buffer.append(beanObjectName.getCanonicalName()) .append("\nAttribute Name: ").append(attributeName); break; } if (attributeName.toLowerCase().contains(name)) { conflictCounter++; buffer.append("\nMBean Name: ").append(beanObjectName.getCanonicalName()) .append("\nAttribute Name: ").append(attributeName).append("\n"); } } } buffer.append("\n................................................................................"); if (conflictCounter == 1) { // Get the attribute name only buffer = new StringBuffer( buffer.toString().split("\n")[2].replaceAll("Attribute Name: ", "") ); } else { buffer.insert(0, "\nERROR:\nThere was a conflict resolving your command!\n"); } return buffer; } /** * Gets attribute help. * * @param beanName the bean name * @param userAttributeName the user attribute name * @param condition the condition * * @return the attribute help */ private StringBuffer getAttributeHelp(String beanName, String userAttributeName, int condition) { StringBuffer buffer = new StringBuffer(); for (ObjectName beanObjectName : JMX_INITIALIZER.getMBeanObjectNames(beanName)) { storage = DefaultDataStorage.getInstance(beanObjectName); for (String attributeName : storage.getBeanAttributes().keySet()) { switch (condition) { case 0: if (attributeName.toLowerCase().contains(userAttributeName)) { formatAttributeHelp(buffer, beanObjectName, attributeName); } break; case 1: if (attributeName.toLowerCase().endsWith(userAttributeName)) { formatAttributeHelp(buffer, beanObjectName, attributeName); } break; case 2: if (attributeName.toLowerCase().startsWith(userAttributeName)) { formatAttributeHelp(buffer, beanObjectName, attributeName); } break; } } } return buffer; } /** * Format attribute help. * * @param buffer the buffer * @param beanObjectName the bean object name * @param attributeName the attribute name */ private void formatAttributeHelp(StringBuffer buffer, ObjectName beanObjectName, String attributeName) { buffer .append("\n") .append("\n---------------------------------------------------------------------------------------\n") .append(" ATTRIBUTE HELP ") .append("\n---------------------------------------------------------------------------------------\n") .append("MBean Name : ").append(beanObjectName.getCanonicalName()).append("\n") .append("Name : ").append(attributeName).append("\n") .append("Value : ").append(getAttributeValue(beanObjectName, attributeName)).append("\n") .append("Type : ").append(storage.getBeanAttributes().get(attributeName).get(storage.CLASS_NAME)).append("\n") .append("Is Readable : ").append(storage.getBeanAttributes().get(attributeName).get(storage.READABLE)).append("\n") .append("Is Writable : ").append(storage.getBeanAttributes().get(attributeName).get(storage.WRITEABLE)).append("\n") .append("Is Boolean : ").append(storage.getBeanAttributes().get(attributeName).get(storage.IS_GETTER)).append("\n") .append("Description : ").append(storage.getBeanAttributes().get(attributeName).get(storage.DESCRIPTION)).append("\n") .append("---------------------------------------------------------------------------------------\n"); } /** * Gets attribute info. * * @param beanName the bean name * @param buffer the buffer * @param userAttributeName the user attribute name * @param condition the condition */ private void getAttributeInfo(String beanName, StringBuffer buffer, String userAttributeName, int condition) { for (ObjectName beanObjectName : JMX_INITIALIZER.getMBeanObjectNames(beanName)) { storage = DefaultDataStorage.getInstance(beanObjectName); for (String attributeName : storage.getBeanAttributes().keySet()) { switch (condition) { case 0: if (attributeName.toLowerCase().contains(userAttributeName)) { formatAttributeInfo(buffer, beanObjectName, attributeName); } break; case 1: if (attributeName.toLowerCase().endsWith(userAttributeName)) { formatAttributeInfo(buffer, beanObjectName, attributeName); } break; case 2: if (attributeName.toLowerCase().startsWith(userAttributeName)) { formatAttributeInfo(buffer, beanObjectName, attributeName); } break; } } } } /** * Format attribute info. * * @param buffer the buffer * @param beanObjectName the bean object name * @param attributeName the attribute name */ private void formatAttributeInfo(StringBuffer buffer, ObjectName beanObjectName, String attributeName) { buffer .append("\n") .append("\n---------------------------------------------------------------------------------------\n") .append(" ATTRIBUTE INFORMATION ") .append("\n---------------------------------------------------------------------------------------\n") .append("MBean Name : ").append(beanObjectName.getCanonicalName()).append("\n") .append("Name : ").append(attributeName).append("\n") .append("Description : ").append(storage.getBeanAttributes().get(attributeName).get(storage.DESCRIPTION)).append("\n") .append("---------------------------------------------------------------------------------------\n"); } /** * Gets attribute value. * * @param beanName the bean name * @param buffer the buffer * @param userAttributeName the user attribute name * @param condition the condition */ private void getAttributeValue(String beanName, StringBuffer buffer, String userAttributeName, int condition) { for (ObjectName beanObjectName : JMX_INITIALIZER.getMBeanObjectNames(beanName)) { storage = DefaultDataStorage.getInstance(beanObjectName); for (String attributeName : storage.getBeanAttributes().keySet()) { switch (condition) { case 0: if (attributeName.toLowerCase().contains(userAttributeName)) { getAttributeValue(buffer, beanObjectName, attributeName); } break; case 1: if (attributeName.toLowerCase().endsWith(userAttributeName)) { getAttributeValue(buffer, beanObjectName, attributeName); } break; case 2: if (attributeName.toLowerCase().startsWith(userAttributeName)) { getAttributeValue(buffer, beanObjectName, attributeName); } break; } } } } /** * Gets value. * * @param buffer the buffer * @param beanObjectName the bean object name * @param attributeName the attribute name */ private void getAttributeValue(StringBuffer buffer, ObjectName beanObjectName, String attributeName) { buffer .append("\nMBean Name : ").append(beanObjectName.getCanonicalName()) .append("\nAttribute Name : ").append(attributeName) .append("\nAttribute Value : ").append(getAttributeValue(beanObjectName, attributeName)) .append("\n"); } /** * Gets attribute value. * * @param beanObjectName the bean object name * @param attributeName the attribute name * * @return the attribute value */ private String getAttributeValue(ObjectName beanObjectName, String attributeName) { String attributeValue = null; if (Boolean.parseBoolean(storage.getBeanAttributes().get(attributeName).get(storage.READABLE))) { try { attributeValue = (String) JMX_INITIALIZER.getMbsc().getAttribute(beanObjectName, attributeName); } catch (Exception e) { } } else { attributeValue = " ** ATTRIBUTE IS NOT READABLE **"; } return attributeValue; } /** * Sets attribute value. * * @param beanName the bean name * @param value the value * @param buffer the buffer * @param userAttributeName the user attribute name * @param condition the condition */ private void setAttributeValue(String beanName, String value, StringBuffer buffer, String userAttributeName, int condition) { for (ObjectName beanObjectName : JMX_INITIALIZER.getMBeanObjectNames(beanName)) { storage = DefaultDataStorage.getInstance(beanObjectName); for (String attributeName : storage.getBeanAttributes().keySet()) { switch (condition) { case 0: if (attributeName.toLowerCase().contains(userAttributeName)) { setValue(value, buffer, beanObjectName, attributeName); } break; case 1: if (attributeName.toLowerCase().endsWith(userAttributeName)) { setValue(value, buffer, beanObjectName, attributeName); } break; case 2: if (attributeName.toLowerCase().startsWith(userAttributeName)) { setValue(value, buffer, beanObjectName, attributeName); } break; } } } } /** * Sets value. * * @param value the value * @param buffer the buffer * @param beanObjectName the bean object name * @param attributeName the attribute name */ private void setValue(String value, StringBuffer buffer, ObjectName beanObjectName, String attributeName) { Attribute attribute = null; Boolean isWritable = Boolean.parseBoolean(storage.getBeanAttributes().get(attributeName).get(storage.WRITEABLE)); if (isWritable) { try { String attributeType = storage.getBeanAttributes().get(attributeName).get(storage.CLASS_NAME); // Configure the attribute according to its type int attributeClassTypeSwitch; if (JavaClassTypes.CLASS_TYPE_MAP.containsKey(attributeType)) { attributeClassTypeSwitch = JavaClassTypes.CLASS_TYPE_MAP.get(attributeType); } else { attributeClassTypeSwitch = -1; } switch (attributeClassTypeSwitch) { case JavaClassTypes.INT_INT: case JavaClassTypes.INTEGER_WRAPPER_INT: attribute = new Attribute(attributeName, Integer.parseInt(value)); break; case JavaClassTypes.FLOAT_INT: case JavaClassTypes.FLOAT_WRAPPER_INT: attribute = new Attribute(attributeName, Float.parseFloat(value)); break; case JavaClassTypes.DOUBLE_INT: case JavaClassTypes.DOUBLE_WRAPPER_INT: attribute = new Attribute(attributeName, Double.parseDouble(value)); break; case JavaClassTypes.BOOLEAN_INT: case JavaClassTypes.BOOLEAN_WRAPPER_INT: attribute = new Attribute(attributeName, Boolean.parseBoolean(value)); break; case JavaClassTypes.STRING_INT: attribute = new Attribute(attributeName, value); break; default: buffer.insert(0, "This attribute contains parameters that can not be set from CLI\n"); break; } // Try to set the value of the attribute if (attribute != null) { JMX_INITIALIZER.getMbsc().setAttribute(beanObjectName, attribute); } } catch (Exception e) { Logger.logException(e, getClass()); } } else { buffer.append(" ** ATTRIBUTE IS NOT WRITABLE **"); } } /** * The type Singleton holder. * <p/> * Initialization on Demand Holder (IODH) idiom which requires very little code and * has zero synchronization overhead. Zero, as in even faster than volatile. * IODH requires the same number of lines of code as plain old synchronization, and it's faster than DCL! * <p/> * {@code SOURCE: http://blog.crazybob.org/2007/01/lazy-loading-singletons.html} */ static class SingletonHolder { /** * The Instance. */ static AttributeHelper instance = new DefaultAttributeHelper(); } }