/*
 * Copyright 2005-2006 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.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();
}
