/*
 * Copyright 2000-2003 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.snmp.agent;


// java imports
//
import java.util.Vector;
import java.util.Enumeration;
import java.util.Iterator;

// jmx imports
//
import javax.management.AttributeList;
import javax.management.Attribute;
import javax.management.MBeanException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.InstanceNotFoundException;
import javax.management.InvalidAttributeValueException;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.NotCompliantMBeanException;
import javax.management.RuntimeOperationsException;
import com.sun.jmx.snmp.SnmpOid;
import com.sun.jmx.snmp.SnmpValue;
import com.sun.jmx.snmp.SnmpVarBind;
import com.sun.jmx.snmp.SnmpStatusException;


/**
 * <p>
 * This class is a utility class that transforms SNMP GET / SET requests
 * into standard JMX getAttributes() setAttributes() requests.
 * </p>
 *
 * <p>
 * The transformation relies on the metadata information provided by the
 * {@link com.sun.jmx.snmp.agent.SnmpGenericMetaServer} object which is
 * passed as the first parameter to every method. This SnmpGenericMetaServer
 * object is usually a Metadata object generated by <code>mibgen</code>.
 * </p>
 *
 * <p><b><i>
 * This class is used internally by mibgen generated metadata objects and
 * you should never need to use it directly.
 * </b></i></p>
 * <p><b>This API is a Sun Microsystems internal API  and is subject
 * to change without notice.</b></p>
 **/

public class SnmpGenericObjectServer {

    // ----------------------------------------------------------------------
    //
    //    Protected variables
    //
    // ----------------------------------------------------------------------

    /**
     * The MBean server through which the MBeans will be accessed.
     **/
    protected final MBeanServer server;

    // ----------------------------------------------------------------------
    //
    // Constructors
    //
    // ----------------------------------------------------------------------

    /**
     * Builds a new SnmpGenericObjectServer. Usually there will be a single
     * object of this type per MIB.
     *
     * @param server The MBeanServer in which the MBean accessed by this
     *               MIB are registered.
     **/
    public SnmpGenericObjectServer(MBeanServer server) {
        this.server = server;
    }

    /**
     * Execute an SNMP GET request.
     *
     * <p>
     * This method first builds the list of attributes that need to be
     * retrieved from the MBean and then calls getAttributes() on the
     * MBean server. Then it updates the SnmpMibSubRequest with the values
     * retrieved from the MBean.
     * </p>
     *
     * <p>
     * The SNMP metadata information is obtained through the given
     * <code>meta</code> object, which usually is an instance of a
     * <code>mibgen</code> generated class.
     * </p>
     *
     * <p><b><i>
     * This method is called internally by <code>mibgen</code> generated
     * objects and you should never need to call it directly.
     * </i></b></p>
     *
     * @param meta  The metadata object impacted by the subrequest
     * @param name  The ObjectName of the MBean impacted by this subrequest
     * @param req   The SNMP subrequest to execute on the MBean
     * @param depth The depth of the SNMP object in the OID tree.
     *
     * @exception SnmpStatusException whenever an SNMP exception must be
     *      raised. Raising an exception will abort the request.<br>
     *      Exceptions should never be raised directly, but only by means of
     * <code>
     * req.registerGetException(<i>VariableId</i>,<i>SnmpStatusException</i>)
     * </code>
     **/
    public void get(SnmpGenericMetaServer meta, ObjectName name,
                    SnmpMibSubRequest req, int depth)
        throws SnmpStatusException {

        // java.lang.System.out.println(">>>>>>>>> GET " + name);

        final int           size     = req.getSize();
        final Object        data     = req.getUserData();
        final String[]      nameList = new String[size];
        final SnmpVarBind[] varList  = new SnmpVarBind[size];
        final long[]        idList   = new long[size];
        int   i = 0;

        for (Enumeration e=req.getElements(); e.hasMoreElements();) {
            final SnmpVarBind var= (SnmpVarBind) e.nextElement();
            try {
                final long id = var.oid.getOidArc(depth);
                nameList[i]   = meta.getAttributeName(id);
                varList[i]    = var;
                idList[i]     = id;

                // Check the access rights according to the MIB.
                // The MBean might be less restrictive (have a getter
                // while the MIB defines the variable as AFN)
                //
                meta.checkGetAccess(id,data);

                //java.lang.System.out.println(nameList[i] + " added.");
                i++;
            } catch(SnmpStatusException x) {
                //java.lang.System.out.println("exception for " + nameList[i]);
                //x.printStackTrace();
                req.registerGetException(var,x);
            }
        }

        AttributeList result = null;
        int errorCode = SnmpStatusException.noSuchInstance;

        try {
            result = server.getAttributes(name,nameList);
        } catch (InstanceNotFoundException f) {
            //java.lang.System.out.println(name + ": instance not found.");
            //f.printStackTrace();
            result = new AttributeList();
        } catch (ReflectionException r) {
            //java.lang.System.out.println(name + ": reflexion error.");
            //r.printStackTrace();
            result = new AttributeList();
        } catch (Exception x) {
            result = new AttributeList();
        }


        final Iterator it = result.iterator();

        for (int j=0; j < i; j++) {
            if (!it.hasNext()) {
                //java.lang.System.out.println(name + "variable[" + j +
                //                           "] absent");
                final SnmpStatusException x =
                    new SnmpStatusException(errorCode);
                req.registerGetException(varList[j],x);
                continue;
            }

            final Attribute att = (Attribute) it.next();

            while ((j < i) && (! nameList[j].equals(att.getName()))) {
                //java.lang.System.out.println(name + "variable[" +j +
                //                           "] not found");
                final SnmpStatusException x =
                    new SnmpStatusException(errorCode);
                req.registerGetException(varList[j],x);
                j++;
            }

            if ( j == i) break;

            try {
                varList[j].value =
                    meta.buildSnmpValue(idList[j],att.getValue());
            } catch (SnmpStatusException x) {
                req.registerGetException(varList[j],x);
            }
            //java.lang.System.out.println(att.getName() + " retrieved.");
        }
        //java.lang.System.out.println(">>>>>>>>> END GET");
    }

