/*
 * Copyright 1997-2007 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;

import java.io.Serializable;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import java.util.logging.Level;

import javax.management.ListenerNotFoundException;
import javax.management.MBeanNotificationInfo;
import javax.management.Notification;
import javax.management.NotificationBroadcaster;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectName;

import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER;
import com.sun.jmx.snmp.EnumRowStatus;
import com.sun.jmx.snmp.SnmpInt;
import com.sun.jmx.snmp.SnmpOid;
import com.sun.jmx.snmp.SnmpStatusException;
import com.sun.jmx.snmp.SnmpValue;
import com.sun.jmx.snmp.SnmpVarBind;

/**
 * This class is the base class for SNMP table metadata.
 * <p>
 * Its responsibility is to manage a sorted array of OID indexes
 * according to the SNMP indexing scheme over the "real" table.
 * Each object of this class can be bound to an
 * {@link com.sun.jmx.snmp.agent.SnmpTableEntryFactory} to which it will
 * forward remote entry creation requests, and invoke callbacks
 * when an entry has been successfully added to / removed from
 * the OID index array.
 * </p>
 *
 * <p>
 * For each table defined in the MIB, mibgen will generate a specific
 * class called Table<i>TableName</i> that will implement the
 * SnmpTableEntryFactory interface, and a corresponding
 * <i>TableName</i>Meta class that will extend this class. <br>
 * The Table<i>TableName</i> class corresponds to the MBean view of the
 * table while the <i>TableName</i>Meta class corresponds to the
 * MIB metadata view of the same table.
 * </p>
 *
 * <p>
 * Objects of this class are instantiated by the generated
 * whole MIB class extending {@link com.sun.jmx.snmp.agent.SnmpMib}
 * You should never need to instantiate this class directly.
 * </p>
 *
 * <p><b>This API is a Sun Microsystems internal API  and is subject
 * to change without notice.</b></p>
 * @see com.sun.jmx.snmp.agent.SnmpMib
 * @see com.sun.jmx.snmp.agent.SnmpMibEntry
 * @see com.sun.jmx.snmp.agent.SnmpTableEntryFactory
 * @see com.sun.jmx.snmp.agent.SnmpTableSupport
 *
 */

