/*
 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.management;

import com.sun.management.DiagnosticCommandMBean;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.Permission;
import java.util.*;
import javax.management.*;

/**
 * Implementation class for the diagnostic commands subsystem.
 *
 * @since 8
 */
class DiagnosticCommandImpl extends NotificationEmitterSupport
    implements DiagnosticCommandMBean {

    private final VMManagement jvm;
    private volatile Map<String, Wrapper> wrappers = null;
    private static final String strClassName = "".getClass().getName();
    private static final String strArrayClassName = String[].class.getName();
    private final boolean isSupported;

    @Override
    public Object getAttribute(String attribute) throws AttributeNotFoundException,
        MBeanException, ReflectionException {
        throw new AttributeNotFoundException(attribute);
    }

    @Override
    public void setAttribute(Attribute attribute) throws AttributeNotFoundException,
        InvalidAttributeValueException, MBeanException, ReflectionException {
        throw new AttributeNotFoundException(attribute.getName());
    }

    @Override
    public AttributeList getAttributes(String[] attributes) {
        return new AttributeList();
    }

    @Override
    public AttributeList setAttributes(AttributeList attributes) {
        return new AttributeList();
    }

    private class Wrapper {

        String name;
        String cmd;
        DiagnosticCommandInfo info;
        Permission permission;

        Wrapper(String name, String cmd, DiagnosticCommandInfo info)
                throws InstantiationException {
            this.name = name;
            this.cmd = cmd;
            this.info = info;
            this.permission = null;
            Exception cause = null;
            if (info.getPermissionClass() != null) {
                try {
                    Class c = Class.forName(info.getPermissionClass());
                    if (info.getPermissionAction() == null) {
                        try {
                            Constructor constructor = c.getConstructor(String.class);
                            permission = (Permission) constructor.newInstance(info.getPermissionName());

                        } catch (InstantiationException | IllegalAccessException
                                | IllegalArgumentException | InvocationTargetException
                                | NoSuchMethodException | SecurityException ex) {
                            cause = ex;
                        }
                    }
                    if (permission == null) {
                        try {
                            Constructor constructor = c.getConstructor(String.class, String.class);
                            permission = (Permission) constructor.newInstance(
                                    info.getPermissionName(),
                                    info.getPermissionAction());
                        } catch (InstantiationException | IllegalAccessException
                                | IllegalArgumentException | InvocationTargetException
                                | NoSuchMethodException | SecurityException ex) {
                            cause = ex;
                        }
                    }
                } catch (ClassNotFoundException ex) { }
                if (permission == null) {
                    InstantiationException iex =
                            new InstantiationException("Unable to instantiate required permission");
                    iex.initCause(cause);
                }
            }
        }

        public String execute(String[] args) {
            if (permission != null) {
                SecurityManager sm = System.getSecurityManager();
                if (sm != null) {
                    sm.checkPermission(permission);
                }
            }
            if(args == null) {
                return executeDiagnosticCommand(cmd);
            } else {
                StringBuilder sb = new StringBuilder();
                sb.append(cmd);
                for(int i=0; i<args.length; i++) {
                    if(args[i] == null) {
                        throw new IllegalArgumentException("Invalid null argument");
                    }
                    sb.append(" ");
                    sb.append(args[i]);
                }
                return executeDiagnosticCommand(sb.toString());
            }
        }
    }

    DiagnosticCommandImpl(VMManagement jvm) {
        this.jvm = jvm;
        isSupported = jvm.isRemoteDiagnosticCommandsSupported();
    }

    private static class OperationInfoComparator implements Comparator<MBeanOperationInfo> {
        @Override
        public int compare(MBeanOperationInfo o1, MBeanOperationInfo o2) {
            return o1.getName().compareTo(o2.getName());
        }
    }

    @Override
    public MBeanInfo getMBeanInfo() {
        SortedSet<MBeanOperationInfo> operations = new TreeSet<>(new OperationInfoComparator());
        Map<String, Wrapper> wrappersmap;
        if (!isSupported) {
            wrappersmap = (Map<String, Wrapper>) Collections.EMPTY_MAP;
        } else {
            try {
                String[] command = getDiagnosticCommands();
                DiagnosticCommandInfo[] info = getDiagnosticCommandInfo(command);
                MBeanParameterInfo stringArgInfo[] = new MBeanParameterInfo[]{
                    new MBeanParameterInfo("arguments", strArrayClassName,
                    "Array of Diagnostic Commands Arguments and Options")
                };
                wrappersmap = new HashMap<>();
                for (int i = 0; i < command.length; i++) {
                    String name = transform(command[i]);
                    try {
                        Wrapper w = new Wrapper(name, command[i], info[i]);
                        wrappersmap.put(name, w);
                        operations.add(new MBeanOperationInfo(
                                w.name,
                                w.info.getDescription(),
                                (w.info.getArgumentsInfo() == null
                                    || w.info.getArgumentsInfo().isEmpty())
                                    ? null : stringArgInfo,
                                strClassName,
                                MBeanOperationInfo.ACTION_INFO,
                                commandDescriptor(w)));
                    } catch (InstantiationException ex) {
                        // If for some reasons the creation of a diagnostic command
                        // wrappers fails, the diagnostic command is just ignored
                        // and won't appear in the DynamicMBean
                    }
                }
            } catch (IllegalArgumentException | UnsupportedOperationException e) {
                wrappersmap = (Map<String, Wrapper>) Collections.EMPTY_MAP;
            }
        }
        wrappers =  Collections.unmodifiableMap(wrappersmap);
        HashMap<String, Object> map = new HashMap<>();
        map.put("immutableInfo", "false");
        map.put("interfaceClassName","com.sun.management.DiagnosticCommandMBean");
        map.put("mxbean", "false");
        Descriptor desc = new ImmutableDescriptor(map);
        return new MBeanInfo(
                this.getClass().getName(),
                "Diagnostic Commands",
                null, // attributes
                null, // constructors
                operations.toArray(new MBeanOperationInfo[operations.size()]), // operations
                getNotificationInfo(), // notifications
                desc);
    }

    @Override
    public Object invoke(String actionName, Object[] params, String[] signature)
            throws MBeanException, ReflectionException {
        if (!isSupported) {
            throw new UnsupportedOperationException();
        }
        if (wrappers == null) {
            getMBeanInfo();
        }
        Wrapper w = wrappers.get(actionName);
        if (w != null) {
            if (w.info.getArgumentsInfo().isEmpty()
                    && (params == null || params.length == 0)
                    && (signature == null || signature.length == 0)) {
                return w.execute(null);
            } else if((params != null && params.length == 1)
                    && (signature != null && signature.length == 1
                    && signature[0] != null
                    && signature[0].compareTo(strArrayClassName) == 0)) {
                return w.execute((String[]) params[0]);
            }
        }
        throw new ReflectionException(new NoSuchMethodException(actionName));
    }

    private static String transform(String name) {
        StringBuilder sb = new StringBuilder();
        boolean toLower = true;
        boolean toUpper = false;
        for (int i = 0; i < name.length(); i++) {
            char c = name.charAt(i);
            if (c == '.' || c == '_') {
                toLower = false;
                toUpper = true;
            } else {
                if (toUpper) {
                    toUpper = false;
                    sb.append(Character.toUpperCase(c));
                } else if(toLower) {
                    sb.append(Character.toLowerCase(c));
                } else {
                    sb.append(c);
                }
            }
        }
        return sb.toString();
    }

    private Descriptor commandDescriptor(Wrapper w) throws IllegalArgumentException {
        HashMap<String, Object> map = new HashMap<>();
        map.put("dcmd.name", w.info.getName());
        map.put("dcmd.description", w.info.getDescription());
        map.put("dcmd.vmImpact", w.info.getImpact());
        map.put("dcmd.permissionClass", w.info.getPermissionClass());
        map.put("dcmd.permissionName", w.info.getPermissionName());
        map.put("dcmd.permissionAction", w.info.getPermissionAction());
        map.put("dcmd.enabled", w.info.isEnabled());
        StringBuilder sb = new StringBuilder();
        sb.append("help ");
        sb.append(w.info.getName());
        map.put("dcmd.help", executeDiagnosticCommand(sb.toString()));
        if (w.info.getArgumentsInfo() != null && !w.info.getArgumentsInfo().isEmpty()) {
            HashMap<String, Object> allargmap = new HashMap<>();
            for (DiagnosticCommandArgumentInfo arginfo : w.info.getArgumentsInfo()) {
                HashMap<String, Object> argmap = new HashMap<>();
                argmap.put("dcmd.arg.name", arginfo.getName());
                argmap.put("dcmd.arg.type", arginfo.getType());
                argmap.put("dcmd.arg.description", arginfo.getDescription());
                argmap.put("dcmd.arg.isMandatory", arginfo.isMandatory());
                argmap.put("dcmd.arg.isMultiple", arginfo.isMultiple());
                boolean isOption = arginfo.isOption();
                argmap.put("dcmd.arg.isOption", isOption);
                if(!isOption) {
                    argmap.put("dcmd.arg.position", arginfo.getPosition());
                } else {
                    argmap.put("dcmd.arg.position", -1);
                }
                allargmap.put(arginfo.getName(), new ImmutableDescriptor(argmap));
            }
            map.put("dcmd.arguments", new ImmutableDescriptor(allargmap));
        }
        return new ImmutableDescriptor(map);
    }

    private final static String notifName =
        "javax.management.Notification";

    private final static String[] diagFramNotifTypes = {
        "jmx.mbean.info.changed"
    };

    private MBeanNotificationInfo[] notifInfo = null;

    @Override
    public MBeanNotificationInfo[] getNotificationInfo() {
        synchronized (this) {
            if (notifInfo == null) {
                 notifInfo = new MBeanNotificationInfo[1];
                 notifInfo[0] =
                         new MBeanNotificationInfo(diagFramNotifTypes,
                                                   notifName,
                                                   "Diagnostic Framework Notification");
            }
        }
        return notifInfo;
    }

    private static long seqNumber = 0;
    private static long getNextSeqNumber() {
        return ++seqNumber;
    }

    private void createDiagnosticFrameworkNotification() {

        if (!hasListeners()) {
            return;
        }
        ObjectName on = null;
        try {
            on = ObjectName.getInstance(ManagementFactoryHelper.HOTSPOT_DIAGNOSTIC_COMMAND_MBEAN_NAME);
        } catch (MalformedObjectNameException e) { }
        Notification notif = new Notification("jmx.mbean.info.changed",
                                              on,
                                              getNextSeqNumber());
        notif.setUserData(getMBeanInfo());
        sendNotification(notif);
    }

    @Override
    public synchronized void addNotificationListener(NotificationListener listener,
            NotificationFilter filter,
            Object handback) {
        boolean before = hasListeners();
        super.addNotificationListener(listener, filter, handback);
        boolean after = hasListeners();
        if (!before && after) {
            setNotificationEnabled(true);
        }
    }

    @Override
    public synchronized void removeNotificationListener(NotificationListener listener)
            throws ListenerNotFoundException {
        boolean before = hasListeners();
        super.removeNotificationListener(listener);
        boolean after = hasListeners();
        if (before && !after) {
            setNotificationEnabled(false);
        }
    }

    @Override
    public synchronized void removeNotificationListener(NotificationListener listener,
            NotificationFilter filter,
            Object handback)
            throws ListenerNotFoundException {
        boolean before = hasListeners();
        super.removeNotificationListener(listener, filter, handback);
        boolean after = hasListeners();
        if (before && !after) {
            setNotificationEnabled(false);
        }
    }

    private native void setNotificationEnabled(boolean enabled);
    private native String[] getDiagnosticCommands();
    private native DiagnosticCommandInfo[] getDiagnosticCommandInfo(String[] commands);
    private native String executeDiagnosticCommand(String command);

}