    /**
     * Get the value of an SNMP variable.
     *
     * <p><b><i>
     * You should never need to use this method directly.
     * </i></b></p>
     *
     * @param meta  The impacted metadata object
     * @param name  The ObjectName of the impacted MBean
     * @param id    The OID arc identifying the variable we're trying to set.
     * @param data  User contextual data allocated through the
     *        {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}
     *
     * @return The value of the variable.
     *
     * @exception SnmpStatusException whenever an SNMP exception must be
     *      raised. Raising an exception will abort the request. <br>
     *      Exceptions should never be raised directly, but only by means of
     * <code>
     * req.registerGetException(<i>VariableId</i>,<i>SnmpStatusException</i>)
     * </code>
     **/
    public SnmpValue get(SnmpGenericMetaServer meta, ObjectName name,
                         long id, Object data)
        throws SnmpStatusException {
        final String attname = meta.getAttributeName(id);
        Object result = null;

        try {
            result = server.getAttribute(name,attname);
        } catch (MBeanException m) {
            Exception t = m.getTargetException();
            if (t instanceof SnmpStatusException)
                throw (SnmpStatusException) t;
            throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
        } catch (Exception e) {
            throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
        }

        return meta.buildSnmpValue(id,result);
    }

    /**
     * Execute an SNMP SET request.
     *
     * <p>
     * This method first builds the list of attributes that need to be
     * set on the MBean and then calls setAttributes() on the
     * MBean server. Then it updates the SnmpMibSubRequest with the new
     * values retrieved from the MBean.
     * </p>
     *
     * <p>
     * The SNMP metadata information is obtained through the given
     * <code>meta</code> object, which usually is an instance of a
     * <code>mibgen</code> generated class.
     * </p>
     *
     * <p><b><i>
     * This method is called internally by <code>mibgen</code> generated
     * objects and you should never need to call it directly.
     * </i></b></p>
     *
     * @param meta  The metadata object impacted by the subrequest
     * @param name  The ObjectName of the MBean impacted by this subrequest
     * @param req   The SNMP subrequest to execute on the MBean
     * @param depth The depth of the SNMP object in the OID tree.
     *
     * @exception SnmpStatusException whenever an SNMP exception must be
     *      raised. Raising an exception will abort the request. <br>
     *      Exceptions should never be raised directly, but only by means of
     * <code>
     * req.registerGetException(<i>VariableId</i>,<i>SnmpStatusException</i>)
     * </code>
     **/
    public void set(SnmpGenericMetaServer meta, ObjectName name,
                    SnmpMibSubRequest req, int depth)
        throws SnmpStatusException {

        final int size               = req.getSize();
        final AttributeList attList  = new AttributeList(size);
        final String[]      nameList = new String[size];
        final SnmpVarBind[] varList  = new SnmpVarBind[size];
        final long[]        idList   = new long[size];
        int   i = 0;

        for (Enumeration e=req.getElements(); e.hasMoreElements();) {
            final SnmpVarBind var= (SnmpVarBind) e.nextElement();
            try {
                final long id = var.oid.getOidArc(depth);
                final String attname = meta.getAttributeName(id);
                final Object attvalue=
                    meta.buildAttributeValue(id,var.value);
                final Attribute att = new Attribute(attname,attvalue);
                attList.add(att);
                nameList[i]   = attname;
                varList[i]    = var;
                idList[i]     = id;
                i++;
            } catch(SnmpStatusException x) {
                req.registerSetException(var,x);
            }
        }

        AttributeList result = null;
        int errorCode = SnmpStatusException.noAccess;

        try {
            result = server.setAttributes(name,attList);
        } catch (InstanceNotFoundException f) {
            result = new AttributeList();
            errorCode = SnmpStatusException.snmpRspInconsistentName;
        } catch (ReflectionException r) {
            errorCode = SnmpStatusException.snmpRspInconsistentName;
            result = new AttributeList();
        } catch (Exception x) {
            result = new AttributeList();
        }

        final Iterator it = result.iterator();

        for (int j=0; j < i; j++) {
            if (!it.hasNext()) {
                final SnmpStatusException x =
                    new SnmpStatusException(errorCode);
                req.registerSetException(varList[j],x);
                continue;
            }

            final Attribute att = (Attribute) it.next();

            while ((j < i) && (! nameList[j].equals(att.getName()))) {
                final SnmpStatusException x =
                    new SnmpStatusException(SnmpStatusException.noAccess);
                req.registerSetException(varList[j],x);
                j++;
            }

            if ( j == i) break;

            try {
                varList[j].value =
                    meta.buildSnmpValue(idList[j],att.getValue());
            } catch (SnmpStatusException x) {
                req.registerSetException(varList[j],x);
            }

        }
    }

