FileDocCategorySizeDatePackage
SnmpMibTable.javaAPI DocJava SE 6 API87828Tue Jun 10 00:22:08 BST 2008com.sun.jmx.snmp.agent

SnmpMibTable

public abstract class SnmpMibTable extends SnmpMibNode implements Serializable, NotificationBroadcaster
This class is the base class for SNMP table metadata.

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.

For each table defined in the MIB, mibgen will generate a specific class called TableTableName that will implement the SnmpTableEntryFactory interface, and a corresponding TableNameMeta class that will extend this class.
The TableTableName class corresponds to the MBean view of the table while the TableNameMeta class corresponds to the MIB metadata view of the same table.

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.

This API is a Sun Microsystems internal API and is subject to change without notice.

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
version
4.59 04/07/06
author
Sun Microsystems, Inc

Fields Summary
protected int
nodeId
The id of the contained entry object.
protected SnmpMib
theMib
The MIB to which the metadata is linked.
protected boolean
creationEnabled
true if remote creation of entries via SET operations is enabled. [default value is false]
protected SnmpTableEntryFactory
factory
The entry factory
private int
size
The number of elements in the table.
private static final int
Delta
The list of OIDs.
private int
tablecount
private int
tablesize
private SnmpOid[]
tableoids
private final Vector
entries
The list of entries.
private final Vector
entrynames
The list of object names.
private Hashtable
handbackTable
Listener hastable containing the hand-back objects.
private Hashtable
filterTable
Listener hastable containing the filter objects.
transient long
sequenceNumber
SNMP table sequence number. The default value is set to 0.
Constructors Summary
public SnmpMibTable(SnmpMib mib)
Create a new SnmpMibTable metadata node.

param
mib The SNMP MIB to which the metadata will be linked.

        this.theMib= mib;    
	setCreationEnabled(false);
    
Methods Summary
public voidaddEntry(com.sun.jmx.snmp.SnmpOid rowOid, java.lang.Object entry)
Add a new entry in this SnmpMibTable. 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.
This function is mainly provided for backward compatibility.

param
rowOid The SnmpOid 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 rowOid, or this version of the metadata requires ObjectName's.

      
	 addEntry(rowOid, null, entry);
    
public synchronized voidaddEntry(com.sun.jmx.snmp.SnmpOid oid, javax.management.ObjectName name, java.lang.Object entry)
Add a new entry in this SnmpMibTable. Also triggers the addEntryCB() callback of the {@link com.sun.jmx.snmp.agent.SnmpTableEntryFactory} interface if this node is bound to a factory.

param
oid The SnmpOid 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 rowOid, or if this version of the metadata requires ObjectName's, and the given name is null.

        
	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);
    
public synchronized voidaddNotificationListener(javax.management.NotificationListener listener, javax.management.NotificationFilter filter, java.lang.Object handback)
Enable to add an SNMP entry listener to this SnmpMibTable.

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.


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

        // 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 ) {
            handbackList = new java.util.Vector() ;
            filterList = new java.util.Vector() ;
            handbackTable.put(listener, handbackList) ;
            filterTable.put(listener, filterList) ;
        }

        // Add the handback and the filter
        //
        handbackList.addElement(handback) ;
        filterList.addElement(filter) ;
    
protected synchronized voidbeginRowAction(com.sun.jmx.snmp.agent.SnmpMibSubRequest req, com.sun.jmx.snmp.SnmpOid rowOid, int depth, int rowAction)
This method takes care of initial RowStatus handling during the check() phase of a SET request. In particular it will:
  • check that the given rowAction returned by getRowAction() is valid.
  • Then depending on the rowAction specified it will:
    • either call createNewEntry() ( rowAction = createAndGo or createAndWait ),
    • or call checkRemoveTableRow() ( rowAction = destroy),
    • or call checkRowStatusChange() ( rowAction = active or notInService),
    • or generate a SnmpStatusException if the passed rowAction is not correct.

In principle, you should not need to redefine this method.

