| /* |
| * Copyright (c) 2000, 2006, 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.util.Vector; |
| import java.util.ArrayList; |
| import java.util.Hashtable; |
| import java.util.Enumeration; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.NoSuchElementException; |
| import java.util.Arrays; |
| import java.util.logging.Level; |
| |
| import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER; |
| import com.sun.jmx.snmp.SnmpVarBind; |
| import com.sun.jmx.snmp.SnmpStatusException; |
| import com.sun.jmx.snmp.SnmpDefinitions; |
| import com.sun.jmx.snmp.SnmpOid; |
| import com.sun.jmx.snmp.SnmpPdu; |
| import com.sun.jmx.snmp.SnmpEngine; |
| |
| // XXX: things to do: use SnmpOid rather than `instance' for future |
| // evolutions. |
| // XXX: Maybe use hashlists rather than vectors for entries? |
| // => in that case, the key should be SnmpOid.toString() |
| // |
| /** |
| * This class is used to register varbinds from a SNMP varbind list with |
| * the SnmpMibNode responsible for handling the requests concerning that |
| * varbind. |
| * This class holds a hashtable of Handler nodes, whith the involved |
| * SnmpMibNode as a key. |
| * When the involved SnmpMibNode is a group, the sublist of varbind is |
| * directly stored in the Handler node. |
| * When the involved SnmpMibNode is a table, the sublist is stored in a |
| * sorted array indexed by the OID of the entry involved. |
| */ |
| final class SnmpRequestTree { |
| |
| // Constructor: |
| // @param req The SnmpMibRequest that will be segmented in this |
| // tree. It holds the original varbind vector passed |
| // by the SnmpSubRequestHandler to this MIB. This |
| // varbind vector is used to retrieve the "real" |
| // position of a varbind in the vector. There is no other easy |
| // way to do this - since as a result of the segmentation the |
| // original positions will be lost. |
| // @param creationflag indicates whether the operation involved |
| // allows for entry creation (ie: it is a SET request). |
| // @param pdutype indicates the type of the request PDU as defined |
| // in SnmpDefinitions |
| // |
| SnmpRequestTree(SnmpMibRequest req, boolean creationflag, int pdutype) { |
| this.request = req; |
| this.version = req.getVersion(); |
| this.creationflag = creationflag; |
| this.hashtable = new Hashtable<Object, Handler>(); |
| setPduType(pdutype); |
| } |
| |
| public static int mapSetException(int errorStatus, int version) |
| throws SnmpStatusException { |
| |
| final int errorCode = errorStatus; |
| |
| if (version == SnmpDefinitions.snmpVersionOne) |
| return errorCode; |
| |
| int mappedErrorCode = errorCode; |
| |
| // Now take care of V2 errorCodes that can be stored |
| // in the varbind itself: |
| if (errorCode == SnmpStatusException.noSuchObject) |
| // noSuchObject => notWritable |
| mappedErrorCode = SnmpStatusException.snmpRspNotWritable; |
| |
| else if (errorCode == SnmpStatusException.noSuchInstance) |
| // noSuchInstance => notWritable |
| mappedErrorCode = SnmpStatusException.snmpRspNotWritable; |
| |
| return mappedErrorCode; |
| } |
| |
| public static int mapGetException(int errorStatus, int version) |
| throws SnmpStatusException { |
| |
| final int errorCode = errorStatus; |
| if (version == SnmpDefinitions.snmpVersionOne) |
| return errorCode; |
| |
| int mappedErrorCode = errorCode; |
| |
| // Now take care of V2 errorCodes that can be stored |
| // in the varbind itself: |
| if (errorCode == |
| SnmpStatusException.noSuchObject) |
| // noSuchObject => noSuchObject |
| mappedErrorCode = errorCode; |
| |
| else if (errorCode == |
| SnmpStatusException.noSuchInstance) |
| // noSuchInstance => noSuchInstance |
| mappedErrorCode = errorCode; |
| |
| // Now we're going to try to transform every other |
| // global code in either noSuchInstance or noSuchObject, |
| // so that the get can return a partial result. |
| // |
| // Only noSuchInstance or noSuchObject can be stored |
| // in the varbind itself. |
| // |
| |
| // According to RFC 1905: noAccess is emitted when the |
| // the access is denied because it is not in the MIB view... |
| // |
| else if (errorCode == |
| SnmpStatusException.noAccess) |
| // noAccess => noSuchInstance |
| mappedErrorCode = SnmpStatusException.noSuchInstance; |
| |
| // According to RFC 1905: (my interpretation because it is not |
| // really clear) The specified variable name exists - but the |
| // variable does not exists and cannot be created under the |
| // present circumstances (probably because the request specifies |
| // another variable/value which is incompatible, or because the |
| // value of some other variable in the MIB prevents the creation) |
| // |
| // Note that this error should never be raised in a GET context |
| // but who knows? |
| // |
| else if (errorCode == SnmpStatusException.snmpRspInconsistentName) |
| // inconsistentName => noSuchInstance |
| mappedErrorCode = SnmpStatusException.noSuchInstance; |
| |
| // All the errors comprised between snmpRspWrongType and |
| // snmpRspInconsistentValue concern values: so we're going |
| // to assume the OID was correct, and reply with noSuchInstance. |
| // |
| // Note that this error should never be raised in a GET context |
| // but who knows? |
| // |
| else if ((errorCode >= SnmpStatusException.snmpRspWrongType) && |
| (errorCode <= SnmpStatusException.snmpRspInconsistentValue)) |
| mappedErrorCode = SnmpStatusException.noSuchInstance; |
| |
| // We're going to assume the OID was correct, and reply |
| // with noSuchInstance. |
| // |
| else if (errorCode == SnmpStatusException.readOnly) |
| mappedErrorCode = SnmpStatusException.noSuchInstance; |
| |
| // For all other errors but genErr, we're going to reply with |
| // noSuchObject |
| // |
| else if (errorCode != SnmpStatusException.snmpRspAuthorizationError && |
| errorCode != SnmpStatusException.snmpRspGenErr) |
| mappedErrorCode = SnmpStatusException.noSuchObject; |
| |
| // Only genErr will abort the GET and be returned as global |
| // error. |
| // |
| return mappedErrorCode; |
| |
| } |
| |
| //------------------------------------------------------------------- |
| // This class is a package implementation of the enumeration of |
| // SnmSubRequest associated with an Handler node. |
| //------------------------------------------------------------------- |
| |
| static final class Enum implements Enumeration { |
| Enum(SnmpRequestTree hlist,Handler h) { |
| handler = h; |
| this.hlist = hlist; |
| size = h.getSubReqCount(); |
| } |
| private final Handler handler; |
| private final SnmpRequestTree hlist; |
| private int entry = 0; |
| private int iter = 0; |
| private int size = 0; |
| |
| public boolean hasMoreElements() { |
| return iter < size; |
| } |
| |
| public Object nextElement() throws NoSuchElementException { |
| if (iter == 0) { |
| if (handler.sublist != null) { |
| iter++; |
| return hlist.getSubRequest(handler); |
| } |
| } |
| iter ++; |
| if (iter > size) throw new NoSuchElementException(); |
| Object result = hlist.getSubRequest(handler,entry); |
| entry++; |
| return result; |
| } |
| } |
| |
| //------------------------------------------------------------------- |
| // This class is a package implementation of the SnmpMibSubRequest |
| // interface. It can only be instantiated by SnmpRequestTree. |
| //------------------------------------------------------------------- |
| |
| static final class SnmpMibSubRequestImpl implements SnmpMibSubRequest { |
| SnmpMibSubRequestImpl(SnmpMibRequest global, Vector<SnmpVarBind> sublist, |
| SnmpOid entryoid, boolean isnew, |
| boolean getnextflag, SnmpVarBind rs) { |
| this.global = global; |
| varbinds = sublist; |
| this.version = global.getVersion(); |
| this.entryoid = entryoid; |
| this.isnew = isnew; |
| this.getnextflag = getnextflag; |
| this.statusvb = rs; |
| } |
| |
| final private Vector<SnmpVarBind> varbinds; |
| final private SnmpMibRequest global; |
| final private int version; |
| final private boolean isnew; |
| final private SnmpOid entryoid; |
| final private boolean getnextflag; |
| final private SnmpVarBind statusvb; |
| |
| // ------------------------------------------------------------- |
| // Implements the method defined in SnmpMibRequest interface. |
| // See SnmpMibRequest for the java doc. |
| // ------------------------------------------------------------- |
| public Enumeration getElements() { |
| return varbinds.elements(); |
| } |
| |
| // ------------------------------------------------------------- |
| // Implements the method defined in SnmpMibRequest interface. |
| // See SnmpMibRequest for the java doc. |
| // ------------------------------------------------------------- |
| public Vector<SnmpVarBind> getSubList() { |
| return varbinds; |
| } |
| |
| // ------------------------------------------------------------- |
| // Implements the method defined in SnmpMibRequest interface. |
| // See SnmpMibRequest for the java doc. |
| // ------------------------------------------------------------- |
| public final int getSize() { |
| if (varbinds == null) return 0; |
| return varbinds.size(); |
| } |
| |
| // ------------------------------------------------------------- |
| // Implements the method defined in SnmpMibRequest interface. |
| // See SnmpMibRequest for the java doc. |
| // ------------------------------------------------------------- |
| public void addVarBind(SnmpVarBind varbind) { |
| // XXX not sure we must also add the varbind in the global |
| // request? or whether we should raise an exception: |
| // in principle, this method should not be called! |
| varbinds.addElement(varbind); |
| global.addVarBind(varbind); |
| } |
| |
| // ------------------------------------------------------------- |
| // Implements the method defined in SnmpMibSubRequest interface. |
| // See SnmpMibSubRequest for the java doc. |
| // ------------------------------------------------------------- |
| public boolean isNewEntry() { |
| return isnew; |
| } |
| |
| // ------------------------------------------------------------- |
| // Implements the method defined in SnmpMibSubRequest interface. |
| // See SnmpMibSubRequest for the java doc. |
| // ------------------------------------------------------------- |
| public SnmpOid getEntryOid() { |
| return entryoid; |
| } |
| |
| // ------------------------------------------------------------- |
| // Implements the method defined in SnmpMibRequest interface. |
| // See SnmpMibRequest for the java doc. |
| // ------------------------------------------------------------- |
| public int getVarIndex(SnmpVarBind varbind) { |
| if (varbind == null) return 0; |
| return global.getVarIndex(varbind); |
| } |
| |
| // ------------------------------------------------------------- |
| // Implements the method defined in SnmpMibRequest interface. |
| // See SnmpMibRequest for the java doc. |
| // ------------------------------------------------------------- |
| public Object getUserData() { return global.getUserData(); } |
| |
| |
| // ------------------------------------------------------------- |
| // Implements the method defined in SnmpMibSubRequest interface. |
| // See SnmpMibSubRequest for the java doc. |
| // ------------------------------------------------------------- |
| |
| public void registerGetException(SnmpVarBind var, |
| SnmpStatusException exception) |
| throws SnmpStatusException { |
| // The index in the exception must correspond to |
| // the SNMP index ... |
| // |
| if (version == SnmpDefinitions.snmpVersionOne) |
| throw new SnmpStatusException(exception, getVarIndex(var)+1); |
| |
| if (var == null) |
| throw exception; |
| |
| // If we're doing a getnext ==> endOfMibView |
| if (getnextflag) { |
| var.value = SnmpVarBind.endOfMibView; |
| return; |
| } |
| |
| final int errorCode = mapGetException(exception.getStatus(), |
| version); |
| |
| // Now take care of V2 errorCodes that can be stored |
| // in the varbind itself: |
| if (errorCode == |
| SnmpStatusException.noSuchObject) |
| // noSuchObject => noSuchObject |
| var.value= SnmpVarBind.noSuchObject; |
| |
| else if (errorCode == |
| SnmpStatusException.noSuchInstance) |
| // noSuchInstance => noSuchInstance |
| var.value= SnmpVarBind.noSuchInstance; |
| |
| else |
| throw new SnmpStatusException(errorCode, getVarIndex(var)+1); |
| |
| } |
| |
| // ------------------------------------------------------------- |
| // Implements the method defined in SnmpMibSubRequest interface. |
| // See SnmpMibSubRequest for the java doc. |
| // ------------------------------------------------------------- |
| public void registerSetException(SnmpVarBind var, |
| SnmpStatusException exception) |
| throws SnmpStatusException { |
| // The index in the exception must correspond to |
| // the SNMP index ... |
| // |
| if (version == SnmpDefinitions.snmpVersionOne) |
| throw new SnmpStatusException(exception, getVarIndex(var)+1); |
| |
| // Although the first pass of check() did not fail, |
| // the set() phase could not be carried out correctly. |
| // Since we don't know how to make an "undo", and some |
| // assignation may already have been performed, we're going |
| // to throw an snmpRspUndoFailed. |
| // |
| throw new SnmpStatusException(SnmpDefinitions.snmpRspUndoFailed, |
| getVarIndex(var)+1); |
| } |
| |
| // ------------------------------------------------------------- |
| // Implements the method defined in SnmpMibSubRequest interface. |
| // See SnmpMibSubRequest for the java doc. |
| // ------------------------------------------------------------- |
| public void registerCheckException(SnmpVarBind var, |
| SnmpStatusException exception) |
| throws SnmpStatusException { |
| // The index in the exception must correspond to |
| // the SNMP index ... |
| // |
| // We throw the exception in order to abort the SET operation |
| // in an atomic way. |
| final int errorCode = exception.getStatus(); |
| final int mappedErrorCode = mapSetException(errorCode, |
| version); |
| |
| if (errorCode != mappedErrorCode) |
| throw new |
| SnmpStatusException(mappedErrorCode, getVarIndex(var)+1); |
| else |
| throw new SnmpStatusException(exception, getVarIndex(var)+1); |
| } |
| |
| // ------------------------------------------------------------- |
| // Implements the method defined in SnmpMibRequest interface. |
| // See SnmpMibRequest for the java doc. |
| // ------------------------------------------------------------- |
| public int getVersion() { |
| return version; |
| } |
| |
| public SnmpVarBind getRowStatusVarBind() { |
| return statusvb; |
| } |
| |
| public SnmpPdu getPdu() { |
| return global.getPdu(); |
| } |
| |
| public int getRequestPduVersion() { |
| return global.getRequestPduVersion(); |
| } |
| |
| public SnmpEngine getEngine() { |
| return global.getEngine(); |
| } |
| |
| public String getPrincipal() { |
| return global.getPrincipal(); |
| } |
| |
| public int getSecurityLevel() { |
| return global.getSecurityLevel(); |
| } |
| |
| public int getSecurityModel() { |
| return global.getSecurityModel(); |
| } |
| |
| public byte[] getContextName() { |
| return global.getContextName(); |
| } |
| |
| public byte[] getAccessContextName() { |
| return global.getAccessContextName(); |
| } |
| } |
| |
| //------------------------------------------------------------------- |
| // This class implements a node in the SnmpRequestTree. |
| // It stores: |
| // o The SnmpMibNode involved (key) |
| // o The sublist of varbind directly handled by this node |
| // o A vector of sublists concerning the entries (existing or not) |
| // of the SnmpMIbNode (when it is a table). |
| //------------------------------------------------------------------- |
| |
| static final class Handler { |
| SnmpMibNode meta; // The meta which handles the sublist. |
| int depth; // The depth of the meta node. |
| Vector<SnmpVarBind> sublist; // The sublist of varbinds to be handled. |
| // List entryoids; // Sorted array of entry oids |
| // List entrylists; // Sorted array of entry lists |
| // List isentrynew; // Sorted array of booleans |
| SnmpOid[] entryoids = null; // Sorted array of entry oids |
| Vector<SnmpVarBind>[] entrylists = null; // Sorted array of entry lists |
| boolean[] isentrynew = null; // Sorted array of booleans |
| SnmpVarBind[] rowstatus = null; // RowStatus varbind, if any |
| int entrycount = 0; |
| int entrysize = 0; |
| |
| final int type; // request PDU type as defined in SnmpDefinitions |
| final private static int Delta = 10; |
| |
| public Handler(int pduType) { |
| this.type = pduType; |
| } |
| |
| /** |
| * Adds a varbind in this node sublist. |
| */ |
| public void addVarbind(SnmpVarBind varbind) { |
| if (sublist == null) sublist = new Vector<SnmpVarBind>(); |
| sublist.addElement(varbind); |
| } |
| |
| /** |
| * register an entry for the given oid at the given position with |
| * the given sublist. |
| */ |
| @SuppressWarnings("unchecked") |
| // We need this because of new Vector[n] instead of |
| // new Vector<SnmpVarBind>[n], which is illegal. |
| void add(int pos,SnmpOid oid, Vector<SnmpVarBind> v, boolean isnew, |
| SnmpVarBind statusvb) { |
| |
| if (entryoids == null) { |
| // Vectors are null: Allocate new vectors |
| |
| entryoids = new SnmpOid[Delta]; |
| entrylists = new Vector[Delta]; |
| isentrynew = new boolean[Delta]; |
| rowstatus = new SnmpVarBind[Delta]; |
| entrysize = Delta; |
| pos = 0; |
| |
| } else if (pos >= entrysize || entrycount == entrysize) { |
| // Vectors must be enlarged |
| |
| // Save old vectors |
| SnmpOid[] olde = entryoids; |
| Vector[] oldl = entrylists; |
| boolean[] oldn = isentrynew; |
| SnmpVarBind[] oldr = rowstatus; |
| |
| // Allocate larger vectors |
| entrysize += Delta; |
| entryoids = new SnmpOid[entrysize]; |
| entrylists = new Vector[entrysize]; |
| isentrynew = new boolean[entrysize]; |
| rowstatus = new SnmpVarBind[entrysize]; |
| |
| // Check pos validity |
| if (pos > entrycount) pos = entrycount; |
| if (pos < 0) pos = 0; |
| |
| final int l1 = pos; |
| final int l2 = entrycount - pos; |
| |
| // Copy original vectors up to `pos' |
| if (l1 > 0) { |
| java.lang.System.arraycopy(olde,0,entryoids, |
| 0,l1); |
| java.lang.System.arraycopy(oldl,0,entrylists, |
| 0,l1); |
| java.lang.System.arraycopy(oldn,0,isentrynew, |
| 0,l1); |
| java.lang.System.arraycopy(oldr,0,rowstatus, |
| 0,l1); |
| } |
| |
| // Copy original vectors from `pos' to end, leaving |
| // an empty room at `pos' in the new vectors. |
| if (l2 > 0) { |
| final int l3 = l1+1; |
| java.lang.System.arraycopy(olde,l1,entryoids, |
| l3,l2); |
| java.lang.System.arraycopy(oldl,l1,entrylists, |
| l3,l2); |
| java.lang.System.arraycopy(oldn,l1,isentrynew, |
| l3,l2); |
| java.lang.System.arraycopy(oldr,l1,rowstatus, |
| l3,l2); |
| } |
| |
| |
| } else if (pos < entrycount) { |
| // Vectors are large enough to accomodate one additional |
| // entry. |
| // |
| // Shift vectors, making an empty room at `pos' |
| final int l1 = pos+1; |
| final int l2 = entrycount - pos; |
| |
| java.lang.System.arraycopy(entryoids,pos,entryoids, |
| l1,l2); |
| java.lang.System.arraycopy(entrylists,pos,entrylists, |
| l1,l2); |
| java.lang.System.arraycopy(isentrynew,pos,isentrynew, |
| l1,l2); |
| java.lang.System.arraycopy(rowstatus,pos,rowstatus, |
| l1,l2); |
| } |
| |
| // Fill the gap at `pos' |
| entryoids[pos] = oid; |
| entrylists[pos] = v; |
| isentrynew[pos] = isnew; |
| rowstatus[pos] = statusvb; |
| entrycount++; |
| } |
| |
| public void addVarbind(SnmpVarBind varbind, SnmpOid entryoid, |
| boolean isnew, SnmpVarBind statusvb) |
| throws SnmpStatusException { |
| Vector<SnmpVarBind> v = null; |
| SnmpVarBind rs = statusvb; |
| |
| if (entryoids == null) { |
| // entryoids = new ArrayList(); |
| // entrylists = new ArrayList(); |
| // isentrynew = new ArrayList(); |
| v = new Vector<SnmpVarBind>(); |
| // entryoids.add(entryoid); |
| // entrylists.add(v); |
| // isentrynew.add(new Boolean(isnew)); |
| add(0,entryoid,v,isnew,rs); |
| } else { |
| // int pos = findOid(entryoids,entryoid); |
| // int pos = findOid(entryoids,entrycount,entryoid); |
| final int pos = |
| getInsertionPoint(entryoids,entrycount,entryoid); |
| if (pos > -1 && pos < entrycount && |
| entryoid.compareTo(entryoids[pos]) == 0) { |
| v = entrylists[pos]; |
| rs = rowstatus[pos]; |
| } else { |
| // if (pos == -1 || pos >= entryoids.size() ) { |
| // if (pos == -1 || pos >= entrycount ) { |
| // pos = getInsertionPoint(entryoids,entryoid); |
| // pos = getInsertionPoint(entryoids,entrycount,entryoid); |
| v = new Vector<SnmpVarBind>(); |
| // entryoids.add(pos,entryoid); |
| // entrylists.add(pos,v); |
| // isentrynew.add(pos,new Boolean(isnew)); |
| add(pos,entryoid,v,isnew,rs); |
| } |
| // } else v = (Vector) entrylists.get(pos); |
| // } else v = entrylists[pos]; |
| if (statusvb != null) { |
| if ((rs != null) && (rs != statusvb) && |
| ((type == SnmpDefinitions.pduWalkRequest) || |
| (type == SnmpDefinitions.pduSetRequestPdu))) { |
| throw new SnmpStatusException( |
| SnmpStatusException.snmpRspInconsistentValue); |
| } |
| rowstatus[pos] = statusvb; |
| } |
| } |
| |
| // We do not include the status variable in the varbind, |
| // because we're going to set it separately... |
| // |
| if (statusvb != varbind) |
| v.addElement(varbind); |
| } |
| |
| public int getSubReqCount() { |
| int count = 0; |
| if (sublist != null) count++; |
| // if (entryoids != null) count += entryoids.size(); |
| if (entryoids != null) count += entrycount; |
| return count; |
| } |
| |
| public Vector<SnmpVarBind> getSubList() { |
| return sublist; |
| } |
| |
| public int getEntryPos(SnmpOid entryoid) { |
| // return findOid(entryoids,entryoid); |
| return findOid(entryoids,entrycount,entryoid); |
| } |
| |
| public SnmpOid getEntryOid(int pos) { |
| if (entryoids == null) return null; |
| // if (pos == -1 || pos >= entryoids.size() ) return null; |
| if (pos == -1 || pos >= entrycount ) return null; |
| // return (SnmpOid) entryoids.get(pos); |
| return entryoids[pos]; |
| } |
| |
| public boolean isNewEntry(int pos) { |
| if (entryoids == null) return false; |
| // if (pos == -1 || pos >= entryoids.size() ) return false; |
| if (pos == -1 || pos >= entrycount ) return false; |
| // return ((Boolean)isentrynew.get(pos)).booleanValue(); |
| return isentrynew[pos]; |
| } |
| |
| public SnmpVarBind getRowStatusVarBind(int pos) { |
| if (entryoids == null) return null; |
| // if (pos == -1 || pos >= entryoids.size() ) return false; |
| if (pos == -1 || pos >= entrycount ) return null; |
| // return ((Boolean)isentrynew.get(pos)).booleanValue(); |
| return rowstatus[pos]; |
| } |
| |
| public Vector<SnmpVarBind> getEntrySubList(int pos) { |
| if (entrylists == null) return null; |
| // if (pos == -1 || pos >= entrylists.size() ) return null; |
| if (pos == -1 || pos >= entrycount ) return null; |
| // return (Vector) entrylists.get(pos); |
| return entrylists[pos]; |
| } |
| |
| public Iterator<SnmpOid> getEntryOids() { |
| if (entryoids == null) return null; |
| // return entryoids.iterator(); |
| return Arrays.asList(entryoids).iterator(); |
| } |
| |
| public int getEntryCount() { |
| if (entryoids == null) return 0; |
| // return entryoids.size(); |
| return entrycount; |
| } |
| |
| } |
| |
| |
| //------------------------------------------------------------------- |
| //------------------------------------------------------------------- |
| // Public interface |
| //------------------------------------------------------------------- |
| //------------------------------------------------------------------- |
| |
| //------------------------------------------------------------------- |
| // Returns the contextual object containing user-data allocated |
| // through the SnmpUserDataFactory for this request. |
| //------------------------------------------------------------------- |
| |
| public Object getUserData() { return request.getUserData(); } |
| |
| //------------------------------------------------------------------- |
| // Tells whether creation of new entries is allowed with respect |
| // to the operation involved (GET=>false/SET=>true) |
| //------------------------------------------------------------------- |
| |
| public boolean isCreationAllowed() { |
| return creationflag; |
| } |
| |
| //------------------------------------------------------------------- |
| // Tells whether we are currently processing a SET request (check/set) |
| //------------------------------------------------------------------- |
| |
| public boolean isSetRequest() { |
| return setreqflag; |
| } |
| |
| //------------------------------------------------------------------- |
| // Returns the protocol version in which the original request is |
| // evaluated. |
| //------------------------------------------------------------------- |
| |
| public int getVersion() { |
| return version; |
| } |
| |
| //------------------------------------------------------------------- |
| // Returns the actual protocol version of the request PDU. |
| //------------------------------------------------------------------- |
| |
| public int getRequestPduVersion() { |
| return request.getRequestPduVersion(); |
| } |
| |
| //------------------------------------------------------------------- |
| // Returns the SnmpMibNode associated with the given handler |
| //------------------------------------------------------------------- |
| |
| public SnmpMibNode getMetaNode(Handler handler) { |
| return handler.meta; |
| } |
| |
| //------------------------------------------------------------------- |
| // Indicates the depth of the arc in the OID that identifies the |
| // SnmpMibNode associated with the given handler |
| //------------------------------------------------------------------- |
| |
| public int getOidDepth(Handler handler) { |
| return handler.depth; |
| } |
| |
| //------------------------------------------------------------------- |
| // returns an enumeration of the SnmpMibSubRequest's to be invoked on |
| // the SnmpMibNode associated with a given Handler node. |
| // If this node is a group, there will be a single subrequest. |
| // If it is a table, there will be one subrequest per entry involved. |
| //------------------------------------------------------------------- |
| |
| public Enumeration getSubRequests(Handler handler) { |
| return new Enum(this,handler); |
| } |
| |
| //------------------------------------------------------------------- |
| // returns an enumeration of the Handlers stored in the Hashtable. |
| //------------------------------------------------------------------- |
| |
| public Enumeration getHandlers() { |
| return hashtable.elements(); |
| } |
| |
| //------------------------------------------------------------------- |
| // adds a varbind to a handler node sublist |
| //------------------------------------------------------------------- |
| |
| public void add(SnmpMibNode meta, int depth, SnmpVarBind varbind) |
| throws SnmpStatusException { |
| registerNode(meta,depth,null,varbind,false,null); |
| } |
| |
| //------------------------------------------------------------------- |
| // adds an entry varbind to a handler node sublist |
| //------------------------------------------------------------------- |
| |
| public void add(SnmpMibNode meta, int depth, SnmpOid entryoid, |
| SnmpVarBind varbind, boolean isnew) |
| throws SnmpStatusException { |
| registerNode(meta,depth,entryoid,varbind,isnew,null); |
| } |
| |
| //------------------------------------------------------------------- |
| // adds an entry varbind to a handler node sublist - specifying the |
| // varbind which holds the row status |
| //------------------------------------------------------------------- |
| |
| public void add(SnmpMibNode meta, int depth, SnmpOid entryoid, |
| SnmpVarBind varbind, boolean isnew, |
| SnmpVarBind statusvb) |
| throws SnmpStatusException { |
| registerNode(meta,depth,entryoid,varbind,isnew,statusvb); |
| } |
| |
| |
| //------------------------------------------------------------------- |
| //------------------------------------------------------------------- |
| // Protected interface |
| //------------------------------------------------------------------- |
| //------------------------------------------------------------------- |
| |
| //------------------------------------------------------------------- |
| // Type of the request (see SnmpDefinitions) |
| //------------------------------------------------------------------- |
| |
| void setPduType(int pduType) { |
| type = pduType; |
| setreqflag = ((pduType == SnmpDefinitions.pduWalkRequest) || |
| (pduType == SnmpDefinitions.pduSetRequestPdu)); |
| } |
| |
| //------------------------------------------------------------------- |
| // We deal with a GET-NEXT request |
| //------------------------------------------------------------------- |
| |
| void setGetNextFlag() { |
| getnextflag = true; |
| } |
| |
| //------------------------------------------------------------------- |
| // Tell whether creation is allowed. |
| //------------------------------------------------------------------- |
| void switchCreationFlag(boolean flag) { |
| creationflag = flag; |
| } |
| |
| |
| //------------------------------------------------------------------- |
| // Returns the subrequest handled by the SnmpMibNode itself |
| // (in principle, only for Groups) |
| //------------------------------------------------------------------- |
| |
| SnmpMibSubRequest getSubRequest(Handler handler) { |
| if (handler == null) return null; |
| return new SnmpMibSubRequestImpl(request,handler.getSubList(), |
| null,false,getnextflag,null); |
| } |
| |
| //------------------------------------------------------------------- |
| // Returns the subrequest associated with the entry identified by |
| // the given entry (only for tables) |
| //------------------------------------------------------------------- |
| |
| SnmpMibSubRequest getSubRequest(Handler handler, SnmpOid oid) { |
| if (handler == null) return null; |
| final int pos = handler.getEntryPos(oid); |
| if (pos == -1) return null; |
| return new SnmpMibSubRequestImpl(request, |
| handler.getEntrySubList(pos), |
| handler.getEntryOid(pos), |
| handler.isNewEntry(pos), |
| getnextflag, |
| handler.getRowStatusVarBind(pos)); |
| } |
| |
| //------------------------------------------------------------------- |
| // Returns the subrequest associated with the entry identified by |
| // the given entry (only for tables). The `entry' parameter is an |
| // index relative to the position of the entry in the handler sublist. |
| //------------------------------------------------------------------- |
| |
| SnmpMibSubRequest getSubRequest(Handler handler, int entry) { |
| if (handler == null) return null; |
| return new |
| SnmpMibSubRequestImpl(request,handler.getEntrySubList(entry), |
| handler.getEntryOid(entry), |
| handler.isNewEntry(entry),getnextflag, |
| handler.getRowStatusVarBind(entry)); |
| } |
| |
| //------------------------------------------------------------------- |
| //------------------------------------------------------------------- |
| // Private section |
| //------------------------------------------------------------------- |
| //------------------------------------------------------------------- |
| |
| |
| //------------------------------------------------------------------- |
| // stores a handler node in the Hashtable |
| //------------------------------------------------------------------- |
| |
| private void put(Object key, Handler handler) { |
| if (handler == null) return; |
| if (key == null) return; |
| if (hashtable == null) hashtable = new Hashtable<Object, Handler>(); |
| hashtable.put(key,handler); |
| } |
| |
| //------------------------------------------------------------------- |
| // finds a handler node in the Hashtable |
| //------------------------------------------------------------------- |
| |
| private Handler get(Object key) { |
| if (key == null) return null; |
| if (hashtable == null) return null; |
| return hashtable.get(key); |
| } |
| |
| //------------------------------------------------------------------- |
| // Search for the given oid in `oids'. If none is found, returns -1 |
| // otherwise, returns the index at which the oid is located. |
| //------------------------------------------------------------------- |
| |
| private static int findOid(SnmpOid[] oids, int count, SnmpOid oid) { |
| final int size = count; |
| int low= 0; |
| int max= size - 1; |
| int curr= low + (max-low)/2; |
| //System.out.println("Try to retrieve: " + oid.toString()); |
| while (low <= max) { |
| |
| final SnmpOid pos = oids[curr]; |
| |
| //System.out.println("Compare with" + pos.toString()); |
| // never know ...we might find something ... |
| // |
| final int comp = oid.compareTo(pos); |
| if (comp == 0) |
| return curr; |
| |
| if (oid.equals(pos)) { |
| return curr; |
| } |
| if (comp > 0) { |
| low = curr + 1; |
| } else { |
| max = curr - 1; |
| } |
| curr = low + (max-low)/2; |
| } |
| return -1; |
| } |
| |
| //------------------------------------------------------------------- |
| // Return the index at which the given oid should be inserted in the |
| // `oids' array. |
| //------------------------------------------------------------------- |
| |
| private static int getInsertionPoint(SnmpOid[] oids, int count, |
| SnmpOid oid) { |
| final SnmpOid[] localoids = oids; |
| final int size = count; |
| int low= 0; |
| int max= size - 1; |
| int curr= low + (max-low)/2; |
| |
| |
| while (low <= max) { |
| |
| final SnmpOid pos = localoids[curr]; |
| |
| // never know ...we might find something ... |
| // |
| final int comp= oid.compareTo(pos); |
| |
| // In the calling method we will have to check for this case... |
| // if (comp == 0) |
| // return -1; |
| // Returning curr instead of -1 avoids having to call |
| // findOid() first and getInsertionPoint() afterwards. |
| // We can simply call getInsertionPoint() and then checks whether |
| // there's an OID at the returned position which equals the |
| // given OID. |
| if (comp == 0) |
| return curr; |
| |
| if (comp>0) { |
| low= curr +1; |
| } else { |
| max= curr -1; |
| } |
| curr= low + (max-low)/2; |
| } |
| return curr; |
| } |
| |
| //------------------------------------------------------------------- |
| // adds a varbind in a handler node sublist |
| //------------------------------------------------------------------- |
| |
| private void registerNode(SnmpMibNode meta, int depth, SnmpOid entryoid, |
| SnmpVarBind varbind, boolean isnew, |
| SnmpVarBind statusvb) |
| throws SnmpStatusException { |
| if (meta == null) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, |
| SnmpRequestTree.class.getName(), |
| "registerNode", "meta-node is null!"); |
| return; |
| } |
| if (varbind == null) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, |
| SnmpRequestTree.class.getName(), |
| "registerNode", "varbind is null!"); |
| return ; |
| } |
| |
| final Object key = meta; |
| |
| // retrieve the handler node associated with the given meta, |
| // if any |
| Handler handler = get(key); |
| |
| // If no handler node was found for that meta, create one. |
| if (handler == null) { |
| // if (isDebugOn()) |
| // debug("registerNode", "adding node for " + |
| // varbind.oid.toString()); |
| handler = new Handler(type); |
| handler.meta = meta; |
| handler.depth = depth; |
| put(key,handler); |
| } |
| // else { |
| // if (isDebugOn()) |
| // debug("registerNode","found node for " + |
| // varbind.oid.toString()); |
| // } |
| |
| // Adds the varbind in the handler node's sublist. |
| if (entryoid == null) |
| handler.addVarbind(varbind); |
| else |
| handler.addVarbind(varbind,entryoid,isnew,statusvb); |
| return ; |
| } |
| |
| |
| //------------------------------------------------------------------- |
| // private variables |
| //------------------------------------------------------------------- |
| |
| private Hashtable<Object, Handler> hashtable = null; |
| // Hashtable of Handler objects |
| private SnmpMibRequest request = null; // The original list of varbinds |
| private int version = 0; // The protocol version |
| private boolean creationflag = false; // Does the operation allow |
| // creation of entries |
| private boolean getnextflag = false; // Does the operation allow |
| // creation of entries |
| private int type = 0; // Request PDU type as defined |
| // in SnmpDefinitions |
| private boolean setreqflag = false; // True if we're processing a |
| // SET request (check/set). |
| } |