    /**
     * Set the value of an SNMP variable.
     *
     * <p><b><i>
     * You should never need to use this method directly.
     * </i></b></p>
     *
     * @param meta  The impacted metadata object
     * @param name  The ObjectName of the impacted MBean
     * @param x     The new requested SnmpValue
     * @param id    The OID arc identifying the variable we're trying to set.
     * @param data  User contextual data allocated through the
     *        {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}
     *
     * @return The new value of the variable after the operation.
     *
     * @exception SnmpStatusException whenever an SNMP exception must be
     *      raised. Raising an exception will abort the request. <br>
     *      Exceptions should never be raised directly, but only by means of
     * <code>
     * req.registerSetException(<i>VariableId</i>,<i>SnmpStatusException</i>)
     * </code>
     **/
    public SnmpValue set(SnmpGenericMetaServer meta, ObjectName name,
                         SnmpValue x, long id, Object data)
        throws SnmpStatusException {
        final String attname = meta.getAttributeName(id);
        final Object attvalue=
            meta.buildAttributeValue(id,x);
        final Attribute att = new Attribute(attname,attvalue);

        Object result = null;

        try {
            server.setAttribute(name,att);
            result = server.getAttribute(name,attname);
        } catch(InvalidAttributeValueException iv) {
            throw new
                SnmpStatusException(SnmpStatusException.snmpRspWrongValue);
        } catch (InstanceNotFoundException f) {
            throw new
                SnmpStatusException(SnmpStatusException.snmpRspInconsistentName);
        } catch (ReflectionException r) {
            throw new
                SnmpStatusException(SnmpStatusException.snmpRspInconsistentName);
        } catch (MBeanException m) {
            Exception t = m.getTargetException();
            if (t instanceof SnmpStatusException)
                throw (SnmpStatusException) t;
            throw new
                SnmpStatusException(SnmpStatusException.noAccess);
        } catch (Exception e) {
            throw new
                SnmpStatusException(SnmpStatusException.noAccess);
        }

        return meta.buildSnmpValue(id,result);
    }