beginRowAction() is called during the check phase of a SET request, before actual checking on the varbind list is performed.

param
req The sub-request that must be handled by this node.
param
rowOid The SnmpOid 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 getRowAction(): 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 unspecified value which is SNMP Runtime specific.
exception
SnmpStatusException if the specified rowAction 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 beginRowAction() if needed.
see
com.sun.jmx.snmp.EnumRowStatus

	final boolean     isnew  = req.isNewEntry();
	final SnmpOid     oid    = rowOid;
	final int         action = rowAction;
	
	switch (action) {
	case EnumRowStatus.unspecified:
	    if (isnew) {
		if (isDebugOn()) 
		    debug("beginRowAction","Failed to create row[" + rowOid + 
			  "] : RowStatus = unspecified");
		checkRowStatusFail(req,SnmpStatusException.snmpRspNoAccess);
	    }
	    break;
 	case EnumRowStatus.createAndGo:
 	case EnumRowStatus.createAndWait:
            if (isnew) {
		if (isCreationEnabled()) {
		    if (isDebugOn()) 
			debug("beginRowAction","Creating row[" + rowOid + 
			      "] : RowStatus = createAndGo | createAndWait");
		    createNewEntry(req,oid,depth);
		} else {
		    if (isDebugOn()) 
			debug("beginRowAction","Can't create row[" + rowOid + 
			      "] : RowStatus = createAndGo | createAndWait" +
			      " but creation is disabled");
		    checkRowStatusFail(req,
                       SnmpStatusException.snmpRspNoAccess);
		}
	    } else {
		if (isDebugOn()) 
		    debug("beginRowAction","Can't create row[" + rowOid + 
			  "] : RowStatus = createAndGo | createAndWait" +
			  " but row already exists");
		checkRowStatusFail(req,
                       SnmpStatusException.snmpRspInconsistentValue);
	    }
	    break;
 	case EnumRowStatus.destroy:
	    if (isnew) {
		if (isDebugOn()) 
		    debug("beginRowAction","Warning: can't destroy row[" + 
			  rowOid + "] : RowStatus = destroy" +
			  " but row does not exist");
	    } else if (!isCreationEnabled()) {
		if (isDebugOn()) 
		    debug("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 (isDebugOn()) 
		    debug("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 (isDebugOn()) 
		debug("beginRowAction","Invalid RowStatus value for row[" + 
		      rowOid + "] : specified RowStatus = " + action);
	    checkRowStatusFail(req,
		    SnmpStatusException.snmpRspInconsistentValue);	    
	}
    
protected abstract voidcheck(com.sun.jmx.snmp.agent.SnmpMibSubRequest req, com.sun.jmx.snmp.SnmpOid rowOid, int depth)
This method is used internally and is implemented by the SnmpMibTable subclasses generated by mibgen.

public voidcheck(com.sun.jmx.snmp.agent.SnmpMibSubRequest req, int depth)
Generic handling of the check operation.

The default implementation of this method is to

  • check whether a new entry must be created, and if remote creation of entries is enabled, create it.
  • call the generated check(req,oid,depth+1) method.

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);
}

You should not need to override this method in any cases, because it will eventually call check(SnmpMibSubRequest req, int depth) on the generated derivative of SnmpMibEntry. 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 check(SnmpMibSubRequest req, int depth) on the generated derivative of SnmpMibEntry.

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

	final boolean dbg = isDebugOn();

	if (dbg) debug("check","Calling beginRowAction");

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

	if (dbg) debug("check","Calling check for " + req.getSize() + 
		       " varbinds.");

	check(req,oid,depth+1);

	if (dbg) debug("check","check finished");
    
protected voidcheckRemoveTableRow(com.sun.jmx.snmp.agent.SnmpMibSubRequest req, com.sun.jmx.snmp.SnmpOid rowOid, int depth)
Check whether the specified row can be removed from the table.

This method is called during the check phase of a SET request when the control variable specifies destroy

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.

Note that if the actual row deletion fails afterward, the atomicity of the request is no longer guaranteed.

param
req The sub-request that must be handled by this node.
param
rowOid The SnmpOid 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 voidcheckRowStatusChange(com.sun.jmx.snmp.agent.SnmpMibSubRequest req, com.sun.jmx.snmp.SnmpOid rowOid, int depth, int newStatus)
Check whether the control variable of the given row can be switched to the new specified newStatus.

This method is called during the check phase of a SET request when the control variable specifies active or notInService.

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.

Note that if the actual row deletion fails afterward, the atomicity of the request is no longer guaranteed.

param
req The sub-request that must be handled by this node.
param
rowOid The SnmpOid 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 unspecified value which is SNMP Runtime specific.
exception
SnmpStatusException if switching to this new state would fail.


    
static final voidcheckRowStatusFail(com.sun.jmx.snmp.agent.SnmpMibSubRequest req, int errorStatus)

	final SnmpVarBind statusvb  = req.getRowStatusVarBind();
	final SnmpStatusException x = new SnmpStatusException(errorStatus);
	req.registerCheckException(statusvb,x);
    
protected booleancontains(com.sun.jmx.snmp.SnmpOid oid, java.lang.Object userData)
Return true if the entry identified by the given OID index is contained in this table.

Do not call this method directly.

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.

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 {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory} for each incoming SNMP request.
return
true if the entry is found, false otherwise.
since
1.5

	return (findObject(oid) > -1);
    
public abstract voidcreateNewEntry(com.sun.jmx.snmp.agent.SnmpMibSubRequest req, com.sun.jmx.snmp.SnmpOid rowOid, int depth)
This method is invoked when the creation of a new entry is requested by a remote SNMP manager.
By default, remote entry creation is disabled - and this method will not be called. You can dynamically switch the entry creation policy by calling setCreationEnabled(true) and setCreationEnabled(false) on this object.

This method is called internally by the SNMP runtime and you should never need to call it directly. 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.

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.

private final voiddebug(java.lang.String func, java.lang.String info)

        Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP, 
		   getClass().getName(), func, info);
    
