blob: 52b952e2734f3949199c097665f83ec57dfb8e2b [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26
27package com.sun.jmx.snmp.agent;
28
29
30
31// java imports
32//
33import java.io.Serializable;
34import java.util.Vector;
35import java.util.Hashtable;
36import java.util.Enumeration;
37
38// jmx imports
39//
40import com.sun.jmx.snmp.SnmpOid;
41import com.sun.jmx.snmp.SnmpValue;
42import com.sun.jmx.snmp.SnmpVarBind;
43import com.sun.jmx.snmp.SnmpDefinitions;
44import 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
57public 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 noSuchObjectException;
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 noSuchObjectException;
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 noSuchObjectException;
351
352 int low= 0;
353 int max= a.length;
354 int curr= low + (max-low)/2;
355 int elmt= 0;
356
357 // Basic check
358 //
359 if (max < 1)
360 throw noSuchObjectException;
361
362 if (a[max-1] <= val)
363 throw noSuchObjectException;
364
365 while (low <= max) {
366 elmt= a[curr];
367 if (val == elmt) {
368 // We ned to get the next index ...
369 //
370 curr++;
371 return a[curr];
372 }
373 if (elmt < val) {
374 low= curr +1;
375 } else {
376 max= curr -1;
377 }
378 curr= low + (max-low)/2;
379 }
380 return a[curr];
381 }
382
383
384 //----------------------------------------------------------------------
385 // PRIVATE METHODS
386 //----------------------------------------------------------------------
387
388 final static private void swap(int a[], int i, int j) {
389 int T;
390 T = a[i];
391 a[i] = a[j];
392 a[j] = T;
393 }
394
395 //----------------------------------------------------------------------
396 // PROTECTED VARIABLES
397 //----------------------------------------------------------------------
398
399 /**
400 * Contains the list of variable identifiers.
401 */
402 protected int[] varList;
403
404 /**
405 * Contains a predefined exception that is often fired when an
406 * object is not found in the MIB.
407 */
408 static final protected SnmpStatusException noSuchInstanceException =
409 new SnmpStatusException(SnmpStatusException.noSuchInstance);
410 static final protected SnmpStatusException noSuchObjectException =
411 new SnmpStatusException(SnmpStatusException.noSuchObject);
412 static final protected SnmpStatusException noSuchNameException =
413 new SnmpStatusException(SnmpDefinitions.snmpRspNoSuchName);
414}