public abstract class SnmpMibTable extends SnmpMibNode
    implements NotificationBroadcaster, Serializable {

    /**
     * Create a new <CODE>SnmpMibTable</CODE> metadata node.
     *
     * <p>
     * @param mib The SNMP MIB to which the metadata will be linked.
     */
    public SnmpMibTable(SnmpMib mib) {
        this.theMib= mib;
        setCreationEnabled(false);
    }

    // -------------------------------------------------------------------
    // PUBLIC METHODS
    // -------------------------------------------------------------------

    /**
     * This method is invoked when the creation of a new entry is requested
     * by a remote SNMP manager.
     * <br>By default, remote entry creation is disabled - and this method
     * will not be called. You can dynamically switch the entry creation
     * policy by calling <code>setCreationEnabled(true)</code> and <code>
     * setCreationEnabled(false)</code> on this object.
     * <p><b><i>
     * This method is called internally by the SNMP runtime and you
     * should never need to call it directly. </b></i>However you might want
     * to extend it in order to implement your own specific application
     * behaviour, should the default behaviour not be at your convenience.
     * </p>
     * <p>
     * @param req   The SNMP  subrequest requesting this creation
     * @param rowOid  The OID indexing the conceptual row (entry) for which
     *                the creation was requested.
     * @param depth The position of the columnar object arc in the OIDs
     *              from the varbind list.
     *
     * @exception SnmpStatusException if the entry cannot be created.
     */
    public abstract void createNewEntry(SnmpMibSubRequest req, SnmpOid rowOid,
                                        int depth)
        throws SnmpStatusException;

    /**
     * Tell whether the specific version of this metadata generated
     * by <code>mibgen</code> requires entries to be registered with
     * the MBeanServer. In this case an ObjectName will have to be
     * passed to addEntry() in order for the table to behave correctly
     * (case of the generic metadata).
     * <p>
     * If that version of the metadata does not require entry to be
     * registered, then passing an ObjectName becomes optional (null
     * can be passed instead).
     *
     * @return <code>true</code> if registration is required by this
     *         version of the metadata.
     */
    public abstract boolean isRegistrationRequired();

    /**
     * Tell whether a new entry should be created when a SET operation
     * is received for an entry that does not exist yet.
     *
     * @return true if a new entry must be created, false otherwise.<br>
     *         [default: returns <CODE>false</CODE>]
     **/
    public boolean isCreationEnabled() {
        return creationEnabled;
    }

    /**
     * This method lets you dynamically switch the creation policy.
     *
     * <p>
     * @param remoteCreationFlag Tells whether remote entry creation must
     *        be enabled or disabled.
     * <ul><li>
     * <CODE>setCreationEnabled(true)</CODE> will enable remote entry
     *      creation via SET operations.</li>
     * <li>
     * <CODE>setCreationEnabled(false)</CODE> will disable remote entry
     *      creation via SET operations.</li>
     * <p> By default remote entry creation via SET operation is disabled.
     * </p>
     * </ul>
     **/
    public void setCreationEnabled(boolean remoteCreationFlag) {
        creationEnabled = remoteCreationFlag;
    }

    /**
     * Return <code>true</code> if the conceptual row contains a columnar
     * object used to control creation/deletion of rows in this table.
     * <p>
     * This  columnar object can be either a variable with RowStatus
     * syntax as defined by RFC 2579, or a plain variable whose
     * semantics is table specific.
     * <p>
     * By default, this function returns <code>false</code>, and it is
     * assumed that the table has no such control variable.<br>
     * When <code>mibgen</code> is used over SMIv2 MIBs, it will generate
     * an <code>hasRowStatus()</code> method returning <code>true</code>
     * for each table containing an object with RowStatus syntax.
     * <p>
     * When this method returns <code>false</code> the default mechanism
     * for remote entry creation is used.
     * Otherwise, creation/deletion is performed as specified
     * by the control variable (see getRowAction() for more details).
     * <p>
     * This method is called internally when a SET request involving
     * this table is processed.
     * <p>
     * If you need to implement a control variable which do not use
     * the RowStatus convention as defined by RFC 2579, you should
     * subclass the generated table metadata class in order to redefine
     * this method and make it returns <code>true</code>.<br>
     * You will then have to redefine the isRowStatus(), mapRowStatus(),
     * isRowReady(), and setRowStatus() methods to suit your specific
     * implementation.
     * <p>
     * @return <li><code>true</code> if this table contains a control
     *         variable (eg: a variable with RFC 2579 RowStatus syntax),
     *         </li>
     *         <li><code>false</code> if this table does not contain
     *         any control variable.</li>
     *
     **/
    public boolean hasRowStatus() {
        return false;
    }

    // ---------------------------------------------------------------------
    //
    // Implements the method defined in SnmpMibNode.
    //
    // ---------------------------------------------------------------------
    /**
     * Generic handling of the <CODE>get</CODE> operation.
     * <p> The default implementation of this method is to
     * <ul>
     * <li> check whether the entry exists, and if not register an
     *      exception for each varbind in the list.
     * <li> call the generated
     *      <CODE>get(req,oid,depth+1)</CODE> method. </li>
     * </ul>
     * <p>
     * <pre>
     * public void get(SnmpMibSubRequest req, int depth)
     *    throws SnmpStatusException {
     *    boolean         isnew  = req.isNewEntry();
     *
     *    // if the entry does not exists, then registers an error for
     *    // each varbind involved (nb: this should not happen, since
     *    // the error should already have been detected earlier)
     *    //
     *    if (isnew) {
     *        SnmpVarBind     var = null;
     *        for (Enumeration e= req.getElements(); e.hasMoreElements();) {
     *            var = (SnmpVarBind) e.nextElement();
     *            req.registerGetException(var,noSuchNameException);
     *        }
     *    }
     *
     *    final SnmpOid oid = req.getEntryOid();
     *    get(req,oid,depth+1);
     * }
     * </pre>
     * <p> You should not need to override this method in any cases, because
     * it will eventually call
     * <CODE>get(SnmpMibSubRequest req, int depth)</CODE> on the generated
     * derivative of <CODE>SnmpMibEntry</CODE>. If you need to implement
     * specific policies for minimizing the accesses made to some remote
     * underlying resources, or if you need to implement some consistency
     * checks between the different values provided in the varbind list,
     * you should then rather override
     * <CODE>get(SnmpMibSubRequest req, int depth)</CODE> on the generated
     * derivative of <CODE>SnmpMibEntry</CODE>.
     * <p>
     *
     */
    public void get(SnmpMibSubRequest req, int depth)
        throws SnmpStatusException {

        final boolean         isnew  = req.isNewEntry();
        final SnmpMibSubRequest  r      = req;

        // if the entry does not exists, then registers an error for
        // each varbind involved (nb: should not happen, the error
        // should have been registered earlier)
        if (isnew) {
            SnmpVarBind     var = null;
            for (Enumeration e= r.getElements(); e.hasMoreElements();) {
                var      = (SnmpVarBind) e.nextElement();
                r.registerGetException(var,noSuchInstanceException);
            }
        }

        final SnmpOid     oid    = r.getEntryOid();

        // SnmpIndex   index  = buildSnmpIndex(oid.longValue(false), 0);
        // get(req,index,depth+1);
        //
        get(req,oid,depth+1);
    }

    // ---------------------------------------------------------------------
    //
    // Implements the method defined in SnmpMibNode.
    //
    // ---------------------------------------------------------------------
    /**
     * Generic handling of the <CODE>check</CODE> operation.
     * <p> The default implementation of this method is to
     * <ul>
     * <li> check whether a new entry must be created, and if remote
     *      creation of entries is enabled, create it. </li>
     * <li> call the generated
     *      <CODE>check(req,oid,depth+1)</CODE> method. </li>
     * </ul>
     * <p>
     * <pre>
     * public void check(SnmpMibSubRequest req, int depth)
     *    throws SnmpStatusException {
     *    final SnmpOid     oid    = req.getEntryOid();
     *    final int         action = getRowAction(req,oid,depth+1);
     *
     *    beginRowAction(req,oid,depth+1,action);
     *    check(req,oid,depth+1);
     * }
     * </pre>
     * <p> You should not need to override this method in any cases, because
     * it will eventually call
     * <CODE>check(SnmpMibSubRequest req, int depth)</CODE> on the generated
     * derivative of <CODE>SnmpMibEntry</CODE>. If you need to implement
     * specific policies for minimizing the accesses made to some remote
     * underlying resources, or if you need to implement some consistency
     * checks between the different values provided in the varbind list,
     * you should then rather override
     * <CODE>check(SnmpMibSubRequest req, int depth)</CODE> on the generated
     * derivative of <CODE>SnmpMibEntry</CODE>.
     * <p>
     *
     */
    public void check(SnmpMibSubRequest req, int depth)
        throws SnmpStatusException {
        final SnmpOid     oid    = req.getEntryOid();
        final int         action = getRowAction(req,oid,depth+1);

        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
            SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMibTable.class.getName(),
                    "check", "Calling beginRowAction");
        }

        beginRowAction(req,oid,depth+1,action);

        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
            SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMibTable.class.getName(),
                    "check",
                    "Calling check for " + req.getSize() + " varbinds");
        }

        check(req,oid,depth+1);

        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
            SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMibTable.class.getName(),
                    "check", "check finished");
        }
    }

    // ---------------------------------------------------------------------
    //
    // Implements the method defined in SnmpMibNode.
    //
    // ---------------------------------------------------------------------
    /**
     * Generic handling of the <CODE>set</CODE> operation.
     * <p> The default implementation of this method is to
     * call the generated
     * <CODE>set(req,oid,depth+1)</CODE> method.
     * <p>
     * <pre>
     * public void set(SnmpMibSubRequest req, int depth)
     *    throws SnmpStatusException {
     *    final SnmpOid oid = req.getEntryOid();
     *    final int  action = getRowAction(req,oid,depth+1);
     *
     *    set(req,oid,depth+1);
     *    endRowAction(req,oid,depth+1,action);
     * }
     * </pre>
     * <p> You should not need to override this method in any cases, because
     * it will eventually call
     * <CODE>set(SnmpMibSubRequest req, int depth)</CODE> on the generated
     * derivative of <CODE>SnmpMibEntry</CODE>. If you need to implement
     * specific policies for minimizing the accesses made to some remote
     * underlying resources, or if you need to implement some consistency
     * checks between the different values provided in the varbind list,
     * you should then rather override
     * <CODE>set(SnmpMibSubRequest req, int depth)</CODE> on the generated
     * derivative of <CODE>SnmpMibEntry</CODE>.
     * <p>
     *
     */
    public void set(SnmpMibSubRequest req, int depth)
        throws SnmpStatusException {


        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
            SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMibTable.class.getName(),
                    "set", "Entering set");
        }

        final SnmpOid     oid    = req.getEntryOid();
        final int         action = getRowAction(req,oid,depth+1);

        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
            SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMibTable.class.getName(),
                    "set", "Calling set for " + req.getSize() + " varbinds");
        }

        set(req,oid,depth+1);

        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
            SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMibTable.class.getName(),
                    "set", "Calling endRowAction");
        }

        endRowAction(req,oid,depth+1,action);

        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
            SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMibTable.class.getName(),
                    "set", "RowAction finished");
        }

    }

    /**
     * Add a new entry in this <CODE>SnmpMibTable</CODE>.
     * Also triggers the addEntryCB() callback of the
     * {@link com.sun.jmx.snmp.agent.SnmpTableEntryFactory} interface
     * if this node is bound to a factory.
     *
     * This method assumes that the given entry will not be registered.
     * If the entry is going to be registered, or if ObjectName's are
     * required, then
     * {@link com.sun.jmx.snmp.agent.SnmpMibTable#addEntry(SnmpOid,
     * ObjectName, Object)} should be prefered.
     * <br> This function is mainly provided for backward compatibility.
     *
     * <p>
     * @param rowOid The <CODE>SnmpOid</CODE> identifying the table
     *               row to be added.
     * @param entry The entry to add.
     *
     * @exception SnmpStatusException The entry couldn't be added
     *            at the position identified by the given
     *            <code>rowOid</code>, or this version of the metadata
     *            requires ObjectName's.
     */
     // public void addEntry(SnmpIndex index, Object entry)
     public void addEntry(SnmpOid rowOid, Object entry)
        throws SnmpStatusException {

         addEntry(rowOid, null, entry);
    }

    /**
     * Add a new entry in this <CODE>SnmpMibTable</CODE>.
     * Also triggers the addEntryCB() callback of the
     * {@link com.sun.jmx.snmp.agent.SnmpTableEntryFactory} interface
     * if this node is bound to a factory.
     *
     * <p>
     * @param oid    The <CODE>SnmpOid</CODE> identifying the table
     *               row to be added.
     *
     * @param name  The ObjectName with which this entry is registered.
     *              This parameter can be omitted if isRegistrationRequired()
     *              return false.
     *
     * @param entry The entry to add.
     *
     * @exception SnmpStatusException The entry couldn't be added
     *            at the position identified by the given
     *            <code>rowOid</code>, or if this version of the metadata
     *            requires ObjectName's, and the given name is null.
     */
    // protected synchronized void addEntry(SnmpIndex index, ObjectName name,
    //                                      Object entry)
    public synchronized void addEntry(SnmpOid oid, ObjectName name,
                                      Object entry)
        throws SnmpStatusException {

        if (isRegistrationRequired() == true && name == null)
            throw new SnmpStatusException(SnmpStatusException.badValue);

        if (size == 0) {
            //            indexes.addElement(index);
            // XX oids.addElement(oid);
            insertOid(0,oid);
            if (entries != null)
                entries.addElement(entry);
            if (entrynames != null)
                entrynames.addElement(name);
            size++;

            // triggers callbacks on the entry factory
            //
            if (factory != null) {
                try {
                    factory.addEntryCb(0,oid,name,entry,this);
                } catch (SnmpStatusException x) {
                    removeOid(0);
                    if (entries != null)
                        entries.removeElementAt(0);
                    if (entrynames != null)
                        entrynames.removeElementAt(0);
                    throw x;
                }
            }

            // sends the notifications
            //
            sendNotification(SnmpTableEntryNotification.SNMP_ENTRY_ADDED,
                             (new Date()).getTime(), entry, name);
            return;
        }

        // Get the insertion position ...
        //
        int pos= 0;
        // bug jaw.00356.B : use oid rather than index to get the
        // insertion point.
        //
        pos= getInsertionPoint(oid,true);
        if (pos == size) {
            // Add a new element in the vectors ...
            //
            //            indexes.addElement(index);
            // XX oids.addElement(oid);
            insertOid(tablecount,oid);
            if (entries != null)
                entries.addElement(entry);
            if (entrynames != null)
                entrynames.addElement(name);
            size++;
        } else {
            // Insert new element ...
            //
            try {
                //                indexes.insertElementAt(index, pos);
                // XX oids.insertElementAt(oid, pos);
                insertOid(pos,oid);
                if (entries != null)
                    entries.insertElementAt(entry, pos);
                if (entrynames != null)
                    entrynames.insertElementAt(name,pos);
                size++;
            } catch(ArrayIndexOutOfBoundsException e) {
            }
        }

        // triggers callbacks on the entry factory
        //
        if (factory != null) {
            try {
                factory.addEntryCb(pos,oid,name,entry,this);
            } catch (SnmpStatusException x) {
                removeOid(pos);
                if (entries != null)
                    entries.removeElementAt(pos);
                if (entrynames != null)
                    entrynames.removeElementAt(pos);
                throw x;
            }
        }

        // sends the notifications
        //
        sendNotification(SnmpTableEntryNotification.SNMP_ENTRY_ADDED,
                         (new Date()).getTime(), entry, name);
    }

    /**
     * Remove the specified entry from the table.
     * Also triggers the removeEntryCB() callback of the
     * {@link com.sun.jmx.snmp.agent.SnmpTableEntryFactory} interface
     * if this node is bound to a factory.
     *
     * <p>
     * @param rowOid The <CODE>SnmpOid</CODE> identifying the table
     *               row to remove.
     *
     * @param entry The entry to be removed. This parameter is not used
     *              internally, it is simply passed along to the
     *              removeEntryCB() callback.
     *
     * @exception SnmpStatusException if the specified entry couldn't
     *            be removed (if the given <code>rowOid</code> is not
     *            valid for instance).
     */
    public synchronized void removeEntry(SnmpOid rowOid, Object entry)
        throws SnmpStatusException {
        int pos = findObject(rowOid);
        if (pos == -1)
            return;
        removeEntry(pos,entry);
    }

    /**
     * Remove the specified entry from the table.
     * Also triggers the removeEntryCB() callback of the
     * {@link com.sun.jmx.snmp.agent.SnmpTableEntryFactory} interface
     * if this node is bound to a factory.
     *
     * <p>
     * @param rowOid The <CODE>SnmpOid</CODE> identifying the table
     *               row to remove.
     *
     * @exception SnmpStatusException if the specified entry couldn't
     *            be removed (if the given <code>rowOid</code> is not
     *            valid for instance).
     */
    public void removeEntry(SnmpOid rowOid)
        throws SnmpStatusException {
        int pos = findObject(rowOid);
        if (pos == -1)
            return;
        removeEntry(pos,null);
    }

    /**
     * Remove the specified entry from the table.
     * Also triggers the removeEntryCB() callback of the
     * {@link com.sun.jmx.snmp.agent.SnmpTableEntryFactory} interface
     * if this node is bound to a factory.
     *
     * <p>
     * @param pos The position of the entry in the table.
     *
     * @param entry The entry to be removed. This parameter is not used
     *              internally, it is simply passed along to the
     *              removeEntryCB() callback.
     *
     * @exception SnmpStatusException if the specified entry couldn't
     *            be removed.
     */
    public synchronized void removeEntry(int pos, Object entry)
        throws SnmpStatusException {
        if (pos == -1)
            return;
        if (pos >= size) return;

        Object obj = entry;
        if (entries != null && entries.size() > pos) {
            obj = entries.elementAt(pos);
            entries.removeElementAt(pos);
        }

        ObjectName name = null;
        if (entrynames != null && entrynames.size() > pos) {
            name = entrynames.elementAt(pos);
            entrynames.removeElementAt(pos);
        }

        final SnmpOid rowOid = tableoids[pos];
        removeOid(pos);
        size --;

        if (obj == null) obj = entry;

        if (factory != null)
            factory.removeEntryCb(pos,rowOid,name,obj,this);

        sendNotification(SnmpTableEntryNotification.SNMP_ENTRY_REMOVED,
                         (new Date()).getTime(), obj, name);
    }

    /**
     * Get the entry corresponding to the specified rowOid.
     *
     * <p>
     * @param rowOid The <CODE>SnmpOid</CODE> identifying the
     *        row to be retrieved.
     *
     * @return The entry.
     *
     * @exception SnmpStatusException There is no entry with the specified
     *      <code>rowOid</code> in the table.
     */
    public synchronized Object getEntry(SnmpOid rowOid)
        throws SnmpStatusException {
        int pos= findObject(rowOid);
        if (pos == -1)
            throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
        return entries.elementAt(pos);
    }

    /**
     * Get the ObjectName of the entry corresponding to the
     * specified rowOid.
     * The result of this method is only meaningful if
     * isRegistrationRequired() yields true.
     *
     * <p>
     * @param rowOid The <CODE>SnmpOid</CODE> identifying the table
     *        row whose ObjectName we want to retrieve.
     *
     * @return The object name of the entry.
     *
     * @exception SnmpStatusException There is no entry with the specified
     *      <code>rowOid</code> in the table.
     */
    public synchronized ObjectName getEntryName(SnmpOid rowOid)
        throws SnmpStatusException {
        int pos = findObject(rowOid);
        if (entrynames == null) return null;
        if (pos == -1 || pos >= entrynames.size())
            throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
        return entrynames.elementAt(pos);
    }

    /**
     * Return the entries stored in this table <CODE>SnmpMibTable</CODE>.
     * <p>
     * If the subclass generated by mibgen uses the generic way to access
     * the entries (i.e. if it goes through the MBeanServer) then some of
     * the entries may be <code>null</code>. It all depends whether a non
     * <code>null</code> entry was passed to addEntry().<br>
     * Otherwise, if it uses the standard way (access the entry directly
     * through their standard MBean interface) this array will contain all
     * the entries.
     * <p>
     * @return The entries array.
     */
    public Object[] getBasicEntries() {
        Object[] array= new Object[size];
        entries.copyInto(array);
        return array;
    }

    /**
     * Get the size of the table.
     *
     * @return The number of entries currently registered in this table.
     */
    public int getSize() {
        return size;
    }

    // EVENT STUFF
    //------------

    /**
     * Enable to add an SNMP entry listener to this
     * <CODE>SnmpMibTable</CODE>.
     *
     * <p>
     * @param listener The listener object which will handle the
     *    notifications emitted by the registered MBean.
     *
     * @param filter The filter object. If filter is null, no filtering
     *    will be performed before handling notifications.
     *
     * @param handback The context to be sent to the listener when a
     *    notification is emitted.
     *
     * @exception IllegalArgumentException Listener parameter is null.
     */
    public synchronized void
        addNotificationListener(NotificationListener listener,
                                NotificationFilter filter, Object handback)  {

        // Check listener
        //
        if (listener == null) {
            throw new java.lang.IllegalArgumentException
                ("Listener can't be null") ;
        }

        // looking for listener in handbackTable
        //
        Vector<Object> handbackList =
            handbackTable.get(listener) ;
        Vector<NotificationFilter> filterList =
            filterTable.get(listener) ;
        if ( handbackList == null ) {
            handbackList = new Vector<Object>() ;
            filterList = new Vector<NotificationFilter>() ;
            handbackTable.put(listener, handbackList) ;
            filterTable.put(listener, filterList) ;
        }

        // Add the handback and the filter
        //
        handbackList.addElement(handback) ;
        filterList.addElement(filter) ;
    }

    /**
     * Enable to remove an SNMP entry listener from this
     * <CODE>SnmpMibTable</CODE>.
     *
     * @param listener The listener object which will handle the
     *    notifications emitted by the registered MBean.
     *    This method will remove all the information related to this
     *    listener.
     *
     * @exception ListenerNotFoundException The listener is not registered
     *    in the MBean.
     */
    public synchronized void
        removeNotificationListener(NotificationListener listener)
        throws ListenerNotFoundException {

        // looking for listener in handbackTable
        //
        java.util.Vector handbackList =
            (java.util.Vector) handbackTable.get(listener) ;
        java.util.Vector filterList =
            (java.util.Vector) filterTable.get(listener) ;
        if ( handbackList == null ) {
            throw new ListenerNotFoundException("listener");
        }

        // If handback is null, remove the listener entry
        //
        handbackTable.remove(listener) ;
        filterTable.remove(listener) ;
    }

    /**
     * Return a <CODE>NotificationInfo</CODE> object containing the
     * notification class and the notification type sent by the
     * <CODE>SnmpMibTable</CODE>.
     */
    public MBeanNotificationInfo[] getNotificationInfo() {

        String[] types = {SnmpTableEntryNotification.SNMP_ENTRY_ADDED,
                          SnmpTableEntryNotification.SNMP_ENTRY_REMOVED};

        MBeanNotificationInfo[] notifsInfo = {
            new MBeanNotificationInfo
            (types, "com.sun.jmx.snmp.agent.SnmpTableEntryNotification",
             "Notifications sent by the SnmpMibTable")
        };

        return notifsInfo;
    }


    /**
     * Register the factory through which table entries should
     * be created when remote entry creation is enabled.
     *
     * <p>
     * @param factory The
     *        {@link com.sun.jmx.snmp.agent.SnmpTableEntryFactory} through
     *        which entries will be created when a remote SNMP manager
     *        request the creation of a new entry via an SNMP SET request.
     */
    public void registerEntryFactory(SnmpTableEntryFactory factory) {
        this.factory = factory;
    }

    // ----------------------------------------------------------------------
    // PROTECTED METHODS - RowStatus
    // ----------------------------------------------------------------------

    /**
     * Return true if the columnar object identified by <code>var</code>
     * is used to control the addition/deletion of rows in this table.
     *
     * <p>
     * By default, this method assumes that there is no control variable
     * and always return <code>false</code>
     * <p>
     * If this table was defined using SMIv2, and if it contains a
     * control variable with RowStatus syntax, <code>mibgen</code>
     * will generate a non default implementation for this method
     * that will identify the RowStatus control variable.
     * <p>
     * You will have to redefine this method if you need to implement
     * control variables that do not conform to RFC 2579 RowStatus
     * TEXTUAL-CONVENTION.
     * <p>
     * @param rowOid The <CODE>SnmpOid</CODE> identifying the table
     *               row involved in the operation.
     *
     * @param var The OID arc identifying the involved columnar object.
     *
     * @param userData A contextual object containing user-data.
     *        This object is allocated through the <code>
     *        {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}</code>
     *        for each incoming SNMP request.
     *
     **/
    protected boolean isRowStatus(SnmpOid rowOid, long var,
                                    Object  userData) {
        return false;
    }


    /**
     * Return the RowStatus code value specified in this request.
     * <p>
     * The RowStatus code value should be one of the values defined
     * by {@link com.sun.jmx.snmp.EnumRowStatus}. These codes correspond
     * to RowStatus codes as defined in RFC 2579, plus the <i>unspecified</i>
     * value which is SNMP Runtime specific.
     * <p>
     *
     * @param req    The sub-request that must be handled by this node.
     *
     * @param rowOid The <CODE>SnmpOid</CODE> identifying the table
     *               row involved in the operation.
     *
     * @param depth  The depth reached in the OID tree.
     *
     * @return The RowStatus code specified in this request, if any:
     * <ul>
     * <li>If the specified row does not exist and this table do
     *     not use any variable to control creation/deletion of
     *     rows, then default creation mechanism is assumed and
     *     <i>createAndGo</i> is returned</li>
     * <li>Otherwise, if the row exists and this table do not use any
     *     variable to control creation/deletion of rows,
     *     <i>unspecified</i> is returned.</li>
     * <li>Otherwise, if the request does not contain the control variable,
     *     <i>unspecified</i> is returned.</li>
     * <li>Otherwise, mapRowStatus() is called to extract the RowStatus
     *     code from the SnmpVarBind that contains the control variable.</li>
     * </ul>
     *
     * @exception SnmpStatusException if the value of the control variable
     *            could not be mapped to a RowStatus code.
     *
     * @see com.sun.jmx.snmp.EnumRowStatus
     **/
    protected int getRowAction(SnmpMibSubRequest req, SnmpOid rowOid,
                               int depth)
        throws SnmpStatusException {
        final boolean     isnew  = req.isNewEntry();
        final SnmpVarBind vb = req.getRowStatusVarBind();
        if (vb == null) {
            if (isnew && ! hasRowStatus())
                return EnumRowStatus.createAndGo;
            else return EnumRowStatus.unspecified;
        }

        try {
            return mapRowStatus(rowOid, vb, req.getUserData());
        } catch( SnmpStatusException x) {
            checkRowStatusFail(req, x.getStatus());
        }
        return EnumRowStatus.unspecified;
    }

    /**
     * Map the value of the <code>vbstatus</code> varbind to the
     * corresponding RowStatus code defined in
     * {@link com.sun.jmx.snmp.EnumRowStatus}.
     * These codes correspond to RowStatus codes as defined in RFC 2579,
     * plus the <i>unspecified</i> value which is SNMP Runtime specific.
     * <p>
     * By default, this method assumes that the control variable is
     * an Integer, and it simply returns its value without further
     * analysis.
     * <p>
     * If this table was defined using SMIv2, and if it contains a
     * control variable with RowStatus syntax, <code>mibgen</code>
     * will generate a non default implementation for this method.
     * <p>
     * You will have to redefine this method if you need to implement
     * control variables that do not conform to RFC 2579 RowStatus
     * TEXTUAL-CONVENTION.
     *
     * <p>
     * @param rowOid The <CODE>SnmpOid</CODE> identifying the table
     *               row involved in the operation.
     *
     * @param vbstatus The SnmpVarBind containing the value of the control
     *           variable, as identified by the isRowStatus() method.
     *
     * @param userData A contextual object containing user-data.
     *        This object is allocated through the <code>
     *        {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}</code>
     *        for each incoming SNMP request.
     *
     * @return The RowStatus code mapped from the value contained
     *     in <code>vbstatus</code>.
     *
     * @exception SnmpStatusException if the value of the control variable
     *            could not be mapped to a RowStatus code.
     *
     * @see com.sun.jmx.snmp.EnumRowStatus
     **/
    protected int mapRowStatus(SnmpOid rowOid, SnmpVarBind vbstatus,
                               Object userData)
        throws SnmpStatusException {
        final SnmpValue rsvalue = vbstatus.value;

        if (rsvalue instanceof SnmpInt)
            return ((SnmpInt)rsvalue).intValue();
        else
            throw new SnmpStatusException(
                       SnmpStatusException.snmpRspInconsistentValue);
    }

    /**
     * Set the control variable to the specified <code>newStatus</code>
     * value.
     *
     * <p>
     * This method maps the given <code>newStatus</code> to the appropriate
     * value for the control variable, then sets the control variable in
     * the entry identified by <code>rowOid</code>. It returns the new
     * value of the control variable.
     * <p>
     * By default, it is assumed that there is no control variable so this
     * method does nothing and simply returns <code>null</code>.
     * <p>
     * If this table was defined using SMIv2, and if it contains a
     * control variable with RowStatus syntax, <code>mibgen</code>
     * will generate a non default implementation for this method.
     * <p>
     * You will have to redefine this method if you need to implement
     * control variables that do not conform to RFC 2579 RowStatus
     * TEXTUAL-CONVENTION.
     *
     * <p>
     * @param rowOid The <CODE>SnmpOid</CODE> identifying the table
     *               row involved in the operation.
     *
     * @param newStatus The new status for the row: one of the
     *        RowStatus code defined in
     *        {@link com.sun.jmx.snmp.EnumRowStatus}. These codes
     *        correspond to RowStatus codes as defined in RFC 2579,
     *        plus the <i>unspecified</i> value which is SNMP Runtime specific.
     *
     * @param userData A contextual object containing user-data.
     *        This object is allocated through the <code>
     *        {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}</code>
     *        for each incoming SNMP request.
     *
     * @return The new value of the control variable (usually
     *         <code>new SnmpInt(newStatus)</code>) or <code>null</code>
     *         if the table do not have any control variable.
     *
     * @exception SnmpStatusException If the given <code>newStatus</code>
     *            could not be set on the specified entry, or if the
     *            given <code>newStatus</code> is not valid.
     *
     * @see com.sun.jmx.snmp.EnumRowStatus
     **/
    protected SnmpValue setRowStatus(SnmpOid rowOid, int newStatus,
                                     Object userData)
        throws SnmpStatusException {
        return null;
    }

    /**
     * Tell whether the specified row is ready and can be put in the
     * <i>notInService</i> state.
     * <p>
     * This method is called only once, after all the varbind have been
     * set on a new entry for which <i>createAndWait</i> was specified.
     * <p>
     * If the entry is not yet ready, this method should return false.
     * It will then be the responsibility of the entry to switch its
     * own state to <i>notInService</i> when it becomes ready.
     * No further call to <code>isRowReady()</code> will be made.
     * <p>
     * By default, this method always return true. <br>
     * <code>mibgen</code> will not generate any specific implementation
     * for this method - meaning that by default, a row created using
     * <i>createAndWait</i> will always be placed in <i>notInService</i>
     * state at the end of the request.
     * <p>
     * If this table was defined using SMIv2, and if it contains a
     * control variable with RowStatus syntax, <code>mibgen</code>
     * will generate an implementation for this method that will
     * delegate the work to the metadata class modelling the conceptual
     * row, so that you can override the default behaviour by subclassing
     * that metadata class.
     * <p>
     * You will have to redefine this method if this default mechanism
     * does not suit your needs.
     *
     * <p>
     * @param rowOid The <CODE>SnmpOid</CODE> identifying the table
     *               row involved in the operation.
     *
     * @param userData A contextual object containing user-data.
     *        This object is allocated through the <code>
     *        {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}</code>
     *        for each incoming SNMP request.
     *
     * @return <code>true</code> if the row can be placed in
     *         <i>notInService</i> state.
     *
     * @exception SnmpStatusException An error occured while trying
     *            to retrieve the row status, and the operation should
     *            be aborted.
     *
     * @see com.sun.jmx.snmp.EnumRowStatus
     **/
    protected boolean isRowReady(SnmpOid rowOid, Object userData)
        throws SnmpStatusException {
        return true;
    }

    /**
     * Check whether the control variable of the given row can be
     * switched to the new specified <code>newStatus</code>.
     * <p>
     * This method is called during the <i>check</i> phase of a SET
     * request when the control variable specifies <i>active</i> or
     * <i>notInService</i>.
     * <p>
     * By default it is assumed that nothing prevents putting the
     * row in the requested state, and this method does nothing.
     * It is simply provided as a hook so that specific checks can
     * be implemented.
     * <p>
     * Note that if the actual row deletion fails afterward, the
     * atomicity of the request is no longer guaranteed.
     *
     * <p>
     * @param req    The sub-request that must be handled by this node.
     *
     * @param rowOid The <CODE>SnmpOid</CODE> identifying the table
     *               row involved in the operation.
     *
     * @param depth  The depth reached in the OID tree.
     *
     * @param newStatus The new status for the row: one of the
     *        RowStatus code defined in
     *        {@link com.sun.jmx.snmp.EnumRowStatus}. These codes
     *        correspond to RowStatus codes as defined in RFC 2579,
     *        plus the <i>unspecified</i> value which is SNMP Runtime specific.
     *
     * @exception SnmpStatusException if switching to this new state
     *            would fail.
     *
     **/
    protected void checkRowStatusChange(SnmpMibSubRequest req,
                                        SnmpOid rowOid, int depth,
                                        int newStatus)
        throws SnmpStatusException {

    }

    /**
     * Check whether the specified row can be removed from the table.
     * <p>
     * This method is called during the <i>check</i> phase of a SET
     * request when the control variable specifies <i>destroy</i>
     * <p>
     * By default it is assumed that nothing prevents row deletion
     * and this method does nothing. It is simply provided as a hook
     * so that specific checks can be implemented.
     * <p>
     * Note that if the actual row deletion fails afterward, the
     * atomicity of the request is no longer guaranteed.
     *
     * <p>
     * @param req    The sub-request that must be handled by this node.
     *
     * @param rowOid The <CODE>SnmpOid</CODE> identifying the table
     *               row involved in the operation.
     *
     * @param depth  The depth reached in the OID tree.
     *
     * @exception SnmpStatusException if the row deletion must be
     *            rejected.
     **/
    protected void checkRemoveTableRow(SnmpMibSubRequest req, SnmpOid rowOid,
                                       int depth)
        throws SnmpStatusException {

    }

    /**
     * Remove a table row upon a remote manager request.
     *
     * This method is called internally when <code>getRowAction()</code>
     * yields <i>destroy</i> - i.e.: it is only called when a remote
     * manager requests the removal of a table row.<br>
     * You should never need to call this function directly.
     * <p>
     * By default, this method simply calls <code>removeEntry(rowOid)
     * </code>.
     * <p>
     * You can redefine this method if you need to implement some
     * specific behaviour when a remote row deletion is invoked.
     * <p>
     * Note that specific checks should not be implemented in this
     * method, but rather in <code>checkRemoveTableRow()</code>.
     * If <code>checkRemoveTableRow()</code> succeeds and this method
     * fails afterward, the atomicity of the original SET request can no
     * longer be guaranteed.
     * <p>
     *
     * @param req    The sub-request that must be handled by this node.
     *
     * @param rowOid The <CODE>SnmpOid</CODE> identifying the table
     *               row involved in the operation.
     *
     * @param depth  The depth reached in the OID tree.
     *
     * @exception SnmpStatusException if the actual row deletion fails.
     *            This should not happen since it would break the
     *            atomicity of the SET request. Specific checks should
     *            be implemented in <code>checkRemoveTableRow()</code>
     *            if needed. If the entry does not exists, no exception
     *            is generated and the method simply returns.
     *
     **/
    protected void removeTableRow(SnmpMibSubRequest req, SnmpOid rowOid,
                                  int depth)
        throws SnmpStatusException {

        removeEntry(rowOid);
    }

    /**
     * This method takes care of initial RowStatus handling during the
     * check() phase of a SET request.
     *
     * In particular it will:
     * <ul><li>check that the given <code>rowAction</code> returned by
     *         <code>getRowAction()</code> is valid.</li>
     * <li>Then depending on the <code>rowAction</code> specified it will:
     *     <ul><li>either call <code>createNewEntry()</code> (<code>
     *         rowAction = <i>createAndGo</i> or <i>createAndWait</i>
     *         </code>),</li>
     *     <li>or call <code>checkRemoveTableRow()</code> (<code>
     *         rowAction = <i>destroy</i></code>),</li>
     *     <li>or call <code>checkRowStatusChange()</code> (<code>
     *         rowAction = <i>active</i> or <i>notInService</i></code>),</li>
     *     <li>or generate a SnmpStatusException if the passed <code>
     *         rowAction</code> is not correct.</li>
     * </ul></li></ul>
     * <p>
     * In principle, you should not need to redefine this method.
     * <p>
     * <code>beginRowAction()</code> is called during the check phase
     * of a SET request, before actual checking on the varbind list
     * is performed.
     *
     * <p>
     * @param req    The sub-request that must be handled by this node.
     *
     * @param rowOid The <CODE>SnmpOid</CODE> identifying the table
     *               row involved in the operation.
     *
     * @param depth  The depth reached in the OID tree.
     *
     * @param rowAction The requested action as returned by <code>
     *        getRowAction()</code>: one of the RowStatus codes defined in
     *        {@link com.sun.jmx.snmp.EnumRowStatus}. These codes
     *        correspond to RowStatus codes as defined in RFC 2579,
     *        plus the <i>unspecified</i> value which is SNMP Runtime specific.
     *
     * @exception SnmpStatusException if the specified <code>rowAction</code>
     *            is not valid or cannot be executed.
     *            This should not happen since it would break the
     *            atomicity of the SET request. Specific checks should
     *            be implemented in <code>beginRowAction()</code> if needed.
     *
     * @see com.sun.jmx.snmp.EnumRowStatus
     **/
    protected synchronized void beginRowAction(SnmpMibSubRequest req,
                              SnmpOid rowOid, int depth, int rowAction)
        throws SnmpStatusException {
        final boolean     isnew  = req.isNewEntry();
        final SnmpOid     oid    = rowOid;
        final int         action = rowAction;

        switch (action) {
        case EnumRowStatus.unspecified:
            if (isnew) {
                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                    SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
                            SnmpMibTable.class.getName(),
                            "beginRowAction", "Failed to create row[" +
                            rowOid + "] : RowStatus = unspecified");
                }
                checkRowStatusFail(req,SnmpStatusException.snmpRspNoAccess);
            }
            break;
        case EnumRowStatus.createAndGo:
        case EnumRowStatus.createAndWait:
            if (isnew) {
                if (isCreationEnabled()) {
                    if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                        SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
                                SnmpMibTable.class.getName(),
                                "beginRowAction", "Creating row[" + rowOid +
                                "] : RowStatus = createAndGo | createAndWait");
                    }
                    createNewEntry(req,oid,depth);
                } else {
                    if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                        SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
                                SnmpMibTable.class.getName(),
                                "beginRowAction", "Can't create row[" + rowOid +
                                "] : RowStatus = createAndGo | createAndWait " +
                                "but creation is disabled");
                    }
                    checkRowStatusFail(req,
                       SnmpStatusException.snmpRspNoAccess);
                }
            } else {
                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                    SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
                            SnmpMibTable.class.getName(),
                            "beginRowAction", "Can't create row[" + rowOid +
                            "] : RowStatus = createAndGo | createAndWait " +
                            "but row already exists");
                }
                checkRowStatusFail(req,
                       SnmpStatusException.snmpRspInconsistentValue);
            }
            break;
        case EnumRowStatus.destroy:
            if (isnew) {
                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                    SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
                            SnmpMibTable.class.getName(),
                            "beginRowAction",
                            "Warning: can't destroy row[" + rowOid +
                            "] : RowStatus = destroy but row does not exist");
                }
            } else if (!isCreationEnabled()) {
                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                    SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
                            SnmpMibTable.class.getName(),
                            "beginRowAction",
                            "Can't destroy row[" + rowOid + "] : " +
                            "RowStatus = destroy but creation is disabled");
                }
                checkRowStatusFail(req,SnmpStatusException.snmpRspNoAccess);
            }
            checkRemoveTableRow(req,rowOid,depth);
            break;
        case EnumRowStatus.active:
        case EnumRowStatus.notInService:
            if (isnew) {
                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                    SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
                            SnmpMibTable.class.getName(),
                            "beginRowAction", "Can't switch state of row[" +
                            rowOid + "] : specified RowStatus = active | " +
                            "notInService but row does not exist");
                }
                checkRowStatusFail(req,
                        SnmpStatusException.snmpRspInconsistentValue);
            }
            checkRowStatusChange(req,rowOid,depth,action);
            break;
        case EnumRowStatus.notReady:
        default:
            if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
                        SnmpMibTable.class.getName(),
                        "beginRowAction", "Invalid RowStatus value for row[" +
                        rowOid + "] : specified RowStatus = " + action);
            }
            checkRowStatusFail(req,
                    SnmpStatusException.snmpRspInconsistentValue);
        }
    }

    /**
     * This method takes care of final RowStatus handling during the
     * set() phase of a SET request.
     *
     * In particular it will:
     *     <ul><li>either call <code>setRowStatus(<i>active</i>)</code>
     *         (<code> rowAction = <i>createAndGo</i> or <i>active</i>
     *         </code>),</li>
     *     <li>or call <code>setRowStatus(<i>notInService</i> or <i>
     *         notReady</i>)</code> depending on the result of <code>
     *         isRowReady()</code> (<code>rowAction = <i>createAndWait</i>
     *         </code>),</li>
     *     <li>or call <code>setRowStatus(<i>notInService</i>)</code>
     *         (<code> rowAction = <i>notInService</i></code>),
     *     <li>or call <code>removeTableRow()</code> (<code>
     *         rowAction = <i>destroy</i></code>),</li>
     *     <li>or generate a SnmpStatusException if the passed <code>
     *         rowAction</code> is not correct. This should be avoided
     *         since it would break SET request atomicity</li>
     *     </ul>
     * <p>
     * In principle, you should not need to redefine this method.
     * <p>
     * <code>endRowAction()</code> is called during the set() phase
     * of a SET request, after the actual set() on the varbind list
     * has been performed. The varbind containing the control variable
     * is updated with the value returned by setRowStatus() (if it is
     * not <code>null</code>).
     *
     * <p>
     * @param req    The sub-request that must be handled by this node.
     *
     * @param rowOid The <CODE>SnmpOid</CODE> identifying the table
     *               row involved in the operation.
     *
     * @param depth  The depth reached in the OID tree.
     *
     * @param rowAction The requested action as returned by <code>
     *        getRowAction()</code>: one of the RowStatus codes defined in
     *        {@link com.sun.jmx.snmp.EnumRowStatus}. These codes
     *        correspond to RowStatus codes as defined in RFC 2579,
     *        plus the <i>unspecified</i> value which is SNMP Runtime specific.
     *
     * @exception SnmpStatusException if the specified <code>rowAction</code>
     *            is not valid.
     *
     * @see com.sun.jmx.snmp.EnumRowStatus
     **/
    protected void endRowAction(SnmpMibSubRequest req, SnmpOid rowOid,
                               int depth, int rowAction)
        throws SnmpStatusException {
        final boolean     isnew  = req.isNewEntry();
        final SnmpOid     oid    = rowOid;
        final int         action = rowAction;
        final Object      data   = req.getUserData();
        SnmpValue         value  = null;

        switch (action) {
        case EnumRowStatus.unspecified:
            break;
        case EnumRowStatus.createAndGo:
            if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
                        SnmpMibTable.class.getName(),
                        "endRowAction", "Setting RowStatus to 'active' " +
                        "for row[" + rowOid + "] : requested RowStatus = " +
                        "createAndGo");
            }
            value = setRowStatus(oid,EnumRowStatus.active,data);
            break;
        case EnumRowStatus.createAndWait:
            if (isRowReady(oid,data)) {
                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                    SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
                            SnmpMibTable.class.getName(),
                            "endRowAction",
                            "Setting RowStatus to 'notInService' for row[" +
                            rowOid + "] : requested RowStatus = createAndWait");
                }
                value = setRowStatus(oid,EnumRowStatus.notInService,data);
            } else {
                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                    SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
                            SnmpMibTable.class.getName(),
                            "endRowAction", "Setting RowStatus to 'notReady' " +
                            "for row[" + rowOid + "] : requested RowStatus = " +
                            "createAndWait");
                }
                value = setRowStatus(oid,EnumRowStatus.notReady,data);
            }
            break;
        case EnumRowStatus.destroy:
            if (isnew) {
                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                    SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
                            SnmpMibTable.class.getName(),
                            "endRowAction",
                            "Warning: requested RowStatus = destroy, " +
                            "but row[" + rowOid + "] does not exist");
                }
            } else {
                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                    SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
                            SnmpMibTable.class.getName(),
                            "endRowAction", "Destroying row[" + rowOid +
                            "] : requested RowStatus = destroy");
                }
            }
            removeTableRow(req,oid,depth);
            break;
        case EnumRowStatus.active:
            if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
                        SnmpMibTable.class.getName(),
                        "endRowAction",
                        "Setting RowStatus to 'active' for row[" +
                        rowOid + "] : requested RowStatus = active");
            }
            value = setRowStatus(oid,EnumRowStatus.active,data);
            break;
        case EnumRowStatus.notInService:
            if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
                        SnmpMibTable.class.getName(),
                        "endRowAction",
                        "Setting RowStatus to 'notInService' for row[" +
                        rowOid + "] : requested RowStatus = notInService");
            }
            value = setRowStatus(oid,EnumRowStatus.notInService,data);
            break;
        case EnumRowStatus.notReady:
        default:
            if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
                        SnmpMibTable.class.getName(),
                        "endRowAction", "Invalid RowStatus value for row[" +
                        rowOid + "] : specified RowStatus = " + action);
            }
            setRowStatusFail(req,
                          SnmpStatusException.snmpRspInconsistentValue);
        }
        if (value != null) {
            final SnmpVarBind vb = req.getRowStatusVarBind();
            if (vb != null) vb.value = value;
        }
    }

    // -------------------------------------------------------------------
    // PROTECTED METHODS - get next
    // -------------------------------------------------------------------

    /**
     * Return the next OID arc corresponding to a readable columnar
     * object in the underlying entry OBJECT-TYPE, possibly skipping over
     * those objects that must not or cannot be returned.
     * Calls {@link
     * #getNextVarEntryId(com.sun.jmx.snmp.SnmpOid,long,java.lang.Object)},
     * until
     * {@link #skipEntryVariable(com.sun.jmx.snmp.SnmpOid,long,
     * java.lang.Object,int)} returns false.
     *
     *
     * @param rowOid The OID index of the row involved in the operation.
     *
     * @param var Id of the variable we start from, looking for the next.
     *
     * @param userData A contextual object containing user-data.
     *        This object is allocated through the <code>
     *        {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}</code>
     *        for each incoming SNMP request.
     *
     * @param pduVersion Protocol version of the original request PDU.
     *
     * @return The next columnar object id which can be returned using
     *         the given PDU's protocol version.
     *
     * @exception SnmpStatusException If no id is found after the given id.
     *
     **/
    protected long getNextVarEntryId(SnmpOid rowOid,
                                     long var,
                                     Object userData,
                                     int pduVersion)
        throws SnmpStatusException {

        long varid=var;
        do {
            varid = getNextVarEntryId(rowOid,varid,userData);
        } while (skipEntryVariable(rowOid,varid,userData,pduVersion));

        return varid;
    }

    /**
     * Hook for subclasses.
     * The default implementation of this method is to always return
     * false. Subclasses should redefine this method so that it returns
     * true when:
     * <ul><li>the variable is a leaf that is not instantiated,</li>
     * <li>or the variable is a leaf whose type cannot be returned by that
     *     version of the protocol (e.g. an Counter64 with SNMPv1).</li>
     * </ul>
     *
     * @param rowOid The OID index of the row involved in the operation.
     *
     * @param var Id of the variable we start from, looking for the next.
     *
     * @param userData A contextual object containing user-data.
     *        This object is allocated through the <code>
     *        {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}</code>
     *        for each incoming SNMP request.
     *
     * @param pduVersion Protocol version of the original request PDU.
     *
     * @return true if the variable must be skipped by the get-next
     *         algorithm.
     */
    protected boolean skipEntryVariable(SnmpOid rowOid,
                                        long var,
                                        Object userData,
                                        int pduVersion) {
        return false;
    }

    /**
     * Get the <CODE>SnmpOid</CODE> index of the row that follows
     * the given <CODE>oid</CODE> in the table. The given <CODE>
     * oid</CODE> does not need to be a valid row OID index.
     *
     * <p>
     * @param oid The OID from which the search will begin.
     *
     * @param userData A contextual object containing user-data.
     *        This object is allocated through the <code>
     *        {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}</code>
     *        for each incoming SNMP request.
     *
     * @return The next <CODE>SnmpOid</CODE> index.
     *
     * @exception SnmpStatusException There is no index following the
     *     specified <CODE>oid</CODE> in the table.
     */
    protected SnmpOid getNextOid(SnmpOid oid, Object userData)
        throws SnmpStatusException {

        if (size == 0)
            throw noSuchInstanceException;

        final SnmpOid resOid = oid;

        // Just a simple check to speed up retrieval of last element ...
        //
        // XX SnmpOid last= (SnmpOid) oids.lastElement();
        SnmpOid last= tableoids[tablecount-1];
        if (last.equals(resOid)) {
            // Last element of the table ...
            //
            throw noSuchInstanceException;
        }

        // First find the oid. This will allow to speed up retrieval process
        // during smart discovery of table (using the getNext) as the
        // management station will use the valid index returned during a
        // previous getNext ...
        //

        // Returns the position following the position at which resOid
        // is found, or the position at which resOid should be inserted.
        //
        final int newPos = getInsertionPoint(resOid,false);

        // If the position returned is not out of bound, we will find
        // the next element in the array.
        //
        if (newPos > -1 && newPos < size) {
            try {
                // XX last = (SnmpOid) oids.elementAt(newPos);
                last = tableoids[newPos];
            } catch(ArrayIndexOutOfBoundsException e) {
                throw noSuchInstanceException;
            }
        } else {
            // We are dealing with the last element of the table ..
            //
            throw noSuchInstanceException;
        }


        return last;
    }

    /**
     * Return the first entry OID registered in the table.
     *
     * <p>
     * @param userData A contextual object containing user-data.
     *        This object is allocated through the <code>
     *        {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}</code>
     *        for each incoming SNMP request.
     *
     * @return The <CODE>SnmpOid</CODE> of the first entry in the table.
     *
     * @exception SnmpStatusException If the table is empty.
     */
    protected SnmpOid getNextOid(Object userData)
        throws SnmpStatusException {
        if (size == 0)
            throw noSuchInstanceException;
        // XX return (SnmpOid) oids.firstElement();
        return tableoids[0];
    }

    // -------------------------------------------------------------------
    // Abstract Protected Methods
    // -------------------------------------------------------------------

    /**
     * This method is used internally and is implemented by the
     * <CODE>SnmpMibTable</CODE> subclasses generated by <CODE>mibgen</CODE>.
     *
     * <p> Return the next OID arc corresponding to a readable columnar
     *     object in the underlying entry OBJECT-TYPE.</p>
     *
     * <p>
     * @param rowOid The OID index of the row involved in the operation.
     *
     * @param var Id of the variable we start from, looking for the next.
     *
     * @param userData A contextual object containing user-data.
     *        This object is allocated through the <code>
     *        {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}</code>
     *        for each incoming SNMP request.
     *
     * @return The next columnar object id.
     *
     * @exception SnmpStatusException If no id is found after the given id.
     *
     **/
    abstract protected long getNextVarEntryId(SnmpOid rowOid, long var,
                                              Object userData)
        throws SnmpStatusException;

    /**
     * This method is used internally and is implemented by the
     * <CODE>SnmpMibTable</CODE> subclasses generated by <CODE>mibgen</CODE>.
     *
     * <p>
     * @param rowOid The OID index of the row involved in the operation.
     *
     * @param var The var we want to validate.
     *
     * @param userData A contextual object containing user-data.
     *        This object is allocated through the <code>
     *        {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}</code>
     *        for each incoming SNMP request.
     *
     * @exception SnmpStatusException If this id is not valid.
     *
     */
    abstract protected void validateVarEntryId(SnmpOid rowOid, long var,
                                               Object userData)
        throws SnmpStatusException;

    /**
     *
     * This method is used internally and is implemented by the
     * <CODE>SnmpMibTable</CODE> subclasses generated by <CODE>mibgen</CODE>.
     *
     * <p>
     * @param rowOid The OID index of the row involved in the operation.
     *
     * @param var The OID arc.
     *
     * @param userData A contextual object containing user-data.
     *        This object is allocated through the <code>
     *        {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}</code>
     *        for each incoming SNMP request.
     *
     * @exception SnmpStatusException If this id is not valid.
     *
     */
    abstract protected boolean isReadableEntryId(SnmpOid rowOid, long var,
                                                 Object userData)
        throws SnmpStatusException;

    /**
     * This method is used internally and is implemented by the
     * <CODE>SnmpMibTable</CODE> subclasses generated by <CODE>mibgen</CODE>.
     */
    abstract protected void get(SnmpMibSubRequest req,
                                SnmpOid rowOid, int depth)
        throws SnmpStatusException;

    /**
     * This method is used internally and is implemented by the
     * <CODE>SnmpMibTable</CODE> subclasses generated by <CODE>mibgen</CODE>.
     */
    abstract protected void check(SnmpMibSubRequest req,
                                  SnmpOid rowOid, int depth)
        throws SnmpStatusException;

    /**
     * This method is used internally and is implemented by the
     * <CODE>SnmpMibTable</CODE> subclasses generated by <CODE>mibgen</CODE>.
     */
    abstract protected void set(SnmpMibSubRequest req,
                                SnmpOid rowOid, int depth)
        throws SnmpStatusException;

    // ----------------------------------------------------------------------
    // PACKAGE METHODS
    // ----------------------------------------------------------------------

    /**
     * Get the <CODE>SnmpOid</CODE> index of the row that follows the
     * index extracted from the specified OID array.
     * Builds the SnmpOid corresponding to the row OID and calls
     * <code>getNextOid(oid,userData)</code>;
     *
     * <p>
     * @param oid The OID array.
     *
     * @param pos The position in the OID array at which the index starts.
     *
     * @param userData A contextual object containing user-data.
     *        This object is allocated through the <code>
     *        {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}</code>
     *        for each incoming SNMP request.
     *
     * @return The next <CODE>SnmpOid</CODE>.
     *
     * @exception SnmpStatusException There is no index following the
     *     specified one in the table.
     */
    SnmpOid getNextOid(long[] oid, int pos, Object userData)
        throws SnmpStatusException {

        // Construct the sub-oid starting at pos.
        // This sub-oid correspond to the oid part just after the entry
        // variable oid.
        //
        final SnmpOid resOid = new SnmpEntryOid(oid,pos);

        return getNextOid(resOid,userData);
    }

    // ---------------------------------------------------------------------
    //
    // Register an exception when checking the RowStatus variable
    //
    // ---------------------------------------------------------------------

    final static void checkRowStatusFail(SnmpMibSubRequest req,
                                         int errorStatus)
        throws SnmpStatusException {
        final SnmpVarBind statusvb  = req.getRowStatusVarBind();
        final SnmpStatusException x = new SnmpStatusException(errorStatus);
        req.registerCheckException(statusvb,x);
    }

    // ---------------------------------------------------------------------
    //
    // Register an exception when checking the RowStatus variable
    //
    // ---------------------------------------------------------------------

    final static void setRowStatusFail(SnmpMibSubRequest req,
                                       int errorStatus)
        throws SnmpStatusException {
        final SnmpVarBind statusvb  = req.getRowStatusVarBind();
        final SnmpStatusException x = new SnmpStatusException(errorStatus);
        req.registerSetException(statusvb,x);
    }

    // ---------------------------------------------------------------------
    //
    // Implements the method defined in SnmpMibNode.
    //
    // ---------------------------------------------------------------------
    final synchronized void findHandlingNode(SnmpVarBind varbind,
                                             long[] oid, int depth,
                                             SnmpRequestTree handlers)
        throws SnmpStatusException {

        final int  length = oid.length;

        if (handlers == null)
            throw new SnmpStatusException(SnmpStatusException.snmpRspGenErr);

        if (depth >= length)
            throw new SnmpStatusException(SnmpStatusException.noAccess);

        if (oid[depth] != nodeId)
            throw new SnmpStatusException(SnmpStatusException.noAccess);

        if (depth+2 >= length)
            throw new SnmpStatusException(SnmpStatusException.noAccess);

        // Checks that the oid is valid
        // validateOid(oid,depth);

        // Gets the part of the OID that identifies the entry
        final SnmpOid entryoid = new SnmpEntryOid(oid, depth+2);

        // Finds the entry: false means that the entry does not exists
        final Object data = handlers.getUserData();
        final boolean hasEntry = contains(entryoid, data);

        // Fails if the entry is not found and the table does not
        // not support creation.
        // We know that the entry does not exists if (isentry == false).
        if (!hasEntry) {
            if (!handlers.isCreationAllowed())
                // we're not doing a set
                throw noSuchInstanceException;
            else if (!isCreationEnabled())
                // we're doing a set but creation is disabled.
                throw new
                    SnmpStatusException(SnmpStatusException.snmpRspNoAccess);
        }

        final long   var  = oid[depth+1];

        // Validate the entry id
        if (hasEntry) {
            // The entry already exists - validate the id
            validateVarEntryId(entryoid,var,data);
        }

        // Registers this node for the identified entry.
        //
        if (handlers.isSetRequest() && isRowStatus(entryoid,var,data))

            // We only try to identify the RowStatus for SET operations
            //
            handlers.add(this,depth,entryoid,varbind,(!hasEntry),varbind);

        else
            handlers.add(this,depth,entryoid,varbind,(!hasEntry));
    }


    // ---------------------------------------------------------------------
    //
    // Implements the method defined in SnmpMibNode. The algorithm is very
    // largely inspired from the original getNext() method.
    //
    // ---------------------------------------------------------------------
    final synchronized long[] findNextHandlingNode(SnmpVarBind varbind,
                                      long[] oid, int pos, int depth,
                                      SnmpRequestTree handlers,
                                      AcmChecker checker)
        throws SnmpStatusException {
            int length = oid.length;

            if (handlers == null)
            // This should be considered as a genErr, but we do not want to
            // abort the whole request, so we're going to throw
            // a noSuchObject...
            //
            throw noSuchObjectException;

            final Object data = handlers.getUserData();
            final int pduVersion = handlers.getRequestPduVersion();

            long var= -1;

            // If the querried oid contains less arcs than the OID of the
            // xxxEntry object, we must return the first leaf under the
            // first columnar object: the best way to do that is to reset
            // the queried oid:
            //   oid[0] = nodeId (arc of the xxxEntry object)
            //   pos    = 0 (points to the arc of the xxxEntry object)
            // then we just have to proceed...
            //
            if (pos >= length) {
                // this will have the side effect to set
                //    oid[pos] = nodeId
                // and
                //    (pos+1) = length
                // so we won't fall into the "else if" cases below -
                // so using "else if" rather than "if ..." is guaranteed
                // to be safe.
                //
                oid = new long[1];
                oid[0] = nodeId;
                pos = 0;
                length = 1;
            } else if (oid[pos] > nodeId) {
                // oid[pos] is expected to be the id of the xxxEntry ...
                // The id requested is greater than the id of the xxxEntry,
                // so we won't find the next element in this table... (any
                // element in this table will have a smaller OID)
                //
                throw noSuchObjectException;
            } else if (oid[pos] < nodeId) {
                // we must return the first leaf under the first columnar
                // object, so we are back to our first case where pos was
                // out of bounds... => reset the oid to contain only the
                // arc of the xxxEntry object.
                //
                oid = new long[1];
                oid[0] = nodeId;
                pos = 0;
                length = 0;
            } else if ((pos + 1) < length) {
                // The arc at the position "pos+1" is the id of the columnar
                // object (ie: the id of the variable in the table entry)
                //
                var = oid[pos+1];
            }

            // Now that we've got everything right we can begin.
            SnmpOid entryoid = null ;

            if (pos == (length - 1)) {
                // pos points to the last arc in the oid, and this arc is
                // guaranteed to be the xxxEntry id (we have handled all
                // the other possibilities before)
                //
                // We must therefore return the first leaf below the first
                // columnar object in the table.
                //
                // Get the first index. If an exception is raised,
                // then it means that the table is empty. We thus do not
                // have to catch the exception - we let it propagate to
                // the caller.
                //
                entryoid = getNextOid(data);
                var = getNextVarEntryId(entryoid,var,data,pduVersion);
            } else if ( pos == (length-2)) {
                // In that case we have (pos+1) = (length-1), so pos
                // points to the arc of the querried variable (columnar object).
                // Since the requested oid stops there, it means we have
                // to return the first leaf under this columnar object.
                //
                // So we first get the first index:
                // Note: if this raises an exception, this means that the table
                // is empty, so we can let the exception propagate to the caller.
                //
                entryoid = getNextOid(data);

                // XXX revisit: not exactly perfect:
                //     a specific row could be empty.. But we don't know
                //     how to make the difference! => tradeoff holes
                //     in tables can't be properly supported (all rows
                //     must have the same holes)
                //
                if (skipEntryVariable(entryoid,var,data,pduVersion)) {
                    var = getNextVarEntryId(entryoid,var,data,pduVersion);
                }
            } else {

                // So now there remain one last case, namely: some part of the
                // index is provided by the oid...
                // We build a possibly incomplete and invalid index from
                // the OID.
                // The piece of index provided should begin at pos+2
                //   oid[pos]   = id of the xxxEntry object,
                //   oid[pos+1] = id of the columnar object,
                //   oid[pos+2] ... oid[length-1] = piece of index.
                //

                // We get the next index following the provided index.
                // If this raises an exception, then it means that we have
                // reached the last index in the table, and we must then
                // try with the next columnar object.
                //
                // Bug fix 4269251
                // The SnmpIndex is defined to contain a valid oid:
                // this is not an SNMP requirement for the getNext request.
                // So we no more use the SnmpIndex but directly the SnmpOid.
                //
                try {
                    entryoid = getNextOid(oid, pos + 2, data);

                    // If the variable must ne skipped, fall through...
                    //
                    // XXX revisit: not exactly perfect:
                    //     a specific row could be empty.. But we don't know
                    //     how to make the difference! => tradeoff holes
                    //     in tables can't be properly supported (all rows
                    //     must have the same holes)
                    //
                    if (skipEntryVariable(entryoid,var,data,pduVersion))
                        throw noSuchObjectException;
                } catch(SnmpStatusException se) {
                    entryoid = getNextOid(data);
                    var = getNextVarEntryId(entryoid,var,data,pduVersion);
                }
            }

            return findNextAccessibleOid(entryoid,
                                         varbind,
                                         oid,
                                         depth,
                                         handlers,
                                         checker,
                                         data,
                                         var);
        }

    private long[] findNextAccessibleOid(SnmpOid entryoid,
                                         SnmpVarBind varbind,long[] oid,
                                         int depth, SnmpRequestTree handlers,
                                         AcmChecker checker, Object data,
                                         long var)
        throws SnmpStatusException {
        final int pduVersion = handlers.getRequestPduVersion();

        // Loop on each var (column)
        while(true) {
            // This should not happen. If it happens, (bug, or customized
            // methods returning garbage instead of raising an exception),
            // it probably means that there is nothing to return anyway.
            // So we throw the exception.
            // => will skip to next node in the MIB tree.
            //
            if (entryoid == null || var == -1 ) throw noSuchObjectException;


            // So here we know both the row (entryoid) and the column (var)
            //

            try {
                // Raising an exception here will make the catch() clause
                // switch to the next variable. If `var' is not readable
                // for this specific entry, it is not readable for any
                // other entry => skip to next column.
                //
                if (!isReadableEntryId(entryoid,var,data))
                    throw noSuchObjectException;

                // Prepare the result and the ACM checker.
                //
                final long[] etable  = entryoid.longValue(false);
                final int    elength = etable.length;
                final long[] result  = new long[depth + 2 + elength];
                result[0] = -1 ; // Bug detector!

                // Copy the entryOid at the end of `result'
                //
                java.lang.System.arraycopy(etable, 0, result,
                                           depth+2, elength);

                // Set the node Id and var Id in result.
                //
                result[depth] = nodeId;
                result[depth+1] = var;

                // Append nodeId.varId.<rowOid> to ACM checker.
                //
                checker.add(depth,result,depth,elength+2);

                // No we're going to ACM check our OID.
                try {
                    checker.checkCurrentOid();

                    // No exception thrown by checker => this is all OK!
                    // we have it: register the handler and return the
                    // result.
                    //
                    handlers.add(this,depth,entryoid,varbind,false);
                    return result;
                } catch(SnmpStatusException e) {
                    // Skip to the next entry. If an exception is
                    // thrown, will be catch by enclosing catch
                    // and a skip is done to the next var.
                    //
                    entryoid = getNextOid(entryoid, data);
                } finally {
                    // Clean the checker.
                    //
                    checker.remove(depth,elength+2);
                }
            } catch(SnmpStatusException e) {
                // Catching an exception here means we have to skip to the
                // next column.
                //
                // Back to the first row.
                entryoid = getNextOid(data);

                // Find out the next column.
                //
                var = getNextVarEntryId(entryoid,var,data,pduVersion);

            }

            // This should not happen. If it happens, (bug, or customized
            // methods returning garbage instead of raising an exception),
            // it probably means that there is nothing to return anyway.
            // No need to continue, we throw an exception.
            // => will skip to next node in the MIB tree.
            //
            if (entryoid == null || var == -1 )
                throw noSuchObjectException;
        }
    }


    /**
     * Validate the specified OID.
     *
     * <p>
     * @param oid The OID array.
     *
     * @param pos The position in the array.
     *
     * @exception SnmpStatusException If the validation fails.
     */
    final void validateOid(long[] oid, int pos) throws SnmpStatusException {
        final int length= oid.length;

        // Control the length of the oid
        //
        if (pos +2 >= length)
            throw noSuchInstanceException;

        // Check that the entry identifier is specified
        //
        if (oid[pos] != nodeId)
            throw noSuchObjectException;

    }

    // ----------------------------------------------------------------------
    // PRIVATE METHODS
    // ----------------------------------------------------------------------

    /**
     * Enable this <CODE>SnmpMibTable</CODE> to send a notification.
     *
     * <p>
     * @param notification The notification to send.
     */
    private synchronized void sendNotification(Notification notification) {

        // loop on listener
        //
        for(java.util.Enumeration k = handbackTable.keys();
            k.hasMoreElements(); ) {

            NotificationListener listener =
                (NotificationListener) k.nextElement();

            // Get the associated handback list and the associated filter list
            //
            java.util.Vector handbackList =
                (java.util.Vector) handbackTable.get(listener) ;
            java.util.Vector filterList =
                (java.util.Vector) filterTable.get(listener) ;

            // loop on handback
            //
            java.util.Enumeration f = filterList.elements();
            for(java.util.Enumeration h = handbackList.elements();
                h.hasMoreElements(); ) {

                Object handback = h.nextElement();
                NotificationFilter filter =
                    (NotificationFilter)f.nextElement();

                if ((filter == null) ||
                     (filter.isNotificationEnabled(notification))) {

                    listener.handleNotification(notification,handback) ;
                }
            }
        }
    }

    /**
     * This method is used by the SnmpMibTable to create and send a table
     * entry notification to all the listeners registered for this kind of
     * notification.
     *
     * <p>
     * @param type The notification type.
     *
     * @param timeStamp The notification emission date.
     *
     * @param entry The entry object.
     */
    private void sendNotification(String type, long timeStamp,
                                  Object entry, ObjectName name) {

        synchronized(this) {
            sequenceNumber = sequenceNumber + 1;
        }

        SnmpTableEntryNotification notif =
            new SnmpTableEntryNotification(type, this, sequenceNumber,
                                           timeStamp, entry, name);

        this.sendNotification(notif) ;
    }

    /**
     * Return true if the entry identified by the given OID index
     * is contained in this table.
     * <p>
     * <b>Do not call this method directly</b>.
     * <p>
     * This method is provided has a hook for subclasses.
     * It is called when a get/set request is received in order to
     * determine whether the specified entry is contained in the table.
     * You may want to override this method if you need to perform e.g.
     * lazy evaluation of tables (you need to update the table when a
     * request is received) or if your table is virtual.
     * <p>
     * Note that this method is called by the Runtime from within a
     * synchronized block.
     *
     * @param oid The index part of the OID we're looking for.
     * @param userData A contextual object containing user-data.
     *        This object is allocated through the <code>
     *        {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}</code>
     *        for each incoming SNMP request.
     *
     * @return <code>true</code> if the entry is found, <code>false</code>
     *         otherwise.
     *
     * @since 1.5
     **/
    protected boolean contains(SnmpOid oid, Object userData) {
        return (findObject(oid) > -1);
    }

    /**
     * Look for the given oid in the OID table (tableoids) and returns
     * its position.
     *
     * <p>
     * @param oid The OID we're looking for.
     *
     * @return The position of the OID in the table. -1 if the given
     *         OID was not found.
     *
     **/
    private final int findObject(SnmpOid oid) {
        int low= 0;
        int max= size - 1;
        SnmpOid pos;
        int comp;
        int curr= low + (max-low)/2;
        //System.out.println("Try to retrieve: " + oid.toString());
        while (low <= max) {

            // XX pos = (SnmpOid) oids.elementAt(curr);
            pos = tableoids[curr];

            //System.out.println("Compare with" + pos.toString());
            // never know ...we might find something ...
            //
            comp = oid.compareTo(pos);
            if (comp == 0)
                return curr;

            if (oid.equals(pos) == true) {
                return curr;
            }
            if (comp > 0) {
                low = curr + 1;
            } else {
                max = curr - 1;
            }
            curr = low + (max-low)/2;
        }
        return -1;
    }

    /**
     * Search the position at which the given oid should be inserted
     * in the OID table (tableoids).
     *
     * <p>
     * @param oid The OID we would like to insert.
     *
     * @return The position at which the OID should be inserted in
     *         the table.
     *
     * @exception SnmpStatusException if the OID is already present in the
     *            table.
     *
     **/
    private final int getInsertionPoint(SnmpOid oid)
        throws SnmpStatusException {
        return getInsertionPoint(oid, true);
    }

    /**
     * Search the position at which the given oid should be inserted
     * in the OID table (tableoids).
     *
     * <p>
     * @param oid The OID we would like to insert.
     *
     * @param fail Tells whether a SnmpStatusException must be generated
     *             if the given OID is already present in the table.
     *
     * @return The position at which the OID should be inserted in
     *         the table. When the OID is found, it returns the next
     *         position. Note that it is not valid to insert twice the
     *         same OID. This feature is only an optimization to improve
     *         the getNextOid() behaviour.
     *
     * @exception SnmpStatusException if the OID is already present in the
     *            table and <code>fail</code> is <code>true</code>.
     *
     **/
    private final int getInsertionPoint(SnmpOid oid, boolean fail)
        throws SnmpStatusException {

        final int failStatus = SnmpStatusException.snmpRspNotWritable;
        int low= 0;
        int max= size - 1;
        SnmpOid pos;
        int comp;
        int curr= low + (max-low)/2;
        while (low <= max) {

            // XX pos= (SnmpOid) oids.elementAt(curr);
            pos= tableoids[curr];

            // never know ...we might find something ...
            //
            comp= oid.compareTo(pos);

            if (comp == 0) {
                if (fail)
                    throw new SnmpStatusException(failStatus,curr);
                else
                    return curr+1;
            }

            if (comp>0) {
                low= curr +1;
            } else {
                max= curr -1;
            }
            curr= low + (max-low)/2;
        }
        return curr;
    }

    /**
     * Remove the OID located at the given position.
     *
     * <p>
     * @param pos The position at which the OID to be removed is located.
     *
     **/
    private final void removeOid(int pos) {
        if (pos >= tablecount) return;
        if (pos < 0) return;
        final int l1 = --tablecount-pos;
        tableoids[pos] = null;
        if (l1 > 0)
            java.lang.System.arraycopy(tableoids,pos+1,tableoids,pos,l1);
        tableoids[tablecount] = null;
    }

    /**
     * Insert an OID at the given position.
     *
     * <p>
     * @param oid The OID to be inserted in the table
     * @param pos The position at which the OID to be added is located.
     *
     **/
    private final void insertOid(int pos, SnmpOid oid) {
        if (pos >= tablesize || tablecount == tablesize) {
                // Vector must be enlarged

                // Save old vector
                final SnmpOid[] olde = tableoids;

                // Allocate larger vectors
                tablesize += Delta;
                tableoids = new SnmpOid[tablesize];

                // Check pos validity
                if (pos > tablecount) pos = tablecount;
                if (pos < 0) pos = 0;

                final int l1 = pos;
                final int l2 = tablecount - pos;

                // Copy original vector up to `pos'
                if (l1 > 0)
                    java.lang.System.arraycopy(olde,0,tableoids,0,l1);

                // Copy original vector from `pos' to end, leaving
                // an empty room at `pos' in the new vector.
                if (l2 > 0)
                    java.lang.System.arraycopy(olde,l1,tableoids,
                                               l1+1,l2);

            } else if (pos < tablecount) {
                // Vector is large enough to accomodate one additional
                // entry.
                //
                // Shift vector, making an empty room at `pos'

                java.lang.System.arraycopy(tableoids,pos,tableoids,
                                           pos+1,tablecount-pos);
            }

            // Fill the gap at `pos'
            tableoids[pos]  = oid;
            tablecount++;
    }


    // ----------------------------------------------------------------------
    // PROTECTED VARIABLES
    // ----------------------------------------------------------------------

    /**
     * The id of the contained entry object.
     * @serial
     */
    protected int nodeId=1;

    /**
     * The MIB to which the metadata is linked.
     * @serial
     */
    protected SnmpMib theMib;

    /**
     * <CODE>true</CODE> if remote creation of entries via SET operations
     * is enabled.
     * [default value is <CODE>false</CODE>]
     * @serial
     */
    protected boolean creationEnabled = false;

    /**
     * The entry factory
     */
    protected SnmpTableEntryFactory factory = null;

    // ----------------------------------------------------------------------
    // PRIVATE VARIABLES
    // ----------------------------------------------------------------------

    /**
     * The number of elements in the table.
     * @serial
     */
    private int size=0;

    /**
     * The list of indexes.
     * @serial
     */
    //    private Vector indexes= new Vector();

    /**
     * The list of OIDs.
     * @serial
     */
    // private Vector oids= new Vector();
    private final static int Delta = 16;
    private int     tablecount     = 0;
    private int     tablesize      = Delta;
    private SnmpOid tableoids[]    = new SnmpOid[tablesize];

    /**
     * The list of entries.
     * @serial
     */
    private final Vector<Object> entries= new Vector<Object>();

    /**
     * The list of object names.
     * @serial
     */
    private final Vector<ObjectName> entrynames= new Vector<ObjectName>();

    /**
     * Callback handlers
     */
    // final Vector callbacks = new Vector();

    /**
     * Listener hastable containing the hand-back objects.
     */
    private Hashtable<NotificationListener, Vector<Object>> handbackTable =
            new Hashtable<NotificationListener, Vector<Object>>();

    /**
     * Listener hastable containing the filter objects.
     */
    private Hashtable<NotificationListener, Vector<NotificationFilter>>
            filterTable =
            new Hashtable<NotificationListener, Vector<NotificationFilter>>();

    // PACKAGE VARIABLES
    //------------------
    /**
     * SNMP table sequence number.
     * The default value is set to 0.
     */
    transient long sequenceNumber = 0;
}