protected voidendRowAction(com.sun.jmx.snmp.agent.SnmpMibSubRequest req, com.sun.jmx.snmp.SnmpOid rowOid, int depth, int rowAction)
This method takes care of final RowStatus handling during the set() phase of a SET request. In particular it will:
  • either call setRowStatus(active) ( rowAction = createAndGo or active ),
  • or call setRowStatus(notInService or notReady) depending on the result of isRowReady() (rowAction = createAndWait ),
  • or call setRowStatus(notInService) ( rowAction = notInService),
  • or call removeTableRow() ( rowAction = destroy),
  • or generate a SnmpStatusException if the passed rowAction is not correct. This should be avoided since it would break SET request atomicity

In principle, you should not need to redefine this method.

endRowAction() 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 null).

param
req The sub-request that must be handled by this node.
param
rowOid The SnmpOid 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 getRowAction(): 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 unspecified value which is SNMP Runtime specific.
exception
SnmpStatusException if the specified rowAction is not valid.
see
com.sun.jmx.snmp.EnumRowStatus

	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 (isDebugOn()) 
		debug("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 (isDebugOn()) 
		    debug("endRowAction",
			  "Setting RowStatus to `notInService'" +
			  " for row[" + rowOid + "] : requested RowStatus = " 
			  + "createAndWait");
		value = setRowStatus(oid,EnumRowStatus.notInService,data);
	    } else {
		if (isDebugOn()) 
		    debug("endRowAction",
			  "Setting RowStatus to `notReady'" +
			  " for row[" + rowOid + "] : requested RowStatus = " 
			  + "createAndWait");
		value = setRowStatus(oid,EnumRowStatus.notReady,data);
	    }
	    break;
 	case EnumRowStatus.destroy:
	    if (isnew) {
		if (isDebugOn()) 
		    debug("endRowAction",
			  "Warning: " + " requested RowStatus = destroy," +
			  "but row[" + rowOid + "] does not exist.");	
	    } else {
		if (isDebugOn()) 
		    debug("endRowAction",
			  "destroying row[" + rowOid + 
			  "] : requested RowStatus = destroy");	   
	    }
	    removeTableRow(req,oid,depth);
	    break;
	case EnumRowStatus.active:
	     if (isDebugOn()) 
		debug("endRowAction",
		      "Setting RowStatus to `active'" +
		      " for row[" + rowOid + "] : requested RowStatus = " 
		      + "active");
	    value = setRowStatus(oid,EnumRowStatus.active,data);
	    break;
	case EnumRowStatus.notInService:
	     if (isDebugOn()) 
		debug("endRowAction",
		      "Setting RowStatus to `notInService'" +
		      " for row[" + rowOid + "] : requested RowStatus = " 
		      + "notInService");
	    value = setRowStatus(oid,EnumRowStatus.notInService,data);
	    break;
	case EnumRowStatus.notReady:
	default:
	    if (isDebugOn()) 
		debug("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;
	}
    
