com.vmware.bdd.cli.commands.CommandsUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.vmware.bdd.cli.commands.CommandsUtils.java

Source

/*****************************************************************************
 *   Copyright (c) 2012-2015 VMware, Inc. All Rights Reserved.
 *   Licensed 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.vmware.bdd.cli.commands;

import java.io.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jline.console.ConsoleReader;
import jline.internal.Configuration;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.log4j.Logger;
import org.fusesource.jansi.internal.Kernel32;
import org.springframework.shell.core.JLineShell;
import org.springframework.shell.support.util.OsUtils;
import org.springframework.util.ClassUtils;

import com.vmware.bdd.apitypes.NodeGroupRead;
import com.vmware.bdd.apitypes.NodeRead;
import com.vmware.bdd.utils.CommonUtil;

public class CommandsUtils {

    static final Logger logger = Logger.getLogger(CommandsUtils.class);

    public static List<String> inputsConvert(String inputs) {

        return CommonUtil.inputsConvert(inputs);
    }

    public static Set<String> inputsConvertSet(String inputs) {
        return CommonUtil.inputsConvertSet(inputs);
    }

    public static String prettyRoleOutput(List<String> roles, final String delimiter) {
        StringBuilder roleStr = new StringBuilder();
        if (roles != null) {
            for (String role : roles) {
                roleStr.append(role + delimiter);
            }
        }

        if (roleStr.length() > 0) {
            roleStr.deleteCharAt(roleStr.length() - 1);
        }
        return roleStr.toString();
    }

    public static String dataFromFile(String filePath) throws IOException, FileNotFoundException {
        StringBuilder dataStringBuffer = new StringBuilder();
        FileInputStream fis = null;
        InputStreamReader inputStreamReader = null;
        BufferedReader bufferedReader = null;
        try {
            fis = new FileInputStream(filePath);
            inputStreamReader = new InputStreamReader(fis, "UTF-8");
            bufferedReader = new BufferedReader(inputStreamReader);
            String line = "";
            while ((line = bufferedReader.readLine()) != null) {
                dataStringBuffer.append(line);
                dataStringBuffer.append("\n");
            }
        } finally {
            if (fis != null) {
                fis.close();
            }
            if (inputStreamReader != null) {
                inputStreamReader.close();
            }
            if (bufferedReader != null) {
                bufferedReader.close();
            }
        }
        return dataStringBuffer.toString();
    }

    public static <T> T getObjectByJsonString(Class<T> entityType, String jsonString)
            throws JsonParseException, JsonMappingException, IOException {
        ObjectMapper mapper = getMapper();
        T mappedObject = null;
        mappedObject = mapper.readValue(jsonString, entityType);
        return mappedObject;
    }

    public static void prettyJsonOutput(Object object, String fileName) throws Exception {
        OutputStream out = null;
        try {
            if (fileName != null) {
                out = new FileOutputStream(fileName);
            } else {
                out = System.out;
            }
            JsonFactory factory = new JsonFactory();
            JsonGenerator generator = factory.createJsonGenerator(out);
            ObjectMapper mapper = getMapper();
            mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
            generator.setCodec(mapper);
            DefaultPrettyPrinter prettyPrinter = new DefaultPrettyPrinter();
            DefaultPrettyPrinter.Indenter indenter = new DefaultPrettyPrinter.Lf2SpacesIndenter();
            prettyPrinter.indentArraysWith(indenter);
            generator.setPrettyPrinter(prettyPrinter);
            generator.writeObject(object);
            writeEndingMsgToScreen(fileName);
        } finally {
            if (out != null && !(out instanceof PrintStream)) {
                out.close();
            }
        }
    }

    /*
     * Determine if it is the window OS
     */
    public static boolean isJansiAvailable() {
        return ClassUtils.isPresent("org.fusesource.jansi.AnsiConsole", JLineShell.class.getClassLoader())
                && OsUtils.isWindows() && System.getProperty("jline.terminal") == null;
    }

    /**
     * Check whether the given String has actual text. More specifically, returns
     * <code>false</code> if the string not <code>null</code>, its length is
     * greater than 0, and it contains at least one non-whitespace character.
     * <p>
     *
     * <pre>
     * CommandsUtils.isBlank(null) = true
     * CommandsUtils.isBlank("") = true
     * CommandsUtils.isBlank(" ") = true
     * CommandsUtils.isBlank("12345") = false
     * CommandsUtils.isBlank(" 12345 ") = false
     * </pre>
     *
     * @param str
     *           the String to check(may be null).
     * @return the opposite of
     */
    public static boolean isBlank(final String str) {
        return CommonUtil.isBlank(str);
    }

    public static String notNull(final String str, final String desStr) {
        return CommonUtil.notNull(str, desStr);
    }

    /**
     * Show a table(include table column names and table contents) by left
     * justifying. More specifically, the {@code columnNamesWithGetMethodNames}
     * argument is a map struct, the key is table column name and value is method
     * name list which it will be invoked by reflection. The {@code entities}
     * argument is traversed entity array.It is source of table data. In
     * addition,the method name must be each of the {@code entities} argument 's
     * member. The {@code spacesBeforeStart} argument is whitespace in the front
     * of the row.
     * <p>
     *
     * @param columnNamesWithGetMethodNames
     *           the container of table column name and invoked method name.
     * @param entities
     *           the traversed entity array.
     * @param spacesBeforeStart
     *           the whitespace in the front of the row.
     * @throws Exception
     */
    public static void printInTableFormat(LinkedHashMap<String, List<String>> columnNamesWithGetMethodNames,
            Object[] entities, String spacesBeforeStart) throws Exception {
        if (entities != null && entities.length > 0) {
            // get number of columns
            int columnNum = columnNamesWithGetMethodNames.size();

            String[][] table = new String[entities.length + 1][columnNum];

            //build table header: column names
            String[] tableHeader = new String[columnNum];
            Set<String> columnNames = columnNamesWithGetMethodNames.keySet();
            columnNames.toArray(tableHeader);

            //put table column names into the first row
            table[0] = tableHeader;

            //build table contents
            Collection<List<String>> getMethodNamesCollect = columnNamesWithGetMethodNames.values();
            int i = 1;
            for (Object entity : entities) {
                int j = 0;
                for (List<String> getMethodNames : getMethodNamesCollect) {
                    Object tempValue = null;
                    int k = 0;
                    for (String methodName : getMethodNames) {
                        if (tempValue == null)
                            tempValue = entity;
                        Object value = tempValue.getClass().getMethod(methodName).invoke(tempValue);
                        if (k == getMethodNames.size() - 1) {
                            table[i][j] = value == null ? ""
                                    : ((value instanceof Double) ? String.valueOf(
                                            round(((Double) value).doubleValue(), 2, BigDecimal.ROUND_FLOOR))
                                            : value.toString());
                            if (isJansiAvailable() && !isBlank(table[i][j])) {
                                table[i][j] = transferEncoding(table[i][j]);
                            }
                            j++;
                        } else {
                            tempValue = value;
                            k++;
                        }
                    }
                }
                i++;
            }

            printTable(table, spacesBeforeStart);
        }
    }

    public static void printInTableFormat(LinkedHashMap<String, List<String>> columnNamesWithKeys,
            List<Map> entities, String spacesBeforeStart) throws Exception {
        if (MapUtils.isNotEmpty(columnNamesWithKeys)) {
            int columnNum = columnNamesWithKeys.size();

            if (CollectionUtils.isNotEmpty(entities)) {
                String[][] table = new String[entities.size() + 1][columnNum];

                //build table header: column names
                String[] tableHeader = table[0];

                int rowIndex = 1;
                int columnIndex = 0;
                for (Map<String, String> entity : entities) {
                    for (Entry<String, List<String>> columnNameEntry : columnNamesWithKeys.entrySet()) {
                        if (tableHeader[columnIndex] == null) {
                            tableHeader[columnIndex] = columnNameEntry.getKey();
                        }

                        StringBuilder value = new StringBuilder();
                        for (String key : columnNameEntry.getValue()) {
                            if (value.length() > 0) {
                                value.append(',');
                            }

                            Object valueObj = entity.get(key);

                            if (valueObj == null) {
                                value.append(' ');
                            } else {
                                if (valueObj instanceof Double) {
                                    value.append(String.valueOf(
                                            round(((Double) valueObj).doubleValue(), 2, BigDecimal.ROUND_FLOOR)));
                                } else {
                                    value.append(valueObj);
                                }
                            }
                        }

                        if (isJansiAvailable()) {
                            table[rowIndex][columnIndex] = transferEncoding(value.toString());
                        } else {
                            table[rowIndex][columnIndex] = value.toString();
                        }
                        columnIndex++;
                    }
                    rowIndex++;
                }

                printTable(table, spacesBeforeStart);
            }
        }
    }

    private static void printTable(String[][] table, String spacesBeforeStart) {
        // find the maximum length of a string in each column
        int numOfColumns = table[0].length;
        int[] lengths = new int[numOfColumns];

        for (int i = 0; i < table.length; i++) {
            for (int j = 0; j < numOfColumns; j++) {
                if (table[i][j] != null) {
                    lengths[j] = Math.max(table[i][j].length(), lengths[j]);
                }
            }
        }

        // generate a format string for each column
        String[] formats = new String[numOfColumns];

        for (int i = 0; i < lengths.length; i++) {
            lengths[i] += (i + 1 == numOfColumns) ? 0 : Constants.FORMAT_COLUMN_DISTANCE;
            formats[i] = "%1$-" + lengths[i] + "s" + (i + 1 == lengths.length ? "\n" : "");
        }

        // print out
        for (int i = 0; i < table.length; i++) {
            System.out.print(spacesBeforeStart);
            //print '------'
            if (i == 1) {
                StringBuilder outputBuffer = new StringBuilder();
                for (int l : lengths) {
                    for (int k = 0; k < l; k++)
                        outputBuffer.append("-");
                }
                outputBuffer.append("\n").append(spacesBeforeStart);
                System.out.print(outputBuffer.toString());
            }
            for (int j = 0; j < table[i].length; j++) {
                System.out.printf(formats[j], table[i][j]);
            }
        }

        System.out.println();
    }

    public static void printCmdSuccess(String objectType, String result) {
        System.out.println(objectType + " " + result);
    }

    public static void printCmdFailure(String objectType, String opName, String result, String message) {
        if (isJansiAvailable() && !isBlank(message)) {
            try {
                message = transferEncoding(message);
            } catch (UnsupportedEncodingException | CliException e) {
                logger.warn("failed to transferEncoding: " + e.getMessage());
            }
        }
        if (!isBlank(opName)) {
            System.out.println(objectType + " " + opName + " " + result + ": " + message);
        } else {
            System.out.println(objectType + " " + result + ": " + message);
        }
    }

    public static void prettyOutputErrorNode(List<NodeGroupRead> nodegroups) throws Exception {
        List<NodeRead> failedNodes = new ArrayList<NodeRead>();
        for (NodeGroupRead nodegroup : nodegroups) {
            List<NodeRead> nodes = nodegroup.getInstances();
            if (nodes != null) {
                for (NodeRead node : nodes) {
                    if (node.isActionFailed()) {
                        failedNodes.add(node);
                    }
                }
            }
        }

        if (!failedNodes.isEmpty()) {
            System.out.println();
            System.out.println(Constants.FAILED_NODES_MESSAGE + failedNodes.size());
            CommandsUtils.printSeperator();
            for (NodeRead failedNode : failedNodes) {
                System.out.println(" [" + Constants.FORMAT_TABLE_COLUMN_NAME + "] " + failedNode.getName());
                System.out.println(" [" + Constants.FORMAT_TABLE_COLUMN_STATUS + "] " + failedNode.getStatus());
                System.out.println(" [" + Constants.FORMAT_TABLE_COLUMN_ERROR + "] " + failedNode.getErrMessage());
                CommandsUtils.printSeperator();
                ;
            }
            System.out.println();
        }
    }

    private static void printSeperator() {
        StringBuffer seperator = new StringBuffer().append(Constants.OUTPUT_INDENT);
        for (int i = 0; i < Constants.SEPERATOR_LEN; i++) {
            seperator.append("-");
        }
        System.out.println(seperator.toString());
    }

    /**
     * Take the accuracy of double data.
     * <p>
     * For example: <br>
     * A double value = 100.345678; <br>
     * The Double ret = round (value, 4, BigDecimal.ROUND_HALF_UP); <br>
     * "Ret 100.3457 <br>
     *
     * @param value
     *           Double data value. @param scale Precision digits (reserve of
     *           decimal digits).
     * @param roundingMode
     *           Precision value way.
     * @return Precision calculation of data.
     */
    private static double round(double value, int scale, int roundingMode) {
        BigDecimal bd = new BigDecimal(value);
        bd = bd.setScale(scale, roundingMode);
        double d = bd.doubleValue();
        return d;
    }

    private static ObjectMapper getMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
        return mapper;
    }

    public static Properties readProperties(String propertiesFilePath) {
        Properties properties = new Properties();
        FileInputStream fis = null;
        try {
            File file = new File(propertiesFilePath);
            if (!file.exists()) {
                return null;
            }
            fis = new FileInputStream(propertiesFilePath);
            properties.load(fis);
            return properties;
        } catch (IOException e) {
            System.out.println(e.getMessage());
            return null;
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    System.out.println(e.getMessage());
                }
            }
        }
    }

    public static void writeProperties(Properties properties, String propertiesFilePath) {
        FileOutputStream fos = null;
        try {
            Properties prop = null;
            File file = new File(propertiesFilePath);
            if (file.exists()) {
                prop = new Properties();
                prop.load(new FileInputStream(propertiesFilePath));
                prop.putAll(properties);
            } else {
                prop = properties;
            }
            fos = new FileOutputStream(propertiesFilePath);
            prop.store(fos, "");
        } catch (IOException e) {
            System.out.println(e.getMessage());
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e1) {
                    System.out.println(e1.getMessage());
                }
            }
        }
    }

    public static boolean showWarningMsg(final String name, final String targetObject, final String operateType,
            final List<String> warningMsgList, final boolean alwaysAnswerYes, String promptMsg) {
        if (warningMsgList != null && !warningMsgList.isEmpty()) {
            for (String message : warningMsgList) {
                System.out.println(message);
            }
            if (!isContinue(name, targetObject, operateType,
                    promptMsg != null ? promptMsg : Constants.PARAM_PROMPT_CONTINUE_MESSAGE, alwaysAnswerYes)) {
                return false;
            }
        }
        return true;
    }

    private static boolean isContinue(final String name, final String targetObject, final String operateType,
            final String promptMsg, final boolean alwaysAnswerYes) {
        if (alwaysAnswerYes) {
            return true;
        }

        boolean continueCreate = true;
        boolean continueLoop = true;
        String readMsg = "";
        try {
            ConsoleReader reader = new ConsoleReader();
            // Set prompt message
            reader.setPrompt(promptMsg);
            int k = 0;
            while (continueLoop) {
                if (k >= 3) {
                    continueCreate = false;
                    break;
                }
                // Read user input
                readMsg = reader.readLine();
                if ("yes".equalsIgnoreCase(readMsg.trim()) || "y".equalsIgnoreCase(readMsg.trim())) {
                    continueLoop = false;
                } else if ("no".equalsIgnoreCase(readMsg.trim()) || "n".equalsIgnoreCase(readMsg.trim())) {
                    continueLoop = false;
                    continueCreate = false;
                } else {
                    k++;
                }
            }
        } catch (Exception e) {
            CommandsUtils.printCmdFailure(targetObject, operateType, Constants.OUTPUT_OP_RESULT_FAIL,
                    e.getMessage());
            continueCreate = false;
        }
        return continueCreate;
    }

    public static String getExceptionMessage(Exception e) {
        if (e.getCause() == null) {
            return e.getMessage();
        } else {
            return getRootCause(e).getMessage();
        }
    }

    private static Throwable getRootCause(Exception e) {
        Throwable cause = e.getCause();
        Throwable rootCause = null;
        while (cause != null) {
            rootCause = cause;
            cause = cause.getCause();
        }
        return rootCause;
    }

    /*
     * Transfer terminal output encoding to system encoding.
     * It only take effect on windows OS.
     */
    public static String transferEncoding(final String src) throws UnsupportedEncodingException, CliException {
        //      Return CMD output code page.
        int codePage = Kernel32.GetConsoleOutputCP();
        String outputEncoding = "ms" + codePage;
        if (!java.nio.charset.Charset.isSupported(outputEncoding)) {
            outputEncoding = "cp" + codePage;
            if (!java.nio.charset.Charset.isSupported(outputEncoding)) {
                String errorMsg = "Cannot figure out the Java Charset of this code page (" + codePage + ")...";
                logger.error("CommandsUtils::transferEncoding: " + errorMsg);
                throw new CliException(errorMsg);
            }
        }
        return new String(src.getBytes(outputEncoding), Configuration.getEncoding());
    }

    public static void gracefulRackTopologyOutput(Map<String, String> racksTopology, String filename,
            String delimeter) throws Exception {
        CommonUtil.gracefulRackTopologyOutput(racksTopology, filename, delimeter);
        writeEndingMsgToScreen(filename);
    }

    public static void prettyOutputStrings(List<Object> list, String fileName, String delimeter) throws Exception {
        CommonUtil.prettyOutputStrings(list, fileName, delimeter);
        writeEndingMsgToScreen(fileName);
    }

    public static void writeEndingMsgToScreen(String fileName) throws Exception {
        if (fileName == null) {
            System.out.println();
        } else {
            File file = new File(fileName);
            String filePath = file.getAbsolutePath();
            if (isJansiAvailable() && !isBlank(filePath)) {
                filePath = transferEncoding(filePath);
            }
            System.out.println("Exported to file " + filePath);
        }
    }

    public enum PromptType {
        USER_NAME, PASSWORD
    }

    public static String prompt(String msg) throws IOException {
        ConsoleReader reader = getConsoleReader();
        reader.setPrompt(msg);
        return reader.readLine();
    }

    public static boolean prompt(String msg, PromptType promptType, Map<String, String> loginInfo)
            throws Exception {
        int k = 0;
        String enter = "";
        while (k < 3) {
            enter = readEnter(msg, promptType);
            if (!CommandsUtils.isBlank(enter)) {
                if (promptType == PromptType.USER_NAME) {
                    loginInfo.put(Constants.LOGIN_USERNAME, enter);
                } else {
                    loginInfo.put(Constants.LOGIN_PASSWORD, enter);
                }
                break;
            } else {
                StringBuilder warningMsg = new StringBuilder();
                if (promptType == PromptType.USER_NAME) {
                    warningMsg.append(Constants.CONNECT_USER_NAME);
                } else {
                    warningMsg.append(Constants.CONNECT_PASSWORD);
                }
                warningMsg.append(Constants.CONNECT_CAN_NOT_BE_NULL);
                System.out.println(warningMsg.toString());
            }
            k++;
        }
        return k < 3;
    }

    private static String readEnter(String msg, PromptType promptType) throws Exception {
        String enter = "";
        ConsoleReader reader = getConsoleReader();
        reader.setPrompt(msg);
        if (promptType == PromptType.USER_NAME) {
            enter = reader.readLine();
        } else if (promptType == PromptType.PASSWORD) {
            enter = reader.readLine(Character.valueOf('*'));
        }
        return enter;
    }

    public static ConsoleReader getConsoleReader() throws IOException {
        ConsoleReader reader = new ConsoleReader();
        reader.setExpandEvents(false);
        return reader;
    }
}