blob: 4699024649f7be63e17cf89cfdd43f5282a679ab [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2000-2006 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 */
25package com.sun.jmx.snmp.agent;
26
27import java.util.Vector;
28import java.util.ArrayList;
29import java.util.Hashtable;
30import java.util.Enumeration;
31import java.util.Iterator;
32import java.util.List;
33import java.util.NoSuchElementException;
34import java.util.Arrays;
35import java.util.logging.Level;
36
37import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER;
38import com.sun.jmx.snmp.SnmpVarBind;
39import com.sun.jmx.snmp.SnmpStatusException;
40import com.sun.jmx.snmp.SnmpDefinitions;
41import com.sun.jmx.snmp.SnmpOid;
42import com.sun.jmx.snmp.SnmpPdu;
43import com.sun.jmx.snmp.SnmpEngine;
44
45// XXX: things to do: use SnmpOid rather than `instance' for future
46// evolutions.
47// XXX: Maybe use hashlists rather than vectors for entries?
48// => in that case, the key should be SnmpOid.toString()
49//
50/**
51 * This class is used to register varbinds from a SNMP varbind list with
52 * the SnmpMibNode responsible for handling the requests concerning that
53 * varbind.
54 * This class holds a hashtable of Handler nodes, whith the involved
55 * SnmpMibNode as a key.
56 * When the involved SnmpMibNode is a group, the sublist of varbind is
57 * directly stored in the Handler node.
58 * When the involved SnmpMibNode is a table, the sublist is stored in a
59 * sorted array indexed by the OID of the entry involved.
60 */
61final class SnmpRequestTree {
62
63 // Constructor:
64 // @param req The SnmpMibRequest that will be segmented in this
65 // tree. It holds the original varbind vector passed
66 // by the SnmpSubRequestHandler to this MIB. This
67 // varbind vector is used to retrieve the "real"
68 // position of a varbind in the vector. There is no other easy
69 // way to do this - since as a result of the segmentation the
70 // original positions will be lost.
71 // @param creationflag indicates whether the operation involved
72 // allows for entry creation (ie: it is a SET request).
73 // @param pdutype indicates the type of the request PDU as defined
74 // in SnmpDefinitions
75 //
76 SnmpRequestTree(SnmpMibRequest req, boolean creationflag, int pdutype) {
77 this.request = req;
78 this.version = req.getVersion();
79 this.creationflag = creationflag;
80 this.hashtable = new Hashtable<Object, Handler>();
81 setPduType(pdutype);
82 }
83
84 public static int mapSetException(int errorStatus, int version)
85 throws SnmpStatusException {
86
87 final int errorCode = errorStatus;
88
89 if (version == SnmpDefinitions.snmpVersionOne)
90 return errorCode;
91
92 int mappedErrorCode = errorCode;
93
94 // Now take care of V2 errorCodes that can be stored
95 // in the varbind itself:
96 if (errorCode == SnmpStatusException.noSuchObject)
97 // noSuchObject => notWritable
98 mappedErrorCode = SnmpStatusException.snmpRspNotWritable;
99
100 else if (errorCode == SnmpStatusException.noSuchInstance)
101 // noSuchInstance => notWritable
102 mappedErrorCode = SnmpStatusException.snmpRspNotWritable;
103
104 return mappedErrorCode;
105 }
106
107 public static int mapGetException(int errorStatus, int version)
108 throws SnmpStatusException {
109
110 final int errorCode = errorStatus;
111 if (version == SnmpDefinitions.snmpVersionOne)
112 return errorCode;
113
114 int mappedErrorCode = errorCode;
115
116 // Now take care of V2 errorCodes that can be stored
117 // in the varbind itself:
118 if (errorCode ==
119 SnmpStatusException.noSuchObject)
120 // noSuchObject => noSuchObject
121 mappedErrorCode = errorCode;
122
123 else if (errorCode ==
124 SnmpStatusException.noSuchInstance)
125 // noSuchInstance => noSuchInstance
126 mappedErrorCode = errorCode;
127
128 // Now we're going to try to transform every other
129 // global code in either noSuchInstance or noSuchObject,
130 // so that the get can return a partial result.
131 //
132 // Only noSuchInstance or noSuchObject can be stored
133 // in the varbind itself.
134 //
135
136 // According to RFC 1905: noAccess is emitted when the
137 // the access is denied because it is not in the MIB view...
138 //
139 else if (errorCode ==
140 SnmpStatusException.noAccess)
141 // noAccess => noSuchInstance
142 mappedErrorCode = SnmpStatusException.noSuchInstance;
143
144 // According to RFC 1905: (my interpretation because it is not
145 // really clear) The specified variable name exists - but the
146 // variable does not exists and cannot be created under the
147 // present circumstances (probably because the request specifies
148 // another variable/value which is incompatible, or because the
149 // value of some other variable in the MIB prevents the creation)
150 //
151 // Note that this error should never be raised in a GET context
152 // but who knows?
153 //
154 else if (errorCode == SnmpStatusException.snmpRspInconsistentName)
155 // inconsistentName => noSuchInstance
156 mappedErrorCode = SnmpStatusException.noSuchInstance;
157
158 // All the errors comprised between snmpRspWrongType and
159 // snmpRspInconsistentValue concern values: so we're going
160 // to assume the OID was correct, and reply with noSuchInstance.
161 //
162 // Note that this error should never be raised in a GET context
163 // but who knows?
164 //
165 else if ((errorCode >= SnmpStatusException.snmpRspWrongType) &&
166 (errorCode <= SnmpStatusException.snmpRspInconsistentValue))
167 mappedErrorCode = SnmpStatusException.noSuchInstance;
168
169 // We're going to assume the OID was correct, and reply
170 // with noSuchInstance.
171 //
172 else if (errorCode == SnmpStatusException.readOnly)
173 mappedErrorCode = SnmpStatusException.noSuchInstance;
174
175 // For all other errors but genErr, we're going to reply with
176 // noSuchObject
177 //
178 else if (errorCode != SnmpStatusException.snmpRspAuthorizationError &&
179 errorCode != SnmpStatusException.snmpRspGenErr)
180 mappedErrorCode = SnmpStatusException.noSuchObject;
181
182 // Only genErr will abort the GET and be returned as global
183 // error.
184 //
185 return mappedErrorCode;
186
187 }
188
189 //-------------------------------------------------------------------
190 // This class is a package implementation of the enumeration of
191 // SnmSubRequest associated with an Handler node.
192 //-------------------------------------------------------------------
193
194 static final class Enum implements Enumeration {
195 Enum(SnmpRequestTree hlist,Handler h) {
196 handler = h;
197 this.hlist = hlist;
198 size = h.getSubReqCount();
199 }
200 private final Handler handler;
201 private final SnmpRequestTree hlist;
202 private int entry = 0;
203 private int iter = 0;
204 private int size = 0;
205
206 public boolean hasMoreElements() {
207 return iter < size;
208 }
209
210 public Object nextElement() throws NoSuchElementException {
211 if (iter == 0) {
212 if (handler.sublist != null) {
213 iter++;
214 return hlist.getSubRequest(handler);
215 }
216 }
217 iter ++;
218 if (iter > size) throw new NoSuchElementException();
219 Object result = hlist.getSubRequest(handler,entry);
220 entry++;
221 return result;
222 }
223 }
224
225 //-------------------------------------------------------------------
226 // This class is a package implementation of the SnmpMibSubRequest
227 // interface. It can only be instantiated by SnmpRequestTree.
228 //-------------------------------------------------------------------
229
230 static final class SnmpMibSubRequestImpl implements SnmpMibSubRequest {
231 SnmpMibSubRequestImpl(SnmpMibRequest global, Vector<SnmpVarBind> sublist,
232 SnmpOid entryoid, boolean isnew,
233 boolean getnextflag, SnmpVarBind rs) {
234 this.global = global;
235 varbinds = sublist;
236 this.version = global.getVersion();
237 this.entryoid = entryoid;
238 this.isnew = isnew;
239 this.getnextflag = getnextflag;
240 this.statusvb = rs;
241 }
242
243 final private Vector<SnmpVarBind> varbinds;
244 final private SnmpMibRequest global;
245 final private int version;
246 final private boolean isnew;
247 final private SnmpOid entryoid;
248 final private boolean getnextflag;
249 final private SnmpVarBind statusvb;
250
251 // -------------------------------------------------------------
252 // Implements the method defined in SnmpMibRequest interface.
253 // See SnmpMibRequest for the java doc.
254 // -------------------------------------------------------------
255 public Enumeration getElements() {
256 return varbinds.elements();
257 }
258
259 // -------------------------------------------------------------
260 // Implements the method defined in SnmpMibRequest interface.
261 // See SnmpMibRequest for the java doc.
262 // -------------------------------------------------------------
263 public Vector<SnmpVarBind> getSubList() {
264 return varbinds;
265 }
266
267 // -------------------------------------------------------------
268 // Implements the method defined in SnmpMibRequest interface.
269 // See SnmpMibRequest for the java doc.
270 // -------------------------------------------------------------
271 public final int getSize() {
272 if (varbinds == null) return 0;
273 return varbinds.size();
274 }
275
276 // -------------------------------------------------------------
277 // Implements the method defined in SnmpMibRequest interface.
278 // See SnmpMibRequest for the java doc.
279 // -------------------------------------------------------------
280 public void addVarBind(SnmpVarBind varbind) {
281 // XXX not sure we must also add the varbind in the global
282 // request? or whether we should raise an exception:
283 // in principle, this method should not be called!
284 varbinds.addElement(varbind);
285 global.addVarBind(varbind);
286 }
287
288 // -------------------------------------------------------------
289 // Implements the method defined in SnmpMibSubRequest interface.
290 // See SnmpMibSubRequest for the java doc.
291 // -------------------------------------------------------------
292 public boolean isNewEntry() {
293 return isnew;
294 }
295
296 // -------------------------------------------------------------
297 // Implements the method defined in SnmpMibSubRequest interface.
298 // See SnmpMibSubRequest for the java doc.
299 // -------------------------------------------------------------
300 public SnmpOid getEntryOid() {
301 return entryoid;
302 }
303
304 // -------------------------------------------------------------
305 // Implements the method defined in SnmpMibRequest interface.
306 // See SnmpMibRequest for the java doc.
307 // -------------------------------------------------------------
308 public int getVarIndex(SnmpVarBind varbind) {
309 if (varbind == null) return 0;
310 return global.getVarIndex(varbind);
311 }
312
313 // -------------------------------------------------------------
314 // Implements the method defined in SnmpMibRequest interface.
315 // See SnmpMibRequest for the java doc.
316 // -------------------------------------------------------------
317 public Object getUserData() { return global.getUserData(); }
318
319
320 // -------------------------------------------------------------
321 // Implements the method defined in SnmpMibSubRequest interface.
322 // See SnmpMibSubRequest for the java doc.
323 // -------------------------------------------------------------
324
325 public void registerGetException(SnmpVarBind var,
326 SnmpStatusException exception)
327 throws SnmpStatusException {
328 // The index in the exception must correspond to
329 // the SNMP index ...
330 //
331 if (version == SnmpDefinitions.snmpVersionOne)
332 throw new SnmpStatusException(exception, getVarIndex(var)+1);
333
334 if (var == null)
335 throw exception;
336
337 // If we're doing a getnext ==> endOfMibView
338 if (getnextflag) {
339 var.value = SnmpVarBind.endOfMibView;
340 return;
341 }
342
343 final int errorCode = mapGetException(exception.getStatus(),
344 version);
345
346 // Now take care of V2 errorCodes that can be stored
347 // in the varbind itself:
348 if (errorCode ==
349 SnmpStatusException.noSuchObject)
350 // noSuchObject => noSuchObject
351 var.value= SnmpVarBind.noSuchObject;
352
353 else if (errorCode ==
354 SnmpStatusException.noSuchInstance)
355 // noSuchInstance => noSuchInstance
356 var.value= SnmpVarBind.noSuchInstance;
357
358 else
359 throw new SnmpStatusException(errorCode, getVarIndex(var)+1);
360
361 }
362
363 // -------------------------------------------------------------
364 // Implements the method defined in SnmpMibSubRequest interface.
365 // See SnmpMibSubRequest for the java doc.
366 // -------------------------------------------------------------
367 public void registerSetException(SnmpVarBind var,
368 SnmpStatusException exception)
369 throws SnmpStatusException {
370 // The index in the exception must correspond to
371 // the SNMP index ...
372 //
373 if (version == SnmpDefinitions.snmpVersionOne)
374 throw new SnmpStatusException(exception, getVarIndex(var)+1);
375
376 // Although the first pass of check() did not fail,
377 // the set() phase could not be carried out correctly.
378 // Since we don't know how to make an "undo", and some
379 // assignation may already have been performed, we're going
380 // to throw an snmpRspUndoFailed.
381 //
382 throw new SnmpStatusException(SnmpDefinitions.snmpRspUndoFailed,
383 getVarIndex(var)+1);
384 }
385
386 // -------------------------------------------------------------
387 // Implements the method defined in SnmpMibSubRequest interface.
388 // See SnmpMibSubRequest for the java doc.
389 // -------------------------------------------------------------
390 public void registerCheckException(SnmpVarBind var,
391 SnmpStatusException exception)
392 throws SnmpStatusException {
393 // The index in the exception must correspond to
394 // the SNMP index ...
395 //
396 // We throw the exception in order to abort the SET operation
397 // in an atomic way.
398 final int errorCode = exception.getStatus();
399 final int mappedErrorCode = mapSetException(errorCode,
400 version);
401
402 if (errorCode != mappedErrorCode)
403 throw new
404 SnmpStatusException(mappedErrorCode, getVarIndex(var)+1);
405 else
406 throw new SnmpStatusException(exception, getVarIndex(var)+1);
407 }
408
409 // -------------------------------------------------------------
410 // Implements the method defined in SnmpMibRequest interface.
411 // See SnmpMibRequest for the java doc.
412 // -------------------------------------------------------------
413 public int getVersion() {
414 return version;
415 }
416
417 public SnmpVarBind getRowStatusVarBind() {
418 return statusvb;
419 }
420
421 public SnmpPdu getPdu() {
422 return global.getPdu();
423 }
424
425 public int getRequestPduVersion() {
426 return global.getRequestPduVersion();
427 }
428
429 public SnmpEngine getEngine() {
430 return global.getEngine();
431 }
432
433 public String getPrincipal() {
434 return global.getPrincipal();
435 }
436
437 public int getSecurityLevel() {
438 return global.getSecurityLevel();
439 }
440
441 public int getSecurityModel() {
442 return global.getSecurityModel();
443 }
444
445 public byte[] getContextName() {
446 return global.getContextName();
447 }
448
449 public byte[] getAccessContextName() {
450 return global.getAccessContextName();
451 }
452 }
453
454 //-------------------------------------------------------------------
455 // This class implements a node in the SnmpRequestTree.
456 // It stores:
457 // o The SnmpMibNode involved (key)
458 // o The sublist of varbind directly handled by this node
459 // o A vector of sublists concerning the entries (existing or not)
460 // of the SnmpMIbNode (when it is a table).
461 //-------------------------------------------------------------------
462
463 static final class Handler {
464 SnmpMibNode meta; // The meta which handles the sublist.
465 int depth; // The depth of the meta node.
466 Vector<SnmpVarBind> sublist; // The sublist of varbinds to be handled.
467 // List entryoids; // Sorted array of entry oids
468 // List entrylists; // Sorted array of entry lists
469 // List isentrynew; // Sorted array of booleans
470 SnmpOid[] entryoids = null; // Sorted array of entry oids
471 Vector<SnmpVarBind>[] entrylists = null; // Sorted array of entry lists
472 boolean[] isentrynew = null; // Sorted array of booleans
473 SnmpVarBind[] rowstatus = null; // RowStatus varbind, if any
474 int entrycount = 0;
475 int entrysize = 0;
476
477 final int type; // request PDU type as defined in SnmpDefinitions
478 final private static int Delta = 10;
479
480 public Handler(int pduType) {
481 this.type = pduType;
482 }
483
484 /**
485 * Adds a varbind in this node sublist.
486 */
487 public void addVarbind(SnmpVarBind varbind) {
488 if (sublist == null) sublist = new Vector<SnmpVarBind>();
489 sublist.addElement(varbind);
490 }
491
492 /**
493 * register an entry for the given oid at the given position with
494 * the given sublist.
495 */
496 @SuppressWarnings("unchecked")
497 // We need this because of new Vector[n] instead of
498 // new Vector<SnmpVarBind>[n], which is illegal.
499 void add(int pos,SnmpOid oid, Vector<SnmpVarBind> v, boolean isnew,
500 SnmpVarBind statusvb) {
501
502 if (entryoids == null) {
503 // Vectors are null: Allocate new vectors
504
505 entryoids = new SnmpOid[Delta];
506 entrylists = new Vector[Delta];
507 isentrynew = new boolean[Delta];
508 rowstatus = new SnmpVarBind[Delta];
509 entrysize = Delta;
510 pos = 0;
511
512 } else if (pos >= entrysize || entrycount == entrysize) {
513 // Vectors must be enlarged
514
515 // Save old vectors
516 SnmpOid[] olde = entryoids;
517 Vector[] oldl = entrylists;
518 boolean[] oldn = isentrynew;
519 SnmpVarBind[] oldr = rowstatus;
520
521 // Allocate larger vectors
522 entrysize += Delta;
523 entryoids = new SnmpOid[entrysize];
524 entrylists = new Vector[entrysize];
525 isentrynew = new boolean[entrysize];
526 rowstatus = new SnmpVarBind[entrysize];
527
528 // Check pos validity
529 if (pos > entrycount) pos = entrycount;
530 if (pos < 0) pos = 0;
531
532 final int l1 = pos;
533 final int l2 = entrycount - pos;
534
535 // Copy original vectors up to `pos'
536 if (l1 > 0) {
537 java.lang.System.arraycopy(olde,0,entryoids,
538 0,l1);
539 java.lang.System.arraycopy(oldl,0,entrylists,
540 0,l1);
541 java.lang.System.arraycopy(oldn,0,isentrynew,
542 0,l1);
543 java.lang.System.arraycopy(oldr,0,rowstatus,
544 0,l1);
545 }
546
547 // Copy original vectors from `pos' to end, leaving
548 // an empty room at `pos' in the new vectors.
549 if (l2 > 0) {
550 final int l3 = l1+1;
551 java.lang.System.arraycopy(olde,l1,entryoids,
552 l3,l2);
553 java.lang.System.arraycopy(oldl,l1,entrylists,
554 l3,l2);
555 java.lang.System.arraycopy(oldn,l1,isentrynew,
556 l3,l2);
557 java.lang.System.arraycopy(oldr,l1,rowstatus,
558 l3,l2);
559 }
560
561
562 } else if (pos < entrycount) {
563 // Vectors are large enough to accomodate one additional
564 // entry.
565 //
566 // Shift vectors, making an empty room at `pos'
567 final int l1 = pos+1;
568 final int l2 = entrycount - pos;
569
570 java.lang.System.arraycopy(entryoids,pos,entryoids,
571 l1,l2);
572 java.lang.System.arraycopy(entrylists,pos,entrylists,
573 l1,l2);
574 java.lang.System.arraycopy(isentrynew,pos,isentrynew,
575 l1,l2);
576 java.lang.System.arraycopy(rowstatus,pos,rowstatus,
577 l1,l2);
578 }
579
580 // Fill the gap at `pos'
581 entryoids[pos] = oid;
582 entrylists[pos] = v;
583 isentrynew[pos] = isnew;
584 rowstatus[pos] = statusvb;
585 entrycount++;
586 }
587
588 public void addVarbind(SnmpVarBind varbind, SnmpOid entryoid,
589 boolean isnew, SnmpVarBind statusvb)
590 throws SnmpStatusException {
591 Vector<SnmpVarBind> v = null;
592 SnmpVarBind rs = statusvb;
593
594 if (entryoids == null) {
595// entryoids = new ArrayList();
596// entrylists = new ArrayList();
597// isentrynew = new ArrayList();
598 v = new Vector<SnmpVarBind>();
599// entryoids.add(entryoid);
600// entrylists.add(v);
601// isentrynew.add(new Boolean(isnew));
602 add(0,entryoid,v,isnew,rs);
603 } else {
604 // int pos = findOid(entryoids,entryoid);
605 // int pos = findOid(entryoids,entrycount,entryoid);
606 final int pos =
607 getInsertionPoint(entryoids,entrycount,entryoid);
608 if (pos > -1 && pos < entrycount &&
609 entryoid.compareTo(entryoids[pos]) == 0) {
610 v = entrylists[pos];
611 rs = rowstatus[pos];
612 } else {
613 // if (pos == -1 || pos >= entryoids.size() ) {
614 // if (pos == -1 || pos >= entrycount ) {
615 // pos = getInsertionPoint(entryoids,entryoid);
616 // pos = getInsertionPoint(entryoids,entrycount,entryoid);
617 v = new Vector<SnmpVarBind>();
618// entryoids.add(pos,entryoid);
619// entrylists.add(pos,v);
620// isentrynew.add(pos,new Boolean(isnew));
621 add(pos,entryoid,v,isnew,rs);
622 }
623// } else v = (Vector) entrylists.get(pos);
624 // } else v = entrylists[pos];
625 if (statusvb != null) {
626 if ((rs != null) && (rs != statusvb) &&
627 ((type == SnmpDefinitions.pduWalkRequest) ||
628 (type == SnmpDefinitions.pduSetRequestPdu))) {
629 throw new SnmpStatusException(
630 SnmpStatusException.snmpRspInconsistentValue);
631 }
632 rowstatus[pos] = statusvb;
633 }
634 }
635
636 // We do not include the status variable in the varbind,
637 // because we're going to set it separately...
638 //
639 if (statusvb != varbind)
640 v.addElement(varbind);
641 }
642
643 public int getSubReqCount() {
644 int count = 0;
645 if (sublist != null) count++;
646// if (entryoids != null) count += entryoids.size();
647 if (entryoids != null) count += entrycount;
648 return count;
649 }
650
651 public Vector<SnmpVarBind> getSubList() {
652 return sublist;
653 }
654
655 public int getEntryPos(SnmpOid entryoid) {
656 // return findOid(entryoids,entryoid);
657 return findOid(entryoids,entrycount,entryoid);
658 }
659
660 public SnmpOid getEntryOid(int pos) {
661 if (entryoids == null) return null;
662 // if (pos == -1 || pos >= entryoids.size() ) return null;
663 if (pos == -1 || pos >= entrycount ) return null;
664 // return (SnmpOid) entryoids.get(pos);
665 return entryoids[pos];
666 }
667
668 public boolean isNewEntry(int pos) {
669 if (entryoids == null) return false;
670 // if (pos == -1 || pos >= entryoids.size() ) return false;
671 if (pos == -1 || pos >= entrycount ) return false;
672 // return ((Boolean)isentrynew.get(pos)).booleanValue();
673 return isentrynew[pos];
674 }
675
676 public SnmpVarBind getRowStatusVarBind(int pos) {
677 if (entryoids == null) return null;
678 // if (pos == -1 || pos >= entryoids.size() ) return false;
679 if (pos == -1 || pos >= entrycount ) return null;
680 // return ((Boolean)isentrynew.get(pos)).booleanValue();
681 return rowstatus[pos];
682 }
683
684 public Vector<SnmpVarBind> getEntrySubList(int pos) {
685 if (entrylists == null) return null;
686 // if (pos == -1 || pos >= entrylists.size() ) return null;
687 if (pos == -1 || pos >= entrycount ) return null;
688 // return (Vector) entrylists.get(pos);
689 return entrylists[pos];
690 }
691
692 public Iterator<SnmpOid> getEntryOids() {
693 if (entryoids == null) return null;
694 // return entryoids.iterator();
695 return Arrays.asList(entryoids).iterator();
696 }
697
698 public int getEntryCount() {
699 if (entryoids == null) return 0;
700 // return entryoids.size();
701 return entrycount;
702 }
703
704 }
705
706
707 //-------------------------------------------------------------------
708 //-------------------------------------------------------------------
709 // Public interface
710 //-------------------------------------------------------------------
711 //-------------------------------------------------------------------
712
713 //-------------------------------------------------------------------
714 // Returns the contextual object containing user-data allocated
715 // through the SnmpUserDataFactory for this request.
716 //-------------------------------------------------------------------
717
718 public Object getUserData() { return request.getUserData(); }
719
720 //-------------------------------------------------------------------
721 // Tells whether creation of new entries is allowed with respect
722 // to the operation involved (GET=>false/SET=>true)
723 //-------------------------------------------------------------------
724
725 public boolean isCreationAllowed() {
726 return creationflag;
727 }
728
729 //-------------------------------------------------------------------
730 // Tells whether we are currently processing a SET request (check/set)
731 //-------------------------------------------------------------------
732
733 public boolean isSetRequest() {
734 return setreqflag;
735 }
736
737 //-------------------------------------------------------------------
738 // Returns the protocol version in which the original request is
739 // evaluated.
740 //-------------------------------------------------------------------
741
742 public int getVersion() {
743 return version;
744 }
745
746 //-------------------------------------------------------------------
747 // Returns the actual protocol version of the request PDU.
748 //-------------------------------------------------------------------
749
750 public int getRequestPduVersion() {
751 return request.getRequestPduVersion();
752 }
753
754 //-------------------------------------------------------------------
755 // Returns the SnmpMibNode associated with the given handler
756 //-------------------------------------------------------------------
757
758 public SnmpMibNode getMetaNode(Handler handler) {
759 return handler.meta;
760 }
761
762 //-------------------------------------------------------------------
763 // Indicates the depth of the arc in the OID that identifies the
764 // SnmpMibNode associated with the given handler
765 //-------------------------------------------------------------------
766
767 public int getOidDepth(Handler handler) {
768 return handler.depth;
769 }
770
771 //-------------------------------------------------------------------
772 // returns an enumeration of the SnmpMibSubRequest's to be invoked on
773 // the SnmpMibNode associated with a given Handler node.
774 // If this node is a group, there will be a single subrequest.
775 // If it is a table, there will be one subrequest per entry involved.
776 //-------------------------------------------------------------------
777
778 public Enumeration getSubRequests(Handler handler) {
779 return new Enum(this,handler);
780 }
781
782 //-------------------------------------------------------------------
783 // returns an enumeration of the Handlers stored in the Hashtable.
784 //-------------------------------------------------------------------
785
786 public Enumeration getHandlers() {
787 return hashtable.elements();
788 }
789
790 //-------------------------------------------------------------------
791 // adds a varbind to a handler node sublist
792 //-------------------------------------------------------------------
793
794 public void add(SnmpMibNode meta, int depth, SnmpVarBind varbind)
795 throws SnmpStatusException {
796 registerNode(meta,depth,null,varbind,false,null);
797 }
798
799 //-------------------------------------------------------------------
800 // adds an entry varbind to a handler node sublist
801 //-------------------------------------------------------------------
802
803 public void add(SnmpMibNode meta, int depth, SnmpOid entryoid,
804 SnmpVarBind varbind, boolean isnew)
805 throws SnmpStatusException {
806 registerNode(meta,depth,entryoid,varbind,isnew,null);
807 }
808
809 //-------------------------------------------------------------------
810 // adds an entry varbind to a handler node sublist - specifying the
811 // varbind which holds the row status
812 //-------------------------------------------------------------------
813
814 public void add(SnmpMibNode meta, int depth, SnmpOid entryoid,
815 SnmpVarBind varbind, boolean isnew,
816 SnmpVarBind statusvb)
817 throws SnmpStatusException {
818 registerNode(meta,depth,entryoid,varbind,isnew,statusvb);
819 }
820
821
822 //-------------------------------------------------------------------
823 //-------------------------------------------------------------------
824 // Protected interface
825 //-------------------------------------------------------------------
826 //-------------------------------------------------------------------
827
828 //-------------------------------------------------------------------
829 // Type of the request (see SnmpDefinitions)
830 //-------------------------------------------------------------------
831
832 void setPduType(int pduType) {
833 type = pduType;
834 setreqflag = ((pduType == SnmpDefinitions.pduWalkRequest) ||
835 (pduType == SnmpDefinitions.pduSetRequestPdu));
836 }
837
838 //-------------------------------------------------------------------
839 // We deal with a GET-NEXT request
840 //-------------------------------------------------------------------
841
842 void setGetNextFlag() {
843 getnextflag = true;
844 }
845
846 //-------------------------------------------------------------------
847 // Tell whether creation is allowed.
848 //-------------------------------------------------------------------
849 void switchCreationFlag(boolean flag) {
850 creationflag = flag;
851 }
852
853
854 //-------------------------------------------------------------------
855 // Returns the subrequest handled by the SnmpMibNode itself
856 // (in principle, only for Groups)
857 //-------------------------------------------------------------------
858
859 SnmpMibSubRequest getSubRequest(Handler handler) {
860 if (handler == null) return null;
861 return new SnmpMibSubRequestImpl(request,handler.getSubList(),
862 null,false,getnextflag,null);
863 }
864
865 //-------------------------------------------------------------------
866 // Returns the subrequest associated with the entry identified by
867 // the given entry (only for tables)
868 //-------------------------------------------------------------------
869
870 SnmpMibSubRequest getSubRequest(Handler handler, SnmpOid oid) {
871 if (handler == null) return null;
872 final int pos = handler.getEntryPos(oid);
873 if (pos == -1) return null;
874 return new SnmpMibSubRequestImpl(request,
875 handler.getEntrySubList(pos),
876 handler.getEntryOid(pos),
877 handler.isNewEntry(pos),
878 getnextflag,
879 handler.getRowStatusVarBind(pos));
880 }
881
882 //-------------------------------------------------------------------
883 // Returns the subrequest associated with the entry identified by
884 // the given entry (only for tables). The `entry' parameter is an
885 // index relative to the position of the entry in the handler sublist.
886 //-------------------------------------------------------------------
887
888 SnmpMibSubRequest getSubRequest(Handler handler, int entry) {
889 if (handler == null) return null;
890 return new
891 SnmpMibSubRequestImpl(request,handler.getEntrySubList(entry),
892 handler.getEntryOid(entry),
893 handler.isNewEntry(entry),getnextflag,
894 handler.getRowStatusVarBind(entry));
895 }
896
897 //-------------------------------------------------------------------
898 //-------------------------------------------------------------------
899 // Private section
900 //-------------------------------------------------------------------
901 //-------------------------------------------------------------------
902
903
904 //-------------------------------------------------------------------
905 // stores a handler node in the Hashtable
906 //-------------------------------------------------------------------
907
908 private void put(Object key, Handler handler) {
909 if (handler == null) return;
910 if (key == null) return;
911 if (hashtable == null) hashtable = new Hashtable<Object, Handler>();
912 hashtable.put(key,handler);
913 }
914
915 //-------------------------------------------------------------------
916 // finds a handler node in the Hashtable
917 //-------------------------------------------------------------------
918
919 private Handler get(Object key) {
920 if (key == null) return null;
921 if (hashtable == null) return null;
922 return hashtable.get(key);
923 }
924
925 //-------------------------------------------------------------------
926 // Search for the given oid in `oids'. If none is found, returns -1
927 // otherwise, returns the index at which the oid is located.
928 //-------------------------------------------------------------------
929
930 private static int findOid(SnmpOid[] oids, int count, SnmpOid oid) {
931 final int size = count;
932 int low= 0;
933 int max= size - 1;
934 int curr= low + (max-low)/2;
935 //System.out.println("Try to retrieve: " + oid.toString());
936 while (low <= max) {
937
938 final SnmpOid pos = oids[curr];
939
940 //System.out.println("Compare with" + pos.toString());
941 // never know ...we might find something ...
942 //
943 final int comp = oid.compareTo(pos);
944 if (comp == 0)
945 return curr;
946
947 if (oid.equals(pos)) {
948 return curr;
949 }
950 if (comp > 0) {
951 low = curr + 1;
952 } else {
953 max = curr - 1;
954 }
955 curr = low + (max-low)/2;
956 }
957 return -1;
958 }
959
960 //-------------------------------------------------------------------
961 // Return the index at which the given oid should be inserted in the
962 // `oids' array.
963 //-------------------------------------------------------------------
964
965 private static int getInsertionPoint(SnmpOid[] oids, int count,
966 SnmpOid oid) {
967 final SnmpOid[] localoids = oids;
968 final int size = count;
969 int low= 0;
970 int max= size - 1;
971 int curr= low + (max-low)/2;
972
973
974 while (low <= max) {
975
976 final SnmpOid pos = localoids[curr];
977
978 // never know ...we might find something ...
979 //
980 final int comp= oid.compareTo(pos);
981
982 // In the calling method we will have to check for this case...
983 // if (comp == 0)
984 // return -1;
985 // Returning curr instead of -1 avoids having to call
986 // findOid() first and getInsertionPoint() afterwards.
987 // We can simply call getInsertionPoint() and then checks whether
988 // there's an OID at the returned position which equals the
989 // given OID.
990 if (comp == 0)
991 return curr;
992
993 if (comp>0) {
994 low= curr +1;
995 } else {
996 max= curr -1;
997 }
998 curr= low + (max-low)/2;
999 }
1000 return curr;
1001 }
1002
1003 //-------------------------------------------------------------------
1004 // adds a varbind in a handler node sublist
1005 //-------------------------------------------------------------------
1006
1007 private void registerNode(SnmpMibNode meta, int depth, SnmpOid entryoid,
1008 SnmpVarBind varbind, boolean isnew,
1009 SnmpVarBind statusvb)
1010 throws SnmpStatusException {
1011 if (meta == null) {
1012 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
1013 SnmpRequestTree.class.getName(),
1014 "registerNode", "meta-node is null!");
1015 return;
1016 }
1017 if (varbind == null) {
1018 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
1019 SnmpRequestTree.class.getName(),
1020 "registerNode", "varbind is null!");
1021 return ;
1022 }
1023
1024 final Object key = meta;
1025
1026 // retrieve the handler node associated with the given meta,
1027 // if any
1028 Handler handler = get(key);
1029
1030 // If no handler node was found for that meta, create one.
1031 if (handler == null) {
1032 // if (isDebugOn())
1033 // debug("registerNode", "adding node for " +
1034 // varbind.oid.toString());
1035 handler = new Handler(type);
1036 handler.meta = meta;
1037 handler.depth = depth;
1038 put(key,handler);
1039 }
1040 // else {
1041 // if (isDebugOn())
1042 // debug("registerNode","found node for " +
1043 // varbind.oid.toString());
1044 // }
1045
1046 // Adds the varbind in the handler node's sublist.
1047 if (entryoid == null)
1048 handler.addVarbind(varbind);
1049 else
1050 handler.addVarbind(varbind,entryoid,isnew,statusvb);
1051 return ;
1052 }
1053
1054
1055 //-------------------------------------------------------------------
1056 // private variables
1057 //-------------------------------------------------------------------
1058
1059 private Hashtable<Object, Handler> hashtable = null;
1060 // Hashtable of Handler objects
1061 private SnmpMibRequest request = null; // The original list of varbinds
1062 private int version = 0; // The protocol version
1063 private boolean creationflag = false; // Does the operation allow
1064 // creation of entries
1065 private boolean getnextflag = false; // Does the operation allow
1066 // creation of entries
1067 private int type = 0; // Request PDU type as defined
1068 // in SnmpDefinitions
1069 private boolean setreqflag = false; // True if we're processing a
1070 // SET request (check/set).
1071}