/*
 * Copyright (c) 2005, 2006, 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 com.sun.jmx.mbeanserver;

import java.security.AccessController;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.management.AttributeNotFoundException;
import javax.management.InvalidAttributeValueException;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.ReflectionException;

import static com.sun.jmx.mbeanserver.Util.*;

/**
 * Per-MBean-interface behavior.  A single instance of this class can be shared
 * by all MBeans of the same kind (Standard MBean or MXBean) that have the same
 * MBean interface.
 *
 * @since 1.6
 */
final class PerInterface<M> {
    PerInterface(Class<?> mbeanInterface, MBeanIntrospector<M> introspector,
                 MBeanAnalyzer<M> analyzer, MBeanInfo mbeanInfo) {
        this.mbeanInterface = mbeanInterface;
        this.introspector = introspector;
        this.mbeanInfo = mbeanInfo;
        analyzer.visit(new InitMaps());
    }

    Class<?> getMBeanInterface() {
        return mbeanInterface;
    }

    MBeanInfo getMBeanInfo() {
        return mbeanInfo;
    }

    boolean isMXBean() {
        return introspector.isMXBean();
    }

    Object getAttribute(Object resource, String attribute, Object cookie)
            throws AttributeNotFoundException,
                   MBeanException,
                   ReflectionException {

        final M cm = getters.get(attribute);
        if (cm == null) {
            final String msg;
            if (setters.containsKey(attribute))
                msg = "Write-only attribute: " + attribute;
            else
                msg = "No such attribute: " + attribute;
            throw new AttributeNotFoundException(msg);
        }
        return introspector.invokeM(cm, resource, (Object[]) null, cookie);
    }

    void setAttribute(Object resource, String attribute, Object value,
                      Object cookie)
            throws AttributeNotFoundException,
                   InvalidAttributeValueException,
                   MBeanException,
                   ReflectionException {

        final M cm = setters.get(attribute);
        if (cm == null) {
            final String msg;
            if (getters.containsKey(attribute))
                msg = "Read-only attribute: " + attribute;
            else
                msg = "No such attribute: " + attribute;
            throw new AttributeNotFoundException(msg);
        }
        introspector.invokeSetter(attribute, cm, resource, value, cookie);
    }

    Object invoke(Object resource, String operation, Object[] params,
                  String[] signature, Object cookie)
            throws MBeanException, ReflectionException {

        final List<MethodAndSig> list = ops.get(operation);
        if (list == null) {
            final String msg = "No such operation: " + operation;
            return noSuchMethod(msg, resource, operation, params, signature,
                                cookie);
        }
        if (signature == null)
            signature = new String[0];
        MethodAndSig found = null;
        for (MethodAndSig mas : list) {
            if (Arrays.equals(mas.signature, signature)) {
                found = mas;
                break;
            }
        }
        if (found == null) {
            final String badSig = sigString(signature);
            final String msg;
            if (list.size() == 1) {  // helpful exception message
                msg = "Signature mismatch for operation " + operation +
                        ": " + badSig + " should be " +
                        sigString(list.get(0).signature);
            } else {
                msg = "Operation " + operation + " exists but not with " +
                        "this signature: " + badSig;
            }
            return noSuchMethod(msg, resource, operation, params, signature,
                                cookie);
        }
        return introspector.invokeM(found.method, resource, params, cookie);
    }

    /*
     * This method is called when invoke doesn't find the named method.
     * Before throwing an exception, we check to see whether the
     * jmx.invoke.getters property is set, and if so whether the method
     * being invoked might be a getter or a setter.  If so we invoke it
     * and return the result.  This is for compatibility
     * with code based on JMX RI 1.0 or 1.1 which allowed invoking getters
     * and setters.  It is *not* recommended that new code use this feature.
     *
     * Since this method is either going to throw an exception or use
     * functionality that is strongly discouraged, we consider that its
     * performance is not very important.
     *
     * A simpler way to implement the functionality would be to add the getters
     * and setters to the operations map when jmx.invoke.getters is set.
     * However, that means that the property is consulted when an MBean
     * interface is being introspected and not thereafter.  Previously,
     * the property was consulted on every invocation.  So this simpler
     * implementation could potentially break code that sets and unsets
     * the property at different times.
     */
    private Object noSuchMethod(String msg, Object resource, String operation,
                                Object[] params, String[] signature,
                                Object cookie)
            throws MBeanException, ReflectionException {

        // Construct the exception that we will probably throw
        final NoSuchMethodException nsme =
            new NoSuchMethodException(operation + sigString(signature));
        final ReflectionException exception =
            new ReflectionException(nsme, msg);

        if (introspector.isMXBean())
            throw exception; // No compatibility requirement here

        // Is the compatibility property set?
        GetPropertyAction act = new GetPropertyAction("jmx.invoke.getters");
        String invokeGettersS;
        try {
            invokeGettersS = AccessController.doPrivileged(act);
        } catch (Exception e) {
            // We don't expect an exception here but if we get one then
            // we'll simply assume that the property is not set.
            invokeGettersS = null;
        }
        if (invokeGettersS == null)
            throw exception;

        int rest = 0;
        Map<String, M> methods = null;
        if (signature == null || signature.length == 0) {
            if (operation.startsWith("get"))
                rest = 3;
            else if (operation.startsWith("is"))
                rest = 2;
            if (rest != 0)
                methods = getters;
        } else if (signature.length == 1 &&
                   operation.startsWith("set")) {
            rest = 3;
            methods = setters;
        }

        if (rest != 0) {
            String attrName = operation.substring(rest);
            M method = methods.get(attrName);
            if (method != null && introspector.getName(method).equals(operation)) {
                String[] msig = introspector.getSignature(method);
                if ((signature == null && msig.length == 0) ||
                        Arrays.equals(signature, msig)) {
                    return introspector.invokeM(method, resource, params, cookie);
                }
            }
        }

        throw exception;
    }

    private String sigString(String[] signature) {
        StringBuilder b = new StringBuilder("(");
        if (signature != null) {
            for (String s : signature) {
                if (b.length() > 1)
                    b.append(", ");
                b.append(s);
            }
        }
        return b.append(")").toString();
    }

    /**
     * Visitor that sets up the method maps (operations, getters, setters).
     */
    private class InitMaps implements MBeanAnalyzer.MBeanVisitor<M> {
        public void visitAttribute(String attributeName,
                                   M getter,
                                   M setter) {
            if (getter != null) {
                introspector.checkMethod(getter);
                final Object old = getters.put(attributeName, getter);
                assert(old == null);
            }
            if (setter != null) {
                introspector.checkMethod(setter);
                final Object old = setters.put(attributeName, setter);
                assert(old == null);
            }
        }

        public void visitOperation(String operationName,
                                   M operation) {
            introspector.checkMethod(operation);
            final String[] sig = introspector.getSignature(operation);
            final MethodAndSig mas = new MethodAndSig();
            mas.method = operation;
            mas.signature = sig;
            List<MethodAndSig> list = ops.get(operationName);
            if (list == null)
                list = Collections.singletonList(mas);
            else {
                if (list.size() == 1)
                    list = newList(list);
                list.add(mas);
            }
            ops.put(operationName, list);
        }
    }

    private class MethodAndSig {
        M method;
        String[] signature;
    }

    private final Class<?> mbeanInterface;
    private final MBeanIntrospector<M> introspector;
    private final MBeanInfo mbeanInfo;
    private final Map<String, M> getters = newMap();
    private final Map<String, M> setters = newMap();
    private final Map<String, List<MethodAndSig>> ops = newMap();
}
