blob: 8d697e84eaeea71ef56ed76df2de49668b7ec797 [file] [log] [blame]
/*
* 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.Enumeration;
import java.util.logging.Level;
import java.util.Vector;
import javax.management.ObjectName;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.NotCompliantMBeanException;
import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER;
import com.sun.jmx.snmp.SnmpOid;
import com.sun.jmx.snmp.SnmpVarBind;
import com.sun.jmx.snmp.SnmpDefinitions;
import com.sun.jmx.snmp.SnmpStatusException;
import com.sun.jmx.snmp.SnmpEngine;
import com.sun.jmx.snmp.SnmpUnknownModelException;
import com.sun.jmx.snmp.internal.SnmpAccessControlModel;
import com.sun.jmx.snmp.internal.SnmpEngineImpl;
/**
* This list is used in order to construct the OID during the getnext.
* The constructed oid is checked by the checker AcmChecker.
*/
final class LongList {
public static int DEFAULT_CAPACITY = 10;
public static int DEFAULT_INCREMENT = 10;
private final int DELTA;
private int size;
/**
* The list content. Any access to this variable must be protected
* by a synchronized block on the LongList object.
* Only read-only action should be performed on this object.
**/
public long[] list;
LongList() {
this(DEFAULT_CAPACITY,DEFAULT_INCREMENT);
}
LongList(int initialCapacity) {
this(initialCapacity,DEFAULT_INCREMENT);
}
LongList(int initialCapacity, int delta) {
size = 0;
DELTA = delta;
list = allocate(initialCapacity);
}
/**
* Same behaviour than size() in {@link java.util.List}.
**/
public final int size() { return size;}
/**
* Same behaviour than add(long o) in {@link java.util.List}.
* Any access to this method should be protected in a synchronized
* block on the LongList object.
**/
public final boolean add(final long o) {
if (size >= list.length)
resize();
list[size++]=o;
return true;
}
/**
* Same behaviour than add(int index, long o) in
* {@link java.util.List}.
* Any access to this method should be protected in a synchronized
* block on the LongList object.
**/
public final void add(final int index, final long o) {
if (index > size) throw new IndexOutOfBoundsException();
if (index >= list.length) resize();
if (index == size) {
list[size++]=o;
return;
}
java.lang.System.arraycopy(list,index,list,index+1,size-index);
list[index]=o;
size++;
}
/**
* Adds <var>count</var> elements to the list.
* @param at index at which the elements must be inserted. The
* first element will be inserted at this index.
* @param src An array containing the elements we want to insert.
* @param from Index of the first element from <var>src</var> that
* must be inserted.
* @param count number of elements to insert.
* Any access to this method should be protected in a synchronized
* block on the LongList object.
**/
public final void add(final int at,final long[] src, final int from,
final int count) {
if (count <= 0) return;
if (at > size) throw new IndexOutOfBoundsException();
ensure(size+count);
if (at < size) {
java.lang.System.arraycopy(list,at,list,at+count,size-at);
}
java.lang.System.arraycopy(src,from,list,at,count);
size+=count;
}
/**
* Any access to this method should be protected in a synchronized
* block on the LongList object.
**/
public final long remove(final int from, final int count) {
if (count < 1 || from < 0) return -1;
if (from+count > size) return -1;
final long o = list[from];
final int oldsize = size;
size = size - count;
if (from == size) return o;
java.lang.System.arraycopy(list,from+count,list,from,
size-from);
return o;
}
/**
* Same behaviour than remove(int index) in {@link java.util.List}.
* Any access to this method should be protected in a synchronized
* block on the LongList object.
**/
public final long remove(final int index) {
if (index >= size) return -1;
final long o = list[index];
list[index]=0;
if (index == --size) return o;
java.lang.System.arraycopy(list,index+1,list,index,
size-index);
return o;
}
/**
* Same behaviour than the toArray(long[] a) method in
* {@link java.util.List}.
* Any access to this method should be protected in a synchronized
* block on the LongList object.
**/
public final long[] toArray(long[] a) {
java.lang.System.arraycopy(list,0,a,0,size);
return a;
}
/**
* Same behaviour than the toArray() method in
* {@link java.util.List}.
* Any access to this method should be protected in a synchronized
* block on the LongList object.
**/
public final long[] toArray() {
return toArray(new long[size]);
}
/**
* Resize the list. Increase its capacity by DELTA elements.
* Any call to this method must be protected by a synchronized
* block on this LongList.
**/
private final void resize() {
final long[] newlist = allocate(list.length + DELTA);
java.lang.System.arraycopy(list,0,newlist,0,size);
list = newlist;
}
/**
* Resize the list. Insure that the new length will be at
* least equal to <var>length</var>.
* @param length new minimal length requested.
* Any call to this method must be protected by a synchronized
* block on this LongList.
**/
private final void ensure(int length) {
if (list.length < length) {
final int min = list.length+DELTA;
length=(length<min)?min:length;
final long[] newlist = allocate(length);
java.lang.System.arraycopy(list,0,newlist,0,size);
list = newlist;
}
}
/**
* Allocate a new array of object of specified length.
**/
private final long[] allocate(final int length) {
return new long[length];
}
}
/**
* Oid Checker makes use of ACM to check each OID during the getnext process.
*/
class AcmChecker {
SnmpAccessControlModel model = null;
String principal = null;
int securityLevel = -1;
int version = -1;
int pduType = -1;
int securityModel = -1;
byte[] contextName = null;
SnmpEngineImpl engine = null;
LongList l = null;
AcmChecker(SnmpMibRequest req) {
engine = (SnmpEngineImpl) req.getEngine();
//We are in V3 architecture, ACM is in the picture.
if(engine != null) {
if(engine.isCheckOidActivated()) {
try {
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
SnmpMib.class.getName(),
"AcmChecker(SnmpMibRequest)",
"SNMP V3 Access Control to be done");
}
model = (SnmpAccessControlModel)
engine.getAccessControlSubSystem().
getModel(SnmpDefinitions.snmpVersionThree);
principal = req.getPrincipal();
securityLevel = req.getSecurityLevel();
pduType = req.getPdu().type;
version = req.getRequestPduVersion();
securityModel = req.getSecurityModel();
contextName = req.getAccessContextName();
l = new LongList();
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
final StringBuilder strb = new StringBuilder()
.append("Will check oid for : principal : ")
.append(principal)
.append("; securityLevel : ").append(securityLevel)
.append("; pduType : ").append(pduType)
.append("; version : ").append(version)
.append("; securityModel : ").append(securityModel)
.append("; contextName : ").append(contextName);
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
SnmpMib.class.getName(),
"AcmChecker(SnmpMibRequest)", strb.toString());
}
}catch(SnmpUnknownModelException e) {
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
SnmpMib.class.getName(),
"AcmChecker(SnmpMibRequest)",
"Unknown Model, no ACM check.");
}
}
}
}
}
void add(int index, long arc) {
if(model != null)
l.add(index, arc);
}
void remove(int index) {
if(model != null)
l.remove(index);
}
void add(final int at,final long[] src, final int from,
final int count) {
if(model != null)
l.add(at,src,from,count);
}
void remove(final int from, final int count) {
if(model != null)
l.remove(from,count);
}
void checkCurrentOid() throws SnmpStatusException {
if(model != null) {
SnmpOid oid = new SnmpOid(l.toArray());
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMib.class.getName(),
"checkCurrentOid", "Checking access for : " + oid);
}
model.checkAccess(version,
principal,
securityLevel,
pduType,
securityModel,
contextName,
oid);
}
}
}
/**
* Abstract class for representing an SNMP MIB.
* <P>
* When compiling a SNMP MIB, among all the classes generated by
* <CODE>mibgen</CODE>, there is one which extends <CODE>SnmpMib</CODE>
* for representing a whole MIB.
* <BR>The class is used by the SNMP protocol adaptor as the entry point in
* the MIB.
*
* <p>This generated class can be subclassed in your code in order to
* plug in your own specific behaviour.
* </p>
*
* <p><b>This API is a Sun Microsystems internal API and is subject
* to change without notice.</b></p>
*/
public abstract class SnmpMib extends SnmpMibAgent implements Serializable {
/**
* Default constructor.
* Initializes the OID tree.
*/
public SnmpMib() {
root= new SnmpMibOid();
}
// --------------------------------------------------------------------
// POLYMORHIC METHODS
// --------------------------------------------------------------------
/**
* <p>
* This callback should return the OID associated to the group
* identified by the given <code>groupName</code>.
* </p>
*
* <p>
* This method is provided as a hook to plug-in some custom
* specific behavior. Although doing so is discouraged you might
* want to subclass this method in order to store & provide more metadata
* information (mapping OID <-> symbolic name) within the agent,
* or to "change" the root of the MIB OID by prefixing the
* defaultOid by an application dependant OID string, for instance.
* </p>
*
* <p>
* The default implementation of this method is to return the given
* <code>defaultOid</code>
* </p>
*
* @param groupName The java-ized name of the SNMP group.
* @param defaultOid The OID defined in the MIB for that group
* (in dot notation).
*
* @return The OID of the group identified by <code>groupName</code>,
* in dot-notation.
*/
protected String getGroupOid(String groupName, String defaultOid) {
return defaultOid;
}
/**
* <p>
* This callback should return the ObjectName associated to the
* group identified by the given <code>groupName</code>.
* </p>
*
* <p>
* This method is provided as a hook to plug-in some custom
* specific behavior. You might want to override this method
* in order to provide a different object naming scheme than
* that proposed by default by <code>mibgen</code>.
* </p>
*
* <p>
* This method is only meaningful if the MIB is registered
* in the MBeanServer, otherwise, it will not be called.
* </p>
*
* <p>
* The default implementation of this method is to return an ObjectName
* built from the given <code>defaultName</code>.
* </p>
*
* @param name The java-ized name of the SNMP group.
* @param oid The OID returned by getGroupOid() - in dot notation.
* @param defaultName The name by default generated by <code>
* mibgen</code>
*
* @return The ObjectName of the group identified by <code>name</code>
*/
protected ObjectName getGroupObjectName(String name, String oid,
String defaultName)
throws MalformedObjectNameException {
return new ObjectName(defaultName);
}
/**
* <p>
* Register an SNMP group and its metadata node in the MIB.
* </p>
*
* <p>
* This method is provided as a hook to plug-in some custom
* specific behavior. You might want to override this method
* if you want to set special links between the MBean, its metadata
* node, its OID or ObjectName etc..
* </p>
*
* <p>
* If the MIB is not registered in the MBeanServer, the <code>
* server</code> and <code>groupObjName</code> parameters will be
* <code>null</code>.<br>
* If the given group MBean is not <code>null</code>, and if the
* <code>server</code> and <code>groupObjName</code> parameters are
* not null, then this method will also automatically register the
* group MBean with the given MBeanServer <code>server</code>.
* </p>
*
* @param groupName The java-ized name of the SNMP group.
* @param groupOid The OID as returned by getGroupOid() - in dot
* notation.
* @param groupObjName The ObjectName as returned by getGroupObjectName().
* This parameter may be <code>null</code> if the
* MIB is not registered in the MBeanServer.
* @param node The metadata node, as returned by the metadata
* factory method for this group.
* @param group The MBean for this group, as returned by the
* MBean factory method for this group.
* @param server The MBeanServer in which the groups are to be
* registered. This parameter will be <code>null</code>
* if the MIB is not registered, otherwise it is a
* reference to the MBeanServer in which the MIB is
* registered.
*
*/
protected void registerGroupNode(String groupName, String groupOid,
ObjectName groupObjName, SnmpMibNode node,
Object group, MBeanServer server)
throws NotCompliantMBeanException, MBeanRegistrationException,
InstanceAlreadyExistsException, IllegalAccessException {
root.registerNode(groupOid,node);
if (server != null && groupObjName != null && group != null)
server.registerMBean(group,groupObjName);
}
/**
* <p>
* Register an SNMP Table metadata node in the MIB.
* </p>
*
* <p>
* <b><i>
* This method is used internally and you should never need to
* call it directly.</i></b><br> It is used to establish the link
* between an SNMP table metadata node and its bean-like counterpart.
* <br>
* The group metadata nodes will create and register their
* underlying table metadata nodes in the MIB using this
* method. <br>
* The metadata nodes will be later retrieved from the MIB by the
* bean-like table objects using the getRegisterTableMeta() method.
* </p>
*
* @param name The java-ized name of the SNMP table.
* @param table The SNMP table metadata node - usually this
* corresponds to a <code>mibgen</code> generated
* object.
*/
public abstract void registerTableMeta(String name, SnmpMibTable table);
/**
* Returns a registered SNMP Table metadata node.
*
* <p><b><i>
* This method is used internally and you should never need to
* call it directly.
* </i></b></p>
*
*/
public abstract SnmpMibTable getRegisteredTableMeta(String name);
// --------------------------------------------------------------------
// PUBLIC METHODS
// --------------------------------------------------------------------
/**
* Processes a <CODE>get</CODE> operation.
*
**/
// Implements the method defined in SnmpMibAgent. See SnmpMibAgent
// for java-doc
//
public void get(SnmpMibRequest req) throws SnmpStatusException {
// Builds the request tree: creation is not allowed, operation
// is not atomic.
final int reqType = SnmpDefinitions.pduGetRequestPdu;
SnmpRequestTree handlers = getHandlers(req,false,false,reqType);
SnmpRequestTree.Handler h = null;
SnmpMibNode meta = null;
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMib.class.getName(),
"get", "Processing handlers for GET... ");
}
// For each sub-request stored in the request-tree, invoke the
// get() method.
for (Enumeration eh=handlers.getHandlers();eh.hasMoreElements();) {
h = (SnmpRequestTree.Handler) eh.nextElement();
// Gets the Meta node. It can be either a Group Meta or a
// Table Meta.
//
meta = handlers.getMetaNode(h);
// Gets the depth of the Meta node in the OID tree
final int depth = handlers.getOidDepth(h);
for (Enumeration rqs=handlers.getSubRequests(h);
rqs.hasMoreElements();) {
// Invoke the get() operation.
meta.get((SnmpMibSubRequest)rqs.nextElement(),depth);
}
}
}
/**
* Processes a <CODE>set</CODE> operation.
*
*/
// Implements the method defined in SnmpMibAgent. See SnmpMibAgent
// for java-doc
//
public void set(SnmpMibRequest req) throws SnmpStatusException {
SnmpRequestTree handlers = null;
// Optimization: we're going to get the whole SnmpRequestTree
// built in the "check" method, so that we don't have to rebuild
// it here.
//
if (req instanceof SnmpMibRequestImpl)
handlers = ((SnmpMibRequestImpl)req).getRequestTree();
// Optimization didn't work: we have to rebuild the tree.
//
// Builds the request tree: creation is not allowed, operation
// is atomic.
//
final int reqType = SnmpDefinitions.pduSetRequestPdu;
if (handlers == null) handlers = getHandlers(req,false,true,reqType);
handlers.switchCreationFlag(false);
handlers.setPduType(reqType);
SnmpRequestTree.Handler h = null;
SnmpMibNode meta = null;
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMib.class.getName(),
"set", "Processing handlers for SET... ");
}
// For each sub-request stored in the request-tree, invoke the
// get() method.
for (Enumeration eh=handlers.getHandlers();eh.hasMoreElements();) {
h = (SnmpRequestTree.Handler) eh.nextElement();
// Gets the Meta node. It can be either a Group Meta or a
// Table Meta.
//
meta = handlers.getMetaNode(h);
// Gets the depth of the Meta node in the OID tree
final int depth = handlers.getOidDepth(h);
for (Enumeration rqs=handlers.getSubRequests(h);
rqs.hasMoreElements();) {
// Invoke the set() operation
meta.set((SnmpMibSubRequest)rqs.nextElement(),depth);
}
}
}
/**
* Checks if a <CODE>set</CODE> operation can be performed.
* If the operation cannot be performed, the method will raise a
* <CODE>SnmpStatusException</CODE>.
*
*/
// Implements the method defined in SnmpMibAgent. See SnmpMibAgent
// for java-doc
//
public void check(SnmpMibRequest req) throws SnmpStatusException {
final int reqType = SnmpDefinitions.pduWalkRequest;
// Builds the request tree: creation is allowed, operation
// is atomic.
SnmpRequestTree handlers = getHandlers(req,true,true,reqType);
SnmpRequestTree.Handler h = null;
SnmpMibNode meta = null;
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMib.class.getName(),
"check", "Processing handlers for CHECK... ");
}
// For each sub-request stored in the request-tree, invoke the
// check() method.
for (Enumeration eh=handlers.getHandlers();eh.hasMoreElements();) {
h = (SnmpRequestTree.Handler) eh.nextElement();
// Gets the Meta node. It can be either a Group Meta or a
// Table Meta.
//
meta = handlers.getMetaNode(h);
// Gets the depth of the Meta node in the OID tree
final int depth = handlers.getOidDepth(h);
for (Enumeration rqs=handlers.getSubRequests(h);
rqs.hasMoreElements();) {
// Invoke the check() operation
meta.check((SnmpMibSubRequest)rqs.nextElement(),depth);
}
}
// Optimization: we're going to pass the whole SnmpRequestTree
// to the "set" method, so that we don't have to rebuild it there.
//
if (req instanceof SnmpMibRequestImpl) {
((SnmpMibRequestImpl)req).setRequestTree(handlers);
}
}
/**
* Processes a <CODE>getNext</CODE> operation.
*
*/
// Implements the method defined in SnmpMibAgent. See SnmpMibAgent
// for java-doc
//
public void getNext(SnmpMibRequest req) throws SnmpStatusException {
// Build the request tree for the operation
// The subrequest stored in the request tree are valid GET requests
SnmpRequestTree handlers = getGetNextHandlers(req);
SnmpRequestTree.Handler h = null;
SnmpMibNode meta = null;
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMib.class.getName(),
"getNext", "Processing handlers for GET-NEXT... ");
}
// Now invoke get() for each subrequest of the request tree.
for (Enumeration eh=handlers.getHandlers();eh.hasMoreElements();) {
h = (SnmpRequestTree.Handler) eh.nextElement();
// Gets the Meta node. It can be either a Group Meta or a
// Table Meta.
//
meta = handlers.getMetaNode(h);
// Gets the depth of the Meta node in the OID tree
int depth = handlers.getOidDepth(h);
for (Enumeration rqs=handlers.getSubRequests(h);
rqs.hasMoreElements();) {
// Invoke the get() operation
meta.get((SnmpMibSubRequest)rqs.nextElement(),depth);
}
}
}
/**
* Processes a <CODE>getBulk</CODE> operation.
* The method implements the <CODE>getBulk</CODE> operation by calling
* appropriately the <CODE>getNext</CODE> method.
*
*/
// Implements the method defined in SnmpMibAgent. See SnmpMibAgent
// for java-doc
//
public void getBulk(SnmpMibRequest req, int nonRepeat, int maxRepeat)
throws SnmpStatusException {
getBulkWithGetNext(req, nonRepeat, maxRepeat);
}
/**
* Gets the root object identifier of the MIB.
* <P>In order to be accurate, the method should be called once the
* MIB is fully initialized (that is, after a call to <CODE>init</CODE>
* or <CODE>preRegister</CODE>).
*
* @return The root object identifier.
*/
public long[] getRootOid() {
if( rootOid == null) {
Vector<Integer> list= new Vector<Integer>(10);
// Ask the tree to do the job !
//
root.getRootOid(list);
// Now format the result
//
rootOid= new long[list.size()];
int i=0;
for(Enumeration<Integer> e= list.elements(); e.hasMoreElements(); ) {
Integer val= e.nextElement();
rootOid[i++]= val.longValue();
}
}
return rootOid;
}
// --------------------------------------------------------------------
// PRIVATE METHODS
//---------------------------------------------------------------------
/**
* This method builds the temporary request-tree that will be used to
* perform the SNMP request associated with the given vector of varbinds
* `list'.
*
* @param req The SnmpMibRequest object holding the varbind list
* concerning this MIB.
* @param createflag Indicates whether the operation allow for creation
* of new instances (ie: it is a SET).
* @param atomic Indicates whether the operation is atomic or not.
* @param type Request type (from SnmpDefinitions).
*
* @return The request-tree where the original varbind list has been
* dispatched to the appropriate nodes.
*/
private SnmpRequestTree getHandlers(SnmpMibRequest req,
boolean createflag, boolean atomic,
int type)
throws SnmpStatusException {
// Build an empty request tree
SnmpRequestTree handlers =
new SnmpRequestTree(req,createflag,type);
int index=0;
SnmpVarBind var = null;
final int ver= req.getVersion();
// For each varbind in the list finds its handling node.
for (Enumeration e= req.getElements(); e.hasMoreElements(); index++) {
var= (SnmpVarBind) e.nextElement();
try {
// Find the handling node for this varbind.
root.findHandlingNode(var,var.oid.longValue(false),
0,handlers);
} catch(SnmpStatusException x) {
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
SnmpMib.class.getName(),
"getHandlers",
"Couldn't find a handling node for " +
var.oid.toString());
}
// If the operation is atomic (Check/Set) or the version
// is V1 we must generate an exception.
//
if (ver == SnmpDefinitions.snmpVersionOne) {
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
SnmpMib.class.getName(),
"getHandlers", "\tV1: Throwing exception");
}
// The index in the exception must correspond to the
// SNMP index ...
//
final SnmpStatusException sse =
new SnmpStatusException(x, index + 1);
sse.initCause(x);
throw sse;
} else if ((type == SnmpDefinitions.pduWalkRequest) ||
(type == SnmpDefinitions.pduSetRequestPdu)) {
final int status =
SnmpRequestTree.mapSetException(x.getStatus(),ver);
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
SnmpMib.class.getName(),
"getHandlers", "\tSET: Throwing exception");
}
final SnmpStatusException sse =
new SnmpStatusException(status, index + 1);
sse.initCause(x);
throw sse;
} else if (atomic) {
// Should never come here...
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
SnmpMib.class.getName(),
"getHandlers", "\tATOMIC: Throwing exception");
}
final SnmpStatusException sse =
new SnmpStatusException(x, index + 1);
sse.initCause(x);
throw sse;
}
final int status =
SnmpRequestTree.mapGetException(x.getStatus(),ver);
if (status == SnmpStatusException.noSuchInstance) {
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
SnmpMib.class.getName(),
"getHandlers",
"\tGET: Registering noSuchInstance");
}
var.value= SnmpVarBind.noSuchInstance;
} else if (status == SnmpStatusException.noSuchObject) {
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
SnmpMib.class.getName(),
"getHandlers",
"\tGET: Registering noSuchObject");
}
var.value= SnmpVarBind.noSuchObject;
} else {
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
SnmpMib.class.getName(),
"getHandlers",
"\tGET: Registering global error: " + status);
}
final SnmpStatusException sse =
new SnmpStatusException(status, index + 1);
sse.initCause(x);
throw sse;
}
}
}
return handlers;
}
/**
* This method builds the temporary request-tree that will be used to
* perform the SNMP GET-NEXT request associated with the given vector
* of varbinds `list'.
*
* @param req The SnmpMibRequest object holding the varbind list
* concerning this MIB.
*
* @return The request-tree where the original varbind list has been
* dispatched to the appropriate nodes, and where the original
* OIDs have been replaced with the correct "next" OID.
*/
private SnmpRequestTree getGetNextHandlers(SnmpMibRequest req)
throws SnmpStatusException {
// Creates an empty request tree, no entry creation is allowed (false)
SnmpRequestTree handlers = new
SnmpRequestTree(req,false,SnmpDefinitions.pduGetNextRequestPdu);
// Sets the getNext flag: if version=V2, status exception are
// transformed in endOfMibView
handlers.setGetNextFlag();
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMib.class.getName(),
"getGetNextHandlers", "Received MIB request : " + req);
}
AcmChecker checker = new AcmChecker(req);
int index=0;
SnmpVarBind var = null;
final int ver= req.getVersion();
SnmpOid original = null;
// For each varbind, finds the handling node.
// This function has the side effect of transforming a GET-NEXT
// request into a valid GET request, replacing the OIDs in the
// original GET-NEXT request with the OID of the first leaf that
// follows.
for (Enumeration e= req.getElements(); e.hasMoreElements(); index++) {
var = (SnmpVarBind) e.nextElement();
SnmpOid result = null;
try {
// Find the node handling the OID that follows the varbind
// OID. `result' contains this next leaf OID.
//ACM loop.
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
SnmpMib.class.getName(),
"getGetNextHandlers", " Next OID of : " + var.oid);
}
result = new SnmpOid(root.findNextHandlingNode
(var,var.oid.longValue(false),0,
0,handlers, checker));
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
SnmpMib.class.getName(),
"getGetNextHandlers", " is : " + result);
}
// We replace the varbind original OID with the OID of the
// leaf object we have to return.
var.oid = result;
} catch(SnmpStatusException x) {
// if (isDebugOn())
// debug("getGetNextHandlers",
// "Couldn't find a handling node for "
// + var.oid.toString());
if (ver == SnmpDefinitions.snmpVersionOne) {
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
SnmpMib.class.getName(),
"getGetNextHandlers",
"\tThrowing exception " + x.toString());
}
// The index in the exception must correspond to the
// SNMP index ...
//
throw new SnmpStatusException(x, index + 1);
}
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
SnmpMib.class.getName(),
"getGetNextHandlers",
"Exception : " + x.getStatus());
}
var.setSnmpValue(SnmpVarBind.endOfMibView);
}
}
return handlers;
}
// --------------------------------------------------------------------
// PROTECTED VARIABLES
// --------------------------------------------------------------------
/**
* The top element in the Mib tree.
* @serial
*/
protected SnmpMibOid root;
// --------------------------------------------------------------------
// PRIVATE VARIABLES
// --------------------------------------------------------------------
/**
* The root object identifier of the MIB.
*/
private transient long[] rootOid= null;
}