final synchronized voidfindHandlingNode(com.sun.jmx.snmp.SnmpVarBind varbind, long[] oid, int depth, com.sun.jmx.snmp.agent.SnmpRequestTree handlers)


	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));
    
private long[]findNextAccessibleOid(com.sun.jmx.snmp.SnmpOid entryoid, com.sun.jmx.snmp.SnmpVarBind varbind, long[] oid, int depth, com.sun.jmx.snmp.agent.SnmpRequestTree handlers, com.sun.jmx.snmp.agent.AcmChecker checker, java.lang.Object data, long var)

	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;
	}
    
final synchronized long[]findNextHandlingNode(com.sun.jmx.snmp.SnmpVarBind varbind, long[] oid, int pos, int depth, com.sun.jmx.snmp.agent.SnmpRequestTree handlers, com.sun.jmx.snmp.agent.AcmChecker checker)

	    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 final intfindObject(com.sun.jmx.snmp.SnmpOid oid)
Look for the given oid in the OID table (tableoids) and returns its position.

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.

        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;
    
protected abstract voidget(com.sun.jmx.snmp.agent.SnmpMibSubRequest req, com.sun.jmx.snmp.SnmpOid rowOid, int depth)
This method is used internally and is implemented by the SnmpMibTable subclasses generated by mibgen.

public voidget(com.sun.jmx.snmp.agent.SnmpMibSubRequest req, int depth)
Generic handling of the get operation.

The default implementation of this method is to

  • check whether the entry exists, and if not register an exception for each varbind in the list.
  • call the generated get(req,oid,depth+1) method.

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);
}

You should not need to override this method in any cases, because it will eventually call get(SnmpMibSubRequest req, int depth) on the generated derivative of SnmpMibEntry. 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 get(SnmpMibSubRequest req, int depth) on the generated derivative of SnmpMibEntry.


	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);
    
public java.lang.Object[]getBasicEntries()
Return the entries stored in this table SnmpMibTable.

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 null. It all depends whether a non null entry was passed to addEntry().
Otherwise, if it uses the standard way (access the entry directly through their standard MBean interface) this array will contain all the entries.

return
The entries array.

        Object[] array= new Object[size];
        entries.copyInto(array);
        return array;
    
public synchronized java.lang.ObjectgetEntry(com.sun.jmx.snmp.SnmpOid rowOid)
Get the entry corresponding to the specified rowOid.

param
rowOid The SnmpOid identifying the row to be retrieved.
return
The entry.
exception
SnmpStatusException There is no entry with the specified rowOid in the table.

        int pos= findObject(rowOid);
        if (pos == -1)
            throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
        return entries.elementAt(pos);
    
public synchronized javax.management.ObjectNamegetEntryName(com.sun.jmx.snmp.SnmpOid rowOid)
Get the ObjectName of the entry corresponding to the specified rowOid. The result of this method is only meaningful if isRegistrationRequired() yields true.