    /**
     * Checks whether an SNMP SET request can be successfully performed.
     *
     * <p>
     * For each variable in the subrequest, this method calls
     * checkSetAccess() on the meta object, and then tries to invoke the
     * check<i>AttributeName</i>() method on the MBean. If this method
     * is not defined then it is assumed that the SET won't fail.
     * </p>
     *
     * <p><b><i>
     * This method is called internally by <code>mibgen</code> generated
     * objects and you should never need to call it directly.
     * </i></b></p>
     *
     * @param meta  The metadata object impacted by the subrequest
     * @param name  The ObjectName of the MBean impacted by this subrequest
     * @param req   The SNMP subrequest to execute on the MBean
     * @param depth The depth of the SNMP object in the OID tree.
     *
     * @exception SnmpStatusException if the requested SET operation must
     *      be rejected. Raising an exception will abort the request. <br>
     *      Exceptions should never be raised directly, but only by means of
     * <code>
     * req.registerCheckException(<i>VariableId</i>,<i>SnmpStatusException</i>)
     * </code>
     *
     **/
    public void check(SnmpGenericMetaServer meta, ObjectName name,
                      SnmpMibSubRequest req, int depth)
        throws SnmpStatusException {

        final Object data = req.getUserData();

        for (Enumeration e=req.getElements(); e.hasMoreElements();) {
            final SnmpVarBind var= (SnmpVarBind) e.nextElement();
            try {
                final long id = var.oid.getOidArc(depth);
                // call meta.check() here, and meta.check will call check()
                check(meta,name,var.value,id,data);
            } catch(SnmpStatusException x) {
                req.registerCheckException(var,x);
            }
        }
    }

    /**
     * Checks whether a SET operation can be performed on a given SNMP
     * variable.
     *
     * @param meta  The impacted metadata object
     * @param name  The ObjectName of the impacted MBean
     * @param x     The new requested SnmpValue
     * @param id    The OID arc identifying the variable we're trying to set.
     * @param data  User contextual data allocated through the
     *        {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}
     *
     * <p>
     * This method calls checkSetAccess() on the meta object, and then
     * tries to invoke the check<i>AttributeName</i>() method on the MBean.
     * If this method is not defined then it is assumed that the SET
     * won't fail.
     * </p>
     *
     * <p><b><i>
     * This method is called internally by <code>mibgen</code> generated
     * objects and you should never need to call it directly.
     * </i></b></p>
     *
     * @exception SnmpStatusException if the requested SET operation must
     *      be rejected. Raising an exception will abort the request. <br>
     *      Exceptions should never be raised directly, but only by means of
     * <code>
     * req.registerCheckException(<i>VariableId</i>,<i>SnmpStatusException</i>)
     * </code>
     *
     **/
    // XXX xxx ZZZ zzz Maybe we should go through the MBeanInfo here?
    public void check(SnmpGenericMetaServer meta, ObjectName name,
                      SnmpValue x, long id, Object data)
        throws SnmpStatusException {

        meta.checkSetAccess(x,id,data);
        try {
            final String attname = meta.getAttributeName(id);
            final Object attvalue= meta.buildAttributeValue(id,x);
            final  Object[] params = new Object[1];
            final  String[] signature = new String[1];

            params[0]    = attvalue;
            signature[0] = attvalue.getClass().getName();
            server.invoke(name,"check"+attname,params,signature);

        } catch( SnmpStatusException e) {
            throw e;
        }
        catch (InstanceNotFoundException i) {
            throw new
                SnmpStatusException(SnmpStatusException.snmpRspInconsistentName);
        } catch (ReflectionException r) {
            // checkXXXX() not defined => do nothing
        } catch (MBeanException m) {
            Exception t = m.getTargetException();
            if (t instanceof SnmpStatusException)
                throw (SnmpStatusException) t;
            throw new SnmpStatusException(SnmpStatusException.noAccess);
        } catch (Exception e) {
            throw new
                SnmpStatusException(SnmpStatusException.noAccess);
        }
    }

    public void registerTableEntry(SnmpMibTable meta, SnmpOid rowOid,
                                   ObjectName objname, Object entry)
        throws SnmpStatusException {
        if (objname == null)
           throw new
             SnmpStatusException(SnmpStatusException.snmpRspInconsistentName);
        try  {
            if (entry != null && !server.isRegistered(objname))
                server.registerMBean(entry, objname);
        } catch (InstanceAlreadyExistsException e) {
            throw new
              SnmpStatusException(SnmpStatusException.snmpRspInconsistentName);
        } catch (MBeanRegistrationException e) {
            throw new SnmpStatusException(SnmpStatusException.snmpRspNoAccess);
        } catch (NotCompliantMBeanException e) {
            throw new SnmpStatusException(SnmpStatusException.snmpRspGenErr);
        } catch (RuntimeOperationsException e) {
            throw new SnmpStatusException(SnmpStatusException.snmpRspGenErr);
        } catch(Exception e) {
            throw new SnmpStatusException(SnmpStatusException.snmpRspGenErr);
        }
    }

}
