SnmpMibDispatch.java
package eu.linuxengineering.snmp;
import java.util.Map.Entry;
import eu.javaexperience.collection.map.KeyVal;
import eu.javaexperience.log.JavaExperienceLoggingFacility;
import eu.javaexperience.log.LogLevel;
import eu.javaexperience.log.Loggable;
import eu.javaexperience.log.Logger;
import eu.javaexperience.log.LoggingTools;
import eu.javaexperience.reflect.Mirror;
import java.util.Arrays;
import java.util.SortedMap;
import java.util.TreeMap;
import net.sf.snmpadaptor4j.api.AttributeAccessor;
import net.sf.snmpadaptor4j.api.SnmpMib;
import net.sf.snmpadaptor4j.object.SnmpOid;
public class SnmpMibDispatch extends SnmpDispatchNode implements SnmpMib
{
protected static final Logger LOG = JavaExperienceLoggingFacility.getLogger(new Loggable("SnmpMibDispatch"));
//protected boolean listIntermediateNodes;
public void addNode(Integer id, SnmpNode node)
{
subNodes.put(id, node);
}
public SnmpNode getNode(Integer id)
{
return subNodes.get(id);
}
@Override
public AttributeAccessor find(SnmpOid oid)
{
LoggingTools.tryLogFormat(LOG, LogLevel.DEBUG, "SnmpMibDisaptch.find(this: `%s`, oid: `%s`)", this, oid);
SnmpPathDispatch dispatch = new SnmpPathDispatch(oid, 0);
Entry<Integer, SnmpNode> node = new KeyVal(-1, this);
int prevIndex = -1;
do
{
if(prevIndex == dispatch.getCurrentPathIndex())
{
LoggingTools.tryLogFormat
(
LOG,
LogLevel.ERROR,
"SnmpMibDisaptch.find: Snmp dispatch looping ocurred when dispatching oid: `%s` at node: `%s`, node: `%s`",
oid,
prevIndex,
node
);
throw new RuntimeException("Snmp dispatch loop exception oid: "+oid+", node: "+node+" index: "+prevIndex);
}
prevIndex = dispatch.getCurrentPathIndex();
Integer id = dispatch.getCurrentPathOid();
boolean last = dispatch.isLastDispatch();
node = node.getValue().getSubNodeGte(dispatch);
if(null == node)
{
return null;
}
//in this case we looking for an exact match
if(!node.getKey().equals(id))
{
return null;
}
if(last && node.getKey().equals(id))
{
return node.getValue().getAccessor();
}
}
while(dispatch.hasNexOidPath());
return null;
}
public AttributeAccessor next(SnmpOid oid)
{
LoggingTools.tryLogFormat(LOG, LogLevel.DEBUG, "SnmpMibDisaptch.next(this: `%s`, oid: `%s`)", this, oid);
SnmpNode ret = null;
try
{
SnmpPathDispatch dispatch = new SnmpPathDispatch(oid, 0);
ret = findNext(this, dispatch, false);
}
catch(Exception e)
{
LoggingTools.tryLogFormatException(LOG, LogLevel.ERROR, e, "SnmpMibDisaptch.next(this: `%s`, oid: `%s`): Exception: ", this, oid);
Mirror.propagateAnyway(e);
}
LoggingTools.tryLogFormat(LOG, LogLevel.DEBUG, "SnmpMibDisaptch.next(this: `%s`, oid: `%s`): found next: `%s`", this, oid, ret);
return null == ret?null:ret.getAccessor();
}
protected static SnmpPathDispatch modifyDispatchFrom
(
SnmpPathDispatch proto,
int at,
int newValue,
int index
)
{
int[] path = Arrays.copyOf(proto.oids, at+1);
path[at] = newValue;
return new SnmpPathDispatch(path, index);
}
protected static final SnmpNode getDepthFirst(SnmpPathDispatch from, SnmpNode node)
{
int[] dsp = Arrays.copyOf(from.oids, from.index+1);
dsp[from.index] = -1;
SnmpPathDispatch disp = new SnmpPathDispatch(dsp, from.index);
if(node.hasSubNodes())
{
//disp.setPathIndex(0);
Entry<Integer, SnmpNode> next = node.getSubNodeGte(disp);
disp.jumpPreviousNode();
if(null != next)
{
dsp[from.index] = next.getKey();
disp.jumpNextNode();
SnmpNode ret = getDepthFirst(disp, next.getValue());
if(null == ret && !next.getValue().hasSubNodes())
{
return next.getValue();
}
return ret;
}
else
{
return null;
}
}
return node;
}
protected static final SnmpNode findNext
(
SnmpNode node,
SnmpPathDispatch dispatch,
boolean exact
)
{
int pathIndex = dispatch.getCurrentPathIndex();
Integer req = dispatch.getCurrentPathOid();
Entry<Integer, SnmpNode> n = node.getSubNodeGte(dispatch);
//if we found only a bigger one
if(n != null)
{
if(n.getKey() > req)
{
return getDepthFirst
(
modifyDispatchFrom(dispatch, pathIndex, n.getKey(), pathIndex+1),
n.getValue()
);
}
}
SnmpNode next = null == n?null:n.getValue();
if(null == next)
{
return null;
}
//the very last node to dispatch that we found
if(dispatch.isInvalid())
{
if(next.hasSubNodes())
{
return getDepthFirst
(
modifyDispatchFrom(dispatch, pathIndex, n.getKey(), pathIndex+1),
//dispatch,
next
);
}
else
{
if(exact)
{
return next;
}
return findNext
(
node,
modifyDispatchFrom
(
dispatch,
pathIndex,
dispatch.oids[pathIndex]+1,
pathIndex
),
true
);
}
}
next = findNext(next, dispatch, false);
if(null == next)
{
return findNext
(
node,
modifyDispatchFrom
(
dispatch,
pathIndex,
dispatch.oids[pathIndex]+1,
pathIndex
),
true //TODO
);
}
return next;
}
@Override
public SortedMap<SnmpOid, AttributeAccessor> nextSet(SnmpOid oid)
{
int next = 30;
//a simple reuse method
SortedMap<SnmpOid, AttributeAccessor> ret = new TreeMap<>();
while(--next > 0)
{
AttributeAccessor req = next(oid);
if(null == req)
{
break;
}
oid = req.getOid();
ret.put(oid, req);
}
return ret;
}
}