/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.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.
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 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 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 Also:
/**
* 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 SnmpMibTable
metadata node.
Params: - mib – The SNMP MIB to which the metadata will be linked.
/**
* 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.
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.
Params: - req – The SNMP subrequest requesting this creation
- rowOid – The OID indexing the conceptual row (entry) for which
the creation was requested.
- depth – The position of the columnar object arc in the OIDs
from the varbind list.
Throws: - SnmpStatusException – if the entry cannot be created.
/**
* 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 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).
Returns: true
if registration is required by this
version of the metadata.
/**
* 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.
Returns: true if a new entry must be created, false otherwise.
[default: returns false
]
/**
* 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.
Params: - 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.
/**
* 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 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.
Returns: 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 <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 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
.
/**
* 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,new SnmpStatusException(SnmpStatusException.noSuchInstance));
}
}
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 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
.
/**
* 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 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
.
/**
* 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 SnmpMibTable
. Also triggers the addEntryCB() callback of the 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 addEntry(SnmpOid, ObjectName, Object)
should be prefered.
This function is mainly provided for backward compatibility.
Params: - rowOid – The
SnmpOid
identifying the table
row to be added. - entry – The entry to add.
Throws: - SnmpStatusException – The entry couldn't be added
at the position identified by the given
rowOid
, or this version of the metadata
requires ObjectName's.
/**
* 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 SnmpMibTable
. Also triggers the addEntryCB() callback of the SnmpTableEntryFactory
interface if this node is bound to a factory.
Params: - oid – The
SnmpOid
identifying the table
row to be added. - name – The ObjectName with which this entry is registered.
This parameter can be omitted if isRegistrationRequired()
return false.
- entry – The entry to add.
Throws: - 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.
/**
* 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 SnmpTableEntryFactory
interface if this node is bound to a factory.
Params: - rowOid – The
SnmpOid
identifying the table
row to remove. - entry – The entry to be removed. This parameter is not used
internally, it is simply passed along to the
removeEntryCB() callback.
Throws: - SnmpStatusException – if the specified entry couldn't
be removed (if the given
rowOid
is not
valid for instance).
/**
* 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 SnmpTableEntryFactory
interface if this node is bound to a factory.
Params: - rowOid – The
SnmpOid
identifying the table
row to remove.
Throws: - SnmpStatusException – if the specified entry couldn't
be removed (if the given
rowOid
is not
valid for instance).
/**
* 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 SnmpTableEntryFactory
interface if this node is bound to a factory.
Params: - pos – The position of the entry in the table.
- entry – The entry to be removed. This parameter is not used
internally, it is simply passed along to the
removeEntryCB() callback.
Throws: - SnmpStatusException – if the specified entry couldn't
be removed.
/**
* 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.
Params: - rowOid – The
SnmpOid
identifying the
row to be retrieved.
Throws: - SnmpStatusException – There is no entry with the specified
rowOid
in the table.
Returns: The entry.
/**
* 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.
Params: - rowOid – The
SnmpOid
identifying the table
row whose ObjectName we want to retrieve.
Throws: - SnmpStatusException – There is no entry with the specified
rowOid
in the table.
Returns: The object name of the entry.
/**
* 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 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.
Returns: The entries array.
/**
* 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.
Returns: The number of entries currently registered in this table.
/**
* 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
SnmpMibTable
.
Params: - listener – The listener object which will handle the
notifications emitted by the registered MBean.
- filter – The filter object. If filter is null, no filtering
will be performed before handling notifications.
- handback – The context to be sent to the listener when a
notification is emitted.
Throws: - IllegalArgumentException – Listener parameter is null.
/**
* 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
SnmpMibTable
.
Params: - 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.
Throws: - ListenerNotFoundException – The listener is not registered
in the MBean.
/**
* 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 NotificationInfo
object containing the
notification class and the notification type sent by the
SnmpMibTable
.
/**
* 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.
Params: - factory – The
SnmpTableEntryFactory
through which entries will be created when a remote SNMP manager request the creation of a new entry via an SNMP SET request.
/**
* 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 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.
Params: - rowOid – The
SnmpOid
identifying the table
row involved in the operation. - var – The OID arc identifying the involved columnar object.
- userData – A contextual object containing user-data.
This object is allocated through the
SnmpUserDataFactory
for each incoming SNMP request.
/**
* 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.
The RowStatus code value should be one of the values defined by EnumRowStatus
. These codes correspond to RowStatus codes as defined in RFC 2579, plus the unspecified
value which is SNMP Runtime specific.
Params: - req – The sub-request that must be handled by this node.
- rowOid – The
SnmpOid
identifying the table
row involved in the operation. - depth – The depth reached in the OID tree.
Throws: - SnmpStatusException – if the value of the control variable
could not be mapped to a RowStatus code.
See Also: Returns: 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.
/**
* 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 vbstatus
varbind to the corresponding RowStatus code defined in 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.
Params: - rowOid – The
SnmpOid
identifying the table
row involved in the operation. - vbstatus – The SnmpVarBind containing the value of the control
variable, as identified by the isRowStatus() method.
- userData – A contextual object containing user-data.
This object is allocated through the
SnmpUserDataFactory
for each incoming SNMP request.
Throws: - SnmpStatusException – if the value of the control variable
could not be mapped to a RowStatus code.
See Also: Returns: The RowStatus code mapped from the value contained
in vbstatus
.
/**
* 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 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.
Params: - rowOid – The
SnmpOid
identifying the table
row involved in the operation. - newStatus – The new status for the row: one of the RowStatus code defined in
EnumRowStatus
. These codes correspond to RowStatus codes as defined in RFC 2579, plus the unspecified value which is SNMP Runtime specific. - userData – A contextual object containing user-data.
This object is allocated through the
SnmpUserDataFactory
for each incoming SNMP request.
Throws: - SnmpStatusException – If the given
newStatus
could not be set on the specified entry, or if the
given newStatus
is not valid.
See Also: Returns: The new value of the control variable (usually
new SnmpInt(newStatus)
) or null
if the table do not have any control variable.
/**
* 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
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.
Params: - rowOid – The
SnmpOid
identifying the table
row involved in the operation. - userData – A contextual object containing user-data.
This object is allocated through the
SnmpUserDataFactory
for each incoming SNMP request.
Throws: - SnmpStatusException – An error occured while trying
to retrieve the row status, and the operation should
be aborted.
See Also: Returns: true
if the row can be placed in
notInService state.
/**
* 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 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.
Params: - req – The sub-request that must be handled by this node.
- rowOid – The
SnmpOid
identifying the table
row involved in the operation. - depth – The depth reached in the OID tree.
- newStatus – The new status for the row: one of the RowStatus code defined in
EnumRowStatus
. These codes correspond to RowStatus codes as defined in RFC 2579, plus the unspecified value which is SNMP Runtime specific.
Throws: - SnmpStatusException – if switching to this new state
would fail.
/**
* 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.
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.
Params: - req – The sub-request that must be handled by this node.
- rowOid – The
SnmpOid
identifying the table
row involved in the operation. - depth – The depth reached in the OID tree.
Throws: - SnmpStatusException – if the row deletion must be
rejected.
/**
* 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 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.
Params: - req – The sub-request that must be handled by this node.
- rowOid – The
SnmpOid
identifying the table
row involved in the operation. - depth – The depth reached in the OID tree.
Throws: - 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.
/**
* 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:
- 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.
Params: - req – The sub-request that must be handled by this node.
- rowOid – The
SnmpOid
identifying the table
row involved in the operation. - depth – The depth reached in the OID tree.
- rowAction – The requested action as returned by
getRowAction()
: one of the RowStatus codes defined in EnumRowStatus
. These codes correspond to RowStatus codes as defined in RFC 2579, plus the unspecified value which is SNMP Runtime specific.
Throws: - 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 Also:
/**
* 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:
- 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
).
Params: - req – The sub-request that must be handled by this node.
- rowOid – The
SnmpOid
identifying the table
row involved in the operation. - depth – The depth reached in the OID tree.
- rowAction – The requested action as returned by
getRowAction()
: one of the RowStatus codes defined in EnumRowStatus
. These codes correspond to RowStatus codes as defined in RFC 2579, plus the unspecified value which is SNMP Runtime specific.
Throws: - SnmpStatusException – if the specified
rowAction
is not valid.
See Also:
/**
* 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 getNextVarEntryId(SnmpOid, long, Object)
, until skipEntryVariable(SnmpOid, long, Object, int)
returns false. Params: - rowOid – The OID index of the row involved in the operation.
- var – Id of the variable we start from, looking for the next.
- userData – A contextual object containing user-data.
This object is allocated through the
SnmpUserDataFactory
for each incoming SNMP request. - pduVersion – Protocol version of the original request PDU.
Throws: - SnmpStatusException – If no id is found after the given id.
Returns: The next columnar object id which can be returned using
the given PDU's protocol version.
/**
* 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:
- 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).
Params: - rowOid – The OID index of the row involved in the operation.
- var – Id of the variable we start from, looking for the next.
- userData – A contextual object containing user-data.
This object is allocated through the
SnmpUserDataFactory
for each incoming SNMP request. - pduVersion – Protocol version of the original request PDU.
Returns: true if the variable must be skipped by the get-next
algorithm.
/**
* 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 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.
Params: - oid – The OID from which the search will begin.
- userData – A contextual object containing user-data.
This object is allocated through the
SnmpUserDataFactory
for each incoming SNMP request.
Throws: - SnmpStatusException – There is no index following the
specified
oid
in the table.
Returns: The next SnmpOid
index.
/**
* 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 new SnmpStatusException(SnmpStatusException.noSuchInstance);
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 new SnmpStatusException(SnmpStatusException.noSuchInstance);
}
// 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 new SnmpStatusException(SnmpStatusException.noSuchInstance);
}
} else {
// We are dealing with the last element of the table ..
//
throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
}
return last;
}
Return the first entry OID registered in the table.
Params: - userData – A contextual object containing user-data.
This object is allocated through the
SnmpUserDataFactory
for each incoming SNMP request.
Throws: - SnmpStatusException – If the table is empty.
Returns: The SnmpOid
of the first entry in the table.
/**
* 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 new SnmpStatusException(SnmpStatusException.noSuchInstance);
// XX return (SnmpOid) oids.firstElement();
return tableoids[0];
}
// -------------------------------------------------------------------
// Abstract Protected Methods
// -------------------------------------------------------------------
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.
Params: - rowOid – The OID index of the row involved in the operation.
- var – Id of the variable we start from, looking for the next.
- userData – A contextual object containing user-data.
This object is allocated through the
SnmpUserDataFactory
for each incoming SNMP request.
Throws: - SnmpStatusException – If no id is found after the given id.
Returns: The next columnar object id.
/**
* 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
SnmpMibTable
subclasses generated by mibgen
.
Params: - rowOid – The OID index of the row involved in the operation.
- var – The var we want to validate.
- userData – A contextual object containing user-data.
This object is allocated through the
SnmpUserDataFactory
for each incoming SNMP request.
Throws: - SnmpStatusException – If this id is not valid.
/**
* 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
SnmpMibTable
subclasses generated by mibgen
.
Params: - rowOid – The OID index of the row involved in the operation.
- var – The OID arc.
- userData – A contextual object containing user-data.
This object is allocated through the
SnmpUserDataFactory
for each incoming SNMP request.
Throws: - SnmpStatusException – If this id is not valid.
/**
*
* 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
SnmpMibTable
subclasses generated by mibgen
.
/**
* 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
SnmpMibTable
subclasses generated by mibgen
.
/**
* 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
SnmpMibTable
subclasses generated by mibgen
.
/**
* 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 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)
;
Params: - oid – The OID array.
- pos – The position in the OID array at which the index starts.
- userData – A contextual object containing user-data.
This object is allocated through the
SnmpUserDataFactory
for each incoming SNMP request.
Throws: - SnmpStatusException – There is no index following the
specified one in the table.
Returns: The next SnmpOid
.
/**
* 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 new SnmpStatusException(SnmpStatusException.noSuchInstance);
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 new SnmpStatusException(SnmpStatusException.noSuchObject);
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 new SnmpStatusException(SnmpStatusException.noSuchObject);
} 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 new SnmpStatusException(SnmpStatusException.noSuchObject);
} 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 new SnmpStatusException(SnmpStatusException.noSuchObject);
// 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 new SnmpStatusException(SnmpStatusException.noSuchObject);
// 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 new SnmpStatusException(SnmpStatusException.noSuchObject);
}
}
Validate the specified OID.
Params: - oid – The OID array.
- pos – The position in the array.
Throws: - SnmpStatusException – If the validation fails.
/**
* 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 new SnmpStatusException(SnmpStatusException.noSuchInstance);
// Check that the entry identifier is specified
//
if (oid[pos] != nodeId)
throw new SnmpStatusException(SnmpStatusException.noSuchObject);
}
// ----------------------------------------------------------------------
// PRIVATE METHODS
// ----------------------------------------------------------------------
Enable this SnmpMibTable
to send a notification.
Params: - notification – The notification to send.
/**
* 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.
Params: - type – The notification type.
- timeStamp – The notification emission date.
- entry – The entry object.
/**
* 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.
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.
Params: - oid – The index part of the OID we're looking for.
- userData – A contextual object containing user-data.
This object is allocated through the
SnmpUserDataFactory
for each incoming SNMP request.
Returns: true
if the entry is found, false
otherwise.Since: 1.5
/**
* 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.
Params: - oid – The OID we're looking for.
Returns: The position of the OID in the table. -1 if the given
OID was not found.
/**
* 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).
Params: - oid – The OID we would like to insert.
Throws: - SnmpStatusException – if the OID is already present in the
table.
Returns: The position at which the OID should be inserted in
the table.
/**
* 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).
Params: - oid – The OID we would like to insert.
- fail – Tells whether a SnmpStatusException must be generated
if the given OID is already present in the table.
Throws: - SnmpStatusException – if the OID is already present in the
table and
fail
is true
.
Returns: 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.
/**
* 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.
Params: - pos – The position at which the OID to be removed is located.
/**
* 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.
Params: - oid – The OID to be inserted in the table
- pos – The position at which the OID to be added is located.
/**
* 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
/**
* The id of the contained entry object.
* @serial
*/
protected int nodeId=1;
The MIB to which the metadata is linked.
@serial
/**
* The MIB to which the metadata is linked.
* @serial
*/
protected SnmpMib theMib;
true
if remote creation of entries via SET operations
is enabled.
[default value is false
]
@serial
/**
* <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
/**
* The entry factory
*/
protected SnmpTableEntryFactory factory = null;
// ----------------------------------------------------------------------
// PRIVATE VARIABLES
// ----------------------------------------------------------------------
The number of elements in the table.
@serial
/**
* 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
/**
* 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
/**
* The list of entries.
* @serial
*/
private final Vector<Object> entries= new Vector<Object>();
The list of object names.
@serial
/**
* 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.
/**
* Listener hastable containing the hand-back objects.
*/
private Hashtable<NotificationListener, Vector<Object>> handbackTable =
new Hashtable<NotificationListener, Vector<Object>>();
Listener hastable containing the filter objects.
/**
* 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.
/**
* SNMP table sequence number.
* The default value is set to 0.
*/
transient long sequenceNumber = 0;
}