Initial load
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpEntryOid.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpEntryOid.java
new file mode 100644
index 0000000..809a42b
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpEntryOid.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package com.sun.jmx.snmp.agent;
+
+import com.sun.jmx.snmp.SnmpOid;
+
+/**
+ * This class only adds a new constructor to SnmpOid...
+ *
+ **/
+class SnmpEntryOid extends SnmpOid {
+    private static final long serialVersionUID = 9212653887791059564L;
+
+    /**
+     * Constructs a new <CODE>SnmpOid</CODE> from the specified
+     * component array, starting at given position.
+     *
+     * @param oid   The original OID array
+     * @param start The position at which to begin.
+     *
+     **/
+    public SnmpEntryOid(long[] oid, int start) {
+        final int subLength = oid.length - start;
+        final long[] subOid = new long[subLength];
+        java.lang.System.arraycopy(oid, start, subOid, 0, subLength) ;
+        components = subOid;
+        componentCount = subLength;
+    }
+}
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpErrorHandlerAgent.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpErrorHandlerAgent.java
new file mode 100644
index 0000000..e887eab
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpErrorHandlerAgent.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2001-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.jmx.snmp.agent;
+
+import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.logging.Level;
+
+import javax.management.ObjectName;
+import javax.management.MBeanServer;
+
+import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER;
+import com.sun.jmx.snmp.SnmpStatusException;
+import com.sun.jmx.snmp.SnmpDefinitions;
+import com.sun.jmx.snmp.SnmpVarBind;
+
+/**
+ * A simple MIB agent that implements SNMP calls (get, set, getnext and getbulk) in a way that only errors or exceptions are returned. Every call done on this agent fails. Error handling is done according to the manager's SNMP protocol version.
+ * <P>It is used by <CODE>SnmpAdaptorServer</CODE> for its default agent behavior. When a received Oid doesn't match, this agent is called to fill the result list with errors.</P>
+ * <p><b>This API is a Sun Microsystems internal API  and is subject
+ * to change without notice.</b></p>
+ * @since 1.5
+ *
+ */
+
+public class SnmpErrorHandlerAgent extends SnmpMibAgent
+        implements Serializable {
+    private static final long serialVersionUID = 7751082923508885650L;
+
+    public SnmpErrorHandlerAgent() {}
+
+    /**
+     * Initializes the MIB (with no registration of the MBeans into the
+     * MBean server). Does nothing.
+     *
+     * @exception IllegalAccessException The MIB cannot be initialized.
+     */
+
+    public void init() throws IllegalAccessException {
+    }
+
+    /**
+     * Initializes the MIB but each single MBean representing the MIB
+     * is inserted into the MBean server.
+     *
+     * @param server The MBean server to register the service with.
+     * @param name The object name.
+     *
+     * @return The passed name paramter.
+     *
+     * @exception java.lang.Exception
+     */
+
+    public ObjectName preRegister(MBeanServer server, ObjectName name)
+        throws Exception {
+        return name;
+    }
+
+    /**
+     * Gets the root object identifier of the MIB.
+     * <P>The root object identifier is the object identifier uniquely
+     * identifying the MIB.
+     *
+     * @return The returned oid is null.
+     */
+
+    public long[] getRootOid() {
+        return null;
+    }
+
+    /**
+     * Processes a <CODE>get</CODE> operation. It will throw an exception for V1 requests or it will set exceptions within the list for V2 requests.
+     *
+     * @param inRequest The SnmpMibRequest object holding the list of variable to be retrieved.
+     *
+     * @exception SnmpStatusException An error occured during the operation.
+     */
+
+    public void get(SnmpMibRequest inRequest) throws SnmpStatusException {
+
+        SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
+                SnmpErrorHandlerAgent.class.getName(),
+                "get", "Get in Exception");
+
+        if(inRequest.getVersion() == SnmpDefinitions.snmpVersionOne)
+            throw new SnmpStatusException(SnmpStatusException.noSuchName);
+
+        Enumeration l = inRequest.getElements();
+        while(l.hasMoreElements()) {
+            SnmpVarBind varbind = (SnmpVarBind) l.nextElement();
+            varbind.setNoSuchObject();
+        }
+    }
+
+    /**
+     * Checks if a <CODE>set</CODE> operation can be performed.
+     * If the operation can not be performed, the method should emit a
+     * <CODE>SnmpStatusException</CODE>.
+     *
+     * @param inRequest The SnmpMibRequest object holding the list of variables to
+     *            be set. This list is composed of
+     *            <CODE>SnmpVarBind</CODE> objects.
+     *
+     * @exception SnmpStatusException The <CODE>set</CODE> operation
+     *    cannot be performed.
+     */
+
+    public void check(SnmpMibRequest inRequest) throws SnmpStatusException {
+
+        SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
+                SnmpErrorHandlerAgent.class.getName(),
+                "check", "Check in Exception");
+
+        throw new SnmpStatusException(SnmpDefinitions.snmpRspNotWritable);
+    }
+
+    /**
+     * Processes a <CODE>set</CODE> operation. Should never be called (check previously called having failed).
+     *
+     * @param inRequest The SnmpMibRequest object holding the list of variable to be set.
+     *
+     * @exception SnmpStatusException An error occured during the operation.
+     */
+
+    public void set(SnmpMibRequest inRequest) throws SnmpStatusException {
+
+        SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
+                SnmpErrorHandlerAgent.class.getName(),
+                "set", "Set in Exception, CANNOT be called");
+
+        throw new SnmpStatusException(SnmpDefinitions.snmpRspNotWritable);
+    }
+
+    /**
+     * Processes a <CODE>getNext</CODE> operation. It will throw an exception for V1 requests or it will set exceptions within the list for V2 requests..
+     *
+     * @param inRequest The SnmpMibRequest object holding the list of variables to be retrieved.
+     *
+     * @exception SnmpStatusException An error occured during the operation.
+     */
+
+    public void getNext(SnmpMibRequest inRequest) throws SnmpStatusException {
+
+        SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
+                SnmpErrorHandlerAgent.class.getName(),
+                "getNext", "GetNext in Exception");
+
+        if(inRequest.getVersion() == SnmpDefinitions.snmpVersionOne)
+            throw new SnmpStatusException(SnmpStatusException.noSuchName);
+
+        Enumeration l = inRequest.getElements();
+        while(l.hasMoreElements()) {
+            SnmpVarBind varbind = (SnmpVarBind) l.nextElement();
+            varbind.setEndOfMibView();
+        }
+    }
+
+    /**
+     * Processes a <CODE>getBulk</CODE> operation. It will throw an exception if the request is a V1 one or it will set exceptions within the list for V2 ones.
+     *
+     * @param inRequest The SnmpMibRequest object holding the list of variable to be retrieved.
+     *
+     * @exception SnmpStatusException An error occured during the operation.
+     */
+
+    public void getBulk(SnmpMibRequest inRequest, int nonRepeat, int maxRepeat)
+        throws SnmpStatusException {
+
+        SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
+                SnmpErrorHandlerAgent.class.getName(),
+                "getBulk", "GetBulk in Exception");
+
+        if(inRequest.getVersion() == SnmpDefinitions.snmpVersionOne)
+            throw new SnmpStatusException(SnmpDefinitions.snmpRspGenErr, 0);
+
+        Enumeration l = inRequest.getElements();
+        while(l.hasMoreElements()) {
+            SnmpVarBind varbind = (SnmpVarBind) l.nextElement();
+            varbind.setEndOfMibView();
+        }
+    }
+
+}
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpGenericMetaServer.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpGenericMetaServer.java
new file mode 100644
index 0000000..58aecdb
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpGenericMetaServer.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2000-2003 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.jmx.snmp.agent;
+
+// jmx imports
+//
+import com.sun.jmx.snmp.SnmpValue;
+import com.sun.jmx.snmp.SnmpStatusException;
+
+/**
+ * <p>
+ * This interface defines the methods that must be implemented by an
+ * SNMP metadata object that needs to interact with an
+ * {@link com.sun.jmx.snmp.agent.SnmpGenericObjectServer} object.
+ * </p>
+ *
+ * <p>
+ * All these methods are usually generated by <code>mibgen</code> when
+ * run in generic-metadata mode.
+ * </p>
+ *
+ * <p><b><i>
+ * This interface is used internally between the generated Metadata and
+ * the SNMP runtime and you shouldn't need to worry about it, because
+ * you will never have to use it directly.
+ * </b></i></p>
+ *
+ * <p><b>This API is a Sun Microsystems internal API  and is subject
+ * to change without notice.</b></p>
+ **/
+public interface SnmpGenericMetaServer {
+
+    /**
+     * Construct an attribute value (as returned by Attribute::getValue())
+     * from an SnmpValue. The returned attribute value can be used to
+     * construct an Attribute object.
+     *
+     * @param id The OID arc identifying the variable for which the
+     *           value is constructed.
+     * @param value The SnmpValue from which the Attribute::value will be
+     *              constructed.
+     * @return The attribute value built from the given <code>value</code>.
+     * @exception SnmpStatusException if the attribute value cannot be built
+     *            from the given SnmpValue <code>value</code>.
+     *
+     */
+    Object buildAttributeValue(long id, SnmpValue value)
+        throws SnmpStatusException;
+
+    /**
+     * Construct an SnmpValue from an Attribute value as returned by
+     * Attribute::getValue().
+     *
+     * @param id The OID arc identifying the variable for which the
+     *           value is constructed.
+     * @param value The attribute value as returned by Attribute::getValue().
+     *
+     * @return The SnmpValue built from the given <code>value</code>.
+     * @exception SnmpStatusException if the SnmpValue cannot be built from
+     *            the given <code>value</code>.
+     **/
+    SnmpValue buildSnmpValue(long id, Object value)
+        throws SnmpStatusException;
+
+    /**
+     * Return the name of the attribute corresponding to the
+     * SNMP variable identified by the given <code>id</code>.
+     *
+     * @param id The OID arc identifying the variable.
+     *
+     * @return The name of the variable identified by the given
+     *         <code>id</code>.
+     *
+     * @exception SnmpStatusException if the given <code>id</code> does not
+     *            correspond to a known variable.
+     */
+    String getAttributeName(long id)
+        throws SnmpStatusException;
+
+    /**
+     * Check the access rights for a SET operation.
+     *
+     * @param x  The new requested value.
+     * @param id The OID arc identifying the variable for which the SET is
+     *           requested.
+     * @param data 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 the SET operation must be rejected.
+     */
+    void checkSetAccess(SnmpValue x, long id, Object data)
+        throws SnmpStatusException;
+
+    /**
+     * Check the access rights for a GET operation.
+     *
+     * @param id The OID arc identifying the variable for which the SET is
+     *           requested.
+     * @param data 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 the SET operation must be rejected.
+     */
+    void checkGetAccess(long id, Object data)
+        throws SnmpStatusException;
+
+}
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpGenericObjectServer.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpGenericObjectServer.java
new file mode 100644
index 0000000..8b78b26
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpGenericObjectServer.java
@@ -0,0 +1,573 @@
+/*
+ * Copyright 2000-2003 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.jmx.snmp.agent;
+
+
+// java imports
+//
+import java.util.Vector;
+import java.util.Enumeration;
+import java.util.Iterator;
+
+// jmx imports
+//
+import javax.management.AttributeList;
+import javax.management.Attribute;
+import javax.management.MBeanException;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+import javax.management.InstanceNotFoundException;
+import javax.management.InvalidAttributeValueException;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.MBeanRegistrationException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.RuntimeOperationsException;
+import com.sun.jmx.snmp.SnmpOid;
+import com.sun.jmx.snmp.SnmpValue;
+import com.sun.jmx.snmp.SnmpVarBind;
+import com.sun.jmx.snmp.SnmpStatusException;
+
+
+/**
+ * <p>
+ * This class is a utility class that transforms SNMP GET / SET requests
+ * into standard JMX getAttributes() setAttributes() requests.
+ * </p>
+ *
+ * <p>
+ * The transformation relies on the metadata information provided by the
+ * {@link com.sun.jmx.snmp.agent.SnmpGenericMetaServer} object which is
+ * passed as the first parameter to every method. This SnmpGenericMetaServer
+ * object is usually a Metadata object generated by <code>mibgen</code>.
+ * </p>
+ *
+ * <p><b><i>
+ * This class is used internally by mibgen generated metadata objects and
+ * you should never need to use it directly.
+ * </b></i></p>
+ * <p><b>This API is a Sun Microsystems internal API  and is subject
+ * to change without notice.</b></p>
+ **/
+
+public class SnmpGenericObjectServer {
+
+    // ----------------------------------------------------------------------
+    //
+    //    Protected variables
+    //
+    // ----------------------------------------------------------------------
+
+    /**
+     * The MBean server through which the MBeans will be accessed.
+     **/
+    protected final MBeanServer server;
+
+    // ----------------------------------------------------------------------
+    //
+    // Constructors
+    //
+    // ----------------------------------------------------------------------
+
+    /**
+     * Builds a new SnmpGenericObjectServer. Usually there will be a single
+     * object of this type per MIB.
+     *
+     * @param server The MBeanServer in which the MBean accessed by this
+     *               MIB are registered.
+     **/
+    public SnmpGenericObjectServer(MBeanServer server) {
+        this.server = server;
+    }
+
+    /**
+     * Execute an SNMP GET request.
+     *
+     * <p>
+     * This method first builds the list of attributes that need to be
+     * retrieved from the MBean and then calls getAttributes() on the
+     * MBean server. Then it updates the SnmpMibSubRequest with the values
+     * retrieved from the MBean.
+     * </p>
+     *
+     * <p>
+     * The SNMP metadata information is obtained through the given
+     * <code>meta</code> object, which usually is an instance of a
+     * <code>mibgen</code> generated class.
+     * </p>
+     *
+     * <p><b><i>
+     * This method is called internally by <code>mibgen</code> generated
+     * objects and you should never need to call it directly.
+     * </i></b></p>
+     *
+     * @param meta  The metadata object impacted by the subrequest
+     * @param name  The ObjectName of the MBean impacted by this subrequest
+     * @param req   The SNMP subrequest to execute on the MBean
+     * @param depth The depth of the SNMP object in the OID tree.
+     *
+     * @exception SnmpStatusException whenever an SNMP exception must be
+     *      raised. Raising an exception will abort the request.<br>
+     *      Exceptions should never be raised directly, but only by means of
+     * <code>
+     * req.registerGetException(<i>VariableId</i>,<i>SnmpStatusException</i>)
+     * </code>
+     **/
+    public void get(SnmpGenericMetaServer meta, ObjectName name,
+                    SnmpMibSubRequest req, int depth)
+        throws SnmpStatusException {
+
+        // java.lang.System.out.println(">>>>>>>>> GET " + name);
+
+        final int           size     = req.getSize();
+        final Object        data     = req.getUserData();
+        final String[]      nameList = new String[size];
+        final SnmpVarBind[] varList  = new SnmpVarBind[size];
+        final long[]        idList   = new long[size];
+        int   i = 0;
+
+        for (Enumeration e=req.getElements(); e.hasMoreElements();) {
+            final SnmpVarBind var= (SnmpVarBind) e.nextElement();
+            try {
+                final long id = var.oid.getOidArc(depth);
+                nameList[i]   = meta.getAttributeName(id);
+                varList[i]    = var;
+                idList[i]     = id;
+
+                // Check the access rights according to the MIB.
+                // The MBean might be less restrictive (have a getter
+                // while the MIB defines the variable as AFN)
+                //
+                meta.checkGetAccess(id,data);
+
+                //java.lang.System.out.println(nameList[i] + " added.");
+                i++;
+            } catch(SnmpStatusException x) {
+                //java.lang.System.out.println("exception for " + nameList[i]);
+                //x.printStackTrace();
+                req.registerGetException(var,x);
+            }
+        }
+
+        AttributeList result = null;
+        int errorCode = SnmpStatusException.noSuchInstance;
+
+        try {
+            result = server.getAttributes(name,nameList);
+        } catch (InstanceNotFoundException f) {
+            //java.lang.System.out.println(name + ": instance not found.");
+            //f.printStackTrace();
+            result = new AttributeList();
+        } catch (ReflectionException r) {
+            //java.lang.System.out.println(name + ": reflexion error.");
+            //r.printStackTrace();
+            result = new AttributeList();
+        } catch (Exception x) {
+            result = new AttributeList();
+        }
+
+
+        final Iterator it = result.iterator();
+
+        for (int j=0; j < i; j++) {
+            if (!it.hasNext()) {
+                //java.lang.System.out.println(name + "variable[" + j +
+                //                           "] absent");
+                final SnmpStatusException x =
+                    new SnmpStatusException(errorCode);
+                req.registerGetException(varList[j],x);
+                continue;
+            }
+
+            final Attribute att = (Attribute) it.next();
+
+            while ((j < i) && (! nameList[j].equals(att.getName()))) {
+                //java.lang.System.out.println(name + "variable[" +j +
+                //                           "] not found");
+                final SnmpStatusException x =
+                    new SnmpStatusException(errorCode);
+                req.registerGetException(varList[j],x);
+                j++;
+            }
+
+            if ( j == i) break;
+
+            try {
+                varList[j].value =
+                    meta.buildSnmpValue(idList[j],att.getValue());
+            } catch (SnmpStatusException x) {
+                req.registerGetException(varList[j],x);
+            }
+            //java.lang.System.out.println(att.getName() + " retrieved.");
+        }
+        //java.lang.System.out.println(">>>>>>>>> END GET");
+    }
+
+    /**
+     * Get the value of an SNMP variable.
+     *
+     * <p><b><i>
+     * You should never need to use this method directly.
+     * </i></b></p>
+     *
+     * @param meta  The impacted metadata object
+     * @param name  The ObjectName of the impacted MBean
+     * @param id    The OID arc identifying the variable we're trying to set.
+     * @param data  User contextual data allocated through the
+     *        {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}
+     *
+     * @return The value of the variable.
+     *
+     * @exception SnmpStatusException whenever an SNMP exception must be
+     *      raised. Raising an exception will abort the request. <br>
+     *      Exceptions should never be raised directly, but only by means of
+     * <code>
+     * req.registerGetException(<i>VariableId</i>,<i>SnmpStatusException</i>)
+     * </code>
+     **/
+    public SnmpValue get(SnmpGenericMetaServer meta, ObjectName name,
+                         long id, Object data)
+        throws SnmpStatusException {
+        final String attname = meta.getAttributeName(id);
+        Object result = null;
+
+        try {
+            result = server.getAttribute(name,attname);
+        } catch (MBeanException m) {
+            Exception t = m.getTargetException();
+            if (t instanceof SnmpStatusException)
+                throw (SnmpStatusException) t;
+            throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
+        } catch (Exception e) {
+            throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
+        }
+
+        return meta.buildSnmpValue(id,result);
+    }
+
+    /**
+     * Execute an SNMP SET request.
+     *
+     * <p>
+     * This method first builds the list of attributes that need to be
+     * set on the MBean and then calls setAttributes() on the
+     * MBean server. Then it updates the SnmpMibSubRequest with the new
+     * values retrieved from the MBean.
+     * </p>
+     *
+     * <p>
+     * The SNMP metadata information is obtained through the given
+     * <code>meta</code> object, which usually is an instance of a
+     * <code>mibgen</code> generated class.
+     * </p>
+     *
+     * <p><b><i>
+     * This method is called internally by <code>mibgen</code> generated
+     * objects and you should never need to call it directly.
+     * </i></b></p>
+     *
+     * @param meta  The metadata object impacted by the subrequest
+     * @param name  The ObjectName of the MBean impacted by this subrequest
+     * @param req   The SNMP subrequest to execute on the MBean
+     * @param depth The depth of the SNMP object in the OID tree.
+     *
+     * @exception SnmpStatusException whenever an SNMP exception must be
+     *      raised. Raising an exception will abort the request. <br>
+     *      Exceptions should never be raised directly, but only by means of
+     * <code>
+     * req.registerGetException(<i>VariableId</i>,<i>SnmpStatusException</i>)
+     * </code>
+     **/
+    public void set(SnmpGenericMetaServer meta, ObjectName name,
+                    SnmpMibSubRequest req, int depth)
+        throws SnmpStatusException {
+
+        final int size               = req.getSize();
+        final AttributeList attList  = new AttributeList(size);
+        final String[]      nameList = new String[size];
+        final SnmpVarBind[] varList  = new SnmpVarBind[size];
+        final long[]        idList   = new long[size];
+        int   i = 0;
+
+        for (Enumeration e=req.getElements(); e.hasMoreElements();) {
+            final SnmpVarBind var= (SnmpVarBind) e.nextElement();
+            try {
+                final long id = var.oid.getOidArc(depth);
+                final String attname = meta.getAttributeName(id);
+                final Object attvalue=
+                    meta.buildAttributeValue(id,var.value);
+                final Attribute att = new Attribute(attname,attvalue);
+                attList.add(att);
+                nameList[i]   = attname;
+                varList[i]    = var;
+                idList[i]     = id;
+                i++;
+            } catch(SnmpStatusException x) {
+                req.registerSetException(var,x);
+            }
+        }
+
+        AttributeList result = null;
+        int errorCode = SnmpStatusException.noAccess;
+
+        try {
+            result = server.setAttributes(name,attList);
+        } catch (InstanceNotFoundException f) {
+            result = new AttributeList();
+            errorCode = SnmpStatusException.snmpRspInconsistentName;
+        } catch (ReflectionException r) {
+            errorCode = SnmpStatusException.snmpRspInconsistentName;
+            result = new AttributeList();
+        } catch (Exception x) {
+            result = new AttributeList();
+        }
+
+        final Iterator it = result.iterator();
+
+        for (int j=0; j < i; j++) {
+            if (!it.hasNext()) {
+                final SnmpStatusException x =
+                    new SnmpStatusException(errorCode);
+                req.registerSetException(varList[j],x);
+                continue;
+            }
+
+            final Attribute att = (Attribute) it.next();
+
+            while ((j < i) && (! nameList[j].equals(att.getName()))) {
+                final SnmpStatusException x =
+                    new SnmpStatusException(SnmpStatusException.noAccess);
+                req.registerSetException(varList[j],x);
+                j++;
+            }
+
+            if ( j == i) break;
+
+            try {
+                varList[j].value =
+                    meta.buildSnmpValue(idList[j],att.getValue());
+            } catch (SnmpStatusException x) {
+                req.registerSetException(varList[j],x);
+            }
+
+        }
+    }
+
+    /**
+     * Set the value of an SNMP variable.
+     *
+     * <p><b><i>
+     * You should never need to use this method directly.
+     * </i></b></p>
+     *
+     * @param meta  The impacted metadata object
+     * @param name  The ObjectName of the impacted MBean
+     * @param x     The new requested SnmpValue
+     * @param id    The OID arc identifying the variable we're trying to set.
+     * @param data  User contextual data allocated through the
+     *        {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}
+     *
+     * @return The new value of the variable after the operation.
+     *
+     * @exception SnmpStatusException whenever an SNMP exception must be
+     *      raised. Raising an exception will abort the request. <br>
+     *      Exceptions should never be raised directly, but only by means of
+     * <code>
+     * req.registerSetException(<i>VariableId</i>,<i>SnmpStatusException</i>)
+     * </code>
+     **/
+    public SnmpValue set(SnmpGenericMetaServer meta, ObjectName name,
+                         SnmpValue x, long id, Object data)
+        throws SnmpStatusException {
+        final String attname = meta.getAttributeName(id);
+        final Object attvalue=
+            meta.buildAttributeValue(id,x);
+        final Attribute att = new Attribute(attname,attvalue);
+
+        Object result = null;
+
+        try {
+            server.setAttribute(name,att);
+            result = server.getAttribute(name,attname);
+        } catch(InvalidAttributeValueException iv) {
+            throw new
+                SnmpStatusException(SnmpStatusException.snmpRspWrongValue);
+        } catch (InstanceNotFoundException f) {
+            throw new
+                SnmpStatusException(SnmpStatusException.snmpRspInconsistentName);
+        } catch (ReflectionException r) {
+            throw new
+                SnmpStatusException(SnmpStatusException.snmpRspInconsistentName);
+        } catch (MBeanException m) {
+            Exception t = m.getTargetException();
+            if (t instanceof SnmpStatusException)
+                throw (SnmpStatusException) t;
+            throw new
+                SnmpStatusException(SnmpStatusException.noAccess);
+        } catch (Exception e) {
+            throw new
+                SnmpStatusException(SnmpStatusException.noAccess);
+        }
+
+        return meta.buildSnmpValue(id,result);
+    }
+
+    /**
+     * Checks whether an SNMP SET request can be successfully performed.
+     *
+     * <p>
+     * For each variable in the subrequest, this method calls
+     * checkSetAccess() on the meta object, and then tries to invoke the
+     * check<i>AttributeName</i>() method on the MBean. If this method
+     * is not defined then it is assumed that the SET won't fail.
+     * </p>
+     *
+     * <p><b><i>
+     * This method is called internally by <code>mibgen</code> generated
+     * objects and you should never need to call it directly.
+     * </i></b></p>
+     *
+     * @param meta  The metadata object impacted by the subrequest
+     * @param name  The ObjectName of the MBean impacted by this subrequest
+     * @param req   The SNMP subrequest to execute on the MBean
+     * @param depth The depth of the SNMP object in the OID tree.
+     *
+     * @exception SnmpStatusException if the requested SET operation must
+     *      be rejected. Raising an exception will abort the request. <br>
+     *      Exceptions should never be raised directly, but only by means of
+     * <code>
+     * req.registerCheckException(<i>VariableId</i>,<i>SnmpStatusException</i>)
+     * </code>
+     *
+     **/
+    public void check(SnmpGenericMetaServer meta, ObjectName name,
+                      SnmpMibSubRequest req, int depth)
+        throws SnmpStatusException {
+
+        final Object data = req.getUserData();
+
+        for (Enumeration e=req.getElements(); e.hasMoreElements();) {
+            final SnmpVarBind var= (SnmpVarBind) e.nextElement();
+            try {
+                final long id = var.oid.getOidArc(depth);
+                // call meta.check() here, and meta.check will call check()
+                check(meta,name,var.value,id,data);
+            } catch(SnmpStatusException x) {
+                req.registerCheckException(var,x);
+            }
+        }
+    }
+
+    /**
+     * Checks whether a SET operation can be performed on a given SNMP
+     * variable.
+     *
+     * @param meta  The impacted metadata object
+     * @param name  The ObjectName of the impacted MBean
+     * @param x     The new requested SnmpValue
+     * @param id    The OID arc identifying the variable we're trying to set.
+     * @param data  User contextual data allocated through the
+     *        {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}
+     *
+     * <p>
+     * This method calls checkSetAccess() on the meta object, and then
+     * tries to invoke the check<i>AttributeName</i>() method on the MBean.
+     * If this method is not defined then it is assumed that the SET
+     * won't fail.
+     * </p>
+     *
+     * <p><b><i>
+     * This method is called internally by <code>mibgen</code> generated
+     * objects and you should never need to call it directly.
+     * </i></b></p>
+     *
+     * @exception SnmpStatusException if the requested SET operation must
+     *      be rejected. Raising an exception will abort the request. <br>
+     *      Exceptions should never be raised directly, but only by means of
+     * <code>
+     * req.registerCheckException(<i>VariableId</i>,<i>SnmpStatusException</i>)
+     * </code>
+     *
+     **/
+    // XXX xxx ZZZ zzz Maybe we should go through the MBeanInfo here?
+    public void check(SnmpGenericMetaServer meta, ObjectName name,
+                      SnmpValue x, long id, Object data)
+        throws SnmpStatusException {
+
+        meta.checkSetAccess(x,id,data);
+        try {
+            final String attname = meta.getAttributeName(id);
+            final Object attvalue= meta.buildAttributeValue(id,x);
+            final  Object[] params = new Object[1];
+            final  String[] signature = new String[1];
+
+            params[0]    = attvalue;
+            signature[0] = attvalue.getClass().getName();
+            server.invoke(name,"check"+attname,params,signature);
+
+        } catch( SnmpStatusException e) {
+            throw e;
+        }
+        catch (InstanceNotFoundException i) {
+            throw new
+                SnmpStatusException(SnmpStatusException.snmpRspInconsistentName);
+        } catch (ReflectionException r) {
+            // checkXXXX() not defined => do nothing
+        } catch (MBeanException m) {
+            Exception t = m.getTargetException();
+            if (t instanceof SnmpStatusException)
+                throw (SnmpStatusException) t;
+            throw new SnmpStatusException(SnmpStatusException.noAccess);
+        } catch (Exception e) {
+            throw new
+                SnmpStatusException(SnmpStatusException.noAccess);
+        }
+    }
+
+    public void registerTableEntry(SnmpMibTable meta, SnmpOid rowOid,
+                                   ObjectName objname, Object entry)
+        throws SnmpStatusException {
+        if (objname == null)
+           throw new
+             SnmpStatusException(SnmpStatusException.snmpRspInconsistentName);
+        try  {
+            if (entry != null && !server.isRegistered(objname))
+                server.registerMBean(entry, objname);
+        } catch (InstanceAlreadyExistsException e) {
+            throw new
+              SnmpStatusException(SnmpStatusException.snmpRspInconsistentName);
+        } catch (MBeanRegistrationException e) {
+            throw new SnmpStatusException(SnmpStatusException.snmpRspNoAccess);
+        } catch (NotCompliantMBeanException e) {
+            throw new SnmpStatusException(SnmpStatusException.snmpRspGenErr);
+        } catch (RuntimeOperationsException e) {
+            throw new SnmpStatusException(SnmpStatusException.snmpRspGenErr);
+        } catch(Exception e) {
+            throw new SnmpStatusException(SnmpStatusException.snmpRspGenErr);
+        }
+    }
+
+}
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpIndex.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpIndex.java
new file mode 100644
index 0000000..d2511ba
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpIndex.java
@@ -0,0 +1,190 @@
+/*
+ * 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;
+
+
+
+// java imports
+//
+import java.io.Serializable;
+import java.util.Vector;
+import java.util.Enumeration;
+
+// jmx imports
+//
+import com.sun.jmx.snmp.SnmpOid;
+
+/**
+ * Represents a SNMP index.
+ * An <CODE>SnmpIndex</CODE> is represented as a <CODE>Vector</CODE> of <CODE>SnmpOid</CODE>.
+ * <P>
+ * This class is used internally and by the classes generated by <CODE>mibgen</CODE>.
+ * You should not need to use this class directly.
+ *
+ * <p><b>This API is a Sun Microsystems internal API  and is subject
+ * to change without notice.</b></p>
+ */
+
+public class SnmpIndex implements Serializable {
+    private static final long serialVersionUID = 8712159739982192146L;
+
+    /**
+     * Initializes an <CODE>SnmpIndex</CODE> using a vector of object identifiers.
+     * <P>Following the RFC recommendations, every syntax that is used as a
+     * table index should have an object identifier representation. There are
+     * some guidelines on how to map the different syntaxes into an object identifier.
+     * In the different <CODE>SnmpValue</CODE> classes provided, there is a <CODE>toOid</CODE> method to get
+     * the object identifier of the value.
+     *
+     * @param oidList The list of Object Identifiers.
+     */
+    public SnmpIndex(SnmpOid[] oidList) {
+        size= oidList.length;
+        for(int i= 0; i <size; i++) {
+            // The order is important ...
+            //
+            oids.addElement(oidList[i]);
+        }
+    }
+
+    /**
+     * Initializes an <CODE>SnmpIndex</CODE> using the specified Object Identifier.
+     *
+     * @param oid The Object Identifier.
+     */
+    public SnmpIndex(SnmpOid oid) {
+        oids.addElement(oid);
+        size= 1;
+    }
+
+    /**
+     * Gets the number of Object Identifiers the index is made of.
+     *
+     * @return The number of Object Identifiers.
+     */
+    public int getNbComponents() {
+        return size;
+    }
+
+    /**
+     * Gets the index as a vector of Object Identifiers.
+     *
+     * @return The index as a vector.
+     */
+    public Vector<SnmpOid> getComponents() {
+        return oids;
+    }
+
+    /**
+     * Compares two indexes for equality.
+     *
+     * @param index The index to compare <CODE>this</CODE> with.
+     *
+     * @return <CODE>true</CODE> if the two indexes are equal, <CODE>false</CODE> otherwise.
+     */
+    public boolean equals(SnmpIndex index) {
+
+        if (size != index.getNbComponents())
+            return false;
+
+        // The two vectors have the same length.
+        // Compare each single element ...
+        //
+        SnmpOid oid1;
+        SnmpOid oid2;
+        Vector<SnmpOid> components= index.getComponents();
+        for(int i=0; i <size; i++) {
+            oid1= oids.elementAt(i);
+            oid2= components.elementAt(i);
+            if (oid1.equals(oid2) == false)
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * Compares two indexes.
+     *
+     * @param index The index to compare <CODE>this</CODE> with.
+     *
+     * @return The value 0 if the two OID vectors have the same elements, another value otherwise.
+     */
+    public int compareTo(SnmpIndex index) {
+
+        int length= index.getNbComponents();
+        Vector<SnmpOid> components= index.getComponents();
+        SnmpOid oid1;
+        SnmpOid oid2;
+        int comp;
+        for(int i=0; i < size; i++) {
+            if ( i > length) {
+                // There is no more element in the index
+                //
+                return 1;
+            }
+            // Access the element ...
+            //
+            oid1= oids.elementAt(i);
+            oid2= components.elementAt(i);
+            comp= oid1.compareTo(oid2);
+            if (comp == 0)
+                continue;
+            return comp;
+        }
+        return 0;
+    }
+
+    /**
+     * Returns a <CODE>String</CODE> representation of the index.
+     * The different elements are separated by "//".
+     *
+     * @return A string representation of the index.
+     */
+    public String toString() {
+        StringBuffer msg= new StringBuffer();
+        for(Enumeration e= oids.elements(); e.hasMoreElements(); ) {
+            SnmpOid val= (SnmpOid) e.nextElement();
+            msg.append( "//" + val.toString());
+        }
+        return msg.toString();
+    }
+
+    // PRIVATE VARIABLES
+    //------------------
+
+    /**
+     * The list of OIDs.
+     * @serial
+     */
+    private Vector<SnmpOid> oids = new Vector<SnmpOid>();
+
+    /**
+     * The number of elements in the index.
+     * @serial
+     */
+    private int size = 0;
+}
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMib.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMib.java
new file mode 100644
index 0000000..b5c96ff
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMib.java
@@ -0,0 +1,1026 @@
+/*
+ * 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.Enumeration;
+import java.util.logging.Level;
+import java.util.Vector;
+
+import javax.management.ObjectName;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.MBeanRegistrationException;
+import javax.management.NotCompliantMBeanException;
+
+import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER;
+import com.sun.jmx.snmp.SnmpOid;
+import com.sun.jmx.snmp.SnmpVarBind;
+import com.sun.jmx.snmp.SnmpDefinitions;
+import com.sun.jmx.snmp.SnmpStatusException;
+import com.sun.jmx.snmp.SnmpEngine;
+import com.sun.jmx.snmp.SnmpUnknownModelException;
+import com.sun.jmx.snmp.internal.SnmpAccessControlModel;
+import com.sun.jmx.snmp.internal.SnmpEngineImpl;
+
+/**
+ * This list is used in order to construct the OID during the getnext.
+ * The constructed oid is checked by the checker AcmChecker.
+ */
+final class LongList {
+
+    public static int DEFAULT_CAPACITY = 10;
+
+    public static int DEFAULT_INCREMENT = 10;
+
+
+    private final int DELTA;
+    private int size;
+
+    /**
+     * The list content. Any access to this variable must be protected
+     * by a synchronized block on the LongList object.
+     * Only read-only action should be performed on this object.
+     **/
+    public  long[] list;
+
+    LongList() {
+        this(DEFAULT_CAPACITY,DEFAULT_INCREMENT);
+    }
+
+    LongList(int initialCapacity) {
+        this(initialCapacity,DEFAULT_INCREMENT);
+    }
+
+    LongList(int initialCapacity, int delta) {
+        size = 0;
+        DELTA = delta;
+        list = allocate(initialCapacity);
+    }
+
+    /**
+     * Same behaviour than size() in {@link java.util.List}.
+     **/
+    public final int size() { return size;}
+
+    /**
+     * Same behaviour than add(long o) in {@link java.util.List}.
+     * Any access to this method should be protected in a synchronized
+     * block on the LongList object.
+     **/
+    public final boolean add(final long o) {
+        if (size >= list.length)
+            resize();
+        list[size++]=o;
+        return true;
+    }
+
+    /**
+     * Same behaviour than add(int index, long o) in
+     * {@link java.util.List}.
+     * Any access to this method should be protected in a synchronized
+     * block on the LongList object.
+     **/
+    public final void add(final int index, final long o) {
+        if (index >  size) throw new IndexOutOfBoundsException();
+        if (index >= list.length) resize();
+        if (index == size) {
+            list[size++]=o;
+            return;
+        }
+
+        java.lang.System.arraycopy(list,index,list,index+1,size-index);
+        list[index]=o;
+        size++;
+    }
+
+    /**
+     * Adds <var>count</var> elements to the list.
+     * @param at index at which the elements must be inserted. The
+     *        first element will be inserted at this index.
+     * @param src  An array containing the elements we want to insert.
+     * @param from Index of the first element from <var>src</var> that
+     *        must be inserted.
+     * @param count number of elements to insert.
+     * Any access to this method should be protected in a synchronized
+     * block on the LongList object.
+     **/
+    public final void add(final int at,final long[] src, final int from,
+                          final int count) {
+        if (count <= 0) return;
+        if (at > size) throw new IndexOutOfBoundsException();
+        ensure(size+count);
+        if (at < size) {
+            java.lang.System.arraycopy(list,at,list,at+count,size-at);
+        }
+        java.lang.System.arraycopy(src,from,list,at,count);
+        size+=count;
+    }
+
+    /**
+     * Any access to this method should be protected in a synchronized
+     * block on the LongList object.
+     **/
+    public final long remove(final int from, final int count) {
+        if (count < 1 || from < 0) return -1;
+        if (from+count > size) return -1;
+
+        final long o = list[from];
+        final int oldsize = size;
+        size = size - count;
+
+        if (from == size) return o;
+
+        java.lang.System.arraycopy(list,from+count,list,from,
+                                   size-from);
+        return o;
+    }
+
+    /**
+     * Same behaviour than remove(int index) in {@link java.util.List}.
+     * Any access to this method should be protected in a synchronized
+     * block on the LongList object.
+     **/
+    public final long remove(final int index) {
+        if (index >= size) return -1;
+        final long o = list[index];
+        list[index]=0;
+        if (index == --size) return o;
+
+        java.lang.System.arraycopy(list,index+1,list,index,
+                                   size-index);
+        return o;
+    }
+
+    /**
+     * Same behaviour than the toArray(long[] a) method in
+     * {@link java.util.List}.
+     * Any access to this method should be protected in a synchronized
+     * block on the LongList object.
+     **/
+    public final long[] toArray(long[] a) {
+        java.lang.System.arraycopy(list,0,a,0,size);
+        return a;
+    }
+
+    /**
+     * Same behaviour than the toArray() method in
+     * {@link java.util.List}.
+     * Any access to this method should be protected in a synchronized
+     * block on the LongList object.
+     **/
+    public final long[] toArray() {
+        return toArray(new long[size]);
+    }
+
+    /**
+     * Resize the list. Increase its capacity by DELTA elements.
+     * Any call to this method must be protected by a synchronized
+     * block on this LongList.
+     **/
+    private final void resize() {
+        final long[] newlist = allocate(list.length + DELTA);
+        java.lang.System.arraycopy(list,0,newlist,0,size);
+        list = newlist;
+    }
+
+    /**
+     * Resize the list. Insure that the new length will be at
+     * least equal to <var>length</var>.
+     * @param length new minimal length requested.
+     * Any call to this method must be protected by a synchronized
+     * block on this LongList.
+     **/
+    private final void ensure(int length) {
+        if (list.length < length) {
+            final int min = list.length+DELTA;
+            length=(length<min)?min:length;
+            final long[] newlist = allocate(length);
+            java.lang.System.arraycopy(list,0,newlist,0,size);
+            list = newlist;
+        }
+    }
+
+    /**
+     * Allocate a new array of object of specified length.
+     **/
+    private final long[] allocate(final int length) {
+        return new long[length];
+    }
+
+}
+
+/**
+ * Oid Checker makes use of ACM to check each OID during the getnext process.
+ */
+class AcmChecker {
+
+
+    SnmpAccessControlModel model = null;
+    String principal = null;
+    int securityLevel = -1;
+    int version = -1;
+    int pduType = -1;
+    int securityModel = -1;
+    byte[] contextName = null;
+    SnmpEngineImpl engine = null;
+    LongList l = null;
+    AcmChecker(SnmpMibRequest req) {
+        engine = (SnmpEngineImpl) req.getEngine();
+        //We are in V3 architecture, ACM is in the picture.
+        if(engine != null) {
+            if(engine.isCheckOidActivated()) {
+                try {
+                    if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
+                        SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
+                                SnmpMib.class.getName(),
+                                "AcmChecker(SnmpMibRequest)",
+                                "SNMP V3 Access Control to be done");
+                    }
+                    model = (SnmpAccessControlModel)
+                        engine.getAccessControlSubSystem().
+                        getModel(SnmpDefinitions.snmpVersionThree);
+                    principal = req.getPrincipal();
+                    securityLevel = req.getSecurityLevel();
+                    pduType = req.getPdu().type;
+                    version = req.getRequestPduVersion();
+                    securityModel = req.getSecurityModel();
+                    contextName = req.getAccessContextName();
+                    l = new LongList();
+                    if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
+                        final StringBuilder strb = new StringBuilder()
+                        .append("Will check oid for : principal : ")
+                        .append(principal)
+                        .append("; securityLevel : ").append(securityLevel)
+                        .append("; pduType : ").append(pduType)
+                        .append("; version : ").append(version)
+                        .append("; securityModel : ").append(securityModel)
+                        .append("; contextName : ").append(contextName);
+                        SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
+                                SnmpMib.class.getName(),
+                                "AcmChecker(SnmpMibRequest)", strb.toString());
+                    }
+
+                }catch(SnmpUnknownModelException e) {
+                    if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
+                        SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
+                                SnmpMib.class.getName(),
+                                "AcmChecker(SnmpMibRequest)",
+                                "Unknown Model, no ACM check.");
+                    }
+                }
+            }
+        }
+    }
+
+    void add(int index, long arc) {
+        if(model != null)
+            l.add(index, arc);
+    }
+
+    void remove(int index) {
+        if(model != null)
+            l.remove(index);
+    }
+
+    void add(final int at,final long[] src, final int from,
+             final int count) {
+        if(model != null)
+            l.add(at,src,from,count);
+    }
+
+    void remove(final int from, final int count) {
+        if(model != null)
+            l.remove(from,count);
+    }
+
+    void checkCurrentOid() throws SnmpStatusException {
+        if(model != null) {
+            SnmpOid oid = new SnmpOid(l.toArray());
+            if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
+                SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMib.class.getName(),
+                        "checkCurrentOid", "Checking access for : " + oid);
+            }
+            model.checkAccess(version,
+                              principal,
+                              securityLevel,
+                              pduType,
+                              securityModel,
+                              contextName,
+                              oid);
+        }
+    }
+
+}
+
+/**
+ * Abstract class for representing an SNMP MIB.
+ * <P>
+ * When compiling a SNMP MIB, among all the classes generated by
+ * <CODE>mibgen</CODE>, there is one which extends <CODE>SnmpMib</CODE>
+ * for representing a whole MIB.
+ * <BR>The class is used by the SNMP protocol adaptor as the entry point in
+ * the MIB.
+ *
+ * <p>This generated class can be subclassed in your code in order to
+ * plug in your own specific behaviour.
+ * </p>
+ *
+ * <p><b>This API is a Sun Microsystems internal API  and is subject
+ * to change without notice.</b></p>
+ */
+public abstract class SnmpMib extends SnmpMibAgent implements Serializable {
+
+    /**
+     * Default constructor.
+     * Initializes the OID tree.
+     */
+    public SnmpMib() {
+        root= new SnmpMibOid();
+    }
+
+
+    // --------------------------------------------------------------------
+    // POLYMORHIC METHODS
+    // --------------------------------------------------------------------
+
+    /**
+     * <p>
+     * This callback should return the OID associated to the group
+     * identified by the given <code>groupName</code>.
+     * </p>
+     *
+     * <p>
+     * This method is provided as a hook to plug-in some custom
+     * specific behavior. Although doing so is discouraged you might
+     * want to subclass this method in order to store & provide more metadata
+     * information (mapping OID <-> symbolic name) within the agent,
+     * or to "change" the root of the MIB OID by prefixing the
+     * defaultOid by an application dependant OID string, for instance.
+     * </p>
+     *
+     * <p>
+     * The default implementation of this method is to return the given
+     * <code>defaultOid</code>
+     * </p>
+     *
+     * @param groupName   The java-ized name of the SNMP group.
+     * @param defaultOid  The OID defined in the MIB for that group
+     *                    (in dot notation).
+     *
+     * @return The OID of the group identified by <code>groupName</code>,
+     *         in dot-notation.
+     */
+    protected String getGroupOid(String groupName, String defaultOid) {
+        return defaultOid;
+    }
+
+    /**
+     * <p>
+     * This callback should return the ObjectName associated to the
+     * group identified by the given <code>groupName</code>.
+     * </p>
+     *
+     * <p>
+     * This method is provided as a hook to plug-in some custom
+     * specific behavior. You might want to override this method
+     * in order to provide a different object naming scheme than
+     * that proposed by default by <code>mibgen</code>.
+     * </p>
+     *
+     * <p>
+     * This method is only meaningful if the MIB is registered
+     * in the MBeanServer, otherwise, it will not be called.
+     * </p>
+     *
+     * <p>
+     * The default implementation of this method is to return an ObjectName
+     * built from the given <code>defaultName</code>.
+     * </p>
+     *
+     * @param name  The java-ized name of the SNMP group.
+     * @param oid   The OID returned by getGroupOid() - in dot notation.
+     * @param defaultName The name by default generated by <code>
+     *                    mibgen</code>
+     *
+     * @return The ObjectName of the group identified by <code>name</code>
+     */
+    protected ObjectName getGroupObjectName(String name, String oid,
+                                            String defaultName)
+        throws MalformedObjectNameException {
+        return new ObjectName(defaultName);
+    }
+
+    /**
+     * <p>
+     * Register an SNMP group and its metadata node in the MIB.
+     * </p>
+     *
+     * <p>
+     * This method is provided as a hook to plug-in some custom
+     * specific behavior. You might want to override this method
+     * if you want to set special links between the MBean, its metadata
+     * node, its OID or ObjectName etc..
+     * </p>
+     *
+     * <p>
+     * If the MIB is not registered in the MBeanServer, the <code>
+     * server</code> and <code>groupObjName</code> parameters will be
+     * <code>null</code>.<br>
+     * If the given group MBean is not <code>null</code>, and if the
+     * <code>server</code> and <code>groupObjName</code> parameters are
+     * not null, then this method will also automatically register the
+     * group MBean with the given MBeanServer <code>server</code>.
+     * </p>
+     *
+     * @param groupName  The java-ized name of the SNMP group.
+     * @param groupOid   The OID as returned by getGroupOid() - in dot
+     *                   notation.
+     * @param groupObjName The ObjectName as returned by getGroupObjectName().
+     *                   This parameter may be <code>null</code> if the
+     *                   MIB is not registered in the MBeanServer.
+     * @param node       The metadata node, as returned by the metadata
+     *                   factory method for this group.
+     * @param group      The MBean for this group, as returned by the
+     *                   MBean factory method for this group.
+     * @param server     The MBeanServer in which the groups are to be
+     *                   registered. This parameter will be <code>null</code>
+     *                   if the MIB is not registered, otherwise it is a
+     *                   reference to the MBeanServer in which the MIB is
+     *                   registered.
+     *
+     */
+    protected void registerGroupNode(String groupName,   String groupOid,
+                                     ObjectName groupObjName, SnmpMibNode node,
+                                     Object group, MBeanServer server)
+        throws NotCompliantMBeanException, MBeanRegistrationException,
+        InstanceAlreadyExistsException, IllegalAccessException {
+        root.registerNode(groupOid,node);
+        if (server != null && groupObjName != null && group != null)
+            server.registerMBean(group,groupObjName);
+    }
+
+    /**
+     * <p>
+     * Register an SNMP Table metadata node in the MIB.
+     * </p>
+     *
+     * <p>
+     * <b><i>
+     * This method is used internally and you should never need to
+     * call it directly.</i></b><br> It is used to establish the link
+     * between an SNMP table metadata node and its bean-like counterpart.
+     * <br>
+     * The group metadata nodes will create and register their
+     * underlying table metadata nodes in the MIB using this
+     * method. <br>
+     * The metadata nodes will be later retrieved from the MIB by the
+     * bean-like table objects using the getRegisterTableMeta() method.
+     * </p>
+     *
+     * @param name      The java-ized name of the SNMP table.
+     * @param table     The SNMP table metadata node - usually this
+     *                  corresponds to a <code>mibgen</code> generated
+     *                  object.
+     */
+    public abstract void registerTableMeta(String name, SnmpMibTable table);
+
+    /**
+     * Returns a registered SNMP Table metadata node.
+     *
+     * <p><b><i>
+     * This method is used internally and you should never need to
+     * call it directly.
+     * </i></b></p>
+     *
+     */
+    public abstract SnmpMibTable getRegisteredTableMeta(String name);
+
+    // --------------------------------------------------------------------
+    // PUBLIC METHODS
+    // --------------------------------------------------------------------
+
+    /**
+     * Processes a <CODE>get</CODE> operation.
+     *
+     **/
+    // Implements the method defined in SnmpMibAgent. See SnmpMibAgent
+    // for java-doc
+    //
+    public void get(SnmpMibRequest req) throws SnmpStatusException {
+
+        // Builds the request tree: creation is not allowed, operation
+        // is not atomic.
+
+        final int reqType = SnmpDefinitions.pduGetRequestPdu;
+        SnmpRequestTree handlers = getHandlers(req,false,false,reqType);
+
+        SnmpRequestTree.Handler h = null;
+        SnmpMibNode meta = null;
+
+        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
+            SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMib.class.getName(),
+                    "get", "Processing handlers for GET... ");
+        }
+
+        // For each sub-request stored in the request-tree, invoke the
+        // get() method.
+        for (Enumeration eh=handlers.getHandlers();eh.hasMoreElements();) {
+            h = (SnmpRequestTree.Handler) eh.nextElement();
+
+            // Gets the Meta node. It can be either a Group Meta or a
+            // Table Meta.
+            //
+            meta = handlers.getMetaNode(h);
+
+            // Gets the depth of the Meta node in the OID tree
+            final int depth = handlers.getOidDepth(h);
+
+            for (Enumeration rqs=handlers.getSubRequests(h);
+                 rqs.hasMoreElements();) {
+
+                // Invoke the get() operation.
+                meta.get((SnmpMibSubRequest)rqs.nextElement(),depth);
+            }
+        }
+    }
+
+    /**
+     * Processes a <CODE>set</CODE> operation.
+     *
+     */
+    // Implements the method defined in SnmpMibAgent. See SnmpMibAgent
+    // for java-doc
+    //
+    public void set(SnmpMibRequest req) throws SnmpStatusException {
+
+        SnmpRequestTree handlers = null;
+
+        // Optimization: we're going to get the whole SnmpRequestTree
+        // built in the "check" method, so that we don't have to rebuild
+        // it here.
+        //
+        if (req instanceof SnmpMibRequestImpl)
+            handlers = ((SnmpMibRequestImpl)req).getRequestTree();
+
+        // Optimization didn't work: we have to rebuild the tree.
+        //
+        // Builds the request tree: creation is not allowed, operation
+        // is atomic.
+        //
+        final int reqType = SnmpDefinitions.pduSetRequestPdu;
+        if (handlers == null) handlers = getHandlers(req,false,true,reqType);
+        handlers.switchCreationFlag(false);
+        handlers.setPduType(reqType);
+
+        SnmpRequestTree.Handler h = null;
+        SnmpMibNode meta = null;
+
+        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
+            SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMib.class.getName(),
+                    "set", "Processing handlers for SET... ");
+        }
+
+        // For each sub-request stored in the request-tree, invoke the
+        // get() method.
+        for (Enumeration eh=handlers.getHandlers();eh.hasMoreElements();) {
+            h = (SnmpRequestTree.Handler) eh.nextElement();
+
+            // Gets the Meta node. It can be either a Group Meta or a
+            // Table Meta.
+            //
+            meta = handlers.getMetaNode(h);
+
+            // Gets the depth of the Meta node in the OID tree
+            final int depth = handlers.getOidDepth(h);
+
+            for (Enumeration rqs=handlers.getSubRequests(h);
+                 rqs.hasMoreElements();) {
+
+                // Invoke the set() operation
+                meta.set((SnmpMibSubRequest)rqs.nextElement(),depth);
+            }
+        }
+    }
+
+    /**
+     * Checks if a <CODE>set</CODE> operation can be performed.
+     * If the operation cannot be performed, the method will raise a
+     * <CODE>SnmpStatusException</CODE>.
+     *
+     */
+    // Implements the method defined in SnmpMibAgent. See SnmpMibAgent
+    // for java-doc
+    //
+    public void check(SnmpMibRequest req) throws SnmpStatusException {
+
+        final int reqType = SnmpDefinitions.pduWalkRequest;
+        // Builds the request tree: creation is allowed, operation
+        // is atomic.
+        SnmpRequestTree handlers = getHandlers(req,true,true,reqType);
+
+        SnmpRequestTree.Handler h = null;
+        SnmpMibNode meta = null;
+
+        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
+            SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMib.class.getName(),
+                    "check", "Processing handlers for CHECK... ");
+        }
+
+        // For each sub-request stored in the request-tree, invoke the
+        // check() method.
+        for (Enumeration eh=handlers.getHandlers();eh.hasMoreElements();) {
+            h = (SnmpRequestTree.Handler) eh.nextElement();
+
+            // Gets the Meta node. It can be either a Group Meta or a
+            // Table Meta.
+            //
+            meta = handlers.getMetaNode(h);
+
+            // Gets the depth of the Meta node in the OID tree
+            final int depth = handlers.getOidDepth(h);
+
+            for (Enumeration rqs=handlers.getSubRequests(h);
+                 rqs.hasMoreElements();) {
+
+                // Invoke the check() operation
+                meta.check((SnmpMibSubRequest)rqs.nextElement(),depth);
+            }
+        }
+
+        // Optimization: we're going to pass the whole SnmpRequestTree
+        // to the "set" method, so that we don't have to rebuild it there.
+        //
+        if (req instanceof SnmpMibRequestImpl) {
+            ((SnmpMibRequestImpl)req).setRequestTree(handlers);
+        }
+
+    }
+
+    /**
+     * Processes a <CODE>getNext</CODE> operation.
+     *
+     */
+    // Implements the method defined in SnmpMibAgent. See SnmpMibAgent
+    // for java-doc
+    //
+    public void getNext(SnmpMibRequest req) throws SnmpStatusException {
+        // Build the request tree for the operation
+        // The subrequest stored in the request tree are valid GET requests
+        SnmpRequestTree handlers = getGetNextHandlers(req);
+
+        SnmpRequestTree.Handler h = null;
+        SnmpMibNode meta = null;
+
+        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
+            SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMib.class.getName(),
+                    "getNext", "Processing handlers for GET-NEXT... ");
+        }
+
+        // Now invoke get() for each subrequest of the request tree.
+        for (Enumeration eh=handlers.getHandlers();eh.hasMoreElements();) {
+            h = (SnmpRequestTree.Handler) eh.nextElement();
+
+            // Gets the Meta node. It can be either a Group Meta or a
+            // Table Meta.
+            //
+            meta = handlers.getMetaNode(h);
+
+            // Gets the depth of the Meta node in the OID tree
+            int depth = handlers.getOidDepth(h);
+
+            for (Enumeration rqs=handlers.getSubRequests(h);
+                 rqs.hasMoreElements();) {
+
+                // Invoke the get() operation
+                meta.get((SnmpMibSubRequest)rqs.nextElement(),depth);
+            }
+        }
+    }
+
+
+    /**
+     * Processes a <CODE>getBulk</CODE> operation.
+     * The method implements the <CODE>getBulk</CODE> operation by calling
+     * appropriately the <CODE>getNext</CODE> method.
+     *
+     */
+    // Implements the method defined in SnmpMibAgent. See SnmpMibAgent
+    // for java-doc
+    //
+    public void getBulk(SnmpMibRequest req, int nonRepeat, int maxRepeat)
+        throws SnmpStatusException {
+
+        getBulkWithGetNext(req, nonRepeat, maxRepeat);
+    }
+
+    /**
+     * Gets the root object identifier of the MIB.
+     * <P>In order to be accurate, the method should be called once the
+     * MIB is fully initialized (that is, after a call to <CODE>init</CODE>
+     * or <CODE>preRegister</CODE>).
+     *
+     * @return The root object identifier.
+     */
+    public long[] getRootOid() {
+
+        if( rootOid == null) {
+            Vector<Integer> list= new Vector<Integer>(10);
+
+            // Ask the tree to do the job !
+            //
+            root.getRootOid(list);
+
+            // Now format the result
+            //
+            rootOid= new long[list.size()];
+            int i=0;
+            for(Enumeration<Integer> e= list.elements(); e.hasMoreElements(); ) {
+                Integer val= e.nextElement();
+                rootOid[i++]= val.longValue();
+            }
+        }
+        return rootOid;
+
+    }
+
+    // --------------------------------------------------------------------
+    // PRIVATE METHODS
+    //---------------------------------------------------------------------
+
+    /**
+     * This method builds the temporary request-tree that will be used to
+     * perform the SNMP request associated with the given vector of varbinds
+     * `list'.
+     *
+     * @param req The SnmpMibRequest object holding the varbind list
+     *             concerning this MIB.
+     * @param createflag Indicates whether the operation allow for creation
+     *        of new instances (ie: it is a SET).
+     * @param atomic Indicates whether the operation is atomic or not.
+     * @param type Request type (from SnmpDefinitions).
+     *
+     * @return The request-tree where the original varbind list has been
+     *         dispatched to the appropriate nodes.
+     */
+    private SnmpRequestTree getHandlers(SnmpMibRequest req,
+                                        boolean createflag, boolean atomic,
+                                        int type)
+        throws SnmpStatusException {
+
+        // Build an empty request tree
+        SnmpRequestTree handlers =
+            new SnmpRequestTree(req,createflag,type);
+
+        int index=0;
+        SnmpVarBind var = null;
+        final int ver= req.getVersion();
+
+        // For each varbind in the list finds its handling node.
+        for (Enumeration e= req.getElements(); e.hasMoreElements(); index++) {
+
+            var= (SnmpVarBind) e.nextElement();
+
+            try {
+                // Find the handling node for this varbind.
+                root.findHandlingNode(var,var.oid.longValue(false),
+                                      0,handlers);
+            } catch(SnmpStatusException x) {
+
+                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
+                    SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
+                            SnmpMib.class.getName(),
+                            "getHandlers",
+                            "Couldn't find a handling node for " +
+                            var.oid.toString());
+                }
+
+                // If the operation is atomic (Check/Set) or the version
+                // is V1 we must generate an exception.
+                //
+                if (ver == SnmpDefinitions.snmpVersionOne) {
+
+                    if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
+                        SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
+                                SnmpMib.class.getName(),
+                                "getHandlers", "\tV1: Throwing exception");
+                    }
+
+                    // The index in the exception must correspond to the
+                    // SNMP index ...
+                    //
+                    final SnmpStatusException sse =
+                        new SnmpStatusException(x, index + 1);
+                    sse.initCause(x);
+                    throw sse;
+                } else if ((type == SnmpDefinitions.pduWalkRequest)   ||
+                           (type == SnmpDefinitions.pduSetRequestPdu)) {
+                    final int status =
+                        SnmpRequestTree.mapSetException(x.getStatus(),ver);
+
+                    if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
+                        SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
+                                SnmpMib.class.getName(),
+                                "getHandlers", "\tSET: Throwing exception");
+                    }
+
+                    final SnmpStatusException sse =
+                        new SnmpStatusException(status, index + 1);
+                    sse.initCause(x);
+                    throw sse;
+                } else if (atomic) {
+
+                    // Should never come here...
+                    if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
+                        SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
+                                SnmpMib.class.getName(),
+                                "getHandlers", "\tATOMIC: Throwing exception");
+                    }
+
+                    final SnmpStatusException sse =
+                        new SnmpStatusException(x, index + 1);
+                    sse.initCause(x);
+                    throw sse;
+                }
+
+                final int status =
+                    SnmpRequestTree.mapGetException(x.getStatus(),ver);
+
+                if (status == SnmpStatusException.noSuchInstance) {
+
+                    if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
+                        SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
+                                SnmpMib.class.getName(),
+                                "getHandlers",
+                                "\tGET: Registering noSuchInstance");
+                    }
+
+                    var.value= SnmpVarBind.noSuchInstance;
+
+                } else if (status == SnmpStatusException.noSuchObject) {
+                    if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
+                        SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
+                                SnmpMib.class.getName(),
+                                "getHandlers",
+                                "\tGET: Registering noSuchObject");
+                    }
+
+                        var.value= SnmpVarBind.noSuchObject;
+
+                } else {
+
+                    if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
+                        SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
+                                SnmpMib.class.getName(),
+                                "getHandlers",
+                                "\tGET: Registering global error: " + status);
+                    }
+
+                    final SnmpStatusException sse =
+                        new SnmpStatusException(status, index + 1);
+                    sse.initCause(x);
+                    throw sse;
+                }
+            }
+        }
+        return handlers;
+    }
+
+    /**
+     * This method builds the temporary request-tree that will be used to
+     * perform the SNMP GET-NEXT request associated with the given vector
+     * of varbinds `list'.
+     *
+     * @param req The SnmpMibRequest object holding the varbind list
+     *             concerning this MIB.
+     *
+     * @return The request-tree where the original varbind list has been
+     *         dispatched to the appropriate nodes, and where the original
+     *         OIDs have been replaced with the correct "next" OID.
+     */
+    private SnmpRequestTree getGetNextHandlers(SnmpMibRequest req)
+        throws SnmpStatusException {
+
+        // Creates an empty request tree, no entry creation is allowed (false)
+        SnmpRequestTree handlers = new
+            SnmpRequestTree(req,false,SnmpDefinitions.pduGetNextRequestPdu);
+
+        // Sets the getNext flag: if version=V2, status exception are
+        // transformed in  endOfMibView
+        handlers.setGetNextFlag();
+
+        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
+            SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMib.class.getName(),
+                    "getGetNextHandlers", "Received MIB request : " + req);
+        }
+        AcmChecker checker = new AcmChecker(req);
+        int index=0;
+        SnmpVarBind var = null;
+        final int ver= req.getVersion();
+        SnmpOid original = null;
+        // For each varbind, finds the handling node.
+        // This function has the side effect of transforming a GET-NEXT
+        // request into a valid GET request, replacing the OIDs in the
+        // original GET-NEXT request with the OID of the first leaf that
+        // follows.
+        for (Enumeration e= req.getElements(); e.hasMoreElements(); index++) {
+
+            var = (SnmpVarBind) e.nextElement();
+            SnmpOid result = null;
+            try {
+                // Find the node handling the OID that follows the varbind
+                // OID. `result' contains this next leaf OID.
+                //ACM loop.
+                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
+                    SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
+                            SnmpMib.class.getName(),
+                            "getGetNextHandlers", " Next OID of : " + var.oid);
+                }
+                result = new SnmpOid(root.findNextHandlingNode
+                                     (var,var.oid.longValue(false),0,
+                                      0,handlers, checker));
+
+                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
+                    SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
+                            SnmpMib.class.getName(),
+                            "getGetNextHandlers", " is : " + result);
+                }
+                // We replace the varbind original OID with the OID of the
+                // leaf object we have to return.
+                var.oid = result;
+            } catch(SnmpStatusException x) {
+
+                // if (isDebugOn())
+                //    debug("getGetNextHandlers",
+                //        "Couldn't find a handling node for "
+                //        + var.oid.toString());
+
+                if (ver == SnmpDefinitions.snmpVersionOne) {
+                    if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
+                        SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
+                                SnmpMib.class.getName(),
+                                "getGetNextHandlers",
+                                "\tThrowing exception " + x.toString());
+                    }
+                    // The index in the exception must correspond to the
+                    // SNMP index ...
+                    //
+                    throw new SnmpStatusException(x, index + 1);
+                }
+                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
+                    SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
+                            SnmpMib.class.getName(),
+                            "getGetNextHandlers",
+                            "Exception : " + x.getStatus());
+                }
+
+                var.setSnmpValue(SnmpVarBind.endOfMibView);
+            }
+        }
+        return handlers;
+    }
+
+    // --------------------------------------------------------------------
+    // PROTECTED VARIABLES
+    // --------------------------------------------------------------------
+
+    /**
+     * The top element in the Mib tree.
+     * @serial
+     */
+    protected SnmpMibOid root;
+
+
+    // --------------------------------------------------------------------
+    // PRIVATE VARIABLES
+    // --------------------------------------------------------------------
+
+    /**
+     * The root object identifier of the MIB.
+     */
+    private transient long[] rootOid= null;
+}
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibAgent.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibAgent.java
new file mode 100644
index 0000000..c2d48cf
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibAgent.java
@@ -0,0 +1,757 @@
+/*
+ * Copyright 1998-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;
+
+
+
+// java imports
+//
+import java.io.Serializable;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.util.Set;
+
+// jmx imports
+//
+import javax.management.MBeanServer;
+import javax.management.MBeanRegistration;
+import javax.management.ObjectName;
+import javax.management.MalformedObjectNameException;
+import javax.management.InstanceNotFoundException;
+import javax.management.ServiceNotFoundException;
+import javax.management.ReflectionException;
+import javax.management.MBeanException;
+import com.sun.jmx.snmp.SnmpVarBind;
+import com.sun.jmx.snmp.SnmpDefinitions;
+import com.sun.jmx.snmp.SnmpStatusException;
+import com.sun.jmx.snmp.SnmpPdu;
+import com.sun.jmx.snmp.SnmpOid;
+import com.sun.jmx.snmp.SnmpEngine;
+
+/**
+ * Abstract class for representing an SNMP agent.
+ *
+ * The class is used by the SNMP protocol adaptor as the entry point in
+ * the SNMP agent to query.
+ *
+ * <p><b>This API is a Sun Microsystems internal API  and is subject
+ * to change without notice.</b></p>
+ */
+
+public abstract class SnmpMibAgent
+    implements SnmpMibAgentMBean, MBeanRegistration, Serializable {
+
+    /**
+     * Default constructor.
+     */
+    public SnmpMibAgent() {
+    }
+
+    // ---------------------------------------------------------------------
+    // PUBLIC METHODS
+    //----------------------------------------------------------------------
+
+    /**
+     * Initializes the MIB (with no registration of the MBeans into the
+     * MBean server).
+     *
+     * @exception IllegalAccessException The MIB can not be initialized.
+     */
+    public abstract void init() throws IllegalAccessException;
+
+    /**
+     * Initializes the MIB but each single MBean representing the MIB
+     * is inserted into the MBean server.
+     *
+     * @param server The MBean server to register the service with.
+     * @param name The object name.
+     *
+     * @return The name of the SNMP MIB registered.
+     *
+     * @exception java.lang.Exception
+     */
+    public abstract ObjectName preRegister(MBeanServer server,
+                                           ObjectName name)
+        throws java.lang.Exception;
+
+    /**
+     * Not used in this context.
+     */
+    public void postRegister (Boolean registrationDone) {
+    }
+
+    /**
+     * Not used in this context.
+     */
+    public void preDeregister() throws java.lang.Exception {
+    }
+
+    /**
+     * Not used in this context.
+     */
+    public void postDeregister() {
+    }
+
+    /**
+     * Processes a <CODE>get</CODE> operation.
+     * This method must update the SnmpVarBinds contained in the
+     * <var>{@link SnmpMibRequest} req</var> parameter.
+     *
+     * @param req The SnmpMibRequest object holding the list of variable to
+     *            be retrieved. This list is composed of
+     *            <CODE>SnmpVarBind</CODE> objects.
+     *
+     * @exception SnmpStatusException An error occured during the operation.
+     */
+    public abstract void get(SnmpMibRequest req)
+        throws SnmpStatusException;
+
+    /**
+     * Processes a <CODE>getNext</CODE> operation.
+     * This method must update the SnmpVarBinds contained in the
+     * <var>{@link SnmpMibRequest} req</var> parameter.
+     *
+     * @param req The SnmpMibRequest object holding the list of
+     *            OIDs from which the next variables should be retrieved.
+     *            This list is composed of <CODE>SnmpVarBind</CODE> objects.
+     *
+     * @exception SnmpStatusException An error occured during the operation.
+     */
+    public abstract void getNext(SnmpMibRequest req)
+        throws SnmpStatusException;
+
+    /**
+     * Processes a <CODE>getBulk</CODE> operation.
+     * This method must update the SnmpVarBinds contained in the
+     * <var>{@link SnmpMibRequest} req</var> parameter.
+     *
+     * @param req The SnmpMibRequest object holding the list of variable to
+     *            be retrieved. This list is composed of
+     *            <CODE>SnmpVarBind</CODE> objects.
+     *
+     * @param nonRepeat The number of variables, starting with the first
+     *    variable in the variable-bindings, for which a single
+     *    lexicographic successor is requested.
+     *
+     * @param maxRepeat The number of lexicographic successors requested
+     *    for each of the last R variables. R is the number of variables
+     *    following the first <CODE>nonRepeat</CODE> variables for which
+     *    multiple lexicographic successors are requested.
+     *
+     * @exception SnmpStatusException An error occured during the operation.
+     */
+    public abstract void getBulk(SnmpMibRequest req, int nonRepeat,
+                                 int maxRepeat)
+        throws SnmpStatusException;
+
+    /**
+     * Processes a <CODE>set</CODE> operation.
+     * This method must update the SnmpVarBinds contained in the
+     * <var>{@link SnmpMibRequest} req</var> parameter.
+     * This method is called during the second phase of the SET two-phase
+     * commit.
+     *
+     * @param req The SnmpMibRequest object holding the list of variable to
+     *            be set. This list is composed of
+     *            <CODE>SnmpVarBind</CODE> objects.
+     *
+     * @exception SnmpStatusException An error occured during the operation.
+     *            Throwing an exception in this method will break the
+     *            atomicity of the SET operation. Care must be taken so that
+     *            the exception is thrown in the {@link #check(SnmpMibRequest)}
+     *            method instead.
+     */
+    public abstract void set(SnmpMibRequest req)
+        throws SnmpStatusException;
+
+
+    /**
+     * Checks if a <CODE>set</CODE> operation can be performed.
+     * If the operation can not be performed, the method should throw an
+     * <CODE>SnmpStatusException</CODE>.
+     * This method is called during the first phase of the SET two-phase
+     * commit.
+     *
+     * @param req The SnmpMibRequest object holding the list of variable to
+     *            be set. This list is composed of
+     *            <CODE>SnmpVarBind</CODE> objects.
+     *
+     * @exception SnmpStatusException The <CODE>set</CODE> operation
+     *    cannot be performed.
+     */
+    public abstract void check(SnmpMibRequest req)
+        throws SnmpStatusException;
+
+    /**
+     * Gets the root object identifier of the MIB.
+     * <P>The root object identifier is the object identifier uniquely
+     * identifying the MIB.
+     *
+     * @return The root object identifier.
+     */
+    public abstract long[] getRootOid();
+
+    // ---------------------------------------------------------------------
+    // GETTERS AND SETTERS
+    // ---------------------------------------------------------------------
+
+    /**
+     * Gets the reference to the MBean server in which the SNMP MIB is
+     * registered.
+     *
+     * @return The MBean server or null if the MIB is not registered in any
+     *     MBean server.
+     */
+    public MBeanServer getMBeanServer() {
+        return server;
+    }
+
+    /**
+     * Gets the reference to the SNMP protocol adaptor to which the MIB is
+     * bound.
+     *
+     * @return The SNMP MIB handler.
+     */
+    public SnmpMibHandler getSnmpAdaptor() {
+        return adaptor;
+    }
+
+    /**
+     * Sets the reference to the SNMP protocol adaptor through which the MIB
+     * will be SNMP accessible and add this new MIB in the SNMP MIB handler.
+     *
+     * @param stack The SNMP MIB handler.
+     */
+    public void setSnmpAdaptor(SnmpMibHandler stack) {
+        if (adaptor != null) {
+            adaptor.removeMib(this);
+        }
+        adaptor = stack;
+        if (adaptor != null) {
+            adaptor.addMib(this);
+        }
+    }
+
+     /**
+     * Sets the reference to the SNMP protocol adaptor through which the MIB
+     * will be SNMP accessible and add this new MIB in the SNMP MIB handler.
+     * This method is to be called to set a specific agent to a specific OID. This can be useful when dealing with MIB overlapping.
+     * Some OID can be implemented in more than one MIB. In this case, the OID nearest the agent will be used on SNMP operations.
+     * @param stack The SNMP MIB handler.
+     * @param oids The set of OIDs this agent implements.
+     *
+     * @since 1.5
+     */
+    public void setSnmpAdaptor(SnmpMibHandler stack, SnmpOid[] oids) {
+        if (adaptor != null) {
+            adaptor.removeMib(this);
+        }
+        adaptor = stack;
+        if (adaptor != null) {
+            adaptor.addMib(this, oids);
+        }
+    }
+
+    /**
+     * Sets the reference to the SNMP protocol adaptor through which the MIB
+     * will be SNMP accessible and adds this new MIB in the SNMP MIB handler.
+     * Adds a new contextualized MIB in the SNMP MIB handler.
+     *
+     * @param stack The SNMP MIB handler.
+     * @param contextName The MIB context name. If null is passed, will be registered in the default context.
+     *
+     * @exception IllegalArgumentException If the parameter is null.
+     *
+     * @since 1.5
+     */
+    public void setSnmpAdaptor(SnmpMibHandler stack, String contextName) {
+        if (adaptor != null) {
+            adaptor.removeMib(this, contextName);
+        }
+        adaptor = stack;
+        if (adaptor != null) {
+            adaptor.addMib(this, contextName);
+        }
+    }
+    /**
+     * Sets the reference to the SNMP protocol adaptor through which the MIB
+     * will be SNMP accessible and adds this new MIB in the SNMP MIB handler.
+     * Adds a new contextualized MIB in the SNMP MIB handler.
+     *
+     * @param stack The SNMP MIB handler.
+     * @param contextName The MIB context name. If null is passed, will be registered in the default context.
+     * @param oids The set of OIDs this agent implements.
+     * @exception IllegalArgumentException If the parameter is null.
+     *
+     * @since 1.5
+     */
+    public void setSnmpAdaptor(SnmpMibHandler stack,
+                               String contextName,
+                               SnmpOid[] oids) {
+        if (adaptor != null) {
+            adaptor.removeMib(this, contextName);
+        }
+        adaptor = stack;
+        if (adaptor != null) {
+            adaptor.addMib(this, contextName, oids);
+        }
+    }
+
+    /**
+     * Gets the object name of the SNMP protocol adaptor to which the MIB
+     * is bound.
+     *
+     * @return The name of the SNMP protocol adaptor.
+     */
+    public ObjectName getSnmpAdaptorName() {
+        return adaptorName;
+    }
+
+    /**
+     * Sets the reference to the SNMP protocol adaptor through which the MIB
+     * will be SNMP accessible and add this new MIB in the SNMP MIB handler
+     * associated to the specified <CODE>name</CODE>.
+     *
+     * @param name The name of the SNMP protocol adaptor.
+     *
+     * @exception InstanceNotFoundException The SNMP protocol adaptor does
+     *     not exist in the MBean server.
+     *
+     * @exception ServiceNotFoundException This SNMP MIB is not registered
+     *     in the MBean server or the requested service is not supported.
+     */
+    public void setSnmpAdaptorName(ObjectName name)
+        throws InstanceNotFoundException, ServiceNotFoundException {
+
+        if (server == null) {
+            throw new ServiceNotFoundException(mibName + " is not registered in the MBean server");
+        }
+        // First remove the reference on the old adaptor server.
+        //
+        if (adaptor != null) {
+            adaptor.removeMib(this);
+        }
+
+        // Then update the reference to the new adaptor server.
+        //
+        Object[] params = {this};
+        String[] signature = {"com.sun.jmx.snmp.agent.SnmpMibAgent"};
+        try {
+            adaptor = (SnmpMibHandler)(server.invoke(name, "addMib", params,
+                                                     signature));
+        } catch (InstanceNotFoundException e) {
+            throw new InstanceNotFoundException(name.toString());
+        } catch (ReflectionException e) {
+            throw new ServiceNotFoundException(name.toString());
+        } catch (MBeanException e) {
+            // Should never occur...
+        }
+
+        adaptorName = name;
+    }
+    /**
+     * Sets the reference to the SNMP protocol adaptor through which the MIB
+     * will be SNMP accessible and add this new MIB in the SNMP MIB handler
+     * associated to the specified <CODE>name</CODE>.
+     * This method is to be called to set a specific agent to a specific OID. This can be useful when dealing with MIB overlapping.
+     * Some OID can be implemented in more than one MIB. In this case, the OID nearer agent will be used on SNMP operations.
+     * @param name The name of the SNMP protocol adaptor.
+     * @param oids The set of OIDs this agent implements.
+     * @exception InstanceNotFoundException The SNMP protocol adaptor does
+     *     not exist in the MBean server.
+     *
+     * @exception ServiceNotFoundException This SNMP MIB is not registered
+     *     in the MBean server or the requested service is not supported.
+     *
+     * @since 1.5
+     */
+    public void setSnmpAdaptorName(ObjectName name, SnmpOid[] oids)
+        throws InstanceNotFoundException, ServiceNotFoundException {
+
+        if (server == null) {
+            throw new ServiceNotFoundException(mibName + " is not registered in the MBean server");
+        }
+        // First remove the reference on the old adaptor server.
+        //
+        if (adaptor != null) {
+            adaptor.removeMib(this);
+        }
+
+        // Then update the reference to the new adaptor server.
+        //
+        Object[] params = {this, oids};
+        String[] signature = {"com.sun.jmx.snmp.agent.SnmpMibAgent",
+        oids.getClass().getName()};
+        try {
+            adaptor = (SnmpMibHandler)(server.invoke(name, "addMib", params,
+                                                     signature));
+        } catch (InstanceNotFoundException e) {
+            throw new InstanceNotFoundException(name.toString());
+        } catch (ReflectionException e) {
+            throw new ServiceNotFoundException(name.toString());
+        } catch (MBeanException e) {
+            // Should never occur...
+        }
+
+        adaptorName = name;
+    }
+    /**
+     * Sets the reference to the SNMP protocol adaptor through which the MIB
+     * will be SNMP accessible and add this new MIB in the SNMP MIB handler
+     * associated to the specified <CODE>name</CODE>.
+     *
+     * @param name The name of the SNMP protocol adaptor.
+     * @param contextName The MIB context name. If null is passed, will be registered in the default context.
+     * @exception InstanceNotFoundException The SNMP protocol adaptor does
+     *     not exist in the MBean server.
+     *
+     * @exception ServiceNotFoundException This SNMP MIB is not registered
+     *     in the MBean server or the requested service is not supported.
+     *
+     * @since 1.5
+     */
+    public void setSnmpAdaptorName(ObjectName name, String contextName)
+        throws InstanceNotFoundException, ServiceNotFoundException {
+
+        if (server == null) {
+            throw new ServiceNotFoundException(mibName + " is not registered in the MBean server");
+        }
+
+        // First remove the reference on the old adaptor server.
+        //
+        if (adaptor != null) {
+            adaptor.removeMib(this, contextName);
+        }
+
+        // Then update the reference to the new adaptor server.
+        //
+        Object[] params = {this, contextName};
+        String[] signature = {"com.sun.jmx.snmp.agent.SnmpMibAgent", "java.lang.String"};
+        try {
+            adaptor = (SnmpMibHandler)(server.invoke(name, "addMib", params,
+                                                     signature));
+        } catch (InstanceNotFoundException e) {
+            throw new InstanceNotFoundException(name.toString());
+        } catch (ReflectionException e) {
+            throw new ServiceNotFoundException(name.toString());
+        } catch (MBeanException e) {
+            // Should never occur...
+        }
+
+        adaptorName = name;
+    }
+
+    /**
+     * Sets the reference to the SNMP protocol adaptor through which the MIB
+     * will be SNMP accessible and add this new MIB in the SNMP MIB handler
+     * associated to the specified <CODE>name</CODE>.
+     *
+     * @param name The name of the SNMP protocol adaptor.
+     * @param contextName The MIB context name. If null is passed, will be registered in the default context.
+     * @param oids The set of OIDs this agent implements.
+     * @exception InstanceNotFoundException The SNMP protocol adaptor does
+     *     not exist in the MBean server.
+     *
+     * @exception ServiceNotFoundException This SNMP MIB is not registered
+     *     in the MBean server or the requested service is not supported.
+     *
+     * @since 1.5
+     */
+    public void setSnmpAdaptorName(ObjectName name,
+                                   String contextName, SnmpOid[] oids)
+        throws InstanceNotFoundException, ServiceNotFoundException {
+
+        if (server == null) {
+            throw new ServiceNotFoundException(mibName + " is not registered in the MBean server");
+        }
+
+        // First remove the reference on the old adaptor server.
+        //
+        if (adaptor != null) {
+            adaptor.removeMib(this, contextName);
+        }
+
+        // Then update the reference to the new adaptor server.
+        //
+        Object[] params = {this, contextName, oids};
+        String[] signature = {"com.sun.jmx.snmp.agent.SnmpMibAgent", "java.lang.String", oids.getClass().getName()};
+        try {
+            adaptor = (SnmpMibHandler)(server.invoke(name, "addMib", params,
+                                                     signature));
+        } catch (InstanceNotFoundException e) {
+            throw new InstanceNotFoundException(name.toString());
+        } catch (ReflectionException e) {
+            throw new ServiceNotFoundException(name.toString());
+        } catch (MBeanException e) {
+            // Should never occur...
+        }
+
+        adaptorName = name;
+    }
+
+    /**
+     * Indicates whether or not the MIB module is bound to a SNMP protocol
+     * adaptor.
+     * As a reminder, only bound MIBs can be accessed through SNMP protocol
+     * adaptor.
+     *
+     * @return <CODE>true</CODE> if the MIB module is bound,
+     *         <CODE>false</CODE> otherwise.
+     */
+    public boolean getBindingState() {
+        if (adaptor == null)
+            return false;
+        else
+            return true;
+    }
+
+    /**
+     * Gets the MIB name.
+     *
+     * @return The MIB name.
+     */
+    public String getMibName() {
+        return mibName;
+    }
+
+    /**
+     * This is a factory method for creating new SnmpMibRequest objects.
+     * @param reqPdu The received PDU.
+     * @param vblist   The vector of SnmpVarBind objects in which the
+     *        MIB concerned by this request is involved.
+     * @param version  The protocol version of the SNMP request.
+     * @param userData User allocated contextual data.
+     *
+     * @return A new SnmpMibRequest object.
+     *
+     * @since 1.5
+     **/
+    public static SnmpMibRequest newMibRequest(SnmpPdu reqPdu,
+                                               Vector<SnmpVarBind> vblist,
+                                               int version,
+                                               Object userData)
+    {
+        return new SnmpMibRequestImpl(null,
+                                      reqPdu,
+                                      vblist,
+                                      version,
+                                      userData,
+                                      null,
+                                      SnmpDefinitions.noAuthNoPriv,
+                                      getSecurityModel(version),
+                                      null,null);
+    }
+    /**
+     * This is a factory method for creating new SnmpMibRequest objects.
+     * @param engine The local engine.
+     * @param reqPdu The received pdu.
+     * @param vblist The vector of SnmpVarBind objects in which the
+     *        MIB concerned by this request is involved.
+     * @param version The protocol version of the SNMP request.
+     * @param userData User allocated contextual data.
+     *
+     * @return A new SnmpMibRequest object.
+     *
+     * @since 1.5
+     **/
+    public static SnmpMibRequest newMibRequest(SnmpEngine engine,
+                                               SnmpPdu reqPdu,
+                                               Vector<SnmpVarBind> vblist,
+                                               int version,
+                                               Object userData,
+                                               String principal,
+                                               int securityLevel,
+                                               int securityModel,
+                                               byte[] contextName,
+                                               byte[] accessContextName) {
+        return new SnmpMibRequestImpl(engine,
+                                      reqPdu,
+                                      vblist,
+                                      version,
+                                      userData,
+                                      principal,
+                                      securityLevel,
+                                      securityModel,
+                                      contextName,
+                                      accessContextName);
+    }
+    // ---------------------------------------------------------------------
+    // PACKAGE METHODS
+    // ---------------------------------------------------------------------
+
+    /**
+     * Processes a <CODE>getBulk</CODE> operation using call to
+     * <CODE>getNext</CODE>.
+     * The method implements the <CODE>getBulk</CODE> operation by calling
+     * appropriately the <CODE>getNext</CODE> method.
+     *
+     * @param req The SnmpMibRequest containing the variable list to be
+     *        retrieved.
+     *
+     * @param nonRepeat The number of variables, starting with the first
+     *    variable in the variable-bindings, for which a single lexicographic
+     *    successor is requested.
+     *
+     * @param maxRepeat The number of lexicographic successors
+     *    requested for each of the last R variables. R is the number of
+     *    variables following the first nonRepeat variables for which
+     *    multiple lexicographic successors are requested.
+     *
+     * @return The variable list containing returned values.
+     *
+     * @exception SnmpStatusException An error occured during the operation.
+     */
+    void getBulkWithGetNext(SnmpMibRequest req, int nonRepeat, int maxRepeat)
+        throws SnmpStatusException {
+        final Vector<SnmpVarBind> list = req.getSubList();
+
+        // RFC 1905, Section 4.2.3, p14
+        final int L = list.size() ;
+        final int N = Math.max(Math.min(nonRepeat, L), 0) ;
+        final int M = Math.max(maxRepeat, 0) ;
+        final int R = L - N ;
+
+        // Let's build the varBindList for the response pdu
+        //
+        // int errorStatus = SnmpDefinitions.snmpRspNoError ;
+        // int errorIndex = 0 ;
+        if (L != 0) {
+
+            // Non-repeaters and first row of repeaters
+            //
+            getNext(req);
+
+            // Now the remaining repeaters
+            //
+            Vector<SnmpVarBind> repeaters= splitFrom(list, N);
+            SnmpMibRequestImpl repeatedReq =
+                new SnmpMibRequestImpl(req.getEngine(),
+                                       req.getPdu(),
+                                       repeaters,
+                                       SnmpDefinitions.snmpVersionTwo,
+                                       req.getUserData(),
+                                       req.getPrincipal(),
+                                       req.getSecurityLevel(),
+                                       req.getSecurityModel(),
+                                       req.getContextName(),
+                                       req.getAccessContextName());
+            for (int i = 2 ; i <= M ; i++) {
+                getNext(repeatedReq);
+                concatVector(req, repeaters);
+            }
+        }
+    }
+
+
+    // ---------------------------------------------------------------------
+    // PRIVATE METHODS
+    // ---------------------------------------------------------------------
+
+    /**
+     * This method creates a new Vector which does not contain the first
+     * element up to the specified limit.
+     *
+     * @param original The original vector.
+     * @param limit The limit.
+     */
+    private Vector<SnmpVarBind> splitFrom(Vector<SnmpVarBind> original, int limit) {
+
+        int max= original.size();
+        Vector<SnmpVarBind> result= new Vector<SnmpVarBind>(max - limit);
+        int i= limit;
+
+        // Ok the loop looks a bit strange. But in order to improve the
+        // perf, we try to avoid reference to the limit variable from
+        // within the loop ...
+        //
+        for(Enumeration<SnmpVarBind> e= original.elements(); e.hasMoreElements(); --i) {
+            SnmpVarBind var= e.nextElement();
+            if (i >0)
+                continue;
+            result.addElement(new SnmpVarBind(var.oid, var.value));
+        }
+        return result;
+    }
+
+    private void concatVector(SnmpMibRequest req, Vector source) {
+        for(Enumeration e= source.elements(); e.hasMoreElements(); ) {
+            SnmpVarBind var= (SnmpVarBind) e.nextElement();
+            // We need to duplicate the SnmpVarBind otherwise it is going
+            // to be overloaded by the next get Next ...
+            req.addVarBind(new SnmpVarBind(var.oid, var.value));
+        }
+    }
+
+    private void concatVector(Vector<SnmpVarBind> target, Vector<SnmpVarBind> source) {
+        for(Enumeration<SnmpVarBind> e= source.elements(); e.hasMoreElements(); ) {
+            SnmpVarBind var= e.nextElement();
+            // We need to duplicate the SnmpVarBind otherwise it is going
+            // to be overloaded by the next get Next ...
+            target.addElement(new SnmpVarBind(var.oid, var.value));
+        }
+    }
+
+    private static int getSecurityModel(int version) {
+        switch(version) {
+        case SnmpDefinitions.snmpVersionOne:
+            return SnmpDefinitions.snmpV1SecurityModel;
+        default:
+            return SnmpDefinitions.snmpV2SecurityModel;
+        }
+    }
+
+    // ---------------------------------------------------------------------
+    // PROTECTED VARIABLES
+    // ---------------------------------------------------------------------
+
+    /**
+     * The object name of the MIB.
+     * @serial
+     */
+    protected String mibName;
+
+    /**
+     * The reference to the MBean server.
+     * @serial
+     */
+    protected MBeanServer server;
+
+    // ---------------------------------------------------------------------
+    // PRIVATE VARIABLES
+    // ---------------------------------------------------------------------
+
+    /**
+     * The object name of the SNMP protocol adaptor.
+     * @serial
+     */
+    private ObjectName adaptorName;
+
+    /**
+     * The reference to the SNMP stack.
+     */
+    private transient SnmpMibHandler adaptor;
+}
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibAgentMBean.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibAgentMBean.java
new file mode 100644
index 0000000..315ab02
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibAgentMBean.java
@@ -0,0 +1,316 @@
+/*
+ * Copyright 1999-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;
+
+
+
+// java imports
+//
+import java.util.Vector;
+
+// jmx imports
+//
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.MalformedObjectNameException;
+import javax.management.InstanceNotFoundException;
+import javax.management.ServiceNotFoundException;
+import com.sun.jmx.snmp.SnmpOid;
+import com.sun.jmx.snmp.SnmpStatusException;
+
+/**
+ * Exposes the remote management interface of the <CODE>SnmpMibAgent</CODE> MBean.
+ *
+ * <p><b>This API is a Sun Microsystems internal API  and is subject
+ * to change without notice.</b></p>
+ */
+
+public interface SnmpMibAgentMBean {
+
+    // PUBLIC METHODS
+    //---------------
+
+    /**
+     * Processes a <CODE>get</CODE> operation.
+     * This method must not be called from remote.
+     *
+     * @param req The SnmpMibRequest object holding the list of variables to
+     *            be retrieved. This list is composed of
+     *            <CODE>SnmpVarBind</CODE> objects.
+     *
+     * @exception SnmpStatusException An error occured during the operation.
+     * @see SnmpMibAgent#get(SnmpMibRequest)
+     */
+    public void get(SnmpMibRequest req) throws SnmpStatusException;
+
+    /**
+     * Processes a <CODE>getNext</CODE> operation.
+     * This method must not be called from remote.
+     *
+     * @param req The SnmpMibRequest object holding the list of variables to
+     *            be retrieved. This list is composed of
+     *            <CODE>SnmpVarBind</CODE> objects.
+     *
+     * @exception SnmpStatusException An error occured during the operation.
+     * @see SnmpMibAgent#getNext(SnmpMibRequest)
+     */
+    public void getNext(SnmpMibRequest req) throws SnmpStatusException;
+
+    /**
+     * Processes a <CODE>getBulk</CODE> operation.
+     * This method must not be called from remote.
+     *
+     * @param req The SnmpMibRequest object holding the list of variables to
+     *            be retrieved. This list is composed of
+     *            <CODE>SnmpVarBind</CODE> objects.
+     *
+     * @param nonRepeat The number of variables, starting with the first
+     *    variable in the variable-bindings, for which a single
+     *    lexicographic successor is requested.
+     *
+     * @param maxRepeat The number of lexicographic successors requested
+     *    for each of the last R variables. R is the number of variables
+     *    following the first <CODE>nonRepeat</CODE> variables for which
+     *    multiple lexicographic successors are requested.
+     *
+     * @exception SnmpStatusException An error occured during the operation.
+     * @see SnmpMibAgent#getBulk(SnmpMibRequest,int,int)
+     */
+    public void getBulk(SnmpMibRequest req, int nonRepeat, int maxRepeat)
+        throws SnmpStatusException;
+
+    /**
+     * Processes a <CODE>set</CODE> operation.
+     * This method must not be called from remote.
+     *
+     * @param req The SnmpMibRequest object holding the list of variables to
+     *            be set. This list is composed of
+     *            <CODE>SnmpVarBind</CODE> objects.
+     *
+     * @exception SnmpStatusException An error occured during the operation.
+     * @see SnmpMibAgent#set(SnmpMibRequest)
+     */
+    public void set(SnmpMibRequest req) throws SnmpStatusException;
+
+    /**
+     * Checks if a <CODE>set</CODE> operation can be performed.
+     * If the operation cannot be performed, the method should emit a
+     * <CODE>SnmpStatusException</CODE>.
+     *
+     * @param req The SnmpMibRequest object holding the list of variables to
+     *            be set. This list is composed of
+     *            <CODE>SnmpVarBind</CODE> objects.
+     *
+     * @exception SnmpStatusException The <CODE>set</CODE> operation
+     *    cannot be performed.
+     * @see SnmpMibAgent#check(SnmpMibRequest)
+     */
+    public void check(SnmpMibRequest req) throws SnmpStatusException;
+
+    // GETTERS AND SETTERS
+    //--------------------
+
+    /**
+     * Gets the reference to the MBean server in which the SNMP MIB is
+     * registered.
+     *
+     * @return The MBean server or null if the MIB is not registered in any
+     *         MBean server.
+     */
+    public MBeanServer getMBeanServer();
+
+    /**
+     * Gets the reference to the SNMP protocol adaptor to which the MIB is
+     * bound.
+     * <BR>This method is used for accessing the SNMP MIB handler property
+     * of the SNMP MIB agent in case of a standalone agent.
+     *
+     * @return The SNMP MIB handler.
+     */
+    public SnmpMibHandler getSnmpAdaptor();
+
+    /**
+     * Sets the reference to the SNMP protocol adaptor through which the
+     * MIB will be SNMP accessible and add this new MIB in the SNMP MIB
+     * handler.
+     * <BR>This method is used for setting the SNMP MIB handler property of
+     * the SNMP MIB agent in case of a standalone agent.
+     *
+     * @param stack The SNMP MIB handler.
+     */
+    public void setSnmpAdaptor(SnmpMibHandler stack);
+
+    /**
+     * Sets the reference to the SNMP protocol adaptor through which the MIB
+     * will be SNMP accessible and add this new MIB in the SNMP MIB handler.
+     * This method is to be called to set a specific agent to a specific OID.
+     * This can be useful when dealing with MIB overlapping.
+     * Some OID can be implemented in more than one MIB. In this case, the
+     * OID nearer agent will be used on SNMP operations.
+     * @param stack The SNMP MIB handler.
+     * @param oids The set of OIDs this agent implements.
+     *
+     * @since 1.5
+     */
+    public void setSnmpAdaptor(SnmpMibHandler stack, SnmpOid[] oids);
+
+    /**
+     * Sets the reference to the SNMP protocol adaptor through which the MIB
+     * will be SNMP accessible and add this new MIB in the SNMP MIB handler.
+     * Adds a new contextualized MIB in the SNMP MIB handler.
+     *
+     * @param stack The SNMP MIB handler.
+     * @param contextName The MIB context name. If null is passed, will be
+     *        registered in the default context.
+     *
+     * @exception IllegalArgumentException If the parameter is null.
+     *
+     * @since 1.5
+     */
+    public void setSnmpAdaptor(SnmpMibHandler stack, String contextName);
+
+    /**
+     * Sets the reference to the SNMP protocol adaptor through which the MIB
+     * will be SNMP accessible and adds this new MIB in the SNMP MIB handler.
+     * Adds a new contextualized MIB in the SNMP MIB handler.
+     *
+     * @param stack The SNMP MIB handler.
+     * @param contextName The MIB context name. If null is passed, will be
+     *        registered in the default context.
+     * @param oids The set of OIDs this agent implements.
+     * @exception IllegalArgumentException If the parameter is null.
+     *
+     * @since 1.5
+     */
+    public void setSnmpAdaptor(SnmpMibHandler stack,
+                               String contextName,
+                               SnmpOid[] oids);
+
+    /**
+     * Gets the object name of the SNMP protocol adaptor to which the MIB is
+     * bound.
+     *
+     * @return The name of the SNMP protocol adaptor.
+     */
+    public ObjectName getSnmpAdaptorName();
+
+    /**
+     * Sets the reference to the SNMP protocol adaptor through which the MIB
+     * will be SNMP accessible and add this new MIB in the SNMP MIB handler
+     * associated to the specified <CODE>name</CODE>.
+     *
+     * @param name The object name of the SNMP MIB handler.
+     *
+     * @exception InstanceNotFoundException The MBean does not exist in the
+     *        MBean server.
+     * @exception ServiceNotFoundException This SNMP MIB is not registered
+     *        in the MBean server or the requested service is not supported.
+     */
+    public void setSnmpAdaptorName(ObjectName name)
+        throws InstanceNotFoundException, ServiceNotFoundException;
+
+
+    /**
+     * Sets the reference to the SNMP protocol adaptor through which the MIB
+     * will be SNMP accessible and add this new MIB in the SNMP MIB handler
+     * associated to the specified <CODE>name</CODE>.
+     * This method is to be called to set a specific agent to a specific OID.
+     * This can be useful when dealing with MIB overlapping.
+     * Some OID can be implemented in more than one MIB. In this case, the
+     * OID nearer agent will be used on SNMP operations.
+     * @param name The name of the SNMP protocol adaptor.
+     * @param oids The set of OIDs this agent implements.
+     * @exception InstanceNotFoundException The SNMP protocol adaptor does
+     *     not exist in the MBean server.
+     *
+     * @exception ServiceNotFoundException This SNMP MIB is not registered
+     *     in the MBean server or the requested service is not supported.
+     *
+     * @since 1.5
+     */
+    public void setSnmpAdaptorName(ObjectName name, SnmpOid[] oids)
+        throws InstanceNotFoundException, ServiceNotFoundException;
+
+    /**
+     * Sets the reference to the SNMP protocol adaptor through which the MIB
+     * will be SNMP accessible and add this new MIB in the SNMP MIB handler
+     * associated to the specified <CODE>name</CODE>.
+     *
+     * @param name The name of the SNMP protocol adaptor.
+     * @param contextName The MIB context name. If null is passed, will be
+     *     registered in the default context.
+     * @exception InstanceNotFoundException The SNMP protocol adaptor does
+     *     not exist in the MBean server.
+     *
+     * @exception ServiceNotFoundException This SNMP MIB is not registered
+     *     in the MBean server or the requested service is not supported.
+     *
+     * @since 1.5
+     */
+    public void setSnmpAdaptorName(ObjectName name, String contextName)
+        throws InstanceNotFoundException, ServiceNotFoundException;
+
+     /**
+     * Sets the reference to the SNMP protocol adaptor through which the MIB
+     * will be SNMP accessible and add this new MIB in the SNMP MIB handler
+     * associated to the specified <CODE>name</CODE>.
+     *
+     * @param name The name of the SNMP protocol adaptor.
+     * @param contextName The MIB context name. If null is passed, will be
+     *        registered in the default context.
+     * @param oids The set of OIDs this agent implements.
+     * @exception InstanceNotFoundException The SNMP protocol adaptor does
+     *     not exist in the MBean server.
+     *
+     * @exception ServiceNotFoundException This SNMP MIB is not registered
+     *     in the MBean server or the requested service is not supported.
+     *
+     * @since 1.5
+     */
+    public void setSnmpAdaptorName(ObjectName name,
+                                   String contextName,
+                                   SnmpOid[] oids)
+        throws InstanceNotFoundException, ServiceNotFoundException;
+
+    /**
+     * Indicates whether or not the MIB module is bound to a SNMP protocol
+     * adaptor.
+     * As a reminder, only bound MIBs can be accessed through SNMP protocol
+     * adaptor.
+     *
+     * @return <CODE>true</CODE> if the MIB module is bound,
+     *         <CODE>false</CODE> otherwise.
+     */
+    public boolean getBindingState();
+
+    /**
+     * Gets the MIB name.
+     *
+     * @return The MIB name.
+     */
+    public String getMibName();
+}
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibEntry.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibEntry.java
new file mode 100644
index 0000000..2553304
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibEntry.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2000-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;
+
+// java imports
+//
+import java.io.Serializable;
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+// jmx imports
+//
+import com.sun.jmx.snmp.SnmpValue;
+import com.sun.jmx.snmp.SnmpVarBind;
+import com.sun.jmx.snmp.SnmpStatusException;
+import com.sun.jmx.snmp.agent.SnmpMibOid;
+import com.sun.jmx.snmp.agent.SnmpMibNode;
+
+/**
+ * Represents a node in an SNMP MIB which corresponds to a table entry
+ * meta node.
+ * <P>
+ * This class is used by the class generated by <CODE>mibgen</CODE>.
+ * You should not need to use this class directly.
+ *
+ * <p><b>This API is a Sun Microsystems internal API  and is subject
+ * to change without notice.</b></p>
+ */
+
+public abstract class SnmpMibEntry extends SnmpMibNode
+    implements Serializable {
+
+    /**
+     * Tells whether the given arc identifies a variable (scalar object) in
+     * this entry.
+     *
+     * @param arc An OID arc.
+     *
+     * @return <CODE>true</CODE> if `arc' leads to a variable.
+     */
+    public abstract boolean isVariable(long arc);
+
+    /**
+     * Tells whether the given arc identifies a readable scalar object in
+     * this entry.
+     *
+     * @param arc An OID arc.
+     *
+     * @return <CODE>true</CODE> if `arc' leads to a readable variable.
+     */
+    public abstract boolean isReadable(long arc);
+
+    /**
+     * Get the next OID arc corresponding to a readable scalar variable.
+     *
+     */
+    public long getNextVarId(long id, Object userData)
+        throws SnmpStatusException {
+        long nextvar = super.getNextVarId(id,userData);
+        while (!isReadable(nextvar))
+            nextvar = super.getNextVarId(nextvar,userData);
+        return nextvar;
+    }
+
+    /**
+     * Checks whether the given OID arc identifies a variable (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.
+     *
+     * @exception If the given `arc' does not identify any variable in this
+     *    group, throws an SnmpStatusException.
+     */
+    public void validateVarId(long arc, Object userData)
+        throws SnmpStatusException {
+        if (isVariable(arc) == false) throw noSuchNameException;
+    }
+
+    /**
+     * Generic handling of the <CODE>get</CODE> operation.
+     * <p>The actual implementation of this method will be generated
+     * by mibgen. Usually, this implementation only delegates the
+     * job to some other provided runtime class, which knows how to
+     * access the MBean. The current toolkit thus provides two
+     * implementations:
+     * <ul><li>The standard implementation will directly access the
+     *         MBean through a java reference,</li>
+     *     <li>The generic implementation will access the MBean through
+     *         the MBean server.</li>
+     * </ul>
+     * <p>Both implementations rely upon specific - and distinct, set of
+     * mibgen generated methods.
+     * <p> You can override this method if you need to implement some
+     * specific policies for minimizing the accesses made to some remote
+     * underlying resources.
+     * <p>
+     *
+     * @param req   The sub-request that must be handled by this node.
+     *
+     * @param depth The depth reached in the OID tree.
+     *
+     * @exception SnmpStatusException An error occurred while accessing
+     *  the MIB node.
+     */
+    abstract public void get(SnmpMibSubRequest req, int depth)
+        throws SnmpStatusException;
+
+    /**
+     * Generic handling of the <CODE>set</CODE> operation.
+     * <p>The actual implementation of this method will be generated
+     * by mibgen. Usually, this implementation only delegates the
+     * job to some other provided runtime class, which knows how to
+     * access the MBean. The current toolkit thus provides two
+     * implementations:
+     * <ul><li>The standard implementation will directly access the
+     *         MBean through a java reference,</li>
+     *     <li>The generic implementation will access the MBean through
+     *         the MBean server.</li>
+     * </ul>
+     * <p>Both implementations rely upon specific - and distinct, set of
+     * mibgen generated methods.
+     * <p> You can override this method if you need to implement some
+     * specific policies for minimizing the accesses made to some remote
+     * underlying resources.
+     * <p>
+     *
+     * @param req   The sub-request that must be handled by this node.
+     *
+     * @param depth The depth reached in the OID tree.
+     *
+     * @exception SnmpStatusException An error occurred while accessing
+     *  the MIB node.
+     */
+    abstract public void set(SnmpMibSubRequest req, int depth)
+        throws SnmpStatusException;
+
+    /**
+     * Generic handling of the <CODE>check</CODE> operation.
+     *
+     * <p>The actual implementation of this method will be generated
+     * by mibgen. Usually, this implementation only delegates the
+     * job to some other provided runtime class, which knows how to
+     * access the MBean. The current toolkit thus provides two
+     * implementations:
+     * <ul><li>The standard implementation will directly access the
+     *         MBean through a java reference,</li>
+     *     <li>The generic implementation will access the MBean through
+     *         the MBean server.</li>
+     * </ul>
+     * <p>Both implementations rely upon specific - and distinct, set of
+     * mibgen generated methods.
+     * <p> You can override this method if you need to implement some
+     * 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.
+     * <p>
+     *
+     * @param req   The sub-request that must be handled by this node.
+     *
+     * @param depth The depth reached in the OID tree.
+     *
+     * @exception SnmpStatusException An error occurred while accessing
+     *  the MIB node.
+     */
+    abstract public void check(SnmpMibSubRequest req, int depth)
+        throws SnmpStatusException;
+
+}
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibGroup.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibGroup.java
new file mode 100644
index 0000000..bf8ffba
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibGroup.java
@@ -0,0 +1,519 @@
+/*
+ * Copyright 1999-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;
+
+// java imports
+//
+import java.io.Serializable;
+import java.util.Hashtable;
+import java.util.Enumeration;
+import java.util.Vector;
+
+// jmx imports
+//
+import com.sun.jmx.snmp.SnmpOid;
+import com.sun.jmx.snmp.SnmpValue;
+import com.sun.jmx.snmp.SnmpVarBind;
+import com.sun.jmx.snmp.SnmpStatusException;
+
+// SNMP Runtime imports
+//
+import com.sun.jmx.snmp.agent.SnmpMibOid;
+import com.sun.jmx.snmp.agent.SnmpMibNode;
+
+/**
+ * Represents a node in an SNMP MIB which corresponds to a group.
+ * This class allows subnodes to be registered below a group, providing
+ * support for nested groups. The subnodes are registered at run time
+ * when registering the nested groups in the global MIB OID tree.
+ * <P>
+ * This class is used by the class generated by <CODE>mibgen</CODE>.
+ * You should not need to use this class directly.
+ *
+ * <p><b>This API is a Sun Microsystems internal API  and is subject
+ * to change without notice.</b></p>
+ */
+
+public abstract class SnmpMibGroup extends SnmpMibOid
+    implements Serializable {
+
+    // We will register the OID arcs leading to subgroups in this hashtable.
+    // So for each arc in varList, if the arc is also in subgroups, it leads
+    // to a subgroup, if it is not in subgroup, it leads either to a table
+    // or to a variable.
+    protected Hashtable<Long, Long> subgroups = null;
+
+    /**
+     * Tells whether the given arc identifies a table in this group.
+     *
+     * @param arc An OID arc.
+     *
+     * @return <CODE>true</CODE> if `arc' leads to a table.
+     */
+    public abstract boolean      isTable(long arc);
+
+    /**
+     * Tells whether the given arc identifies a variable (scalar object) in
+     * this group.
+     *
+     * @param arc An OID arc.
+     *
+     * @return <CODE>true</CODE> if `arc' leads to a variable.
+     */
+    public abstract boolean      isVariable(long arc);
+
+    /**
+     * Tells whether the given arc identifies a readable scalar object in
+     * this group.
+     *
+     * @param arc An OID arc.
+     *
+     * @return <CODE>true</CODE> if `arc' leads to a readable variable.
+     */
+    public abstract boolean      isReadable(long arc);
+
+
+    /**
+     * Gets the table identified by the given `arc'.
+     *
+     * @param arc An OID arc.
+     *
+     * @return The <CODE>SnmpMibTable</CODE> identified by `arc', or
+     *    <CODE>null</CODE> if `arc' does not identify any table.
+     */
+    public abstract SnmpMibTable getTable(long arc);
+
+    /**
+     * Checks whether the given OID arc identifies a variable (scalar
+     * object).
+     *
+     * @exception If the given `arc' does not identify any variable in this
+     *    group, throws an SnmpStatusException.
+     */
+    public void validateVarId(long arc, Object userData)
+        throws SnmpStatusException {
+        if (isVariable(arc) == false)
+            throw noSuchObjectException;
+    }
+
+
+    // -------------------------------------------------------------------
+    // We use a hashtable (subgroup) in order to determine whether an
+    // OID arc leads to a subgroup. This implementation can be changed if
+    // needed...
+    // For instance, the subclass could provide a generated isNestedArc()
+    // method in which the subgroup OID arcs would be hardcoded.
+    // However, the generic approach was prefered because at this time
+    // groups and subgroups are dynamically registered in the MIB.
+    //
+    /**
+     * Tell whether the given OID arc identifies a sub-tree
+     * leading to a nested SNMP sub-group. This method is used internally.
+     * You shouldn't need to call it directly.
+     *
+     * @param arc An OID arc.
+     *
+     * @return <CODE>true</CODE> if the given OID arc identifies a subtree
+     * leading to a nested SNMP sub-group.
+     *
+     */
+    public boolean isNestedArc(long arc) {
+        if (subgroups == null) return false;
+        Object obj = subgroups.get(new Long(arc));
+        // if the arc is registered in the hashtable,
+        // it leads to a subgroup.
+        return (obj != null);
+    }
+
+    /**
+     * Generic handling of the <CODE>get</CODE> operation.
+     * <p>The actual implementation of this method will be generated
+     * by mibgen. Usually, this implementation only delegates the
+     * job to some other provided runtime class, which knows how to
+     * access the MBean. The current toolkit thus provides two
+     * implementations:
+     * <ul><li>The standard implementation will directly access the
+     *         MBean through a java reference,</li>
+     *     <li>The generic implementation will access the MBean through
+     *         the MBean server.</li>
+     * </ul>
+     * <p>Both implementations rely upon specific - and distinct, set of
+     * mibgen generated methods.
+     * <p> You can override this method if you need to implement some
+     * specific policies for minimizing the accesses made to some remote
+     * underlying resources.
+     * <p>
+     *
+     * @param req   The sub-request that must be handled by this node.
+     *
+     * @param depth The depth reached in the OID tree.
+     *
+     * @exception SnmpStatusException An error occurred while accessing
+     *  the MIB node.
+     */
+    abstract public void get(SnmpMibSubRequest req, int depth)
+        throws SnmpStatusException;
+
+    /**
+     * Generic handling of the <CODE>set</CODE> operation.
+     * <p>The actual implementation of this method will be generated
+     * by mibgen. Usually, this implementation only delegates the
+     * job to some other provided runtime class, which knows how to
+     * access the MBean. The current toolkit thus provides two
+     * implementations:
+     * <ul><li>The standard implementation will directly access the
+     *         MBean through a java reference,</li>
+     *     <li>The generic implementation will access the MBean through
+     *         the MBean server.</li>
+     * </ul>
+     * <p>Both implementations rely upon specific - and distinct, set of
+     * mibgen generated methods.
+     * <p> You can override this method if you need to implement some
+     * specific policies for minimizing the accesses made to some remote
+     * underlying resources.
+     * <p>
+     *
+     * @param req   The sub-request that must be handled by this node.
+     *
+     * @param depth The depth reached in the OID tree.
+     *
+     * @exception SnmpStatusException An error occurred while accessing
+     *  the MIB node.
+     */
+    abstract public void set(SnmpMibSubRequest req, int depth)
+        throws SnmpStatusException;
+
+    /**
+     * Generic handling of the <CODE>check</CODE> operation.
+     *
+     * <p>The actual implementation of this method will be generated
+     * by mibgen. Usually, this implementation only delegates the
+     * job to some other provided runtime class, which knows how to
+     * access the MBean. The current toolkit thus provides two
+     * implementations:
+     * <ul><li>The standard implementation will directly access the
+     *         MBean through a java reference,</li>
+     *     <li>The generic implementation will access the MBean through
+     *         the MBean server.</li>
+     * </ul>
+     * <p>Both implementations rely upon specific - and distinct, set of
+     * mibgen generated methods.
+     * <p> You can override this method if you need to implement some
+     * 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.
+     * <p>
+     *
+     * @param req   The sub-request that must be handled by this node.
+     *
+     * @param depth The depth reached in the OID tree.
+     *
+     * @exception SnmpStatusException An error occurred while accessing
+     *  the MIB node.
+     */
+    abstract public void check(SnmpMibSubRequest req, int depth)
+        throws SnmpStatusException;
+
+    // --------------------------------------------------------------------
+    // If we reach this node, we are below the root OID, so we just
+    // return.
+    // --------------------------------------------------------------------
+    public void getRootOid(Vector result) {
+        return;
+    }
+
+    // -------------------------------------------------------------------
+    // PACKAGE METHODS
+    // -------------------------------------------------------------------
+
+    // -------------------------------------------------------------------
+    // This method can also be overriden in a subclass to provide a
+    // different implementation of the isNestedArc() method.
+    // => if isNestedArc() is hardcoded, then registerSubArc() becomes
+    //    useless and can become empty.
+    /**
+     * Register an OID arc that identifies a sub-tree
+     * leading to a nested SNMP sub-group. This method is used internally.
+     * You shouldn't ever call it directly.
+     *
+     * @param arc An OID arc.
+     *
+     */
+    void registerNestedArc(long arc) {
+        Long obj = new Long(arc);
+        if (subgroups == null) subgroups = new Hashtable<Long, Long>();
+        // registers the arc in the hashtable.
+        subgroups.put(obj,obj);
+    }
+
+    // -------------------------------------------------------------------
+    // The SnmpMibOid algorithm relies on the fact that for every arc
+    // registered in varList, there is a corresponding node at the same
+    // position in children.
+    // So the trick is to register a null node in children for each variable
+    // in varList, so that the real subgroup nodes can be inserted at the
+    // correct location.
+    // registerObject() should be called for each scalar object and each
+    // table arc by the generated subclass.
+    /**
+     * Register an OID arc that identifies a scalar object or a table.
+     * This method is used internally. You shouldn't ever call it directly.
+     *
+     * @param arc An OID arc.
+     *
+     */
+    protected void registerObject(long arc)
+        throws IllegalAccessException {
+
+        // this will register the variable in both varList and children
+        // The node registered in children will be null, so that the parent
+        // algorithm will behave as if no node were registered. This is a
+        // trick that makes the parent algorithm behave as if only subgroups
+        // were registered in varList and children.
+        long[] oid = new long[1];
+        oid[0] = arc;
+        super.registerNode(oid,0,null);
+    }
+
+    // -------------------------------------------------------------------
+    // registerNode() will be called at runtime when nested groups are
+    // registered in the MIB. So we do know that this method will only
+    // be called to register nested-groups.
+    // We trap registerNode() in order to call registerSubArc()
+    /**
+     * Register a child node of this node in the OID tree.
+     * This method is used internally. You shouldn't ever call it directly.
+     *
+     * @param oid The oid of the node being registered.
+     * @param cursor The position reached in the oid.
+     * @param node The node being registered.
+     *
+     */
+    void registerNode(long[] oid, int cursor ,SnmpMibNode node)
+        throws IllegalAccessException {
+        super.registerNode(oid,cursor,node);
+        if (cursor < 0) return;
+        if (cursor >= oid.length) return;
+        // if we get here, then it means we are registering a subgroup.
+        // We will thus register the sub arc in the subgroups hashtable.
+        registerNestedArc(oid[cursor]);
+    }
+
+    // -------------------------------------------------------------------
+    // see comments in SnmpMibNode
+    // -------------------------------------------------------------------
+    void findHandlingNode(SnmpVarBind varbind,
+                          long[] oid, int depth,
+                          SnmpRequestTree handlers)
+        throws SnmpStatusException {
+
+        int length = oid.length;
+        SnmpMibNode node = null;
+
+        if (handlers == null)
+            throw new SnmpStatusException(SnmpStatusException.snmpRspGenErr);
+
+        final Object data = handlers.getUserData();
+
+        if (depth >= length) {
+            // Nothing is left... the oid is not valid
+            throw new SnmpStatusException(SnmpStatusException.noAccess);
+        }
+
+        long arc = oid[depth];
+
+        if (isNestedArc(arc)) {
+            // This arc leads to a subgroup: delegates the search to the
+            // method defined in SnmpMibOid
+            super.findHandlingNode(varbind,oid,depth,handlers);
+            return;
+        } else if (isTable(arc)) {
+            // This arc leads to a table: forward the search to the table.
+
+            // Gets the table
+            SnmpMibTable table = getTable(arc);
+
+            // Forward the search to the table
+            table.findHandlingNode(varbind,oid,depth+1,handlers);
+
+        } else {
+            // If it's not a variable, throws an exception
+            validateVarId(arc, data);
+
+            // The trailing .0 is missing in the OID
+            if (depth+2 > length)
+                throw noSuchInstanceException;
+
+            // There are too many arcs left in the OID (there should remain
+            // a single trailing .0)
+            if (depth+2 < length)
+                throw noSuchInstanceException;
+
+            // The last trailing arc is not .0
+            if (oid[depth+1] != 0L)
+                throw noSuchInstanceException;
+
+            // It's one of our variable, register this node.
+            handlers.add(this,depth,varbind);
+        }
+    }
+
+    // -------------------------------------------------------------------
+    // See comments in SnmpMibNode.
+    // -------------------------------------------------------------------
+    long[] findNextHandlingNode(SnmpVarBind varbind,
+                                long[] oid, int pos, int depth,
+                                SnmpRequestTree handlers, AcmChecker checker)
+        throws SnmpStatusException {
+
+        int length = oid.length;
+        SnmpMibNode node = null;
+
+        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();
+
+
+        // The generic case where the end of the OID has been reached is
+        // handled in the superclass
+        // XXX Revisit: this works but it is somewhat convoluted. Just setting
+        //              arc to -1 would work too.
+        if (pos >= length)
+            return super.findNextHandlingNode(varbind,oid,pos,depth,
+                                              handlers, checker);
+
+        // Ok, we've got the arc.
+        long arc = oid[pos];
+
+        long[] result = null;
+
+        // We have a recursive logic. Should we have a loop instead?
+        try {
+
+            if (isTable(arc)) {
+                // If the arc identifies a table, then we need to forward
+                // the search to the table.
+
+                // Gets the table identified by `arc'
+                SnmpMibTable table = getTable(arc);
+
+                // Forward to the table
+                checker.add(depth, arc);
+                try {
+                    result = table.findNextHandlingNode(varbind,oid,pos+1,
+                                                        depth+1,handlers,
+                                                        checker);
+                }catch(SnmpStatusException ex) {
+                    throw noSuchObjectException;
+                } finally {
+                    checker.remove(depth);
+                }
+                // Build up the leaf OID
+                result[depth] = arc;
+                return result;
+            } else if (isReadable(arc)) {
+                // If the arc identifies a readable variable, then two cases:
+
+                if (pos == (length - 1)) {
+                    // The end of the OID is reached, so we return the leaf
+                    // corresponding to the variable identified by `arc'
+
+                    // Build up the OID
+                    // result = new SnmpOid(0);
+                    // result.insert((int)arc);
+                    result = new long[depth+2];
+                    result[depth+1] = 0L;
+                    result[depth] = arc;
+
+                    checker.add(depth, result, depth, 2);
+                    try {
+                        checker.checkCurrentOid();
+                    } catch(SnmpStatusException e) {
+                        throw noSuchObjectException;
+                    } finally {
+                        checker.remove(depth,2);
+                    }
+
+                    // Registers this node
+                    handlers.add(this,depth,varbind);
+                    return result;
+                }
+
+                // The end of the OID is not yet reached, so we must return
+                // the next leaf following the variable identified by `arc'.
+                // We cannot return the variable because whatever follows in
+                // the OID will be greater or equals to 0, and 0 identifies
+                // the variable itself - so we have indeed to return the
+                // next object.
+                // So we do nothing, because this case is handled at the
+                // end of the if ... else if ... else ... block.
+
+            } else if (isNestedArc(arc)) {
+                // Now if the arc leads to a subgroup, we delegate the
+                // search to the child, just as done in SnmpMibNode.
+                //
+
+                // get the child ( = nested arc node).
+                //
+                final SnmpMibNode child = getChild(arc);
+
+                if (child != null) {
+                    checker.add(depth, arc);
+                    try {
+                        result = child.findNextHandlingNode(varbind,oid,pos+1,
+                                                            depth+1,handlers,
+                                                            checker);
+                        result[depth] = arc;
+                        return result;
+                    } finally {
+                        checker.remove(depth);
+                    }
+                }
+            }
+
+            // The oid is not valid, we will throw an exception in order
+            // to try with the next valid identifier...
+            //
+            throw noSuchObjectException;
+
+        } catch (SnmpStatusException e) {
+            // We didn't find anything at the given arc, so we're going
+            // to try with the next valid arc
+            //
+            long[] newOid = new long[1];
+            newOid[0] = getNextVarId(arc,data,pduVersion);
+            return findNextHandlingNode(varbind,newOid,0,depth,
+                                        handlers,checker);
+        }
+    }
+
+}
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibHandler.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibHandler.java
new file mode 100644
index 0000000..a6cf258
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibHandler.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 1998-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;
+
+
+
+// java imports
+//
+import java.util.Vector;
+import java.io.IOException;
+
+// jmx imports
+//
+import com.sun.jmx.snmp.SnmpOid;
+import com.sun.jmx.snmp.SnmpStatusException;
+
+/**
+ * The logical link between an SNMP MIB and the SNMP communication stack.
+ *
+ * <p><b>This API is a Sun Microsystems internal API  and is subject
+ * to change without notice.</b></p>
+ */
+
+public interface SnmpMibHandler {
+
+    /**
+     * Adds a new MIB in the SNMP MIB handler.
+     * This method is called automatically by {@link com.sun.jmx.snmp.agent.SnmpMibAgent#setSnmpAdaptor(SnmpMibHandler)} and
+     * {@link com.sun.jmx.snmp.agent.SnmpMibAgent#setSnmpAdaptorName(ObjectName)} and should not be called directly.
+     *
+     * @param mib The MIB to add.
+     *
+     * @return A reference on the SNMP MIB handler.
+     *
+     * @exception IllegalArgumentException If the parameter is null.
+     */
+    public SnmpMibHandler addMib(SnmpMibAgent mib) throws IllegalArgumentException;
+
+/**
+     * Adds a new MIB in the SNMP MIB handler.
+     *
+     * @param mib The MIB to add.
+     * @param oids The array of oid used to add the mib. Each oid is a root oid for the mib.
+     * @return A reference on the SNMP MIB handler.
+     *
+     * @exception IllegalArgumentException If the parameter is null.
+     *
+     * @since 1.5
+     */
+    public SnmpMibHandler addMib(SnmpMibAgent mib, SnmpOid[] oids) throws IllegalArgumentException;
+
+    /**
+     * Adds a new contextualized MIB in the SNMP MIB handler.
+     *
+     * @param mib The MIB to add.
+     * @param contextName The MIB context name. If null is passed, will be registered in the default context.
+     *
+     * @return A reference to the SNMP MIB handler.
+     *
+     * @exception IllegalArgumentException If the parameter is null.
+     *
+     * @since 1.5
+     */
+    public SnmpMibHandler addMib(SnmpMibAgent mib, String contextName)
+        throws IllegalArgumentException;
+
+    /**
+     * Adds a new contextualized MIB in the SNMP MIB handler.
+     *
+     * @param mib The MIB to add.
+     * @param contextName The MIB context name. If null is passed, will be registered in the default context.
+     * @param oids The array of oid used to add the mib. Each oid is a root oid for the mib.
+     *
+     * @return A reference to the SNMP MIB handler.
+     *
+     * @exception IllegalArgumentException If the parameter is null.
+     *
+     * @since 1.5
+     */
+    public SnmpMibHandler addMib(SnmpMibAgent mib, String contextName, SnmpOid[] oids)
+        throws IllegalArgumentException;
+
+    /**
+     * Removes the specified MIB from the SNMP protocol adaptor.
+     * This method is called automatically by {@link com.sun.jmx.snmp.agent.SnmpMibAgent#setSnmpAdaptor(SnmpMibHandler)} and
+     * {@link com.sun.jmx.snmp.agent.SnmpMibAgent#setSnmpAdaptorName(ObjectName)} and should not be called directly.
+     *
+     * @param mib The MIB to be removed.
+     *
+     * @return <CODE>true</CODE> if the specified <CODE>mib</CODE> was a MIB included in the SNMP MIB handler,
+     * <CODE>false</CODE> otherwise.
+     */
+    public boolean removeMib(SnmpMibAgent mib);
+  /**
+     * Removes the specified MIB from the SNMP protocol adaptor.
+     * This method is called automatically by {@link com.sun.jmx.snmp.agent.SnmpMibAgent#setSnmpAdaptor(SnmpMibHandler)} and
+     * {@link com.sun.jmx.snmp.agent.SnmpMibAgent#setSnmpAdaptorName(ObjectName)} and should not be called directly.
+     *
+     * @param mib The MIB to be removed.
+     * @param oids The oid the MIB was previously registered for.
+     * @return <CODE>true</CODE> if the specified <CODE>mib</CODE> was a MIB included in the SNMP MIB handler,
+     * <CODE>false</CODE> otherwise.
+     *
+     * @since 1.5
+     */
+    public boolean removeMib(SnmpMibAgent mib, SnmpOid[] oids);
+     /**
+     * Removes the specified MIB from the SNMP protocol adaptor.
+     *
+     * @param mib The MIB to be removed.
+     * @param contextName The context name used at registration time.
+     *
+     * @return <CODE>true</CODE> if the specified <CODE>mib</CODE> was a MIB included in the SNMP MIB handler,
+     * <CODE>false</CODE> otherwise.
+     *
+     * @since 1.5
+     */
+    public boolean removeMib(SnmpMibAgent mib, String contextName);
+     /**
+     * Removes the specified MIB from the SNMP protocol adaptor.
+     *
+     * @param mib The MIB to be removed.
+     * @param contextName The context name used at registration time.
+     * @param oids The oid the MIB was previously registered for.
+     * @return <CODE>true</CODE> if the specified <CODE>mib</CODE> was a MIB included in the SNMP MIB handler,
+     * <CODE>false</CODE> otherwise.
+     *
+     * @since 1.5
+     */
+    public boolean removeMib(SnmpMibAgent mib, String contextName, SnmpOid[] oids);
+}
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibNode.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibNode.java
new file mode 100644
index 0000000..52b952e
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibNode.java
@@ -0,0 +1,414 @@
+/*
+ * 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;
+
+
+
+// java imports
+//
+import java.io.Serializable;
+import java.util.Vector;
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+// jmx imports
+//
+import com.sun.jmx.snmp.SnmpOid;
+import com.sun.jmx.snmp.SnmpValue;
+import com.sun.jmx.snmp.SnmpVarBind;
+import com.sun.jmx.snmp.SnmpDefinitions;
+import com.sun.jmx.snmp.SnmpStatusException;
+
+/**
+ * The <CODE>SnmpMibNode</CODE> class represents a node in an SNMP MIB.
+ * <P>
+ * This class is used internally and by the class generated by
+ * <CODE>mibgen</CODE>.
+ * You should not need to use this class directly.
+ *
+ * <p><b>This API is a Sun Microsystems internal API  and is subject
+ * to change without notice.</b></p>
+ */
+
+public abstract class SnmpMibNode implements Serializable {
+
+    // ---------------------------------------------------------------------
+    // PUBLIC METHODS
+    //----------------------------------------------------------------------
+
+    /**
+     * Get the next OID arc corresponding to a readable scalar variable,
+     * a branch leading to a subgroub, or a table.
+     *
+     * @param id Id 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 id in this group.
+     *
+     * @exception SnmpStatusException If no id is found after the given id.
+     */
+    public long getNextVarId(long id, Object userData)
+        throws SnmpStatusException {
+        return getNextIdentifier(varList,id);
+    }
+
+    /**
+     * Get the next OID arc corresponding to a readable scalar variable,
+     * a branch leading to a subgroub, or a table, possibly skipping over
+     * those arcs that must not or cannot be returned.
+     *
+     * Calls {@link #getNextVarId(long,java.lang.Object)} until
+     * {@link #skipVariable(long,java.lang.Object,int)} returns false.
+     *
+     * @param id Id 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 id in this group which can be returned using
+     *         the given PDU's protocol version.
+     *
+     * @exception SnmpStatusException If no id is found after the given id.
+     */
+    public long getNextVarId(long id, Object userData, int pduVersion)
+        throws SnmpStatusException {
+        long varid=id;
+        do {
+            varid = getNextVarId(varid,userData);
+        } while (skipVariable(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 id Id 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 skipVariable(long id, Object userData, int pduVersion) {
+        return false;
+    }
+
+    /**
+     * Find the node which handles a varbind, and register it in the
+     * SnmpRequestTree. This method is a pure internal method. You should
+     * never try to call it directly.
+     *
+     * @param varbind  The varbind to be handled
+     *
+     * @param oid      The OID array extracted from the varbind
+     *
+     * @param depth    The depth reached in the OID at this step of the
+     *                 processing.
+     *
+     * @param handlers The Hashtable in which the varbind will be registered
+     *                 with its handling node. This hashtable contains
+     *                 <CODE>SnmpRequestTree.Handler</CODE> items.
+     *
+     * @exception SnmpStatusException No handling node was found.
+     **/
+    void findHandlingNode(SnmpVarBind varbind,
+                          long[] oid, int depth,
+                          SnmpRequestTree handlers)
+        throws SnmpStatusException {
+        throw noSuchObjectException;
+    }
+
+    /**
+     * Find the node which handles the leaf that immediately follows the
+     * given varbind OID, and register the it in the SnmpRequestTree.
+     * This method is a pure internal method. You should never try to call
+     * it directly.
+     *
+     * @param varbind  The varbind to be handled
+     *
+     * @param oid      The OID array extracted from the varbind
+     *
+     * @param depth    The depth reached in the OID at this step of the
+     *                 processing.
+     *
+     * @param handlers The Hashtable in which the varbind will be registered
+     *                 with its handling node. This hashtable contains
+     *                 SnmpRequestTree.Handler items.
+     *
+     * @return The SnmpOid of the next leaf.
+     *
+     * @exception SnmpStatusException No handling node was found.
+     **/
+    long[] findNextHandlingNode(SnmpVarBind varbind,
+                                 long[] oid, int pos, int depth,
+                                 SnmpRequestTree handlers, AcmChecker checker)
+        throws SnmpStatusException {
+        throw noSuchObjectException;
+    }
+
+    /**
+     * Generic handling of the <CODE>get</CODE> operation.
+     *
+     * <p> You can override this method if you need to implement some
+     * specific policies for minimizing the accesses made to some remote
+     * underlying resources.
+     * <p>
+     *
+     * @param req   The sub-request that must be handled by this node.
+     *
+     * @param depth The depth reached in the OID tree.
+     *
+     * @exception SnmpStatusException An error occurred while accessing
+     *  the MIB node.
+     */
+    public abstract void get(SnmpMibSubRequest req, int depth)
+        throws SnmpStatusException;
+
+    /**
+     * Generic handling of the <CODE>set</CODE> operation.
+     * <p> You can override this method if you need to implement some
+     * specific policies for minimizing the accesses made to some remote
+     * underlying resources.
+     * <p>
+     *
+     * @param req   The sub-request that must be handled by this node.
+     *
+     * @param depth The depth reached in the OID tree.
+     *
+     * @exception SnmpStatusException An error occurred while accessing
+     *  the MIB node.
+     */
+    public abstract void set(SnmpMibSubRequest req, int depth)
+        throws SnmpStatusException;
+
+    /**
+     * Generic handling of the <CODE>check</CODE> operation.
+     * <p> You can override this method if you need to implement some
+     * 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.
+     * <p>
+     *
+     * @param req   The sub-request that must be handled by this node.
+     *
+     * @param depth The depth reached in the OID tree.
+     *
+     * @exception SnmpStatusException An error occurred while accessing
+     *  the MIB node.
+     */
+    public abstract void check(SnmpMibSubRequest req, int depth)
+        throws SnmpStatusException;
+
+    /**
+     * Sorts the specified integer array.
+     *
+     * @param array An integer array.
+     */
+    static public void sort(int array[]) {
+        QuickSort(array, 0, array.length - 1);
+    }
+
+    /**
+     * Computes the root OID of the MIB.
+     */
+    public void getRootOid(Vector<Integer> result) {
+        return;
+    }
+
+    //----------------------------------------------------------------------
+    // PACKAGE METHODS
+    //----------------------------------------------------------------------
+
+    /**
+     * This is a generic version of C.A.R Hoare's Quick Sort
+     * algorithm.  This will handle arrays that are already
+     * sorted, and arrays with duplicate keys.
+     *
+     * If you think of a one dimensional array as going from
+     * the lowest index on the left to the highest index on the right
+     * then the parameters to this function are lowest index or
+     * left and highest index or right.  The first time you call
+     * this function it will be with the parameters 0, a.length - 1.
+     *
+     * @param a An integer array.
+     * @param lo0 Left boundary of array partition.
+     * @param hi0 Right boundary of array partition.
+     */
+    static void QuickSort(int a[], int lo0, int hi0) {
+        int lo = lo0;
+        int hi = hi0;
+        int mid;
+
+        if ( hi0 > lo0) {
+
+            /* Arbitrarily establishing partition element as the midpoint of
+             * the array.
+             */
+            mid = a[ ( lo0 + hi0 ) / 2 ];
+
+            // loop through the array until indices cross
+            while( lo <= hi ) {
+                /* find the first element that is greater than or equal to
+                 * the partition element starting from the left Index.
+                 */
+                while( ( lo < hi0 )  && ( a[lo] < mid ))
+                    ++lo;
+
+                /* find an element that is smaller than or equal to
+                 * the partition element starting from the right Index.
+                 */
+                while( ( hi > lo0 ) && ( a[hi] > mid ))
+                    --hi;
+
+                // if the indexes have not crossed, swap
+                if( lo <= hi ) {
+                    swap(a, lo, hi);
+                    ++lo;
+                    --hi;
+                }
+            }
+
+            /* If the right index has not reached the left side of array
+             * must now sort the left partition.
+             */
+            if( lo0 < hi )
+                QuickSort( a, lo0, hi );
+
+            /* If the left index has not reached the right side of array
+             * must now sort the right partition.
+             */
+            if( lo < hi0 )
+                QuickSort( a, lo, hi0 );
+
+        }
+    }
+
+    //----------------------------------------------------------------------
+    // PROTECTED METHODS
+    //----------------------------------------------------------------------
+
+    /**
+     * This will give the first element greater than <CODE>value</CODE>
+     * in a sorted array.
+     * If there is no element of the array greater than <CODE>value</CODE>,
+     * the method will throw a <CODE>SnmpStatusException</CODE>.
+     *
+     * @param table A sorted integer array.
+     *
+     * @param value The greatest value.
+     *
+     * @exception SnmpStatusException If there is no element greater than
+     *     <CODE>value</CODE>.
+     */
+    final static protected int getNextIdentifier(int table[], long value)
+        throws SnmpStatusException {
+
+        final int[] a = table;
+        final int val= (int) value;
+
+        if (a == null)
+            throw noSuchObjectException;
+
+        int low= 0;
+        int max= a.length;
+        int curr= low + (max-low)/2;
+        int elmt= 0;
+
+        // Basic check
+        //
+        if (max < 1)
+            throw noSuchObjectException;
+
+        if (a[max-1] <= val)
+            throw noSuchObjectException;
+
+        while (low <= max) {
+            elmt= a[curr];
+            if (val == elmt) {
+                // We ned to get the next index ...
+                //
+                curr++;
+                return a[curr];
+            }
+            if (elmt < val) {
+                low= curr +1;
+            } else {
+                max= curr -1;
+            }
+            curr= low + (max-low)/2;
+        }
+        return a[curr];
+    }
+
+
+    //----------------------------------------------------------------------
+    // PRIVATE METHODS
+    //----------------------------------------------------------------------
+
+    final static private void swap(int a[], int i, int j) {
+        int T;
+        T = a[i];
+        a[i] = a[j];
+        a[j] = T;
+    }
+
+    //----------------------------------------------------------------------
+    // PROTECTED VARIABLES
+    //----------------------------------------------------------------------
+
+    /**
+     * Contains the list of variable identifiers.
+     */
+    protected int[] varList;
+
+    /**
+     * Contains a predefined exception that is often fired when an
+     * object is not found in the MIB.
+     */
+    static final protected SnmpStatusException noSuchInstanceException =
+        new SnmpStatusException(SnmpStatusException.noSuchInstance);
+    static final protected SnmpStatusException noSuchObjectException =
+        new SnmpStatusException(SnmpStatusException.noSuchObject);
+    static final protected SnmpStatusException noSuchNameException =
+        new SnmpStatusException(SnmpDefinitions.snmpRspNoSuchName);
+}
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibOid.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibOid.java
new file mode 100644
index 0000000..d86389b
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibOid.java
@@ -0,0 +1,561 @@
+/*
+ * 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;
+
+
+
+// java imports
+//
+import java.io.Serializable;
+import java.util.Vector;
+import java.util.Enumeration;
+
+// jmx imports
+//
+import com.sun.jmx.snmp.SnmpOid;
+import com.sun.jmx.snmp.SnmpValue;
+import com.sun.jmx.snmp.SnmpVarBind;
+import com.sun.jmx.snmp.SnmpStatusException;
+
+/**
+ * Represents a node in an SNMP MIB which is neither a group nor a variable.
+ * This class defines a list of sub-nodes and the methods that allow to
+ * manipulate the sub-nodes.
+ * <P>
+ * This class is used internally and by the class generated by
+ * <CODE>mibgen</CODE>.
+ * You should not need to use this class directly.
+ *
+ * <p><b>This API is a Sun Microsystems internal API  and is subject
+ * to change without notice.</b></p>
+ */
+
+public class SnmpMibOid extends SnmpMibNode implements Serializable {
+    private static final long serialVersionUID = 5012254771107446812L;
+
+    /**
+     * Default constructor.
+     */
+    public SnmpMibOid() {
+    }
+
+    // PUBLIC METHODS
+    //---------------
+
+    /**
+     * Generic handling of the <CODE>get</CODE> operation.
+     *
+     * <p> This method should be overridden in subclasses.
+     * <p>
+     *
+     * @param req   The sub-request that must be handled by this node.
+     *
+     * @param depth The depth reached in the OID tree.
+     *
+     * @exception SnmpStatusException The default implementation (if not
+     *            overridden) is to generate a SnmpStatusException.
+     */
+    public void get(SnmpMibSubRequest req, int depth)
+        throws SnmpStatusException {
+        for (Enumeration e= req.getElements(); e.hasMoreElements();) {
+            SnmpVarBind var= (SnmpVarBind) e.nextElement();
+            SnmpStatusException x =
+                new SnmpStatusException(SnmpStatusException.noSuchObject);
+            req.registerGetException(var,x);
+        }
+    }
+
+    /**
+     * Generic handling of the <CODE>set</CODE> operation.
+     *
+     * <p> This method should be overridden in subclasses.
+     * <p>
+     *
+     * @param req   The sub-request that must be handled by this node.
+     *
+     * @param depth The depth reached in the OID tree.
+     *
+     * @exception SnmpStatusException The default implementation (if not
+     *            overridden) is to generate a SnmpStatusException.
+     */
+    public void set(SnmpMibSubRequest req, int depth)
+        throws SnmpStatusException {
+        for (Enumeration e= req.getElements(); e.hasMoreElements();) {
+            SnmpVarBind var= (SnmpVarBind) e.nextElement();
+            SnmpStatusException x =
+                new SnmpStatusException(SnmpStatusException.noAccess);
+            req.registerSetException(var,x);
+        }
+    }
+
+    /**
+     * Generic handling of the <CODE>check</CODE> operation.
+     *
+     * <p> This method should be overridden in subclasses.
+     * <p>
+     *
+     * @param req   The sub-request that must be handled by this node.
+     *
+     * @param depth The depth reached in the OID tree.
+     *
+     * @exception SnmpStatusException The default implementation (if not
+     *            overriden) is to generate a SnmpStatusException.
+     */
+    public void check(SnmpMibSubRequest req, int depth)
+        throws SnmpStatusException {
+        for (Enumeration e= req.getElements(); e.hasMoreElements();) {
+            SnmpVarBind var= (SnmpVarBind) e.nextElement();
+            SnmpStatusException x =
+                new SnmpStatusException(SnmpStatusException.noAccess);
+            req.registerCheckException(var,x);
+        }
+    }
+
+
+
+    // ---------------------------------------------------------------------
+    //
+    // Implements the method defined in SnmpMibNode.
+    //
+    // ---------------------------------------------------------------------
+    //
+    void findHandlingNode(SnmpVarBind varbind,
+                          long[] oid, int depth,
+                          SnmpRequestTree handlers)
+        throws SnmpStatusException {
+
+
+        final int length = oid.length;
+        SnmpMibNode node = null;
+
+        if (handlers == null)
+            throw new SnmpStatusException(SnmpStatusException.snmpRspGenErr);
+
+        if (depth > length) {
+            // Nothing is left... the oid is not valid
+            throw noSuchObjectException;
+
+        } else if (depth == length) {
+            // The oid is not complete...
+            throw noSuchInstanceException;
+
+        } else {
+            // Some children variable or subobject is being querried
+            // getChild() will raise an exception if no child is found.
+            //
+            final SnmpMibNode child= getChild(oid[depth]);
+
+            // XXXX zzzz : what about null children?
+            //             (variables for nested groups)
+            // if child==null, then we're dealing with a variable or
+            // a table: we register this node.
+            // This behaviour should be overriden in subclasses,
+            // in particular in group meta classes: the group
+            // meta classes that hold tables should take care
+            // of forwarding this call to all the tables involved.
+            //
+            if (child == null)
+                handlers.add(this,depth,varbind);
+            else
+                child.findHandlingNode(varbind,oid,depth+1,handlers);
+        }
+    }
+
+    // ---------------------------------------------------------------------
+    //
+    // Implements the method defined in SnmpMibNode.
+    //
+    // ---------------------------------------------------------------------
+    //
+    long[] findNextHandlingNode(SnmpVarBind varbind,
+                                long[] oid, int pos, int depth,
+                                SnmpRequestTree handlers,
+                                AcmChecker checker)
+        throws SnmpStatusException {
+
+
+        final int length = oid.length;
+        SnmpMibNode node = null;
+        long[] result = null;
+        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();
+
+        if (pos >= length) {
+            long[] newOid= new long[1];
+            newOid[0]=  getNextVarId(-1,data,pduVersion);
+            result = findNextHandlingNode(varbind,newOid,0,depth,handlers,
+                                          checker);
+            return result;
+        }
+
+        // search the element specified in the oid
+        //
+        long[] newOid= new long[1];
+        long index= oid[pos];
+
+        while (true) {
+
+            try {
+                final SnmpMibNode child = getChild(index);
+                // SnmpOid result = null;
+                if (child == null) {
+                    // shouldn't happen
+                    throw noSuchObjectException;
+                    // validateVarId(index);
+                    // handlers.add(this,varbind,depth);
+                    // result = new SnmpOid(0);
+                } else {
+                    checker.add(depth, index);
+                    try {
+                        result = child.findNextHandlingNode(varbind,oid,pos+1,
+                                                            depth+1,handlers,
+                                                            checker);
+                    } finally {
+                        checker.remove(depth);
+                    }
+                }
+
+                // Build up the leaf OID
+                result[depth] = index;
+                return result;
+
+            } catch(SnmpStatusException e) {
+                // If there is no such element go one level up ...
+                //
+                index= getNextVarId(index,data,pduVersion);
+
+                // There is no need to carry the original oid ...
+                newOid[0]=index;
+                pos= 1;
+                oid=newOid;
+            }
+        }
+    }
+
+
+    /**
+     * Computes the root OID of the MIB.
+     */
+    public void getRootOid(Vector<Integer> result) {
+
+        // If a node has several children, let assume that we are one step to
+        // far in order to get the MIB root.
+        //
+        if (nbChildren != 1)
+            return;
+
+        result.addElement(varList[0]);
+
+        // Now query our child.
+        //
+        children.firstElement().getRootOid(result);
+
+    }
+
+    /**
+     * Registers a specific node in the tree.
+     */
+    public void registerNode(String oidString ,SnmpMibNode node)
+        throws IllegalAccessException {
+        SnmpOid oid= new SnmpOid(oidString);
+        registerNode(oid.longValue(), 0, node);
+    }
+
+    // PROTECTED METHODS
+    //------------------
+
+    /**
+     * Registers a specific node in the tree.
+     */
+    void registerNode(long[] oid, int cursor ,SnmpMibNode node)
+        throws IllegalAccessException {
+
+        if (cursor >= oid.length)
+            throw new IllegalAccessException();
+
+        // Check if the node is already defined
+        //
+        long var= oid[cursor];
+
+        //System.out.println("entering registration for val="
+        // + String.valueOf(var) + " position= " + cursor);
+
+        int pos = retrieveIndex(var);
+        if (pos  == nbChildren) {
+            nbChildren++;
+            varList= new int[nbChildren];
+            varList[0]= (int) var;
+            pos =0;
+            if ( (cursor + 1) == oid.length) {
+                // That 's the end of the trip.
+                // Do not forward the registration
+
+                //System.out.println("End of trip for val="
+                //      + String.valueOf(var) + " position= " + cursor);
+                children.insertElementAt(node,pos);
+                return;
+            }
+
+            //System.out.println("Create node for val="
+            //       + String.valueOf(var) + " position= " + cursor);
+            SnmpMibOid child= new SnmpMibOid();
+            children.insertElementAt(child, pos);
+            child.registerNode(oid, cursor + 1, node);
+            return;
+        }
+        if (pos == -1) {
+            // The node is not yet registered
+            //
+            int[] tmp= new int[nbChildren + 1];
+            tmp[nbChildren]= (int) var;
+            System.arraycopy(varList, 0, tmp, 0, nbChildren);
+            varList= tmp;
+            nbChildren++;
+            SnmpMibNode.sort(varList);
+            int newPos = retrieveIndex(var);
+            varList[newPos]= (int) var;
+            if ( (cursor + 1) == oid.length) {
+                // That 's the end of the trip.
+                // Do not forward the registration
+
+                //System.out.println("End of trip for val="
+                //     + String.valueOf(var) + " position= " + cursor);
+                children.insertElementAt(node, newPos);
+                return;
+            }
+            SnmpMibOid child= new SnmpMibOid();
+            // System.out.println("Create node for val=" +
+            //     String.valueOf(var) + " position= " + cursor);
+            children.insertElementAt(child, newPos);
+            child.registerNode(oid, cursor + 1, node);
+            return;
+        }
+        else {
+            // The node is already registered
+            //
+            SnmpMibNode child= children.elementAt(pos);
+            if ( (cursor + 1) == oid.length ) {
+                //System.out.println("Node already registered val=" +
+                //          String.valueOf(var) + " position= " + cursor);
+                if (child == node) return;
+                if (child != null && node != null) {
+                    // Now we're going to patch the tree the following way:
+                    //   if a subgroup has been registered before its father,
+                    //   we're going to replace the father OID node with
+                    //   the actual group-node and export the children from
+                    //   the temporary OID node to the actual group node.
+                    //
+
+                    if (node instanceof SnmpMibGroup) {
+                        // `node' is a group => replace `child' with `node'
+                        // export the child's subtree to `node'.
+                        //
+                        ((SnmpMibOid)child).exportChildren((SnmpMibOid)node);
+                        children.setElementAt(node,pos);
+                        return;
+
+                    } else if ((node instanceof SnmpMibOid) &&
+                             (child instanceof SnmpMibGroup)) {
+                        // `node' is a temporary node, and `child' is a
+                        //  group => keep child and export the node's
+                        //  subtree to `child'.
+                        //
+                        ((SnmpMibOid)node).exportChildren((SnmpMibOid)child);
+                        return;
+                    } else if (node instanceof SnmpMibOid) {
+                        // `node' and `child' are both temporary OID nodes
+                        // => replace `child' with `node' and export child's
+                        // subtree to `node'.
+                        //
+                        ((SnmpMibOid)child).exportChildren((SnmpMibOid)node);
+                        children.setElementAt(node,pos);
+                        return;
+                    }
+                }
+                children.setElementAt(node,pos);
+                return;
+            } else {
+                if (child == null)
+                    throw new IllegalAccessException();
+                ((SnmpMibOid)child).registerNode(oid, cursor + 1, node);
+            }
+        }
+    }
+
+    /**
+     * Export this node's children to a brother node that will replace
+     * this node in the OID tree.
+     * This method is a patch that fixes the problem of registering
+     * a subnode before its father node.
+     *
+     **/
+    void exportChildren(SnmpMibOid brother)
+        throws IllegalAccessException {
+
+        if (brother == null) return;
+        final long[] oid = new long[1];
+        for (int i=0; i<nbChildren; i++) {
+            final SnmpMibNode child = children.elementAt(i);
+            if (child == null) continue;
+            oid[0] = varList[i];
+            brother.registerNode(oid,0,child);
+        }
+    }
+
+    // PRIVATE METHODS
+    //----------------
+
+    SnmpMibNode getChild(long id) throws SnmpStatusException {
+
+        // first we need to retrieve the identifier in the list of children
+        //
+        final int pos= getInsertAt(id);
+        if (pos >= nbChildren)
+            throw noSuchObjectException;
+
+        if (varList[pos] != (int) id)
+            throw noSuchObjectException;
+
+        // Access the node
+        //
+        SnmpMibNode child = null;
+        try {
+            child = children.elementAtNonSync(pos);
+        } catch(ArrayIndexOutOfBoundsException e) {
+            throw noSuchObjectException;
+        }
+        if (child == null)
+            throw noSuchInstanceException;
+        return child;
+    }
+
+    private int retrieveIndex(long val) {
+
+        int low= 0;
+        int cursor= (int) val;
+        if (varList == null || varList.length < 1)
+            return nbChildren;
+
+        int max= varList.length -1 ;
+        int curr= low + (max-low)/2;
+        int elmt= 0;
+        while (low <= max) {
+            elmt= varList[curr];
+            if (cursor == elmt) {
+                // We need to get the next index ...
+                //
+                return curr;
+            }
+            if (elmt < cursor) {
+                low= curr +1;
+            } else {
+                max= curr -1;
+            }
+            curr= low + (max-low)/2;
+        }
+        return -1;
+    }
+
+    private int getInsertAt(long val) {
+
+        int low= 0;
+        final int index= (int) val;
+        if (varList == null)
+            return -1;
+        int max= varList.length -1 ;
+        int elmt=0;
+        //final int[] v = varList;
+
+        //if (index > a[max])
+        //return max +1;
+
+
+        int curr= low + (max-low)/2;
+        while (low <= max) {
+
+            elmt= varList[curr];
+
+            // never know ...we might find something ...
+            //
+            if (index == elmt)
+                return curr;
+
+            if (elmt < index) {
+                low= curr +1;
+            } else {
+                max= curr -1;
+            }
+            curr= low + (max-low)/2;
+        }
+
+        return curr;
+    }
+
+    // PRIVATE VARIABLES
+    //------------------
+
+    /**
+     * Contains the list of sub nodes.
+     */
+    private NonSyncVector<SnmpMibNode> children = new NonSyncVector<SnmpMibNode>(1);
+
+    /**
+     * The number of sub nodes.
+     */
+    private int nbChildren= 0;
+
+
+    // All the methods of the Vector class are synchronized.
+    // Synchronization is a very expensive operation. In our case it is
+    // not always required...
+    //
+    @SuppressWarnings("serial")  // We will never serialize this
+    class NonSyncVector<E> extends Vector<E> {
+
+        public NonSyncVector(int size) {
+            super(size);
+        }
+
+        final void addNonSyncElement(E obj) {
+            ensureCapacity(elementCount + 1);
+            elementData[elementCount++] = obj;
+        }
+
+        @SuppressWarnings("unchecked")  // cast to E
+        final E elementAtNonSync(int index) {
+            return (E) elementData[index];
+        }
+
+    }
+}
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibRequest.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibRequest.java
new file mode 100644
index 0000000..1b504ab
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibRequest.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package com.sun.jmx.snmp.agent;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import com.sun.jmx.snmp.SnmpVarBind;
+import com.sun.jmx.snmp.SnmpPdu;
+import com.sun.jmx.snmp.SnmpEngine;
+
+/**
+ * This interface models the part of a SNMP request that involves
+ * a specific MIB. One object implementing this interface will be created
+ * for every MIB involved in a SNMP request, and that object will be passed
+ * to the SnmpMibAgent in charge of handling that MIB.
+ *
+ * Objects implementing this interface will be allocated by the SNMP engine.
+ * You will never need to implement this interface. You will only use it.
+ *
+ * <p><b>This API is a Sun Microsystems internal API  and is subject
+ * to change without notice.</b></p>
+ */
+public interface SnmpMibRequest {
+    /**
+     * Returns the list of varbind to be handled by the SNMP mib node.
+     *
+     * @return The element of the enumeration are instances of
+     *         {@link com.sun.jmx.snmp.SnmpVarBind}
+     */
+    public Enumeration getElements();
+
+    /**
+     * Returns the vector of varbind to be handled by the SNMP mib node.
+     * The caller shall not modify this vector.
+     *
+     * @return The element of the vector are instances of
+     *         {@link com.sun.jmx.snmp.SnmpVarBind}
+     */
+    public Vector<SnmpVarBind> getSubList();
+
+    /**
+     * Returns the SNMP protocol version of the original request. If SNMP V1 request are received, the version is upgraded to SNMP V2.
+     *
+     * @return The SNMP protocol version of the original request.
+     */
+    public int getVersion();
+
+    /**
+     * Returns the SNMP protocol version of the original request. No translation is done on the version. The actual received request SNMP version is returned.
+     *
+     * @return The SNMP protocol version of the original request.
+     *
+     * @since 1.5
+     */
+    public int getRequestPduVersion();
+
+    /**
+     * Returns the local engine. This parameter is returned only if <CODE> SnmpV3AdaptorServer </CODE> is the adaptor receiving this request. Otherwise null is returned.
+     * @return the local engine.
+     *
+     * @since 1.5
+     */
+    public SnmpEngine getEngine();
+    /**
+     * Gets the incoming request principal. This parameter is returned only if <CODE> SnmpV3AdaptorServer </CODE> is the adaptor receiving this request. Otherwise null is returned.
+     * @return The request principal.
+     *
+     * @since 1.5
+     **/
+    public String getPrincipal();
+    /**
+     * Gets the incoming request security level. This level is defined in {@link com.sun.jmx.snmp.SnmpEngine SnmpEngine}. This parameter is returned only if <CODE> SnmpV3AdaptorServer </CODE> is the adaptor receiving this request. Otherwise -1 is returned.
+     * @return The security level.
+     *
+     * @since 1.5
+     */
+    public int getSecurityLevel();
+    /**
+     * Gets the incoming request security model. This parameter is returned only if <CODE> SnmpV3AdaptorServer </CODE> is the adaptor receiving this request. Otherwise -1 is returned.
+     * @return The security model.
+     *
+     * @since 1.5
+     */
+    public int getSecurityModel();
+    /**
+     * Gets the incoming request context name. This parameter is returned only if <CODE> SnmpV3AdaptorServer </CODE> is the adaptor receiving this request. Otherwise null is returned.
+     * @return The context name.
+     *
+     * @since 1.5
+     */
+    public byte[] getContextName();
+    /**
+     * Gets the incoming request context name used by Access Control Model in order to allow or deny the access to OIDs. This parameter is returned only if <CODE> SnmpV3AdaptorServer </CODE> is the adaptor receiving this request. Otherwise null is returned.
+     * @return The checked context name.
+     *
+     * @since 1.5
+     */
+    public byte[] getAccessContextName();
+
+    /**
+     * Returns a handle on a user allocated contextual object.
+     * This contextual object is allocated through the SnmpUserDataFactory
+     * on a per SNMP request basis, and is handed back to the user via
+     * SnmpMibRequest (and derivative) objects. It is never accessed by
+     * the system, but might be handed back in multiple threads. It is thus
+     * the user responsibility to make sure he handles this object in a
+     * thread safe manner.
+     */
+    public Object getUserData();
+
+    /**
+     * Returns the varbind index that should be embedded in an
+     * SnmpStatusException for this particular varbind.
+     * This does not necessarily correspond to the "real"
+     * index value that will be returned in the result PDU.
+     *
+     * @param varbind The varbind for which the index value is
+     *        querried. Note that this varbind <b>must</b> have
+     *        been obtained from the enumeration returned by
+     *        <CODE>getElements()</CODE>, or from the vector
+     *        returned by <CODE>getSublist()</CODE>.
+     *
+     * @return The varbind index that should be embedded in an
+     *         SnmpStatusException for this particular varbind.
+     */
+    public int getVarIndex(SnmpVarBind varbind);
+
+    /**
+     * Adds a varbind to this request sublist. This method is used for
+     * internal purposes and you should never need to call it directly.
+     *
+     * @param varbind The varbind to be added in the sublist.
+     *
+     */
+    public void addVarBind(SnmpVarBind varbind);
+
+
+    /**
+     * Returns the number of elements (varbinds) in this request sublist.
+     *
+     * @return The number of elements in the sublist.
+     *
+     **/
+    public int getSize();
+    /**
+     * Returns the SNMP PDU attached to the request.
+     * @return The SNMP PDU.
+     *
+     * @since 1.5
+     **/
+    public SnmpPdu getPdu();
+}
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibRequestImpl.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibRequestImpl.java
new file mode 100644
index 0000000..c0d5e19
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibRequestImpl.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.jmx.snmp.agent;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+
+import com.sun.jmx.snmp.SnmpPdu;
+import com.sun.jmx.snmp.SnmpVarBind;
+import com.sun.jmx.snmp.SnmpEngine;
+
+/**
+ * This class implements the SnmpMibRequest interface.
+ * It represents the part of a SNMP request that involves a specific
+ * MIB. One instance of this class will be created for every MIB
+ * involved in a SNMP request, and will be passed to the SnmpMibAgent
+ * in charge of handling that MIB.
+ *
+ * Instances of this class are allocated by the SNMP engine. You will
+ * never need to use this class directly. You will only access
+ * instances of this class through their SnmpMibRequest interface.
+ *
+ */
+final class SnmpMibRequestImpl implements SnmpMibRequest {
+
+    /**
+     * @param engine The local engine.
+     * @param reqPdu The received pdu.
+     * @param vblist The vector of SnmpVarBind objects in which the
+     *        MIB concerned by this request is involved.
+     * @param protocolVersion  The protocol version of the SNMP request.
+     * @param userData     User allocated contextual data. This object must
+     *        be allocated on a per SNMP request basis through the
+     *        SnmpUserDataFactory registered with the SnmpAdaptorServer,
+     *        and is handed back to the user through SnmpMibRequest objects.
+     */
+    public SnmpMibRequestImpl(SnmpEngine engine,
+                              SnmpPdu reqPdu,
+                              Vector<SnmpVarBind> vblist,
+                              int protocolVersion,
+                              Object userData,
+                              String principal,
+                              int securityLevel,
+                              int securityModel,
+                              byte[] contextName,
+                              byte[] accessContextName) {
+        varbinds   = vblist;
+        version    = protocolVersion;
+        data       = userData;
+        this.reqPdu = reqPdu;
+        this.engine = engine;
+        this.principal = principal;
+        this.securityLevel = securityLevel;
+        this.securityModel = securityModel;
+        this.contextName = contextName;
+        this.accessContextName = accessContextName;
+    }
+    // -------------------------------------------------------------------
+    // PUBLIC METHODS from SnmpMibRequest
+    // -------------------------------------------------------------------
+
+    /**
+     * Returns the local engine. This parameter is returned only if <CODE> SnmpV3AdaptorServer </CODE> is the adaptor receiving this request. Otherwise null is returned.
+     * @return the local engine.
+     */
+    public SnmpEngine getEngine() {
+        return engine;
+    }
+
+    /**
+     * Gets the incoming request principal. This parameter is returned only if <CODE> SnmpV3AdaptorServer </CODE> is the adaptor receiving this request. Otherwise null is returned.
+     * @return The request principal.
+     **/
+    public String getPrincipal() {
+        return principal;
+    }
+
+    /**
+     * Gets the incoming request security level. This level is defined in {@link com.sun.jmx.snmp.SnmpEngine SnmpEngine}. This parameter is returned only if <CODE> SnmpV3AdaptorServer </CODE> is the adaptor receiving this request. Otherwise -1 is returned.
+     * @return The security level.
+     */
+    public int getSecurityLevel() {
+        return securityLevel;
+    }
+    /**
+     * Gets the incoming request security model. This parameter is returned only if <CODE> SnmpV3AdaptorServer </CODE> is the adaptor receiving this request. Otherwise -1 is returned.
+     * @return The security model.
+     */
+    public int getSecurityModel() {
+        return securityModel;
+    }
+    /**
+     * Gets the incoming request context name. This parameter is returned only if <CODE> SnmpV3AdaptorServer </CODE> is the adaptor receiving this request. Otherwise null is returned.
+     * @return The context name.
+     */
+    public byte[] getContextName() {
+        return contextName;
+    }
+
+    /**
+     * Gets the incoming request context name used by Access Control Model in order to allow or deny the access to OIDs. This parameter is returned only if <CODE> SnmpV3AdaptorServer </CODE> is the adaptor receiving this request. Otherwise null is returned.
+     * @return The checked context.
+     */
+    public byte[] getAccessContextName() {
+        return accessContextName;
+    }
+
+    // -------------------------------------------------------------------
+    // Implements the method defined in SnmpMibRequest interface.
+    // See SnmpMibRequest for the java doc.
+    // -------------------------------------------------------------------
+    public final SnmpPdu getPdu() {
+        return reqPdu;
+    }
+
+    // -------------------------------------------------------------------
+    // Implements the method defined in SnmpMibRequest interface.
+    // See SnmpMibRequest for the java doc.
+    // -------------------------------------------------------------------
+    public final Enumeration getElements()  {return varbinds.elements();}
+
+    // -------------------------------------------------------------------
+    // Implements the method defined in SnmpMibRequest interface.
+    // See SnmpMibRequest for the java doc.
+    // -------------------------------------------------------------------
+    public final Vector<SnmpVarBind> getSubList()  {return varbinds;}
+
+    // -------------------------------------------------------------------
+    // Implements the method defined in SnmpMibRequest interface.
+    // See SnmpMibRequest for the java doc.
+    // -------------------------------------------------------------------
+    public final int getSize()  {
+        if (varbinds == null) return 0;
+        return varbinds.size();
+    }
+
+    // -------------------------------------------------------------------
+    // Implements the method defined in SnmpMibRequest interface.
+    // See SnmpMibRequest for the java doc.
+    // -------------------------------------------------------------------
+    public final int         getVersion()  {return version;}
+
+    // -------------------------------------------------------------------
+    // Implements the method defined in SnmpMibRequest interface.
+    // See SnmpMibRequest for the java doc.
+    // -------------------------------------------------------------------
+    public final int         getRequestPduVersion()  {return reqPdu.version;}
+
+    // -------------------------------------------------------------------
+    // Implements the method defined in SnmpMibRequest interface.
+    // See SnmpMibRequest for the java doc.
+    // -------------------------------------------------------------------
+    public final Object      getUserData() {return data;}
+
+    // -------------------------------------------------------------------
+    // Implements the method defined in SnmpMibRequest interface.
+    // See SnmpMibRequest for the java doc.
+    // -------------------------------------------------------------------
+    public final int getVarIndex(SnmpVarBind varbind) {
+        return varbinds.indexOf(varbind);
+    }
+
+    // -------------------------------------------------------------------
+    // Implements the method defined in SnmpMibRequest interface.
+    // See SnmpMibRequest for the java doc.
+    // -------------------------------------------------------------------
+    public void addVarBind(SnmpVarBind varbind) {
+        varbinds.addElement(varbind);
+    }
+
+    // -------------------------------------------------------------------
+    // PACKAGE METHODS
+    // -------------------------------------------------------------------
+
+    // -------------------------------------------------------------------
+    // Allow to pass the request tree built during the check() phase
+    // to the set() method. Note: the if the tree is `null', then the
+    // set() method will rebuild a new tree identical to the tree built
+    // in the check() method.
+    //
+    // Passing this tree in the SnmpMibRequestImpl object allows to
+    // optimize the SET requests.
+    //
+    // -------------------------------------------------------------------
+    final void setRequestTree(SnmpRequestTree tree) {this.tree = tree;}
+
+    // -------------------------------------------------------------------
+    // Returns the SnmpRequestTree object built in the first operation
+    // phase for two-phase SNMP requests (like SET).
+    // -------------------------------------------------------------------
+    final SnmpRequestTree getRequestTree() {return tree;}
+
+    // -------------------------------------------------------------------
+    // Returns the underlying vector of SNMP varbinds (used for algorithm
+    // optimization).
+    // -------------------------------------------------------------------
+    final Vector getVarbinds() {return varbinds;}
+
+    // -------------------------------------------------------------------
+    // Private variables
+    // -------------------------------------------------------------------
+
+    // Ideally these variables should be declared final but it makes
+    // the jdk1.1.x compiler complain (seems to be a compiler bug, jdk1.2
+    // is OK).
+    private Vector<SnmpVarBind> varbinds;
+    private int    version;
+    private Object data;
+    private SnmpPdu reqPdu = null;
+    // Non final variable.
+    private SnmpRequestTree tree = null;
+    private SnmpEngine engine = null;
+    private String principal = null;
+    private int securityLevel = -1;
+    private int securityModel = -1;
+    private byte[] contextName = null;
+    private byte[] accessContextName = null;
+}
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibSubRequest.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibSubRequest.java
new file mode 100644
index 0000000..6a6f3f5
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibSubRequest.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.jmx.snmp.agent;
+
+import java.util.Enumeration;
+import java.util.Vector;
+import com.sun.jmx.snmp.SnmpVarBind;
+import com.sun.jmx.snmp.SnmpStatusException;
+import com.sun.jmx.snmp.SnmpOid;
+// import com.sun.jmx.snmp.SnmpIndex;
+
+/**
+ * This interface models an SNMP sub request to be performed on a specific
+ * SNMP MIB node. The node involved can be either an SNMP group, an SNMP table,
+ * or an SNMP table entry (conceptual row). The conceptual row may or may not
+ * already exist. If the row did not exist at the time when the request
+ * was received, the <CODE>isNewEntry()</CODE> method will return <CODE>
+ * true</CODE>.
+ * <p>
+ * Objects implementing this interface will be allocated by the SNMP engine.
+ * You will never need to implement this interface. You will only use it.
+ * </p>
+ * <p><b>This API is a Sun Microsystems internal API  and is subject
+ * to change without notice.</b></p>
+ */
+public interface SnmpMibSubRequest extends SnmpMibRequest {
+    /**
+     * Return the list of varbind to be handled by the SNMP MIB node.
+     * <p>
+     * <b>Note:</b> <ul>
+     * <i>In case of SET operation, if this node is a table row which
+     * contains a control variable (as identified by the table's
+     * isRowStatus() method) the control variable will not
+     * be included in this list: it will be obtained by calling
+     * getRowStatusVarBind(). This will allow you to handle the control
+     * variable specifically.</i><br>
+     * You will never need to worry about this unless you need to
+     * implement a non standard mechanism for handling row
+     * creation and deletion.
+     * </ul>
+     * <p>
+     * @return The elements of the enumeration are instances of
+     *         {@link com.sun.jmx.snmp.SnmpVarBind}
+     */
+    public Enumeration getElements();
+
+    /**
+     * Return the list of varbind to be handled by the SNMP MIB node.
+     * <p>
+     * <b>Note:</b> <ul>
+     * <i>In case of SET operation, if this node is a table row which
+     * contains a control variable (as identified by the table's
+     * isRowStatus() method) the control variable will not
+     * be included in this list: it will be obtained by calling
+     * getRowStatusVarBind(). This will allow you to handle the control
+     * variable specifically.</i><br>
+     * You will never need to worry about this unless you need to
+     * implement a non standard mechanism for handling row
+     * creation and deletion.
+     * </ul>
+     * <p>
+     * @return The elements of the vector are instances of
+     *         {@link com.sun.jmx.snmp.SnmpVarBind}
+     */
+    public Vector<SnmpVarBind> getSubList();
+
+    /**
+     * Return the part of the OID identifying the table entry involved.
+     * <p>
+     *
+     * @return {@link com.sun.jmx.snmp.SnmpOid} or <CODE>null</CODE>
+     *         if the request is not directed to an entry.
+     */
+    public SnmpOid     getEntryOid();
+
+    /**
+     * Indicate whether the entry involved is a new entry.
+     * This method will return <CODE>true</CODE> if the entry was not
+     * found when the request was processed. As a consequence, <CODE>
+     * true</CODE> means that either the entry does not exist yet,
+     * or it has been created while processing this request.
+     * The result of this method is only significant when an entry
+     * is involved.
+     *
+     * <p>
+     * @return <CODE>true</CODE> If the entry did not exist,
+     *  or <CODE>false</CODE> if the entry involved was found.
+     */
+    public boolean     isNewEntry();
+
+    /**
+     * Return the varbind that holds the RowStatus variable.
+     * It corresponds to the varbind that was identified by
+     * the <code>isRowStatus()</code> method generated by mibgen
+     * on {@link com.sun.jmx.snmp.agent.SnmpMibTable} derivatives.
+     * <ul><li>In SMIv2, it is the varbind which contains the columnar
+     *         object implementing the RowStatus TEXTUAL-CONVENTION.</li>
+     *      <li>In SMIv1 nothing special is generated</li>
+     *      <ul>You may however subclass the generated table metadata
+     *          class in order to provide your own implementation of
+     *          isRowStatus(), getRowAction(), isRowReady() and
+     *          setRowStatus()
+     *          (see  {@link com.sun.jmx.snmp.agent.SnmpMibTable}).</ul>
+     * </ul>
+     * <p>
+     * @return a varbind that serves to control the table modification.
+     *         <code>null</code> means that no such varbind could be
+     *         identified.<br>
+     *         <b>Note:</b><i>The runtime will only try to identify
+     *         the RowStatus varbind when processing an
+     *         SNMP SET request. In this case, the identified
+     *         varbind will not be included in the set of varbinds
+     *         returned by getSubList() and getElements().
+     *         </i>
+     *
+     **/
+    public SnmpVarBind getRowStatusVarBind();
+
+    /**
+     * This method should be called when a status exception needs to
+     * be raised for a given varbind of an SNMP GET request. This method
+     * performs all the necessary conversions (SNMPv1 <=> SNMPv2) and
+     * propagates the exception if needed:
+     * If the version is SNMP v1, the exception is propagated.
+     * If the version is SNMP v2, the exception is stored in the varbind.
+     * This method also takes care of setting the correct value of the
+     * index field.
+     * <p>
+     *
+     * @param varbind The varbind for which the exception is
+     *        registered. Note that this varbind <b>must</b> have
+     *        been obtained from the enumeration returned by
+     *        <CODE>getElements()</CODE>, or from the vector
+     *        returned by <CODE>getSubList()</CODE>
+     *
+     * @param exception The exception to be registered for the given varbind.
+     *
+     */
+    public void registerGetException(SnmpVarBind varbind,
+                                     SnmpStatusException exception)
+        throws SnmpStatusException;
+
+    /**
+     * This method should be called when a status exception needs to
+     * be raised for a given varbind of an SNMP SET request. This method
+     * performs all the necessary conversions (SNMPv1 <=> SNMPv2) and
+     * propagates the exception if needed.
+     * This method also takes care of setting the correct value of the
+     * index field.
+     * <p>
+     *
+     * @param varbind The varbind for which the exception is
+     *        registered. Note that this varbind <b>must</b> have
+     *        been obtained from the enumeration returned by
+     *        <CODE>getElements()</CODE>, or from the vector
+     *        returned by <CODE>getSubList()</CODE>
+     *
+     * @param exception The exception to be registered for the given varbind.
+     *
+     */
+    public void registerSetException(SnmpVarBind varbind,
+                                     SnmpStatusException exception)
+        throws SnmpStatusException;
+
+    /**
+     * This method should be called when a status exception needs to
+     * be raised when checking a given varbind for an SNMP SET request.
+     * This method performs all the necessary conversions (SNMPv1 <=>
+     * SNMPv2) and propagates the exception if needed.
+     * This method also takes care of setting the correct value of the
+     * index field.
+     * <p>
+     *
+     * @param varbind The varbind for which the exception is
+     *        registered. Note that this varbind <b>must</b> have
+     *        been obtained from the enumeration returned by
+     *        <CODE>getElements()</CODE>, or from the vector
+     *        returned by <CODE>getSubList()</CODE>
+     *
+     * @param exception The exception to be registered for the given varbind.
+     *
+     */
+    public void registerCheckException(SnmpVarBind varbind,
+                                       SnmpStatusException exception)
+        throws SnmpStatusException;
+}
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibTable.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibTable.java
new file mode 100644
index 0000000..1164087
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibTable.java
@@ -0,0 +1,2570 @@
+/*
+ * 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;
+}
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpRequestTree.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpRequestTree.java
new file mode 100644
index 0000000..4699024
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpRequestTree.java
@@ -0,0 +1,1071 @@
+/*
+ * Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package com.sun.jmx.snmp.agent;
+
+import java.util.Vector;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Arrays;
+import java.util.logging.Level;
+
+import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER;
+import com.sun.jmx.snmp.SnmpVarBind;
+import com.sun.jmx.snmp.SnmpStatusException;
+import com.sun.jmx.snmp.SnmpDefinitions;
+import com.sun.jmx.snmp.SnmpOid;
+import com.sun.jmx.snmp.SnmpPdu;
+import com.sun.jmx.snmp.SnmpEngine;
+
+//  XXX: things to do: use SnmpOid rather than `instance' for future
+//       evolutions.
+//  XXX: Maybe use hashlists rather than vectors for entries?
+//       => in that case, the key should be SnmpOid.toString()
+//
+/**
+ * This class is used to register varbinds from a SNMP varbind list with
+ * the SnmpMibNode responsible for handling the requests concerning that
+ * varbind.
+ * This class holds a hashtable of Handler nodes, whith the involved
+ * SnmpMibNode as a key.
+ * When the involved SnmpMibNode is a group, the sublist of varbind is
+ * directly stored in the Handler node.
+ * When the involved SnmpMibNode is a table, the sublist is stored in a
+ * sorted array indexed by the OID of the entry involved.
+ */
+final class SnmpRequestTree {
+
+    // Constructor:
+    // @param  req The SnmpMibRequest that will be segmented in this
+    //         tree. It holds the original varbind vector passed
+    //         by the SnmpSubRequestHandler to this MIB. This
+    //         varbind vector is used to retrieve the "real"
+    //         position of a varbind in the vector. There is no other easy
+    //         way to do this - since as a result of the segmentation the
+    //         original positions will be lost.
+    // @param  creationflag indicates whether the operation involved
+    //         allows for entry creation (ie: it is a SET request).
+    // @param  pdutype indicates the type of the request PDU as defined
+    //         in SnmpDefinitions
+    //
+    SnmpRequestTree(SnmpMibRequest req, boolean creationflag, int pdutype) {
+        this.request = req;
+        this.version  = req.getVersion();
+        this.creationflag = creationflag;
+        this.hashtable = new Hashtable<Object, Handler>();
+        setPduType(pdutype);
+    }
+
+    public static int mapSetException(int errorStatus, int version)
+        throws SnmpStatusException {
+
+        final int errorCode = errorStatus;
+
+        if (version == SnmpDefinitions.snmpVersionOne)
+            return errorCode;
+
+        int mappedErrorCode = errorCode;
+
+        // Now take care of V2 errorCodes that can be stored
+        // in the varbind itself:
+        if (errorCode == SnmpStatusException.noSuchObject)
+            // noSuchObject => notWritable
+            mappedErrorCode = SnmpStatusException.snmpRspNotWritable;
+
+        else if (errorCode == SnmpStatusException.noSuchInstance)
+            // noSuchInstance => notWritable
+            mappedErrorCode = SnmpStatusException.snmpRspNotWritable;
+
+        return mappedErrorCode;
+    }
+
+    public static int mapGetException(int errorStatus, int version)
+        throws SnmpStatusException {
+
+        final int errorCode = errorStatus;
+        if (version == SnmpDefinitions.snmpVersionOne)
+            return errorCode;
+
+        int mappedErrorCode = errorCode;
+
+        // Now take care of V2 errorCodes that can be stored
+        // in the varbind itself:
+        if (errorCode ==
+            SnmpStatusException.noSuchObject)
+            // noSuchObject => noSuchObject
+            mappedErrorCode = errorCode;
+
+        else if (errorCode ==
+                 SnmpStatusException.noSuchInstance)
+            // noSuchInstance => noSuchInstance
+            mappedErrorCode = errorCode;
+
+        // Now we're going to try to transform every other
+        // global code in either noSuchInstance or noSuchObject,
+        // so that the get can return a partial result.
+        //
+        // Only noSuchInstance or noSuchObject can be stored
+        // in the varbind itself.
+        //
+
+        // According to RFC 1905: noAccess is emitted when the
+        // the access is denied because it is not in the MIB view...
+        //
+        else if (errorCode ==
+                 SnmpStatusException.noAccess)
+            // noAccess => noSuchInstance
+            mappedErrorCode = SnmpStatusException.noSuchInstance;
+
+        // According to RFC 1905: (my interpretation because it is not
+        // really clear) The specified variable name exists - but the
+        // variable does not exists and cannot be created under the
+        // present circumstances (probably because the request specifies
+        // another variable/value which is incompatible, or because the
+        // value of some other variable in the MIB prevents the creation)
+        //
+        // Note that this error should never be raised in a GET context
+        // but who knows?
+        //
+        else if (errorCode == SnmpStatusException.snmpRspInconsistentName)
+            // inconsistentName => noSuchInstance
+            mappedErrorCode = SnmpStatusException.noSuchInstance;
+
+        // All the errors comprised between snmpRspWrongType and
+        // snmpRspInconsistentValue concern values: so we're going
+        // to assume the OID was correct, and reply with noSuchInstance.
+        //
+        // Note that this error should never be raised in a GET context
+        // but who knows?
+        //
+        else if ((errorCode >= SnmpStatusException.snmpRspWrongType) &&
+                 (errorCode <= SnmpStatusException.snmpRspInconsistentValue))
+            mappedErrorCode = SnmpStatusException.noSuchInstance;
+
+        // We're going to assume the OID was correct, and reply
+        // with noSuchInstance.
+        //
+        else if (errorCode == SnmpStatusException.readOnly)
+            mappedErrorCode = SnmpStatusException.noSuchInstance;
+
+        // For all other errors but genErr, we're going to reply with
+        // noSuchObject
+        //
+        else if (errorCode != SnmpStatusException.snmpRspAuthorizationError &&
+                 errorCode != SnmpStatusException.snmpRspGenErr)
+            mappedErrorCode = SnmpStatusException.noSuchObject;
+
+        // Only genErr will abort the GET and be returned as global
+        // error.
+        //
+        return mappedErrorCode;
+
+    }
+
+    //-------------------------------------------------------------------
+    // This class is a package implementation of the enumeration of
+    // SnmSubRequest associated with an Handler node.
+    //-------------------------------------------------------------------
+
+    static final class Enum implements Enumeration {
+        Enum(SnmpRequestTree hlist,Handler h) {
+            handler = h;
+            this.hlist = hlist;
+            size = h.getSubReqCount();
+        }
+        private final Handler handler;
+        private final SnmpRequestTree hlist;
+        private int   entry = 0;
+        private int   iter  = 0;
+        private int   size  = 0;
+
+        public boolean hasMoreElements() {
+            return iter < size;
+        }
+
+        public Object nextElement() throws NoSuchElementException  {
+            if (iter == 0) {
+                if (handler.sublist != null) {
+                    iter++;
+                    return hlist.getSubRequest(handler);
+                }
+            }
+            iter ++;
+            if (iter > size) throw new NoSuchElementException();
+            Object result = hlist.getSubRequest(handler,entry);
+            entry++;
+            return result;
+        }
+    }
+
+    //-------------------------------------------------------------------
+    // This class is a package implementation of the SnmpMibSubRequest
+    // interface. It can only be instantiated by SnmpRequestTree.
+    //-------------------------------------------------------------------
+
+    static final class SnmpMibSubRequestImpl implements SnmpMibSubRequest {
+        SnmpMibSubRequestImpl(SnmpMibRequest global, Vector<SnmpVarBind> sublist,
+                           SnmpOid entryoid, boolean isnew,
+                           boolean getnextflag, SnmpVarBind rs) {
+            this.global = global;
+            varbinds           = sublist;
+            this.version       = global.getVersion();
+            this.entryoid      = entryoid;
+            this.isnew         = isnew;
+            this.getnextflag   = getnextflag;
+            this.statusvb      = rs;
+        }
+
+        final private Vector<SnmpVarBind> varbinds;
+        final private SnmpMibRequest global;
+        final private int            version;
+        final private boolean        isnew;
+        final private SnmpOid        entryoid;
+        final private boolean        getnextflag;
+        final private SnmpVarBind    statusvb;
+
+        // -------------------------------------------------------------
+        // Implements the method defined in SnmpMibRequest interface.
+        // See SnmpMibRequest for the java doc.
+        // -------------------------------------------------------------
+        public Enumeration getElements() {
+            return varbinds.elements();
+        }
+
+        // -------------------------------------------------------------
+        // Implements the method defined in SnmpMibRequest interface.
+        // See SnmpMibRequest for the java doc.
+        // -------------------------------------------------------------
+        public Vector<SnmpVarBind> getSubList() {
+            return varbinds;
+        }
+
+        // -------------------------------------------------------------
+        // Implements the method defined in SnmpMibRequest interface.
+        // See SnmpMibRequest for the java doc.
+        // -------------------------------------------------------------
+        public final int getSize()  {
+            if (varbinds == null) return 0;
+            return varbinds.size();
+        }
+
+        // -------------------------------------------------------------
+        // Implements the method defined in SnmpMibRequest interface.
+        // See SnmpMibRequest for the java doc.
+        // -------------------------------------------------------------
+        public void addVarBind(SnmpVarBind varbind) {
+            // XXX not sure we must also add the varbind in the global
+            //     request? or whether we should raise an exception:
+            //     in principle, this method should not be called!
+            varbinds.addElement(varbind);
+            global.addVarBind(varbind);
+        }
+
+        // -------------------------------------------------------------
+        // Implements the method defined in SnmpMibSubRequest interface.
+        // See SnmpMibSubRequest for the java doc.
+        // -------------------------------------------------------------
+        public boolean isNewEntry() {
+            return isnew;
+        }
+
+        // -------------------------------------------------------------
+        // Implements the method defined in SnmpMibSubRequest interface.
+        // See SnmpMibSubRequest for the java doc.
+        // -------------------------------------------------------------
+        public SnmpOid getEntryOid() {
+            return entryoid;
+        }
+
+        // -------------------------------------------------------------
+        // Implements the method defined in SnmpMibRequest interface.
+        // See SnmpMibRequest for the java doc.
+        // -------------------------------------------------------------
+        public int getVarIndex(SnmpVarBind varbind) {
+            if (varbind == null) return 0;
+            return global.getVarIndex(varbind);
+        }
+
+        // -------------------------------------------------------------
+        // Implements the method defined in SnmpMibRequest interface.
+        // See SnmpMibRequest for the java doc.
+        // -------------------------------------------------------------
+        public Object getUserData() { return global.getUserData(); }
+
+
+        // -------------------------------------------------------------
+        // Implements the method defined in SnmpMibSubRequest interface.
+        // See SnmpMibSubRequest for the java doc.
+        // -------------------------------------------------------------
+
+        public void registerGetException(SnmpVarBind var,
+                                         SnmpStatusException exception)
+            throws SnmpStatusException {
+            // The index in the exception must correspond to
+            // the SNMP index ...
+            //
+            if (version == SnmpDefinitions.snmpVersionOne)
+                throw new SnmpStatusException(exception, getVarIndex(var)+1);
+
+            if (var == null)
+                throw exception;
+
+            // If we're doing a getnext ==> endOfMibView
+            if (getnextflag) {
+                var.value = SnmpVarBind.endOfMibView;
+                return;
+            }
+
+            final int errorCode = mapGetException(exception.getStatus(),
+                                                  version);
+
+            // Now take care of V2 errorCodes that can be stored
+            // in the varbind itself:
+            if (errorCode ==
+                SnmpStatusException.noSuchObject)
+                // noSuchObject => noSuchObject
+                var.value= SnmpVarBind.noSuchObject;
+
+            else if (errorCode ==
+                     SnmpStatusException.noSuchInstance)
+                // noSuchInstance => noSuchInstance
+                var.value= SnmpVarBind.noSuchInstance;
+
+            else
+                throw new SnmpStatusException(errorCode, getVarIndex(var)+1);
+
+        }
+
+        // -------------------------------------------------------------
+        // Implements the method defined in SnmpMibSubRequest interface.
+        // See SnmpMibSubRequest for the java doc.
+        // -------------------------------------------------------------
+        public void registerSetException(SnmpVarBind var,
+                                         SnmpStatusException exception)
+            throws SnmpStatusException {
+            // The index in the exception must correspond to
+            // the SNMP index ...
+            //
+            if (version == SnmpDefinitions.snmpVersionOne)
+                throw new SnmpStatusException(exception, getVarIndex(var)+1);
+
+            // Although the first pass of check() did not fail,
+            // the set() phase could not be carried out correctly.
+            // Since we don't know how to make an "undo", and some
+            // assignation may already have been performed, we're going
+            // to throw an snmpRspUndoFailed.
+            //
+            throw new SnmpStatusException(SnmpDefinitions.snmpRspUndoFailed,
+                                          getVarIndex(var)+1);
+        }
+
+        // -------------------------------------------------------------
+        // Implements the method defined in SnmpMibSubRequest interface.
+        // See SnmpMibSubRequest for the java doc.
+        // -------------------------------------------------------------
+        public void registerCheckException(SnmpVarBind var,
+                                           SnmpStatusException exception)
+            throws SnmpStatusException {
+            // The index in the exception must correspond to
+            // the SNMP index ...
+            //
+            // We throw the exception in order to abort the SET operation
+            // in an atomic way.
+            final int errorCode = exception.getStatus();
+            final int mappedErrorCode = mapSetException(errorCode,
+                                                        version);
+
+            if (errorCode != mappedErrorCode)
+                throw new
+                    SnmpStatusException(mappedErrorCode, getVarIndex(var)+1);
+            else
+                throw new SnmpStatusException(exception, getVarIndex(var)+1);
+        }
+
+        // -------------------------------------------------------------
+        // Implements the method defined in SnmpMibRequest interface.
+        // See SnmpMibRequest for the java doc.
+        // -------------------------------------------------------------
+        public int getVersion() {
+            return version;
+        }
+
+        public SnmpVarBind getRowStatusVarBind() {
+            return statusvb;
+        }
+
+        public SnmpPdu getPdu() {
+            return global.getPdu();
+        }
+
+        public int getRequestPduVersion() {
+            return global.getRequestPduVersion();
+        }
+
+        public SnmpEngine getEngine() {
+            return global.getEngine();
+        }
+
+        public String getPrincipal() {
+            return global.getPrincipal();
+        }
+
+        public int getSecurityLevel() {
+            return global.getSecurityLevel();
+        }
+
+        public int getSecurityModel() {
+            return global.getSecurityModel();
+        }
+
+        public byte[] getContextName() {
+            return global.getContextName();
+        }
+
+        public byte[] getAccessContextName() {
+            return global.getAccessContextName();
+        }
+    }
+
+    //-------------------------------------------------------------------
+    // This class implements a node in the SnmpRequestTree.
+    // It stores:
+    //    o The SnmpMibNode involved (key)
+    //    o The sublist of varbind directly handled by this node
+    //    o A vector of sublists concerning the entries (existing or not)
+    //      of the SnmpMIbNode (when it is a table).
+    //-------------------------------------------------------------------
+
+    static final class Handler {
+        SnmpMibNode meta;       // The meta  which handles the sublist.
+        int         depth;      // The depth of the meta node.
+        Vector<SnmpVarBind> sublist; // The sublist of varbinds to be handled.
+        // List        entryoids;  // Sorted array of entry oids
+        // List        entrylists; // Sorted array of entry lists
+        // List        isentrynew; // Sorted array of booleans
+        SnmpOid[]     entryoids  = null; // Sorted array of entry oids
+        Vector<SnmpVarBind>[] entrylists = null; // Sorted array of entry lists
+        boolean[]     isentrynew = null; // Sorted array of booleans
+        SnmpVarBind[] rowstatus  = null; // RowStatus varbind, if any
+        int entrycount = 0;
+        int entrysize  = 0;
+
+        final int type; // request PDU type as defined in SnmpDefinitions
+        final private static int Delta = 10;
+
+        public Handler(int pduType) {
+            this.type = pduType;
+        }
+
+        /**
+         * Adds a varbind in this node sublist.
+         */
+        public void addVarbind(SnmpVarBind varbind) {
+            if (sublist == null) sublist = new Vector<SnmpVarBind>();
+            sublist.addElement(varbind);
+        }
+
+        /**
+         * register an entry for the given oid at the given position with
+         * the given sublist.
+         */
+        @SuppressWarnings("unchecked")
+        // We need this because of new Vector[n] instead of
+        // new Vector<SnmpVarBind>[n], which is illegal.
+        void add(int pos,SnmpOid oid, Vector<SnmpVarBind> v, boolean isnew,
+                 SnmpVarBind statusvb) {
+
+            if (entryoids == null) {
+                // Vectors are null: Allocate new vectors
+
+                entryoids  = new SnmpOid[Delta];
+                entrylists = new Vector[Delta];
+                isentrynew = new boolean[Delta];
+                rowstatus  = new SnmpVarBind[Delta];
+                entrysize  = Delta;
+                pos = 0;
+
+            } else if (pos >= entrysize || entrycount == entrysize) {
+                // Vectors must be enlarged
+
+                // Save old vectors
+                SnmpOid[]     olde = entryoids;
+                Vector[]      oldl = entrylists;
+                boolean[]     oldn = isentrynew;
+                SnmpVarBind[] oldr = rowstatus;
+
+                // Allocate larger vectors
+                entrysize += Delta;
+                entryoids =  new SnmpOid[entrysize];
+                entrylists = new Vector[entrysize];
+                isentrynew = new boolean[entrysize];
+                rowstatus  = new SnmpVarBind[entrysize];
+
+                // Check pos validity
+                if (pos > entrycount) pos = entrycount;
+                if (pos < 0) pos = 0;
+
+                final int l1 = pos;
+                final int l2 = entrycount - pos;
+
+                // Copy original vectors up to `pos'
+                if (l1 > 0) {
+                    java.lang.System.arraycopy(olde,0,entryoids,
+                                               0,l1);
+                    java.lang.System.arraycopy(oldl,0,entrylists,
+                                               0,l1);
+                    java.lang.System.arraycopy(oldn,0,isentrynew,
+                                               0,l1);
+                    java.lang.System.arraycopy(oldr,0,rowstatus,
+                                               0,l1);
+                }
+
+                // Copy original vectors from `pos' to end, leaving
+                // an empty room at `pos' in the new vectors.
+                if (l2 > 0) {
+                    final int l3 = l1+1;
+                    java.lang.System.arraycopy(olde,l1,entryoids,
+                                               l3,l2);
+                    java.lang.System.arraycopy(oldl,l1,entrylists,
+                                               l3,l2);
+                    java.lang.System.arraycopy(oldn,l1,isentrynew,
+                                               l3,l2);
+                    java.lang.System.arraycopy(oldr,l1,rowstatus,
+                                               l3,l2);
+                }
+
+
+            } else if (pos < entrycount) {
+                // Vectors are large enough to accomodate one additional
+                // entry.
+                //
+                // Shift vectors, making an empty room at `pos'
+                final int l1 = pos+1;
+                final int l2 = entrycount - pos;
+
+                java.lang.System.arraycopy(entryoids,pos,entryoids,
+                                           l1,l2);
+                java.lang.System.arraycopy(entrylists,pos,entrylists,
+                                           l1,l2);
+                java.lang.System.arraycopy(isentrynew,pos,isentrynew,
+                                           l1,l2);
+                java.lang.System.arraycopy(rowstatus,pos,rowstatus,
+                                           l1,l2);
+            }
+
+            // Fill the gap at `pos'
+            entryoids[pos]  = oid;
+            entrylists[pos] = v;
+            isentrynew[pos] = isnew;
+            rowstatus[pos]  = statusvb;
+            entrycount++;
+        }
+
+        public void addVarbind(SnmpVarBind varbind, SnmpOid entryoid,
+                               boolean isnew, SnmpVarBind statusvb)
+            throws SnmpStatusException {
+            Vector<SnmpVarBind> v = null;
+            SnmpVarBind rs = statusvb;
+
+            if (entryoids == null) {
+//              entryoids = new ArrayList();
+//              entrylists = new ArrayList();
+//              isentrynew = new ArrayList();
+                v = new Vector<SnmpVarBind>();
+//              entryoids.add(entryoid);
+//              entrylists.add(v);
+//              isentrynew.add(new Boolean(isnew));
+                add(0,entryoid,v,isnew,rs);
+            } else {
+                // int pos = findOid(entryoids,entryoid);
+                // int pos = findOid(entryoids,entrycount,entryoid);
+                final int pos =
+                    getInsertionPoint(entryoids,entrycount,entryoid);
+                if (pos > -1 && pos < entrycount &&
+                    entryoid.compareTo(entryoids[pos]) == 0) {
+                    v  = entrylists[pos];
+                    rs = rowstatus[pos];
+                } else {
+                    // if (pos == -1 || pos >= entryoids.size() ) {
+                    // if (pos == -1 || pos >= entrycount ) {
+                    // pos = getInsertionPoint(entryoids,entryoid);
+                    // pos = getInsertionPoint(entryoids,entrycount,entryoid);
+                    v = new Vector<SnmpVarBind>();
+//                  entryoids.add(pos,entryoid);
+//                  entrylists.add(pos,v);
+//                  isentrynew.add(pos,new Boolean(isnew));
+                    add(pos,entryoid,v,isnew,rs);
+                }
+//              } else v = (Vector) entrylists.get(pos);
+                    // } else v = entrylists[pos];
+                if (statusvb != null) {
+                    if ((rs != null) && (rs != statusvb) &&
+                        ((type == SnmpDefinitions.pduWalkRequest) ||
+                         (type == SnmpDefinitions.pduSetRequestPdu))) {
+                        throw new SnmpStatusException(
+                              SnmpStatusException.snmpRspInconsistentValue);
+                    }
+                    rowstatus[pos] = statusvb;
+                }
+            }
+
+            // We do not include the status variable in the varbind,
+            // because we're going to set it separately...
+            //
+            if (statusvb != varbind)
+                v.addElement(varbind);
+        }
+
+        public int getSubReqCount() {
+            int count = 0;
+            if (sublist != null) count++;
+//          if (entryoids != null) count += entryoids.size();
+            if (entryoids != null) count += entrycount;
+            return count;
+        }
+
+        public Vector<SnmpVarBind> getSubList() {
+            return sublist;
+        }
+
+        public int getEntryPos(SnmpOid entryoid) {
+            // return findOid(entryoids,entryoid);
+            return findOid(entryoids,entrycount,entryoid);
+        }
+
+        public SnmpOid getEntryOid(int pos) {
+            if (entryoids == null) return null;
+            // if (pos == -1 || pos >= entryoids.size() ) return null;
+            if (pos == -1 || pos >= entrycount ) return null;
+            // return (SnmpOid) entryoids.get(pos);
+            return entryoids[pos];
+        }
+
+        public boolean isNewEntry(int pos) {
+            if (entryoids == null) return false;
+            // if (pos == -1 || pos >= entryoids.size() ) return false;
+            if (pos == -1 || pos >= entrycount ) return false;
+            // return ((Boolean)isentrynew.get(pos)).booleanValue();
+            return isentrynew[pos];
+        }
+
+        public SnmpVarBind getRowStatusVarBind(int pos) {
+            if (entryoids == null) return null;
+            // if (pos == -1 || pos >= entryoids.size() ) return false;
+            if (pos == -1 || pos >= entrycount ) return null;
+            // return ((Boolean)isentrynew.get(pos)).booleanValue();
+            return rowstatus[pos];
+        }
+
+        public Vector<SnmpVarBind> getEntrySubList(int pos) {
+            if (entrylists == null) return null;
+            // if (pos == -1 || pos >= entrylists.size() ) return null;
+            if (pos == -1 || pos >= entrycount ) return null;
+            // return (Vector) entrylists.get(pos);
+            return entrylists[pos];
+        }
+
+        public Iterator<SnmpOid> getEntryOids() {
+            if (entryoids == null) return null;
+            // return entryoids.iterator();
+            return Arrays.asList(entryoids).iterator();
+        }
+
+        public int getEntryCount() {
+            if (entryoids == null) return 0;
+            // return entryoids.size();
+            return entrycount;
+        }
+
+    }
+
+
+    //-------------------------------------------------------------------
+    //-------------------------------------------------------------------
+    // Public interface
+    //-------------------------------------------------------------------
+    //-------------------------------------------------------------------
+
+    //-------------------------------------------------------------------
+    // Returns the contextual object containing user-data allocated
+    // through the SnmpUserDataFactory for this request.
+    //-------------------------------------------------------------------
+
+    public Object getUserData() { return request.getUserData(); }
+
+    //-------------------------------------------------------------------
+    // Tells whether creation of new entries is allowed with respect
+    // to the operation involved (GET=>false/SET=>true)
+    //-------------------------------------------------------------------
+
+    public boolean isCreationAllowed() {
+        return creationflag;
+    }
+
+    //-------------------------------------------------------------------
+    // Tells whether we are currently processing a SET request (check/set)
+    //-------------------------------------------------------------------
+
+    public boolean isSetRequest() {
+        return setreqflag;
+    }
+
+    //-------------------------------------------------------------------
+    // Returns the protocol version in which the original request is
+    // evaluated.
+    //-------------------------------------------------------------------
+
+    public int getVersion() {
+        return version;
+    }
+
+    //-------------------------------------------------------------------
+    // Returns the actual protocol version of the request PDU.
+    //-------------------------------------------------------------------
+
+    public int getRequestPduVersion() {
+        return request.getRequestPduVersion();
+    }
+
+    //-------------------------------------------------------------------
+    // Returns the SnmpMibNode associated with the given handler
+    //-------------------------------------------------------------------
+
+    public SnmpMibNode getMetaNode(Handler handler) {
+        return handler.meta;
+    }
+
+    //-------------------------------------------------------------------
+    // Indicates the depth of the arc in the OID that identifies the
+    // SnmpMibNode associated with the given handler
+    //-------------------------------------------------------------------
+
+    public int getOidDepth(Handler handler) {
+        return handler.depth;
+    }
+
+    //-------------------------------------------------------------------
+    // returns an enumeration of the SnmpMibSubRequest's to be invoked on
+    // the SnmpMibNode associated with a given Handler node.
+    // If this node is a group, there will be a single subrequest.
+    // If it is a table, there will be one subrequest per entry involved.
+    //-------------------------------------------------------------------
+
+    public Enumeration getSubRequests(Handler handler) {
+        return new Enum(this,handler);
+    }
+
+    //-------------------------------------------------------------------
+    // returns an enumeration of the Handlers stored in the Hashtable.
+    //-------------------------------------------------------------------
+
+    public Enumeration getHandlers() {
+        return hashtable.elements();
+    }
+
+    //-------------------------------------------------------------------
+    // adds a varbind to a handler node sublist
+    //-------------------------------------------------------------------
+
+    public void add(SnmpMibNode meta, int depth, SnmpVarBind varbind)
+        throws SnmpStatusException {
+        registerNode(meta,depth,null,varbind,false,null);
+    }
+
+    //-------------------------------------------------------------------
+    // adds an entry varbind to a handler node sublist
+    //-------------------------------------------------------------------
+
+    public void add(SnmpMibNode meta, int depth, SnmpOid entryoid,
+                    SnmpVarBind varbind, boolean isnew)
+        throws SnmpStatusException {
+        registerNode(meta,depth,entryoid,varbind,isnew,null);
+    }
+
+    //-------------------------------------------------------------------
+    // adds an entry varbind to a handler node sublist - specifying the
+    // varbind which holds the row status
+    //-------------------------------------------------------------------
+
+    public void add(SnmpMibNode meta, int depth, SnmpOid entryoid,
+                    SnmpVarBind varbind, boolean isnew,
+                    SnmpVarBind statusvb)
+        throws SnmpStatusException {
+        registerNode(meta,depth,entryoid,varbind,isnew,statusvb);
+    }
+
+
+    //-------------------------------------------------------------------
+    //-------------------------------------------------------------------
+    // Protected interface
+    //-------------------------------------------------------------------
+    //-------------------------------------------------------------------
+
+    //-------------------------------------------------------------------
+    // Type of the request (see SnmpDefinitions)
+    //-------------------------------------------------------------------
+
+    void setPduType(int pduType) {
+        type = pduType;
+        setreqflag = ((pduType == SnmpDefinitions.pduWalkRequest) ||
+            (pduType == SnmpDefinitions.pduSetRequestPdu));
+    }
+
+    //-------------------------------------------------------------------
+    // We deal with a GET-NEXT request
+    //-------------------------------------------------------------------
+
+    void setGetNextFlag() {
+        getnextflag = true;
+    }
+
+    //-------------------------------------------------------------------
+    // Tell whether creation is allowed.
+    //-------------------------------------------------------------------
+    void switchCreationFlag(boolean flag) {
+        creationflag = flag;
+    }
+
+
+    //-------------------------------------------------------------------
+    // Returns the subrequest handled by the SnmpMibNode itself
+    // (in principle, only for Groups)
+    //-------------------------------------------------------------------
+
+    SnmpMibSubRequest getSubRequest(Handler handler) {
+        if (handler == null) return null;
+        return new SnmpMibSubRequestImpl(request,handler.getSubList(),
+                                      null,false,getnextflag,null);
+    }
+
+    //-------------------------------------------------------------------
+    // Returns the subrequest associated with the entry identified by
+    // the given entry (only for tables)
+    //-------------------------------------------------------------------
+
+    SnmpMibSubRequest getSubRequest(Handler handler, SnmpOid oid) {
+        if (handler == null) return null;
+        final int pos = handler.getEntryPos(oid);
+        if (pos == -1) return null;
+        return new SnmpMibSubRequestImpl(request,
+                                         handler.getEntrySubList(pos),
+                                         handler.getEntryOid(pos),
+                                         handler.isNewEntry(pos),
+                                         getnextflag,
+                                         handler.getRowStatusVarBind(pos));
+    }
+
+    //-------------------------------------------------------------------
+    // Returns the subrequest associated with the entry identified by
+    // the given entry (only for tables). The `entry' parameter is an
+    // index relative to the position of the entry in the handler sublist.
+    //-------------------------------------------------------------------
+
+    SnmpMibSubRequest getSubRequest(Handler handler, int entry) {
+        if (handler == null) return null;
+        return new
+            SnmpMibSubRequestImpl(request,handler.getEntrySubList(entry),
+                                  handler.getEntryOid(entry),
+                                  handler.isNewEntry(entry),getnextflag,
+                                  handler.getRowStatusVarBind(entry));
+    }
+
+    //-------------------------------------------------------------------
+    //-------------------------------------------------------------------
+    // Private section
+    //-------------------------------------------------------------------
+    //-------------------------------------------------------------------
+
+
+    //-------------------------------------------------------------------
+    // stores a handler node in the Hashtable
+    //-------------------------------------------------------------------
+
+    private void put(Object key, Handler handler) {
+        if (handler == null) return;
+        if (key == null) return;
+        if (hashtable == null) hashtable = new Hashtable<Object, Handler>();
+        hashtable.put(key,handler);
+    }
+
+    //-------------------------------------------------------------------
+    // finds a handler node in the Hashtable
+    //-------------------------------------------------------------------
+
+    private Handler get(Object key) {
+        if (key == null) return null;
+        if (hashtable == null) return null;
+        return hashtable.get(key);
+    }
+
+    //-------------------------------------------------------------------
+    // Search for the given oid in `oids'. If none is found, returns -1
+    // otherwise, returns the index at which the oid is located.
+    //-------------------------------------------------------------------
+
+    private static int findOid(SnmpOid[] oids, int count, SnmpOid oid) {
+        final int size = count;
+        int low= 0;
+        int max= size - 1;
+        int curr= low + (max-low)/2;
+        //System.out.println("Try to retrieve: " + oid.toString());
+        while (low <= max) {
+
+            final SnmpOid pos = oids[curr];
+
+            //System.out.println("Compare with" + pos.toString());
+            // never know ...we might find something ...
+            //
+            final int comp = oid.compareTo(pos);
+            if (comp == 0)
+                return curr;
+
+            if (oid.equals(pos)) {
+                return curr;
+            }
+            if (comp > 0) {
+                low = curr + 1;
+            } else {
+                max = curr - 1;
+            }
+            curr = low + (max-low)/2;
+        }
+        return -1;
+    }
+
+    //-------------------------------------------------------------------
+    // Return the index at which the given oid should be inserted in the
+    // `oids' array.
+    //-------------------------------------------------------------------
+
+    private static int getInsertionPoint(SnmpOid[] oids, int count,
+                                         SnmpOid oid) {
+        final SnmpOid[] localoids = oids;
+        final int size = count;
+        int low= 0;
+        int max= size - 1;
+        int curr= low + (max-low)/2;
+
+
+        while (low <= max) {
+
+            final SnmpOid pos = localoids[curr];
+
+            // never know ...we might find something ...
+            //
+            final int comp= oid.compareTo(pos);
+
+            // In the calling method we will have to check for this case...
+            //    if (comp == 0)
+            //       return -1;
+            // Returning curr instead of -1 avoids having to call
+            // findOid() first and getInsertionPoint() afterwards.
+            // We can simply call getInsertionPoint() and then checks whether
+            // there's an OID at the returned position which equals the
+            // given OID.
+            if (comp == 0)
+                return curr;
+
+            if (comp>0) {
+                low= curr +1;
+            } else {
+                max= curr -1;
+            }
+            curr= low + (max-low)/2;
+        }
+        return curr;
+    }
+
+    //-------------------------------------------------------------------
+    // adds a varbind in a handler node sublist
+    //-------------------------------------------------------------------
+
+    private void registerNode(SnmpMibNode meta, int depth, SnmpOid entryoid,
+                              SnmpVarBind varbind, boolean isnew,
+                              SnmpVarBind statusvb)
+        throws SnmpStatusException {
+        if (meta == null) {
+            SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
+                    SnmpRequestTree.class.getName(),
+                    "registerNode", "meta-node is null!");
+            return;
+        }
+        if (varbind == null) {
+            SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
+                    SnmpRequestTree.class.getName(),
+                    "registerNode", "varbind is null!");
+            return ;
+        }
+
+        final Object key = meta;
+
+        // retrieve the handler node associated with the given meta,
+        // if any
+        Handler handler = get(key);
+
+        // If no handler node was found for that meta, create one.
+        if (handler == null) {
+            // if (isDebugOn())
+            //    debug("registerNode", "adding node for " +
+            //          varbind.oid.toString());
+            handler = new Handler(type);
+            handler.meta  = meta;
+            handler.depth = depth;
+            put(key,handler);
+        }
+        // else {
+        //   if (isDebugOn())
+        //      debug("registerNode","found node for " +
+        //            varbind.oid.toString());
+        // }
+
+        // Adds the varbind in the handler node's sublist.
+        if (entryoid == null)
+            handler.addVarbind(varbind);
+        else
+            handler.addVarbind(varbind,entryoid,isnew,statusvb);
+        return ;
+    }
+
+
+    //-------------------------------------------------------------------
+    // private variables
+    //-------------------------------------------------------------------
+
+    private Hashtable<Object, Handler> hashtable = null;
+                                             // Hashtable of Handler objects
+    private SnmpMibRequest request = null;   // The original list of varbinds
+    private int       version      = 0;      // The protocol version
+    private boolean   creationflag = false;  // Does the operation allow
+                                             // creation of entries
+    private boolean   getnextflag  = false;  // Does the operation allow
+                                             // creation of entries
+    private int       type         = 0;      // Request PDU type as defined
+                                             // in SnmpDefinitions
+    private boolean   setreqflag   = false;  // True if we're processing a
+                                             // SET request (check/set).
+}
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpStandardMetaServer.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpStandardMetaServer.java
new file mode 100644
index 0000000..da597f7
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpStandardMetaServer.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2000-2003 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.jmx.snmp.agent;
+
+// jmx imports
+//
+import com.sun.jmx.snmp.SnmpValue;
+import com.sun.jmx.snmp.SnmpStatusException;
+
+/**
+ * <p>
+ * This interface defines the methods that must be implemented by an
+ * SNMP metadata object that needs to interact with an
+ * {@link com.sun.jmx.snmp.agent.SnmpStandardObjectServer} object.
+ * </p>
+ * <p>
+ * All these methods are usually generated by <code>mibgen</code> when
+ * run in standard-metadata mode (default).
+ * </p>
+ * <p><b><i>
+ * This interface is used internally between the generated Metadata and
+ * the SNMP runtime and you shouldn't need to worry about it, because
+ * you will never have to use it directly.
+ * </b></i></p>
+ *
+ * <p><b>This API is a Sun Microsystems internal API  and is subject
+ * to change without notice.</b></p>
+ **/
+public interface SnmpStandardMetaServer {
+    /**
+     * Returns the value of the scalar object identified by the given
+     * OID arc.
+     *
+     * @param arc OID arc of the querried scalar object.
+     *
+     * @return The <CODE>SnmpValue</CODE> of the scalar object identified
+     *         by <CODE>arc</CODE>.
+     *
+     * @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 the arc is not valid, or if
+     *    access is denied.
+     *
+     **/
+    public SnmpValue get(long arc, Object userData)
+        throws SnmpStatusException ;
+
+    /**
+     * Sets the value of the scalar object identified by the given
+     * OID arc.
+     *
+     * @param x New value for the scalar object identified by
+     *    <CODE>arc</CODE>
+     *
+     * @param arc OID arc of the scalar object whose value is set.
+     *
+     * @return The new <CODE>SnmpValue</CODE> of the scalar object
+     *    identified by <CODE>arc</CODE>.
+     *
+     * @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 the arc is not valid, or if
+     *    access is denied.
+     *
+     **/
+    public SnmpValue set(SnmpValue x, long arc, Object userData)
+        throws SnmpStatusException ;
+
+    /**
+     * Checks that the new desired value of the scalar object identified
+     * by the given OID arc is valid.
+     *
+     * @param x New value for the scalar object identified by
+     *    <CODE>arc</CODE>
+     *
+     * @param arc OID arc of the scalar object whose value is set.
+     *
+     * @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 the arc is not valid, or if
+     *    access is denied, or if the new desired value is not valid.
+     *
+     **/
+    public void check(SnmpValue x, long arc, Object userData)
+        throws SnmpStatusException ;
+
+}
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpStandardObjectServer.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpStandardObjectServer.java
new file mode 100644
index 0000000..3d1f92c
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpStandardObjectServer.java
@@ -0,0 +1,264 @@
+/*
+ * Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package com.sun.jmx.snmp.agent;
+
+// java imports
+//
+import java.io.Serializable;
+import java.util.Hashtable;
+import java.util.Enumeration;
+import java.util.Vector;
+
+// jmx imports
+//
+import com.sun.jmx.snmp.SnmpOid;
+import com.sun.jmx.snmp.SnmpValue;
+import com.sun.jmx.snmp.SnmpVarBind;
+import com.sun.jmx.snmp.SnmpStatusException;
+
+// SNMP Runtime imports
+//
+
+/**
+ * <p>
+ * This class is a utility class that transform SNMP GET / SET requests
+ * into series of get<i>AttributeName</i>() set<i>AttributeName</i>()
+ * invoked on the MBean.
+ * </p>
+ *
+ * <p>
+ * The transformation relies on the metadata information provided by the
+ * {@link com.sun.jmx.snmp.agent.SnmpStandardMetaServer} object which is
+ * passed as first parameter to every method. This SnmpStandardMetaServer
+ * object is usually a Metadata object generated by <code>mibgen</code>.
+ * </p>
+ *
+ * <p>
+ * The MBean is not invoked directly by this class but through the
+ * metadata object which holds a reference on it.
+ * </p>
+ *
+ * <p><b><i>
+ * This class is used internally by mibgen generated metadata objects and
+ * you should never need to use it directly.
+ * </b></i></p>
+ * <p><b>This API is a Sun Microsystems internal API  and is subject
+ * to change without notice.</b></p>
+ **/
+
+public class SnmpStandardObjectServer implements Serializable {
+    private static final long serialVersionUID = -4641068116505308488L;
+
+    /**
+     * Generic handling of the <CODE>get</CODE> operation.
+     * <p> The default implementation of this method is to loop over the
+     * varbind list associated with the sub-request and to call
+     * <CODE>get(var.oid.getOidArc(depth), data);</CODE>
+     * <pre>
+     * public void get(SnmpStandardMetaServer meta, SnmpMibSubRequest req,
+     *                 int depth)
+     *    throws SnmpStatusException {
+     *
+     *    final Object data = req.getUserData();
+     *
+     *    for (Enumeration e= req.getElements(); e.hasMoreElements();) {
+     *
+     *        final SnmpVarBind var= (SnmpVarBind) e.nextElement();
+     *
+     *        try {
+     *            // This method will generate a SnmpStatusException
+     *            // if `depth' is out of bounds.
+     *            //
+     *            final long id = var.oid.getOidArc(depth);
+     *            var.value = meta.get(id, data);
+     *        } catch(SnmpStatusException x) {
+     *            req.registerGetException(var,x);
+     *        }
+     *    }
+     * }
+     * </pre>
+     * <p> You can override this method if you need to implement some
+     * specific policies for minimizing the accesses made to some remote
+     * underlying resources.
+     * <p>
+     *
+     * @param meta  A pointer to the generated meta-data object which
+     *              implements the <code>SnmpStandardMetaServer</code>
+     *              interface.
+     *
+     * @param req   The sub-request that must be handled by this node.
+     *
+     * @param depth The depth reached in the OID tree.
+     *
+     * @exception SnmpStatusException An error occurred while accessing
+     *  the MIB node.
+     */
+    public void get(SnmpStandardMetaServer meta, SnmpMibSubRequest req,
+                    int depth)
+        throws SnmpStatusException {
+
+        final Object data = req.getUserData();
+
+        for (Enumeration e= req.getElements(); e.hasMoreElements();) {
+            final SnmpVarBind var= (SnmpVarBind) e.nextElement();
+            try {
+                final long id = var.oid.getOidArc(depth);
+                var.value = meta.get(id, data);
+            } catch(SnmpStatusException x) {
+                req.registerGetException(var,x);
+            }
+        }
+    }
+
+    /**
+     * Generic handling of the <CODE>set</CODE> operation.
+     * <p> The default implementation of this method is to loop over the
+     * varbind list associated with the sub-request and to call
+     * <CODE>set(var.value, var.oid.getOidArc(depth), data);</CODE>
+     * <pre>
+     * public void set(SnmpStandardMetaServer meta, SnmpMibSubRequest req,
+     *                 int depth)
+     *    throws SnmpStatusException {
+     *
+     *    final Object data = req.getUserData();
+     *
+     *    for (Enumeration e= req.getElements(); e.hasMoreElements();) {
+     *
+     *        final SnmpVarBind var= (SnmpVarBind) e.nextElement();
+     *
+     *        try {
+     *            // This method will generate a SnmpStatusException
+     *            // if `depth' is out of bounds.
+     *            //
+     *            final long id = var.oid.getOidArc(depth);
+     *            var.value = meta.set(var.value, id, data);
+     *        } catch(SnmpStatusException x) {
+     *            req.registerSetException(var,x);
+     *        }
+     *    }
+     * }
+     * </pre>
+     * <p> You can override this method if you need to implement some
+     * specific policies for minimizing the accesses made to some remote
+     * underlying resources.
+     * <p>
+     *
+     * @param meta  A pointer to the generated meta-data object which
+     *              implements the <code>SnmpStandardMetaServer</code>
+     *              interface.
+     *
+     * @param req   The sub-request that must be handled by this node.
+     *
+     * @param depth The depth reached in the OID tree.
+     *
+     * @exception SnmpStatusException An error occurred while accessing
+     *  the MIB node.
+     */
+    public void set(SnmpStandardMetaServer meta, SnmpMibSubRequest req,
+                    int depth)
+        throws SnmpStatusException {
+
+        final Object data = req.getUserData();
+
+        for (Enumeration e= req.getElements(); e.hasMoreElements();) {
+            SnmpVarBind var = null;
+            var = (SnmpVarBind) e.nextElement();
+            try {
+                // This method will generate a SnmpStatusException
+                // if `depth' is out of bounds.
+                //
+                final long id = var.oid.getOidArc(depth);
+                var.value = meta.set(var.value, id, data);
+            } catch(SnmpStatusException x) {
+                req.registerSetException(var,x);
+            }
+        }
+    }
+
+    /**
+     * Generic handling of the <CODE>check</CODE> operation.
+     * <p> The default implementation of this method is to loop over the
+     * varbind list associated with the sub-request and to call
+     * <CODE>check(var.value, var.oid.getOidArc(depth), data);</CODE>
+     * <pre>
+     * public void check(SnmpStandardMetaServer meta, SnmpMibSubRequest req,
+     *                   int depth)
+     *    throws SnmpStatusException {
+     *
+     *    final Object data = req.getUserData();
+     *
+     *    for (Enumeration e= req.getElements(); e.hasMoreElements();) {
+     *
+     *        final SnmpVarBind var= (SnmpVarBind) e.nextElement();
+     *
+     *        try {
+     *            // This method will generate a SnmpStatusException
+     *            // if `depth' is out of bounds.
+     *            //
+     *            final long id = var.oid.getOidArc(depth);
+     *            meta.check(var.value, id, data);
+     *        } catch(SnmpStatusException x) {
+     *            req.registerCheckException(var,x);
+     *        }
+     *    }
+     * }
+     * </pre>
+     * <p> You can override this method if you need to implement some
+     * 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.
+     * <p>
+     *
+     * @param meta  A pointer to the generated meta-data object which
+     *              implements the <code>SnmpStandardMetaServer</code>
+     *              interface.
+     *
+     * @param req   The sub-request that must be handled by this node.
+     *
+     * @param depth The depth reached in the OID tree.
+     *
+     * @exception SnmpStatusException An error occurred while accessing
+     *  the MIB node.
+     */
+    public void check(SnmpStandardMetaServer meta, SnmpMibSubRequest req,
+                      int depth)
+        throws SnmpStatusException {
+
+        final Object data = req.getUserData();
+
+        for (Enumeration e= req.getElements(); e.hasMoreElements();) {
+            final SnmpVarBind var = (SnmpVarBind) e.nextElement();
+            try {
+                // This method will generate a SnmpStatusException
+                // if `depth' is out of bounds.
+                //
+                final long id = var.oid.getOidArc(depth);
+                meta.check(var.value,id,data);
+            } catch(SnmpStatusException x) {
+                req.registerCheckException(var,x);
+            }
+        }
+    }
+}
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpTableCallbackHandler.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpTableCallbackHandler.java
new file mode 100644
index 0000000..e08ec34
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpTableCallbackHandler.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2000-2003 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package com.sun.jmx.snmp.agent;
+
+import javax.management.ObjectName;
+import com.sun.jmx.snmp.SnmpStatusException;
+import com.sun.jmx.snmp.SnmpOid;
+import com.sun.jmx.snmp.agent.SnmpMibTable;
+
+/**
+ * This interface ensures the synchronization between Metadata table objects
+ * and bean-like table objects.
+ *
+ * It is used between mibgen generated table meta and table classes.
+ * <p><b><i>
+ * You should never need to use this interface directly.
+ * </p></b></i>
+ *
+ * <p><b>This API is a Sun Microsystems internal API  and is subject
+ * to change without notice.</b></p>
+ **/
+public interface SnmpTableCallbackHandler {
+    /**
+     * This method is called by the SNMP runtime after a new entry
+     * has been added to the table.
+     *
+     * If an SnmpStatusException is raised, the entry will be removed
+     * and the operation will be aborted. In this case, the removeEntryCb()
+     * callback will not be called.
+     *
+     * <p><b><i>
+     * You should never need to use this method directly.
+     * </p></b></i>
+     *
+     **/
+    public void addEntryCb(int pos, SnmpOid row, ObjectName name,
+                           Object entry, SnmpMibTable meta)
+        throws SnmpStatusException;
+
+    /**
+     * This method is called by the SNMP runtime after a new entry
+     * has been removed from the table.
+     *
+     * If raised, SnmpStatusException will be ignored.
+     *
+     * <p><b><i>
+     * You should never need to use this method directly.
+     * </p></b></i>
+     *
+     **/
+    public void removeEntryCb(int pos, SnmpOid row, ObjectName name,
+                              Object entry, SnmpMibTable meta)
+        throws SnmpStatusException;
+}
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpTableEntryFactory.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpTableEntryFactory.java
new file mode 100644
index 0000000..6ebdef4
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpTableEntryFactory.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2000-2003 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.jmx.snmp.agent;
+
+import com.sun.jmx.snmp.SnmpStatusException;
+import com.sun.jmx.snmp.SnmpOid;
+import com.sun.jmx.snmp.agent.SnmpMibTable;
+import com.sun.jmx.snmp.agent.SnmpMibSubRequest;
+
+/**
+ * This interface is implemented by mibgen generated table objects
+ * inheriting from {@link com.sun.jmx.snmp.agent.SnmpTableSupport}.
+ * <p>
+ * It is used internally by the metadata whenever a remote SNMP manager
+ * requests the creation of a new entry through an SNMP SET.
+ * </p>
+ * <p>
+ * At creation, the mibgen generated table object retrieves its
+ * corresponding metadata from the MIB and registers with
+ * this metadata as a SnmpTableEntryFactory.
+ * </p>
+ *
+ * <p><b>This API is a Sun Microsystems internal API  and is subject
+ * to change without notice.</b></p>
+ **/
+
+public interface SnmpTableEntryFactory extends SnmpTableCallbackHandler {
+
+    /**
+     * This method is called by the SNMP runtime whenever a new entry
+     * creation is requested by a remote manager.
+     *
+     * The factory is responsible for instantiating the appropriate MBean
+     * and for registering it with the appropriate metadata object.
+     *
+     * Usually this method will:
+     * <ul>
+     * <li>Check whether the creation can be accepted
+     * <li>Instantiate a new entry
+     * <li>Possibly register this entry with the MBeanServer, if needed.
+     * <li>Call <code>addEntry()</code> on the given <code>meta</code> object.
+     * </ul>
+     * This method is usually generated by <code>mibgen</code> on table
+     * objects (inheriting from
+     * {@link com.sun.jmx.snmp.agent.SnmpTableSupport}). <br>
+     *
+     * <p><b><i>
+     * This method is called internally by the SNMP runtime whenever a
+     * new entry creation is requested by a remote SNMP manager.
+     * You should never need to call this method directlty.
+     * </i></b></p>
+     *
+     * @param request The SNMP subrequest containing the sublist of varbinds
+     *                for the new entry.
+     * @param rowOid  The OID indexing the conceptual row (entry) for which
+     *                the creation was requested.
+     * @param depth   The depth reached in the OID tree (the position at
+     *                which the columnar object ids start in the OIDs
+     *                included in the varbind).
+     * @param meta    The metadata object impacted by the subrequest
+     *
+     * @exception SnmpStatusException The new entry cannot be created.
+     *
+     **/
+    public void createNewEntry(SnmpMibSubRequest request, SnmpOid rowOid,
+                               int depth, SnmpMibTable meta)
+        throws SnmpStatusException;
+}
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpTableEntryNotification.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpTableEntryNotification.java
new file mode 100644
index 0000000..a3b6454
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpTableEntryNotification.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 1998-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;
+
+
+
+// jmx imports
+//
+import javax.management.Notification;
+import javax.management.ObjectName;
+
+/**
+ * Represents a notification emitted when an
+ * entry is added or deleted from an SNMP table.
+ * <P>
+ * The <CODE>SnmpTableEntryNotification</CODE> object contains
+ * the reference to the entry added or removed from the table.
+ * <P>
+ * The list of notifications fired by the <CODE>SnmpMibTable</CODE> is
+ * the following:
+ * <UL>
+ * <LI>A new entry has been added to the SNMP table.
+ * <LI>An existing entry has been removed from the SNMP table.
+  </UL>
+ *
+ * <p><b>This API is a Sun Microsystems internal API  and is subject
+ * to change without notice.</b></p>
+ */
+
+public class SnmpTableEntryNotification extends Notification {
+
+    /**
+     * Creates and initializes a table entry notification object.
+     *
+     * @param type The notification type.
+     * @param source The notification producer.
+     * @param sequenceNumber The notification sequence number within the
+     *                  source object.
+     * @param timeStamp The notification emission date.
+     * @param entry     The entry object (may be null if the entry is
+     *                  registered in the MBeanServer).
+     * @param entryName The ObjectName entry object (may be null if the
+     *                  entry is not registered in the MBeanServer).
+     * @since 1.5
+     */
+    SnmpTableEntryNotification(String type, Object source,
+                               long sequenceNumber, long timeStamp,
+                               Object entry, ObjectName entryName) {
+
+        super(type, source, sequenceNumber, timeStamp);
+        this.entry = entry;
+        this.name  = entryName;
+    }
+
+    /**
+     * Gets the entry object.
+     * May be null if the entry is registered in the MBeanServer, and the
+     * MIB is using the generic MetaData (see mibgen).
+     *
+     * @return The entry.
+     */
+    public Object getEntry() {
+        return entry;
+    }
+
+    /**
+     * Gets the ObjectName of the entry.
+     * May be null if the entry is not registered in the MBeanServer.
+     *
+     * @return The ObjectName of the entry.
+     * @since 1.5
+     */
+    public ObjectName getEntryName() {
+        return name;
+    }
+
+    // PUBLIC VARIABLES
+    //-----------------
+
+    /**
+     * Notification type denoting that a new entry has been added to the
+     * SNMP table.
+     * <BR>The value of this notification type is
+     * <CODE>jmx.snmp.table.entry.added</CODE>.
+     */
+    public static final String SNMP_ENTRY_ADDED =
+        "jmx.snmp.table.entry.added";
+
+    /**
+     * Notification type denoting that an entry has been removed from the
+     * SNMP table.
+     * <BR>The value of this notification type is
+     * <CODE>jmx.snmp.table.entry.removed</CODE>.
+     */
+    public static final String SNMP_ENTRY_REMOVED =
+        "jmx.snmp.table.entry.removed";
+
+    // PRIVATE VARIABLES
+    //------------------
+
+    /**
+     * The entry object.
+     * @serial
+     */
+    private final Object entry;
+
+    /**
+     * The entry name.
+     * @serial
+     * @since 1.5
+     */
+    private final ObjectName name;
+
+    // Ensure compatibility
+    //
+    private static final long serialVersionUID = 5832592016227890252L;
+}
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpTableSupport.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpTableSupport.java
new file mode 100644
index 0000000..e61537e
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpTableSupport.java
@@ -0,0 +1,571 @@
+/*
+ * Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.jmx.snmp.agent;
+
+
+
+// java imports
+//
+import java.io.Serializable;
+import java.util.Date;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.ArrayList;
+
+// jmx imports
+//
+import javax.management.Notification;
+import javax.management.ObjectName;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.NotificationBroadcaster;
+import javax.management.MBeanNotificationInfo;
+import javax.management.ListenerNotFoundException;
+import com.sun.jmx.snmp.SnmpOid;
+import com.sun.jmx.snmp.SnmpValue;
+import com.sun.jmx.snmp.SnmpVarBind;
+import com.sun.jmx.snmp.SnmpStatusException;
+
+/**
+ * This class is an abstraction for an SNMP table.
+ * It is the base class for implementing SNMP tables in the
+ * MBean world.
+ *
+ * <p>
+ * Its responsibility is to synchronize the MBean view of the table
+ * (Table of entries) with the MIB view (array of OID indexes). Each
+ * object of this class will be bound to the Metadata object which
+ * manages the same SNMP Table within the MIB.
+ * </p>
+ *
+ * <p>
+ * For each table defined in a MIB, mibgen will generate a specific
+ * class called Table<i>TableName</i> that will subclass this class, and
+ * a corresponding <i>TableName</i>Meta class extending SnmpMibTable
+ * and corresponding to the MIB view of the same table.
+ * </p>
+ *
+ * <p>
+ * Objects of this class are instantiated by MBeans representing
+ * the SNMP Group to which the table belong.
+ * </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.SnmpTableEntryFactory
+ * @see com.sun.jmx.snmp.agent.SnmpMibTable
+ *
+ */
+public abstract class SnmpTableSupport implements SnmpTableEntryFactory,
+// NPCTE fix for bugId 4499265, esc 0, MR 04 sept 2001
+//  SnmpTableCallbackHandler {
+    SnmpTableCallbackHandler, Serializable {
+// end of NPCTE fix for bugId 4499265
+
+    //-----------------------------------------------------------------
+    //
+    //  Protected Variables
+    //
+    //-----------------------------------------------------------------
+
+    /**
+     * The list of entries
+     **/
+    protected List<Object> entries;
+
+    /**
+     * The associated metadata object
+     **/
+    protected SnmpMibTable meta;
+
+    /**
+     * The MIB to which this table belongs
+     **/
+    protected SnmpMib      theMib;
+
+    //-----------------------------------------------------------------
+    //
+    //  Private Variables
+    //
+    //-----------------------------------------------------------------
+
+    /**
+     * This variable is initialized while binding this object to its
+     * corresponding meta object.
+     **/
+    private boolean registrationRequired = false;
+
+
+
+    //-----------------------------------------------------------------
+    //
+    //  Constructor
+    //
+    //-----------------------------------------------------------------
+
+    /**
+     * Initializes the table.
+     * The steps are these:
+     * <ul><li> allocate an array for storing entry object,</li>
+     *     <li> retrieve the corresponding metadata object
+     *          from the MIB,
+     *     <li> bind this object to the corresponding metadata object
+     *          from the MIB.</li>
+     * </ul>
+     *
+     * @param mib The MIB to which this table belong.
+     *
+     **/
+    protected SnmpTableSupport(SnmpMib mib) {
+        theMib  = mib;
+        meta    = getRegisteredTableMeta(mib);
+        bindWithTableMeta();
+        entries = allocateTable();
+    }
+
+
+    //-----------------------------------------------------------------
+    //
+    //  Implementation of the SnmpTableEntryFactory interface
+    //
+    //-----------------------------------------------------------------
+
+    /**
+     * Creates a new entry in the table.
+     *
+     * This factory method is generated by mibgen and used internally.
+     * It is part of the
+     * {@link com.sun.jmx.snmp.agent.SnmpTableEntryFactory} interface.
+     * You may subclass this method to implement any specific behaviour
+     * your application requires.
+     *
+     * @exception SnmpStatusException if the entry cannot be created.
+     **/
+    public abstract void createNewEntry(SnmpMibSubRequest request,
+                                        SnmpOid rowOid, int depth,
+                                        SnmpMibTable meta)
+        throws SnmpStatusException;
+
+
+    //-----------------------------------------------------------------
+    //
+    //  Public methods
+    //
+    //-----------------------------------------------------------------
+
+    /**
+     * Returns the entry located at the given position in the table.
+     *
+     * @return The entry located at the given position, <code>null</code>
+     *         if no entry can be found at this position.
+     **/
+    // XXXX xxxx zzz ZZZZ => public? or protected?
+    public Object getEntry(int pos) {
+        if (entries == null) return null;
+        return entries.get(pos);
+    }
+
+    /**
+     * Returns the number of entries registered in the table.
+     *
+     * @return The number of entries registered in the table.
+     **/
+    public int getSize() {
+        return meta.getSize();
+    }
+
+    /**
+     * This method lets you dynamically switch the creation policy.
+     *
+     * <CODE>setCreationEnabled()</CODE> will switch the policy of
+     *      remote entry creation via SET operations, by calling
+     *      <code>setCreationEnabled()</code> on the metadata object
+     *      associated with this table.
+     * <BR> By default remote entry creation via SET operation is disabled.
+     *
+     * @param remoteCreationFlag Tells whether remote entry creation must
+     *        be enabled or disabled.
+     * <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>
+     *
+     * @see com.sun.jmx.snmp.agent.SnmpMibTable
+     *
+     **/
+    public void setCreationEnabled(boolean remoteCreationFlag) {
+        meta.setCreationEnabled(remoteCreationFlag);
+    }
+
+    /**
+     * Tells whether a new entry should be created when a SET operation
+     * is received for an entry that does not exist yet.
+     * This method calls <code>isCreationEnabled()</code> on the metadata
+     * object associated with this table.
+     *
+     * @return true if a new entry must be created, false otherwise.<br>
+     *         [default: returns <CODE>false</CODE>]
+     *
+     * @see com.sun.jmx.snmp.agent.SnmpMibTable
+     **/
+    public boolean isCreationEnabled() {
+        return meta.isCreationEnabled();
+    }
+
+    /**
+     * Tells whether the metadata object to which this table is linked
+     * requires entries to be registered. In this case passing an
+     * ObjectName when registering entries will be mandatory.
+     *
+     * @return <code>true</code> if the associated metadata requires entries
+     *         to be registered (mibgen generated generic metadata).
+     **/
+    public boolean isRegistrationRequired() {
+        return registrationRequired;
+    }
+
+    /**
+     * Builds an entry SnmpIndex from its row OID.
+     *
+     * This method is generated by mibgen and used internally.
+     *
+     * @param rowOid The SnmpOid object identifying a table entry.
+     *
+     * @return The SnmpIndex of the entry identified by <code>rowOid</code>.
+     *
+     * @exception SnmpStatusException if the index cannot be built from the
+     *            given OID.
+     **/
+    public SnmpIndex buildSnmpIndex(SnmpOid rowOid)
+        throws SnmpStatusException {
+        return buildSnmpIndex(rowOid.longValue(false), 0);
+    }
+
+    /**
+     * Builds an SnmpOid from an SnmpIndex object.
+     *
+     * This method is generated by mibgen and used internally.
+     *
+     * @param index An SnmpIndex object identifying a table entry.
+     *
+     * @return The SnmpOid form of the given entry index.
+     *
+     * @exception SnmpStatusException if the given index is not valid.
+     **/
+    public abstract SnmpOid buildOidFromIndex(SnmpIndex index)
+        throws SnmpStatusException;
+
+    /**
+     * Builds the default ObjectName of an entry from the SnmpIndex
+     * identifying this entry. No access is made on the entry itself.
+     *
+     * This method is generated by mibgen and used internally.
+     * You can subclass this method if you want to change the default
+     * ObjectName policy. This is only meaningfull when entries
+     * are registered MBeans.
+     *
+     * @param index The SnmpIndex identifying the entry from which we
+     *              want to build the default ObjectName.
+     *
+     * @return The default ObjectName for the entry identified by
+     *         the given index.
+     *
+     * @exception SnmpStatusException if the given index is not valid.
+     **/
+    public abstract ObjectName buildNameFromIndex(SnmpIndex index)
+        throws SnmpStatusException;
+
+
+    //-----------------------------------------------------------------
+    //
+    //  Implementation of the SnmpTableEntryFactory interface
+    //
+    //-----------------------------------------------------------------
+
+    /**
+     * This callback is called by  the associated metadata object
+     * when a new table entry has been registered in the
+     * table metadata.
+     *
+     * This method will update the <code>entries</code> list.
+     *
+     * @param pos   The position at which the new entry was inserted
+     *              in the table.
+     * @param row   The row OID of the new entry
+     * @param name  The ObjectName of the new entry (as specified by the
+     *              factory)
+     * @param entry The new entry (as returned by the factory)
+     * @param meta  The table metadata object.
+     *
+     **/
+    public void addEntryCb(int pos, SnmpOid row, ObjectName name,
+                           Object entry, SnmpMibTable meta)
+        throws SnmpStatusException {
+        try {
+            if (entries != null) entries.add(pos,entry);
+        } catch (Exception e) {
+            throw new SnmpStatusException(SnmpStatusException.noSuchName);
+        }
+    }
+
+    /**
+     * This callback is called by  the associated metadata object
+     * when a new table entry has been removed from the
+     * table metadata.
+     *
+     * This method will update the <code>entries</code> list.
+     *
+     * @param pos   The position from which the entry was deleted
+     * @param row   The row OID of the deleted entry
+     * @param name  The ObjectName of the deleted entry (may be null if
+     *              ObjectName's were not required)
+     * @param entry The deleted entry (may be null if only ObjectName's
+     *              were required)
+     * @param meta  The table metadata object.
+     *
+     **/
+    public void removeEntryCb(int pos, SnmpOid row, ObjectName name,
+                              Object entry, SnmpMibTable meta)
+        throws SnmpStatusException {
+        try {
+            if (entries != null) entries.remove(pos);
+        } catch (Exception e) {
+        }
+    }
+
+
+
+    /**
+     * Enables to add an SNMP entry listener to this
+     * <CODE>SnmpMibTable</CODE>.
+     *
+     * @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 void
+        addNotificationListener(NotificationListener listener,
+                                NotificationFilter filter, Object handback) {
+        meta.addNotificationListener(listener,filter,handback);
+    }
+
+    /**
+     * Enables 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 {
+        meta.removeNotificationListener(listener);
+    }
+
+    /**
+     * Returns a <CODE>NotificationInfo</CODE> object containing the
+     * notification class and the notification type sent by the
+     * <CODE>SnmpMibTable</CODE>.
+     */
+    public MBeanNotificationInfo[] getNotificationInfo() {
+        return meta.getNotificationInfo();
+    }
+
+    //-----------------------------------------------------------------
+    //
+    //  Protected Abstract methods
+    //
+    //-----------------------------------------------------------------
+
+    /**
+     * Builds an SnmpIndex object from the index part of an OID.
+     *
+     * This method is generated by mibgen and used internally.
+     *
+     * @param oid The OID from which to build the index, represented
+     *        as an array of long.
+     * @param start The position where to start from in the OID array.
+     *
+     * @return The SnmpOid form of the given entry index.
+     *
+     * @exception SnmpStatusException if the given index is not valid.
+     **/
+    protected abstract SnmpIndex buildSnmpIndex(long oid[], int start )
+        throws SnmpStatusException;
+
+    /**
+     * Returns the metadata object associated with this table.
+     *
+     * This method is generated by mibgen and used internally.
+     *
+     * @param mib The SnmpMib object holding the Metadata corresponding
+     *            to this table.
+     *
+     * @return The metadata object associated with this table.
+     *         Returns <code>null</code> if this implementation of the
+     *         MIB doesn't support this table.
+     **/
+    protected abstract SnmpMibTable getRegisteredTableMeta(SnmpMib mib);
+
+
+    //-----------------------------------------------------------------
+    //
+    //  Protected methods
+    //
+    //-----------------------------------------------------------------
+
+    /**
+     * Allocates an ArrayList for storing table entries.
+     *
+     * This method is called within the constructor at object creation.
+     * Any object implementing the {@link java.util.List} interface can
+     * be used.
+     *
+     * @return A new list in which to store entries. If <code>null</code>
+     *         is returned then no entry will be stored in the list
+     *         and getEntry() will always return null.
+     **/
+    protected List<Object> allocateTable() {
+        return new ArrayList<Object>();
+    }
+
+    /**
+     * Add an entry in this table.
+     *
+     * This method registers an entry in the table and perform
+     * synchronization with the associated table metadata object.
+     *
+     * This method assumes that the given entry will not be registered,
+     * or will be registered with its default ObjectName built from the
+     * associated  SnmpIndex.
+     * <p>
+     * If the entry is going to be registered, then
+     * {@link com.sun.jmx.snmp.agent.SnmpTableSupport#addEntry(SnmpIndex, ObjectName, Object)} should be prefered.
+     * <br> This function is mainly provided for backward compatibility.
+     *
+     * @param index The SnmpIndex built from the given entry.
+     * @param entry The entry that should be added in the table.
+     *
+     * @exception SnmpStatusException if the entry cannot be registered with
+     *            the given index.
+     **/
+    protected void addEntry(SnmpIndex index, Object entry)
+        throws SnmpStatusException {
+        SnmpOid oid = buildOidFromIndex(index);
+        ObjectName name = null;
+        if (isRegistrationRequired()) {
+            name = buildNameFromIndex(index);
+        }
+        meta.addEntry(oid,name,entry);
+    }
+
+    /**
+     * Add an entry in this table.
+     *
+     * This method registers an entry in the table and performs
+     * synchronization with the associated table metadata object.
+     *
+     * @param index The SnmpIndex built from the given entry.
+     * @param name  The ObjectName with which this entry will be registered.
+     * @param entry The entry that should be added in the table.
+     *
+     * @exception SnmpStatusException if the entry cannot be registered with
+     *            the given index.
+     **/
+    protected void addEntry(SnmpIndex index, ObjectName name, Object entry)
+        throws SnmpStatusException {
+        SnmpOid oid = buildOidFromIndex(index);
+        meta.addEntry(oid,name,entry);
+    }
+
+    /**
+     * Remove an entry from this table.
+     *
+     * This method unregisters an entry from the table and performs
+     * synchronization with the associated table metadata object.
+     *
+     * @param index The SnmpIndex identifying the entry.
+     * @param entry The entry that should be removed in the table. This
+     *              parameter is optional and can be omitted if it doesn't
+     *              need to be passed along to the
+     *              <code>removeEntryCb()</code> callback defined in the
+     *              {@link com.sun.jmx.snmp.agent.SnmpTableCallbackHandler}
+     *              interface.
+     *
+     * @exception SnmpStatusException if the entry cannot be unregistered.
+     **/
+    protected void removeEntry(SnmpIndex index, Object entry)
+        throws SnmpStatusException {
+        SnmpOid oid = buildOidFromIndex(index);
+        meta.removeEntry(oid,entry);
+    }
+
+    // protected void removeEntry(ObjectName name, Object entry)
+    //  throws SnmpStatusException {
+    //  meta.removeEntry(name,entry);
+    // }
+
+    /**
+     * Returns the entries in the table.
+     *
+     * @return An Object[] array containing the entries registered in the
+     *         table.
+     **/
+    protected Object[] getBasicEntries() {
+        if (entries == null) return null;
+        Object[] array= new Object[entries.size()];
+        entries.toArray(array);
+        return array;
+    }
+
+    /**
+     * Binds this table with its associated metadata, registering itself
+     * as an SnmpTableEntryFactory.
+     **/
+    protected void bindWithTableMeta() {
+        if (meta == null) return;
+        registrationRequired = meta.isRegistrationRequired();
+        meta.registerEntryFactory(this);
+    }
+
+}
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpUserDataFactory.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpUserDataFactory.java
new file mode 100644
index 0000000..2c7c07f
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpUserDataFactory.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2000-2003 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.jmx.snmp.agent;
+
+import com.sun.jmx.snmp.SnmpPduPacket;
+import com.sun.jmx.snmp.SnmpPdu;
+import com.sun.jmx.snmp.SnmpStatusException;
+
+/**
+ * This interface is provided to enable fine customization of the SNMP
+ * agent behaviour.
+ *
+ * <p>You will not need to implement this interface except if your agent
+ * needs extra customization requiring some contextual information.</p>
+ *
+ * <p>If an SnmpUserDataFactory is set on the SnmpAdaptorServer, then a new
+ * object containing user-data will be allocated through this factory
+ * for each incoming request. This object will be passed along to
+ * the SnmpMibAgent within SnmpMibRequest objects. By default, no
+ * SnmpUserDataFactory is set on the SnmpAdaptorServer, and the contextual
+ * object passed to SnmpMibAgent is null.</p>
+ *
+ * <p>You can use this feature to obtain on contextual information
+ * (such as community string etc...) or to implement a caching
+ * mechanism, or for whatever purpose might be required by your specific
+ * agent implementation.</p>
+ *
+ * <p>The sequence <code>allocateUserData() / releaseUserData()</code> can
+ * also be used to implement a caching mechanism:
+ * <ul>
+ * <li><code>allocateUserData()</code> could be used to allocate
+ *         some cache space,</li>
+ * <li>and <code>releaseUserData()</code> could be used to flush it.</li>
+ * </ul></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.SnmpMibRequest
+ * @see com.sun.jmx.snmp.agent.SnmpMibAgent
+ * @see com.sun.jmx.snmp.daemon.SnmpAdaptorServer
+ *
+ **/
+public interface SnmpUserDataFactory {
+    /**
+     * Called by the <CODE>SnmpAdaptorServer</CODE> adaptor.
+     * Allocate a contextual object containing some user data. This method
+     * is called once for each incoming SNMP request. The scope
+     * of this object will be the whole request. Since the request can be
+     * handled in several threads, the user should make sure that this
+     * object can be accessed in a thread-safe manner. The SNMP framework
+     * will never access this object directly - it will simply pass
+     * it to the <code>SnmpMibAgent</code> within
+     * <code>SnmpMibRequest</code> objects - from where it can be retrieved
+     * through the {@link com.sun.jmx.snmp.agent.SnmpMibRequest#getUserData() getUserData()} accessor.
+     * <code>null</code> is considered to be a valid return value.
+     *
+     * This method is called just after the SnmpPduPacket has been
+     * decoded.
+     *
+     * @param requestPdu The SnmpPduPacket received from the SNMP manager.
+     *        <b>This parameter is owned by the SNMP framework and must be
+     *        considered as transient.</b> If you wish to keep some of its
+     *        content after this method returns (by storing it in the
+     *        returned object for instance) you should clone that
+     *        information.
+     *
+     * @return A newly allocated user-data contextual object, or
+     *         <code>null</code>
+     * @exception SnmpStatusException If an SnmpStatusException is thrown,
+     *            the request will be aborted.
+     *
+     * @since 1.5
+     **/
+    public Object allocateUserData(SnmpPdu requestPdu)
+        throws SnmpStatusException;
+
+    /**
+     * Called by the <CODE>SnmpAdaptorServer</CODE> adaptor.
+     * Release a previously allocated contextual object containing user-data.
+     * This method is called just before the responsePdu is sent back to the
+     * manager. It gives the user a chance to alter the responsePdu packet
+     * before it is encoded, and to free any resources that might have
+     * been allocated when creating the contextual object.
+     *
+     * @param userData The contextual object being released.
+     * @param responsePdu The SnmpPduPacket that will be sent back to the
+     *        SNMP manager.
+     *        <b>This parameter is owned by the SNMP framework and must be
+     *        considered as transient.</b> If you wish to keep some of its
+     *        content after this method returns you should clone that
+     *        information.
+     *
+     * @exception SnmpStatusException If an SnmpStatusException is thrown,
+     *            the responsePdu is dropped and nothing is returned to
+     *            to the manager.
+     *
+     * @since 1.5
+     **/
+    public void releaseUserData(Object userData, SnmpPdu responsePdu)
+        throws SnmpStatusException;
+}
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/package.html b/jdk/src/share/classes/com/sun/jmx/snmp/agent/package.html
new file mode 100644
index 0000000..d091c65
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/package.html
@@ -0,0 +1,34 @@
+<HTML>
+<HEAD>
+<!--
+
+Copyright 1999-2003 Sun Microsystems, Inc.  All Rights Reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Sun designates this
+particular file as subject to the "Classpath" exception as provided
+by Sun in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+CA 95054 USA or visit www.sun.com if you need additional information or
+have any questions.
+-->
+</HEAD>
+<BODY>
+Provides the classes for creating an <B>SNMP agent</B>.
+<p><b>This API is a Sun Microsystems internal API  and is subject 
+   to change without notice.</b></p>
+</BODY>
+</HTML>