/* * 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.console.gui; import com.sohail.alam.generic.mbean.cli.CliCommands; import com.sohail.alam.generic.mbean.cli.DefaultCliCommands; import com.sohail.alam.generic.mbean.cli.HelperMethods; import com.sohail.alam.generic.mbean.cli.console.ConsoleIO; import com.sohail.alam.generic.mbean.cli.console.ProcessUserInput; import com.sohail.alam.generic.mbean.cli.console.gui.windows.PrimaryGuiWindow; import com.sohail.alam.generic.mbean.cli.console.text.DefaultConsoleIO; import com.sohail.alam.generic.mbean.cli.jmx.*; import com.sohail.alam.generic.mbean.cli.logger.Logger; import com.sohail.alam.generic.mbean.cli.security.Authentication; import com.sohail.alam.generic.mbean.cli.security.DefaultAuthentication; import javax.management.ObjectName; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.StringTokenizer; /** * <p/> * The Implementation of {@link com.sohail.alam.generic.mbean.cli.console.ProcessUserInput} and {@link CliCommands} * defining the methods to process the un-escaped User Inputs, * and to return a properly formatted String Buffer which can then be displayed on the Console. * <p/> * * @author Sohail Alam * @version 1.0.0 Date: 20/5/13 * Time: 7:20 AM * @since 1.0.0 */ public class GuiProcessUserInput implements ProcessUserInput, CliCommands { /** * The AUTHENTICATION. */ private final Authentication AUTHENTICATION; /** * The CONSOLE. */ private final ConsoleIO CONSOLE; /** * The HELPER. */ private final HelperMethods HELPER; /** * The JMX _ iNITIALIZER. */ private final JMXInitializer JMX_INITIALIZER; /** * The ATTRIBUTE. */ private final AttributeHelper ATTRIBUTE; /** * The OPERATION. */ private final OperationHelper OPERATION; /** * The User input buffer. */ private String userInput = null; /** * The Processed input buffer. */ private StringBuffer outputBuffer = null; /** * The Bean name. */ private String beanName = null; /** * Instantiates a new Process user input implementation. */ private GuiProcessUserInput() { AUTHENTICATION = DefaultAuthentication.getInstance(); CONSOLE = DefaultConsoleIO.getInstance(); HELPER = HelperMethods.getInstance(); JMX_INITIALIZER = DefaultJMXInitializer.getInstance(); ATTRIBUTE = DefaultAttributeHelper.getInstance(); OPERATION = DefaultOperationHelper.getInstance(); outputBuffer = new StringBuffer(); } /** * Gets instance. * * @return the instance */ public static ProcessUserInput getInstance() { return SingletonHolder.instance; } /** * Pre process the input by escaping any unwanted sequence of character(s), trimming the input * of unnecessary white-spaces. * * @param input the input */ private void preProcessInput(String input) { userInput = input.trim(); userInput = userInput.replaceAll("\\s+", " "); } /** * Post process is typically done to remove any unwanted * {@link com.sohail.alam.generic.mbean.cli.jmx.States} information from the Output Buffer. */ private void postProcess() { outputBuffer.trimToSize(); } /** * Process string buffer. This is the landing point for the un-escaped, un-processed user input. * * @param input the input * * @return the string buffer */ @Override public StringBuffer process(String input) { outputBuffer = new StringBuffer(); preProcessInput(input); // Split the command at SPACE for identifying if it is a SET or GET command ArrayList<String> commandList = new ArrayList<String>(); StringBuffer attributeBuffer = new StringBuffer(); StringBuffer operationBuffer = new StringBuffer(); /* * TODO: Tokenize wildcard * for incomplete names * DESCRIPTION: For eg. *abc -> means that the name ends with 'abc' * abc* -> means that the name starts with 'abc' * *abc* -> means that the name somewhere contains 'abc' * DATE: 30/5/13 * TIME: 9:21 AM */ /* * TODO: Use double quotes '"' to keep spaces in the user input * DESCRIPTION: When the user input requires spaces not to be tokenized, the user must be given * the option to enter his input in double quotes * DATE: 30/5/13 * TIME: 9:23 AM */ StringTokenizer stringTokenizer = new StringTokenizer(userInput); while (stringTokenizer.hasMoreTokens()) { commandList.add(stringTokenizer.nextToken()); } // Convert the User's Command to appropriate Integer Value for Switch Case int commandSwitch; if (DefaultCliCommands.COMMAND_MAP.containsKey(commandList.get(0).toUpperCase())) { commandSwitch = DefaultCliCommands.COMMAND_MAP.get(commandList.get(0).toUpperCase()); } else { commandSwitch = -1; } // TODO: improve the user command: // Use -a to execute command specific to Attributes // Use -o to execute command specific to Operations // Otherwise do an intelligent search and execute the appropriate command /* * THIS IS WHERE THE ACTIONS ARE TAKEN ACCORDING TO THE USER'S COMMANDS */ switch (commandSwitch) { case ALL_MBEANS_INT: showAllBeans(); break; case ALL_ATTRIBUTES_INT: showAllAttributes(commandList); break; case ALL_OPERATIONS_INT: showAllOperations(commandList); break; case CLEAR_INT: HELPER.clearScreen(); break; //TODO: improve the close_connection command case CLOSE_CONNECTION_INT: JMX_INITIALIZER.disconnect(); break; // TODO: Fix the exit case case EXIT_INT: PrimaryGuiWindow.getInstance().doExit(); break; // TODO: improve the GET command : GET ATTRIBUTE_NAME // Do not show "No such attribute found, try using wildcard (*) search" more than once case GET_INT: getAttributeValue(commandList); break; case HELP_INT: showHelp(commandList); break; case INFO_INT: showInfo(commandList); break; case INVOKE_INT: invokeOperation(commandList); break; case LOGIN_INT: doLogin(); break; case LOGOUT_INT: doLogout(); break; case NEW_CONNECTION_INT: startNewJMXConnection(commandList); break; // TODO: Add a SEARCH case -> it will search for the existence of a parameter/operation case SEARCH_INT: break; // TODO: improve the SET command // Accept wildcard without throwing // "There was a conflict resolving your command!" more than once case SET_INT: setAttributeValue(commandList); break; // TODO: Complete the default action default: break; } postProcess(); return outputBuffer; } /** * Invoke operation. * * @param commandList the command list */ private void invokeOperation(ArrayList<String> commandList) { String mbeanName = null; if (commandList.size() >= 3) { int beanPosition; try { beanPosition = Integer.parseInt(commandList.get(1)); if (JMX_INITIALIZER.getMBeanObjectNames().size() > beanPosition) { mbeanName = JMX_INITIALIZER.getMBeanObjectNames().get(beanPosition).getCanonicalName(); } else { outputBuffer.append("\n No such Bean Position Exists => ").append(beanPosition); } } catch (NumberFormatException ex) { mbeanName = commandList.get(1); } String operationName = commandList.get(2); ArrayList<String> operationParameters = new ArrayList<String>(); operationParameters.addAll(commandList); operationParameters.remove(0); // Remove the "INVOKE" command operationParameters.remove(0); // Remove the MBean Name operationParameters.remove(0); // Remove the Operation Name outputBuffer = OPERATION.invokeOperation(mbeanName, operationName, operationParameters); } else { // TODO: improve this section of the INVOKE command } } /** * Sets attribute value. * * @param commandList the command list */ private void setAttributeValue(ArrayList<String> commandList) { String mbeanName; int beanPosition; String attributeName; String attributeValue; if (commandList.size() >= 4) { mbeanName = commandList.get(1); attributeName = commandList.get(2); attributeValue = commandList.get(3); outputBuffer = ATTRIBUTE.checkConflicts(attributeName); if (!outputBuffer.toString().contains("\nERROR:\n")) { try { beanPosition = Integer.parseInt(mbeanName); if (JMX_INITIALIZER.getMBeanObjectNames().size() > beanPosition) { outputBuffer = ATTRIBUTE.setAttributeValue( JMX_INITIALIZER.getMBeanObjectNames().get(beanPosition).getCanonicalName(), attributeName, attributeValue); } else { outputBuffer.append("\n No such Bean Position Exists => ").append(beanPosition); } } catch (NumberFormatException ex) { outputBuffer = ATTRIBUTE.setAttributeValue(mbeanName, attributeName, attributeValue); } } } else { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); try { Logger.logMessage("\nSet new value to a parameter:"); Logger.logMessage("Enter the MBean Name/Number: "); mbeanName = bufferedReader.readLine(); Logger.logMessage("Enter the Attribute Name: "); attributeName = bufferedReader.readLine(); Logger.logMessage("Enter the Attribute Value: "); attributeValue = bufferedReader.readLine(); outputBuffer = ATTRIBUTE.checkConflicts(attributeName); if (!outputBuffer.toString().contains("\nERROR:\n")) { try { beanPosition = Integer.parseInt(mbeanName); if (JMX_INITIALIZER.getMBeanObjectNames().size() > beanPosition) { outputBuffer = ATTRIBUTE.setAttributeValue( JMX_INITIALIZER.getMBeanObjectNames().get(beanPosition).getCanonicalName(), attributeName, attributeValue); } else { outputBuffer.append("\n No such Bean Position Exists => ").append(beanPosition); } } catch (NumberFormatException ex) { outputBuffer = ATTRIBUTE.setAttributeValue(mbeanName, attributeName, attributeValue); } } } catch (Exception e) { Logger.logException(e, getClass()); } } } /** * Show all operations. * * @param commandList the command list */ private void showAllOperations(ArrayList<String> commandList) { Logger.logTrace("Inside Case: ALL_OPERATIONS_INT", getClass(), false); if (commandList.size() > 1) { // Display all attributes of the given Bean int beanPosition; try { beanPosition = Integer.parseInt(commandList.get(1)); if (JMX_INITIALIZER.getMBeanObjectNames().size() > beanPosition) { outputBuffer = OPERATION.getAllOperations(JMX_INITIALIZER.getMBeanObjectNames().get(beanPosition).getCanonicalName()); } else { outputBuffer.append("\n No such Bean Position Exists => ").append(beanPosition); } } catch (NumberFormatException ex) { outputBuffer = OPERATION.getAllOperations(commandList.get(1)); } } else { // Display all attributes of all the beans outputBuffer = OPERATION.getAllOperations(); } } /** * Show help. * * @param commandList the command list */ private void showHelp(ArrayList<String> commandList) { // If only HELP was typed then bring the Help Page if (commandList.size() == 1) { outputBuffer = HELPER.getHelp(); } else { if (commandList.size() > 2) { int beanPosition; try { beanPosition = Integer.parseInt(commandList.get(1)); if (JMX_INITIALIZER.getMBeanObjectNames().size() > beanPosition) { beanName = JMX_INITIALIZER.getMBeanObjectNames().get(beanPosition).getCanonicalName(); outputBuffer = ATTRIBUTE.getAttributeHelp(beanName, commandList.get(2)); outputBuffer.append(OPERATION.getOperationHelp(beanName, commandList.get(2))); } else { outputBuffer.append("\n No such Bean Position Exists => ").append(beanPosition); } } catch (Exception ex) { beanName = commandList.get(1); outputBuffer = ATTRIBUTE.getAttributeHelp(beanName, commandList.get(2)); outputBuffer.append(OPERATION.getOperationHelp(beanName, commandList.get(2))); } } else if (commandList.size() == 2) { outputBuffer = ATTRIBUTE.getAttributeHelp(commandList.get(1)); outputBuffer.append(OPERATION.getOperationHelp(commandList.get(1))); } } } /** * Show info. * * @param commandList the command list */ private void showInfo(ArrayList<String> commandList) { if (commandList.size() > 2) { int beanPosition; try { beanPosition = Integer.parseInt(commandList.get(1)); if (JMX_INITIALIZER.getMBeanObjectNames().size() > beanPosition) { beanName = JMX_INITIALIZER.getMBeanObjectNames().get(beanPosition).getCanonicalName(); outputBuffer = ATTRIBUTE.getAttributeInfo(beanName, commandList.get(2)); outputBuffer.append(OPERATION.getOperationInfo(beanName, commandList.get(2))); } else { outputBuffer.append("\n No such Bean Position Exists => ").append(beanPosition); } } catch (Exception ex) { beanName = commandList.get(1); outputBuffer = ATTRIBUTE.getAttributeInfo(beanName, commandList.get(2)); outputBuffer.append(OPERATION.getOperationInfo(beanName, commandList.get(2))); } } else if (commandList.size() == 2) { outputBuffer = ATTRIBUTE.getAttributeInfo(commandList.get(1)); outputBuffer.append(OPERATION.getOperationInfo(commandList.get(1))); } } /** * Gets attribute value. * * @param commandList the command list */ private void getAttributeValue(ArrayList<String> commandList) { if (commandList.size() > 2) { int beanPosition; try { beanPosition = Integer.parseInt(commandList.get(1)); if (JMX_INITIALIZER.getMBeanObjectNames().size() > beanPosition) { outputBuffer = ATTRIBUTE.getAttributeValue(JMX_INITIALIZER.getMBeanObjectNames().get(beanPosition).getCanonicalName(), commandList.get(2)); } else { outputBuffer.append("\nNo such Bean Position Exists => ").append(beanPosition).append("\n"); } } catch (NumberFormatException ex) { outputBuffer = ATTRIBUTE.getAttributeValue(commandList.get(1), commandList.get(2)); } } else if (commandList.size() == 2) { outputBuffer = ATTRIBUTE.getAttributeValue(commandList.get(1)); } } /** * Do login. */ private void doLogin() { AUTHENTICATION.logout(); CONSOLE.run(); } /** * Do logout. */ private void doLogout() { outputBuffer.append("You have successfully logged out!"); AUTHENTICATION.logout(); //CONSOLE.run(); } /** * Start new jMX connection. * * @param commandList the command list */ private void startNewJMXConnection(ArrayList<String> commandList) { if (commandList.size() == 2) { outputBuffer.append("You have not entered the JMX Port! Please try again"); } else if (commandList.size() >= 3) { String ip = commandList.get(1); int port = 0; try { port = Integer.parseInt(commandList.get(2)); } catch (NumberFormatException ex) { outputBuffer.append("Please enter a valid Port Number"); } JMX_INITIALIZER.disconnect(); JMX_INITIALIZER.setIP(ip); JMX_INITIALIZER.setPort(port); JMX_INITIALIZER.connect(); } else if (commandList.size() == 1) { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); try { int port = 0; String ip; // AUTHENTICATION.logout(); // Logger.logMessage("You have successfully logged out!"); JMX_INITIALIZER.disconnect(); Logger.logMessage("\nSet up a new JMX Connection:"); Logger.logMessage("Enter the JMX IP: "); ip = bufferedReader.readLine(); JMX_INITIALIZER.setIP(ip); Logger.logMessage("Enter the JMX Port: "); String tempPort = bufferedReader.readLine(); port = Integer.parseInt(tempPort); JMX_INITIALIZER.setPort(port); JMX_INITIALIZER.connect(); } catch (Exception e) { Logger.logException(e, getClass()); } } } /** * Show all attributes. * * @param commandList the command list */ private void showAllAttributes(ArrayList<String> commandList) { Logger.logTrace("Inside Case: ALL_ATTRIBUTES_INT", getClass(), false); if (commandList.size() > 1) { // Display all attributes of the given Bean int beanPosition; try { beanPosition = Integer.parseInt(commandList.get(1)); if (JMX_INITIALIZER.getMBeanObjectNames().size() > beanPosition) { outputBuffer = ATTRIBUTE.getAllAttributes(JMX_INITIALIZER.getMBeanObjectNames().get(beanPosition).getCanonicalName()); } else { outputBuffer.append("\n No such Bean Position Exists => ").append(beanPosition); } } catch (NumberFormatException ex) { outputBuffer = ATTRIBUTE.getAllAttributes(commandList.get(1)); } } else { // Display all attributes of all the beans outputBuffer = ATTRIBUTE.getAllAttributes(); } } /** * Show all beans. */ private void showAllBeans() { ArrayList<ObjectName> allBeans = JMX_INITIALIZER.getMBeanObjectNames(); outputBuffer .append("==================================================================================================\n") .append("All Available MBeans :") .append("\n") .append("--------------------------------------------------------------------------------------------------\n") .append(String.format("%-10s", "Position")) .append(" | ") .append(String.format("%-40s", "Bean Name")) .append("\n") .append("==================================================================================================\n"); for (int i = 0; i < allBeans.size(); i++) { outputBuffer .append(String.format("%-10s", i)) .append(" | ") .append(String.format("%-36s", allBeans.get(i))) .append("\n"); } outputBuffer.append("--------------------------------------------------------------------------------------------------\n"); } /** * 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 ProcessUserInput instance = new GuiProcessUserInput(); } }