param
rowOid The SnmpOid 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 rowOid in the table.

        int pos = findObject(rowOid);
	if (entrynames == null) return null;
        if (pos == -1 || pos >= entrynames.size())
            throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
        return (ObjectName) entrynames.elementAt(pos);
    
private final intgetInsertionPoint(com.sun.jmx.snmp.SnmpOid oid)
Search the position at which the given oid should be inserted in the OID table (tableoids).

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.

	return getInsertionPoint(oid, true);
    
private final intgetInsertionPoint(com.sun.jmx.snmp.SnmpOid oid, boolean fail)
Search the position at which the given oid should be inserted in the OID table (tableoids).

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 fail is true.


	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;
    
protected com.sun.jmx.snmp.SnmpOidgetNextOid(com.sun.jmx.snmp.SnmpOid oid, java.lang.Object userData)
Get the SnmpOid index of the row that follows the given oid in the table. The given oid does not need to be a valid row OID index.

param
oid The OID from which the search will begin.
param
userData A contextual object containing user-data. This object is allocated through the {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory} for each incoming SNMP request.
return
The next SnmpOid index.
exception
SnmpStatusException There is no index following the specified oid in the table.

    
        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;      
    
protected com.sun.jmx.snmp.SnmpOidgetNextOid(java.lang.Object userData)
Return the first entry OID registered in the table.

param
userData A contextual object containing user-data. This object is allocated through the {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory} for each incoming SNMP request.
return
The SnmpOid of the first entry in the table.
exception
SnmpStatusException If the table is empty.

        if (size == 0) 
            throw noSuchInstanceException;
	// XX return (SnmpOid) oids.firstElement();      
	return tableoids[0];      
    
com.sun.jmx.snmp.SnmpOidgetNextOid(long[] oid, int pos, java.lang.Object userData)
Get the SnmpOid index of the row that follows the index extracted from the specified OID array. Builds the SnmpOid corresponding to the row OID and calls getNextOid(oid,userData);

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 {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory} for each incoming SNMP request.
return
The next SnmpOid.
exception
SnmpStatusException There is no index following the specified one in the table.

        
        // 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);
    
protected longgetNextVarEntryId(com.sun.jmx.snmp.SnmpOid rowOid, long var, java.lang.Object userData, int pduVersion)
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 {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory} 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.

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

	return varid;
    
protected abstract longgetNextVarEntryId(com.sun.jmx.snmp.SnmpOid rowOid, long var, java.lang.Object userData)
This method is used internally and is implemented by the SnmpMibTable subclasses generated by mibgen.

Return the next OID arc corresponding to a readable columnar object in the underlying entry OBJECT-TYPE.

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 {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory} for each incoming SNMP request.
return
The next columnar object id.
exception
SnmpStatusException If no id is found after the given id.

public javax.management.MBeanNotificationInfo[]getNotificationInfo()
Return a NotificationInfo object containing the notification class and the notification type sent by the SnmpMibTable.

        
        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;
    
protected intgetRowAction(com.sun.jmx.snmp.agent.SnmpMibSubRequest req, com.sun.jmx.snmp.SnmpOid rowOid, int depth)
Return the RowStatus code value specified in this request.

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 unspecified value which is SNMP Runtime specific.

param
req The sub-request that must be handled by this node.
param
rowOid The SnmpOid 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:
  • 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 createAndGo is returned
  • Otherwise, if the row exists and this table do not use any variable to control creation/deletion of rows, unspecified is returned.
  • Otherwise, if the request does not contain the control variable, unspecified is returned.
  • Otherwise, mapRowStatus() is called to extract the RowStatus code from the SnmpVarBind that contains the control variable.
exception
SnmpStatusException if the value of the control variable could not be mapped to a RowStatus code.
see
com.sun.jmx.snmp.EnumRowStatus

	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;
    
public intgetSize()
Get the size of the table.

return
The number of entries currently registered in this table.

        return size;
    
