1 /* 2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 27 package com.sun.jmx.snmp.agent; 28 29 30 31 // java imports 32 // 33 import java.io.Serializable; 34 import java.util.Vector; 35 import java.util.Hashtable; 36 import java.util.Enumeration; 37 38 // jmx imports 39 // 40 import com.sun.jmx.snmp.SnmpOid; 41 import com.sun.jmx.snmp.SnmpValue; 42 import com.sun.jmx.snmp.SnmpVarBind; 43 import com.sun.jmx.snmp.SnmpDefinitions; 44 import com.sun.jmx.snmp.SnmpStatusException; 45 46 /** 47 * The <CODE>SnmpMibNode</CODE> class represents a node in an SNMP MIB. 48 * <P> 49 * This class is used internally and by the class generated by 50 * <CODE>mibgen</CODE>. 51 * You should not need to use this class directly. 52 * 53 * <p><b>This API is a Sun Microsystems internal API and is subject 54 * to change without notice.</b></p> 55 */ 56 @SuppressWarnings("serial") // JDK implementation class 57 public abstract class SnmpMibNode implements Serializable { 58 59 // --------------------------------------------------------------------- 60 // PUBLIC METHODS 61 //---------------------------------------------------------------------- 62 63 /** 64 * Get the next OID arc corresponding to a readable scalar variable, 65 * a branch leading to a subgroub, or a table. 66 * 67 * @param id Id we start from looking for the next. 68 * @param userData A contextual object containing user-data. 69 * This object is allocated through the <code> 70 * {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}</code> 71 * for each incoming SNMP request. 72 * 73 * @return The next id in this group. 74 * 75 * @exception SnmpStatusException If no id is found after the given id. 76 */ 77 public long getNextVarId(long id, Object userData) 78 throws SnmpStatusException { 79 return getNextIdentifier(varList,id); 80 } 81 82 /** 83 * Get the next OID arc corresponding to a readable scalar variable, 84 * a branch leading to a subgroub, or a table, possibly skipping over 85 * those arcs that must not or cannot be returned. 86 * 87 * Calls {@link #getNextVarId(long,java.lang.Object)} until 88 * {@link #skipVariable(long,java.lang.Object,int)} returns false. 89 * 90 * @param id Id we start from looking for the next. 91 * @param userData A contextual object containing user-data. 92 * This object is allocated through the <code> 93 * {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}</code> 94 * for each incoming SNMP request. 95 * @param pduVersion Protocol version of the original request PDU. 96 * 97 * @return The next id in this group which can be returned using 98 * the given PDU's protocol version. 99 * 100 * @exception SnmpStatusException If no id is found after the given id. 101 */ 102 public long getNextVarId(long id, Object userData, int pduVersion) 103 throws SnmpStatusException { 104 long varid=id; 105 do { 106 varid = getNextVarId(varid,userData); 107 } while (skipVariable(varid,userData,pduVersion)); 108 109 return varid; 110 } 111 112 /** 113 * Hook for subclasses. 114 * The default implementation of this method is to always return 115 * false. Subclasses should redefine this method so that it returns 116 * true when: 117 * <ul><li>the variable is a leaf that is not instantiated,</li> 118 * <li>or the variable is a leaf whose type cannot be returned by that 119 * version of the protocol (e.g. an Counter64 with SNMPv1).</li> 120 * </ul> 121 * 122 * @param id Id we start from looking for the next. 123 * @param userData A contextual object containing user-data. 124 * This object is allocated through the <code> 125 * {@link com.sun.jmx.snmp.agent.SnmpUserDataFactory}</code> 126 * for each incoming SNMP request. 127 * @param pduVersion Protocol version of the original request PDU. 128 * 129 * @return true if the variable must be skipped by the get-next 130 * algorithm. 131 */ 132 protected boolean skipVariable(long id, Object userData, int pduVersion) { 133 return false; 134 } 135 136 /** 137 * Find the node which handles a varbind, and register it in the 138 * SnmpRequestTree. This method is a pure internal method. You should 139 * never try to call it directly. 140 * 141 * @param varbind The varbind to be handled 142 * 143 * @param oid The OID array extracted from the varbind 144 * 145 * @param depth The depth reached in the OID at this step of the 146 * processing. 147 * 148 * @param handlers The Hashtable in which the varbind will be registered 149 * with its handling node. This hashtable contains 150 * <CODE>SnmpRequestTree.Handler</CODE> items. 151 * 152 * @exception SnmpStatusException No handling node was found. 153 **/ 154 void findHandlingNode(SnmpVarBind varbind, 155 long[] oid, int depth, 156 SnmpRequestTree handlers) 157 throws SnmpStatusException { 158 throw new SnmpStatusException(SnmpStatusException.noSuchObject); 159 } 160 161 /** 162 * Find the node which handles the leaf that immediately follows the 163 * given varbind OID, and register the it in the SnmpRequestTree. 164 * This method is a pure internal method. You should never try to call 165 * it directly. 166 * 167 * @param varbind The varbind to be handled 168 * 169 * @param oid The OID array extracted from the varbind 170 * 171 * @param depth The depth reached in the OID at this step of the 172 * processing. 173 * 174 * @param handlers The Hashtable in which the varbind will be registered 175 * with its handling node. This hashtable contains 176 * SnmpRequestTree.Handler items. 177 * 178 * @return The SnmpOid of the next leaf. 179 * 180 * @exception SnmpStatusException No handling node was found. 181 **/ 182 long[] findNextHandlingNode(SnmpVarBind varbind, 183 long[] oid, int pos, int depth, 184 SnmpRequestTree handlers, AcmChecker checker) 185 throws SnmpStatusException { 186 throw new SnmpStatusException(SnmpStatusException.noSuchObject); 187 } 188 189 /** 190 * Generic handling of the <CODE>get</CODE> operation. 191 * 192 * <p> You can override this method if you need to implement some 193 * specific policies for minimizing the accesses made to some remote 194 * underlying resources. 195 * <p> 196 * 197 * @param req The sub-request that must be handled by this node. 198 * 199 * @param depth The depth reached in the OID tree. 200 * 201 * @exception SnmpStatusException An error occurred while accessing 202 * the MIB node. 203 */ 204 public abstract void get(SnmpMibSubRequest req, int depth) 205 throws SnmpStatusException; 206 207 /** 208 * Generic handling of the <CODE>set</CODE> operation. 209 * <p> You can override this method if you need to implement some 210 * specific policies for minimizing the accesses made to some remote 211 * underlying resources. 212 * <p> 213 * 214 * @param req The sub-request that must be handled by this node. 215 * 216 * @param depth The depth reached in the OID tree. 217 * 218 * @exception SnmpStatusException An error occurred while accessing 219 * the MIB node. 220 */ 221 public abstract void set(SnmpMibSubRequest req, int depth) 222 throws SnmpStatusException; 223 224 /** 225 * Generic handling of the <CODE>check</CODE> operation. 226 * <p> You can override this method if you need to implement some 227 * specific policies for minimizing the accesses made to some remote 228 * underlying resources, or if you need to implement some consistency 229 * checks between the different values provided in the varbind list. 230 * <p> 231 * 232 * @param req The sub-request that must be handled by this node. 233 * 234 * @param depth The depth reached in the OID tree. 235 * 236 * @exception SnmpStatusException An error occurred while accessing 237 * the MIB node. 238 */ 239 public abstract void check(SnmpMibSubRequest req, int depth) 240 throws SnmpStatusException; 241 242 /** 243 * Sorts the specified integer array. 244 * 245 * @param array An integer array. 246 */ 247 static public void sort(int array[]) { 248 QuickSort(array, 0, array.length - 1); 249 } 250 251 /** 252 * Computes the root OID of the MIB. 253 */ 254 public void getRootOid(Vector<Integer> result) { 255 return; 256 } 257 258 //---------------------------------------------------------------------- 259 // PACKAGE METHODS 260 //---------------------------------------------------------------------- 261 262 /** 263 * This is a generic version of C.A.R Hoare's Quick Sort 264 * algorithm. This will handle arrays that are already 265 * sorted, and arrays with duplicate keys. 266 * 267 * If you think of a one dimensional array as going from 268 * the lowest index on the left to the highest index on the right 269 * then the parameters to this function are lowest index or 270 * left and highest index or right. The first time you call 271 * this function it will be with the parameters 0, a.length - 1. 272 * 273 * @param a An integer array. 274 * @param lo0 Left boundary of array partition. 275 * @param hi0 Right boundary of array partition. 276 */ 277 static void QuickSort(int a[], int lo0, int hi0) { 278 int lo = lo0; 279 int hi = hi0; 280 int mid; 281 282 if ( hi0 > lo0) { 283 284 /* Arbitrarily establishing partition element as the midpoint of 285 * the array. 286 */ 287 mid = a[ ( lo0 + hi0 ) / 2 ]; 288 289 // loop through the array until indices cross 290 while( lo <= hi ) { 291 /* find the first element that is greater than or equal to 292 * the partition element starting from the left Index. 293 */ 294 while( ( lo < hi0 ) && ( a[lo] < mid )) 295 ++lo; 296 297 /* find an element that is smaller than or equal to 298 * the partition element starting from the right Index. 299 */ 300 while( ( hi > lo0 ) && ( a[hi] > mid )) 301 --hi; 302 303 // if the indexes have not crossed, swap 304 if( lo <= hi ) { 305 swap(a, lo, hi); 306 ++lo; 307 --hi; 308 } 309 } 310 311 /* If the right index has not reached the left side of array 312 * must now sort the left partition. 313 */ 314 if( lo0 < hi ) 315 QuickSort( a, lo0, hi ); 316 317 /* If the left index has not reached the right side of array 318 * must now sort the right partition. 319 */ 320 if( lo < hi0 ) 321 QuickSort( a, lo, hi0 ); 322 323 } 324 } 325 326 //---------------------------------------------------------------------- 327 // PROTECTED METHODS 328 //---------------------------------------------------------------------- 329 330 /** 331 * This will give the first element greater than <CODE>value</CODE> 332 * in a sorted array. 333 * If there is no element of the array greater than <CODE>value</CODE>, 334 * the method will throw a <CODE>SnmpStatusException</CODE>. 335 * 336 * @param table A sorted integer array. 337 * 338 * @param value The greatest value. 339 * 340 * @exception SnmpStatusException If there is no element greater than 341 * <CODE>value</CODE>. 342 */ 343 final static protected int getNextIdentifier(int table[], long value) 344 throws SnmpStatusException { 345 346 final int[] a = table; 347 final int val= (int) value; 348 349 if (a == null) { 350 throw new SnmpStatusException(SnmpStatusException.noSuchObject); 351 } 352 353 int low= 0; 354 int max= a.length; 355 int curr= low + (max-low)/2; 356 int elmt= 0; 357 358 // Basic check 359 // 360 if (max < 1) { 361 throw new SnmpStatusException(SnmpStatusException.noSuchObject); 362 } 363 364 if (a[max-1] <= val) { 365 throw new SnmpStatusException(SnmpStatusException.noSuchObject); 366 } 367 368 while (low <= max) { 369 elmt= a[curr]; 370 if (val == elmt) { 371 // We ned to get the next index ... 372 // 373 curr++; 374 return a[curr]; 375 } 376 if (elmt < val) { 377 low= curr +1; 378 } else { 379 max= curr -1; 380 } 381 curr= low + (max-low)/2; 382 } 383 return a[curr]; 384 } 385 386 387 //---------------------------------------------------------------------- 388 // PRIVATE METHODS 389 //---------------------------------------------------------------------- 390 391 final static private void swap(int a[], int i, int j) { 392 int T; 393 T = a[i]; 394 a[i] = a[j]; 395 a[j] = T; 396 } 397 398 //---------------------------------------------------------------------- 399 // PROTECTED VARIABLES 400 //---------------------------------------------------------------------- 401 402 /** 403 * Contains the list of variable identifiers. 404 */ 405 protected int[] varList; 406 }