public booleanhasRowStatus()
Return true if the conceptual row contains a columnar object used to control creation/deletion of rows in this table.

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.

By default, this function returns false, and it is assumed that the table has no such control variable.
When mibgen is used over SMIv2 MIBs, it will generate an hasRowStatus() method returning true for each table containing an object with RowStatus syntax.

When this method returns false 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).

This method is called internally when a SET request involving this table is processed.

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 true.
You will then have to redefine the isRowStatus(), mapRowStatus(), isRowReady(), and setRowStatus() methods to suit your specific implementation.

return
  • true if this table contains a control variable (eg: a variable with RFC 2579 RowStatus syntax),
  • false if this table does not contain any control variable.
  • 	return false;
        
    private final voidinsertOid(int pos, com.sun.jmx.snmp.SnmpOid oid)
    Insert an OID at the given position.

    param
    oid The OID to be inserted in the table
    param
    pos The position at which the OID to be added is located.

    	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++;
        
    public booleanisCreationEnabled()
    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.
    [default: returns false]

    	return creationEnabled;
        
    private static final booleanisDebugOn()

            return Trace.isSelected(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP);
        
    protected abstract booleanisReadableEntryId(com.sun.jmx.snmp.SnmpOid rowOid, long var, java.lang.Object userData)
    This method is used internally and is implemented by the SnmpMibTable subclasses generated by mibgen.

    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 {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory} for each incoming SNMP request.
    exception
    SnmpStatusException If this id is not valid.

    public abstract booleanisRegistrationRequired()
    Tell whether the specific version of this metadata generated by mibgen 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).

    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
    true if registration is required by this version of the metadata.

    protected booleanisRowReady(com.sun.jmx.snmp.SnmpOid rowOid, java.lang.Object userData)
    Tell whether the specified row is ready and can be put in the notInService state.

    This method is called only once, after all the varbind have been set on a new entry for which createAndWait was specified.

    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 notInService when it becomes ready. No further call to isRowReady() will be made.

    By default, this method always return true.
    mibgen will not generate any specific implementation for this method - meaning that by default, a row created using createAndWait will always be placed in notInService state at the end of the request.

    If this table was defined using SMIv2, and if it contains a control variable with RowStatus syntax, mibgen 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.

    You will have to redefine this method if this default mechanism does not suit your needs.

    param
    rowOid The SnmpOid identifying the table row involved in the operation.
    param
    userData A contextual object containing user-data. This object is allocated through the {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory} for each incoming SNMP request.
    return
    true if the row can be placed in notInService 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

    	return true;
        
    protected booleanisRowStatus(com.sun.jmx.snmp.SnmpOid rowOid, long var, java.lang.Object userData)
    Return true if the columnar object identified by var is used to control the addition/deletion of rows in this table.

    By default, this method assumes that there is no control variable and always return false

    If this table was defined using SMIv2, and if it contains a control variable with RowStatus syntax, mibgen will generate a non default implementation for this method that will identify the RowStatus control variable.

    You will have to redefine this method if you need to implement control variables that do not conform to RFC 2579 RowStatus TEXTUAL-CONVENTION.

    param
    rowOid The SnmpOid 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 {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory} for each incoming SNMP request.

    	return false;
        
    protected intmapRowStatus(com.sun.jmx.snmp.SnmpOid rowOid, com.sun.jmx.snmp.SnmpVarBind vbstatus, java.lang.Object userData)
    Map the value of the vbstatus 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 unspecified value which is SNMP Runtime specific.

    By default, this method assumes that the control variable is an Integer, and it simply returns its value without further analysis.

    If this table was defined using SMIv2, and if it contains a control variable with RowStatus syntax, mibgen will generate a non default implementation for this method.

    You will have to redefine this method if you need to implement control variables that do not conform to RFC 2579 RowStatus TEXTUAL-CONVENTION.

    param
    rowOid The SnmpOid 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 {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory} for each incoming SNMP request.
    return
    The RowStatus code mapped from the value contained in vbstatus.
    exception
    SnmpStatusException if the value of the control variable could not be mapped to a RowStatus code.
    see
    com.sun.jmx.snmp.EnumRowStatus

    	final SnmpValue rsvalue = vbstatus.value;
    	
    	if (rsvalue instanceof SnmpInt)
    	    return ((SnmpInt)rsvalue).intValue();
    	else
    	    throw new SnmpStatusException(
    		       SnmpStatusException.snmpRspInconsistentValue);
        
    public voidregisterEntryFactory(com.sun.jmx.snmp.agent.SnmpTableEntryFactory factory)
    Register the factory through which table entries should be created when remote entry creation is enabled.

    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.

    	this.factory = factory;
        
    public synchronized voidremoveEntry(com.sun.jmx.snmp.SnmpOid rowOid, java.lang.Object 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.

    param
    rowOid The SnmpOid 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 rowOid is not valid for instance).

            int pos = findObject(rowOid);
            if (pos == -1)
                return;
    	removeEntry(pos,entry);
        
    public voidremoveEntry(com.sun.jmx.snmp.SnmpOid rowOid)
    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.

    param
    rowOid The SnmpOid identifying the table row to remove.
    exception
    SnmpStatusException if the specified entry couldn't be removed (if the given rowOid is not valid for instance).

            int pos = findObject(rowOid);
            if (pos == -1)
                return;
    	removeEntry(pos,null);
        
    public synchronized voidremoveEntry(int pos, java.lang.Object 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.

    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.

            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 = (ObjectName) 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);
        
    public synchronized voidremoveNotificationListener(javax.management.NotificationListener listener)
    Enable to remove an SNMP entry listener from this SnmpMibTable.

    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.

    
            // 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) ;
        
    private final voidremoveOid(int pos)
    Remove the OID located at the given position.

    param
    pos The position at which the OID to be removed is located.

    	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;
        
    protected voidremoveTableRow(com.sun.jmx.snmp.agent.SnmpMibSubRequest req, com.sun.jmx.snmp.SnmpOid rowOid, int depth)
    Remove a table row upon a remote manager request. This method is called internally when getRowAction() yields destroy - i.e.: it is only called when a remote manager requests the removal of a table row.
    You should never need to call this function directly.

    By default, this method simply calls removeEntry(rowOid) .

    You can redefine this method if you need to implement some specific behaviour when a remote row deletion is invoked.

    Note that specific checks should not be implemented in this method, but rather in checkRemoveTableRow(). If checkRemoveTableRow() succeeds and this method fails afterward, the atomicity of the original SET request can no longer be guaranteed.

    param
    req The sub-request that must be handled by this node.
    param
    rowOid The SnmpOid 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 checkRemoveTableRow() if needed. If the entry does not exists, no exception is generated and the method simply returns.

    	
    	
    	removeEntry(rowOid);
        
    private synchronized voidsendNotification(javax.management.Notification notification)
    Enable this SnmpMibTable to send a notification.

    param
    notification The notification to send.

    
            // 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 != null) && 
    		     (filter.isNotificationEnabled(notification)))) {
    		    
                        listener.handleNotification(notification,handback) ;
                    }
                }
            }
        
    private voidsendNotification(java.lang.String type, long timeStamp, java.lang.Object entry, javax.management.ObjectName name)
    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.

    param
    type The notification type.
    param
    timeStamp The notification emission date.
    param
    entry The entry object.

            
            synchronized(this) {
                sequenceNumber = sequenceNumber + 1;
            }
    
            SnmpTableEntryNotification notif = 
    	    new SnmpTableEntryNotification(type, this, sequenceNumber, 
    					   timeStamp, entry, name);
                
            this.sendNotification(notif) ;
        
    protected abstract voidset(com.sun.jmx.snmp.agent.SnmpMibSubRequest req, com.sun.jmx.snmp.SnmpOid rowOid, int depth)
    This method is used internally and is implemented by the SnmpMibTable subclasses generated by mibgen.

    public voidset(com.sun.jmx.snmp.agent.SnmpMibSubRequest req, int depth)
    Generic handling of the set operation.

    The default implementation of this method is to call the generated set(req,oid,depth+1) method.

    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);
    }
    

    You should not need to override this method in any cases, because it will eventually call set(SnmpMibSubRequest req, int depth) on the generated derivative of SnmpMibEntry. 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 set(SnmpMibSubRequest req, int depth) on the generated derivative of SnmpMibEntry.

    
    	final boolean dbg = isDebugOn();
     	if (dbg) debug("set","Entering set.");
    
    	final SnmpOid     oid    = req.getEntryOid();
    	final int         action = getRowAction(req,oid,depth+1);
    
     	if (dbg) debug("set","Calling set for " + req.getSize() + 
    		       "varbinds.");
    
    	set(req,oid,depth+1);
    
    	if (dbg) debug("set","Calling endRowAction");
    
    	endRowAction(req,oid,depth+1,action);
    
    	if (dbg) debug("set","RowAction finished");
        
    public voidsetCreationEnabled(boolean remoteCreationFlag)
    This method lets you dynamically switch the creation policy.

    param
    remoteCreationFlag Tells whether remote entry creation must be enabled or disabled.
    • setCreationEnabled(true) will enable remote entry creation via SET operations.
    • setCreationEnabled(false) will disable remote entry creation via SET operations.
    • By default remote entry creation via SET operation is disabled.

    	creationEnabled = remoteCreationFlag;
        
    protected com.sun.jmx.snmp.SnmpValuesetRowStatus(com.sun.jmx.snmp.SnmpOid rowOid, int newStatus, java.lang.Object userData)
    Set the control variable to the specified newStatus value.

    This method maps the given newStatus to the appropriate value for the control variable, then sets the control variable in the entry identified by rowOid. It returns the new value of the control variable.

    By default, it is assumed that there is no control variable so this method does nothing and simply returns null.

    If this table was defined using SMIv2, and if it contains a control variable with RowStatus syntax, mibgen will generate a non default implementation for this method.

    You will have to redefine this method if you need to implement control variables that do not conform to RFC 2579 RowStatus TEXTUAL-CONVENTION.

    param
    rowOid The SnmpOid 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 unspecified value which is SNMP Runtime specific.
    param
    userData A contextual object containing user-data. This object is allocated through the {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory} for each incoming SNMP request.
    return
    The new value of the control variable (usually new SnmpInt(newStatus)) or null if the table do not have any control variable.
    exception
    SnmpStatusException If the given newStatus could not be set on the specified entry, or if the given newStatus is not valid.
    see
    com.sun.jmx.snmp.EnumRowStatus

    	return null;
        
    static final voidsetRowStatusFail(com.sun.jmx.snmp.agent.SnmpMibSubRequest req, int errorStatus)

    	final SnmpVarBind statusvb  = req.getRowStatusVarBind();
    	final SnmpStatusException x = new SnmpStatusException(errorStatus);
    	req.registerSetException(statusvb,x);
        
    protected booleanskipEntryVariable(com.sun.jmx.snmp.SnmpOid rowOid, long var, java.lang.Object userData, int pduVersion)
    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:
    • the variable is a leaf that is not instantiated,
    • or the variable is a leaf whose type cannot be returned by that version of the protocol (e.g. an Counter64 with SNMPv1).

    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 {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory} 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.

    	return false;
        
    final voidvalidateOid(long[] oid, int pos)
    Validate the specified OID.

    param
    oid The OID array.
    param
    pos The position in the array.
    exception
    SnmpStatusException If the validation fails.

            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;
    
        
    protected abstract voidvalidateVarEntryId(com.sun.jmx.snmp.SnmpOid rowOid, long var, java.lang.Object userData)
    This method is used internally and is implemented by the SnmpMibTable subclasses generated by mibgen.

    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 {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory} for each incoming SNMP request.
    exception
    SnmpStatusException If this id is not valid.