blob: b5c96fff9931b1f182928f8360541bde49eb850d [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
26package com.sun.jmx.snmp.agent;
27
28import java.io.Serializable;
29import java.util.Enumeration;
30import java.util.logging.Level;
31import java.util.Vector;
32
33import javax.management.ObjectName;
34import javax.management.MBeanServer;
35import javax.management.MalformedObjectNameException;
36import javax.management.InstanceAlreadyExistsException;
37import javax.management.MBeanRegistrationException;
38import javax.management.NotCompliantMBeanException;
39
40import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER;
41import com.sun.jmx.snmp.SnmpOid;
42import com.sun.jmx.snmp.SnmpVarBind;
43import com.sun.jmx.snmp.SnmpDefinitions;
44import com.sun.jmx.snmp.SnmpStatusException;
45import com.sun.jmx.snmp.SnmpEngine;
46import com.sun.jmx.snmp.SnmpUnknownModelException;
47import com.sun.jmx.snmp.internal.SnmpAccessControlModel;
48import com.sun.jmx.snmp.internal.SnmpEngineImpl;
49
50/**
51 * This list is used in order to construct the OID during the getnext.
52 * The constructed oid is checked by the checker AcmChecker.
53 */
54final class LongList {
55
56 public static int DEFAULT_CAPACITY = 10;
57
58 public static int DEFAULT_INCREMENT = 10;
59
60
61 private final int DELTA;
62 private int size;
63
64 /**
65 * The list content. Any access to this variable must be protected
66 * by a synchronized block on the LongList object.
67 * Only read-only action should be performed on this object.
68 **/
69 public long[] list;
70
71 LongList() {
72 this(DEFAULT_CAPACITY,DEFAULT_INCREMENT);
73 }
74
75 LongList(int initialCapacity) {
76 this(initialCapacity,DEFAULT_INCREMENT);
77 }
78
79 LongList(int initialCapacity, int delta) {
80 size = 0;
81 DELTA = delta;
82 list = allocate(initialCapacity);
83 }
84
85 /**
86 * Same behaviour than size() in {@link java.util.List}.
87 **/
88 public final int size() { return size;}
89
90 /**
91 * Same behaviour than add(long o) in {@link java.util.List}.
92 * Any access to this method should be protected in a synchronized
93 * block on the LongList object.
94 **/
95 public final boolean add(final long o) {
96 if (size >= list.length)
97 resize();
98 list[size++]=o;
99 return true;
100 }
101
102 /**
103 * Same behaviour than add(int index, long o) in
104 * {@link java.util.List}.
105 * Any access to this method should be protected in a synchronized
106 * block on the LongList object.
107 **/
108 public final void add(final int index, final long o) {
109 if (index > size) throw new IndexOutOfBoundsException();
110 if (index >= list.length) resize();
111 if (index == size) {
112 list[size++]=o;
113 return;
114 }
115
116 java.lang.System.arraycopy(list,index,list,index+1,size-index);
117 list[index]=o;
118 size++;
119 }
120
121 /**
122 * Adds <var>count</var> elements to the list.
123 * @param at index at which the elements must be inserted. The
124 * first element will be inserted at this index.
125 * @param src An array containing the elements we want to insert.
126 * @param from Index of the first element from <var>src</var> that
127 * must be inserted.
128 * @param count number of elements to insert.
129 * Any access to this method should be protected in a synchronized
130 * block on the LongList object.
131 **/
132 public final void add(final int at,final long[] src, final int from,
133 final int count) {
134 if (count <= 0) return;
135 if (at > size) throw new IndexOutOfBoundsException();
136 ensure(size+count);
137 if (at < size) {
138 java.lang.System.arraycopy(list,at,list,at+count,size-at);
139 }
140 java.lang.System.arraycopy(src,from,list,at,count);
141 size+=count;
142 }
143
144 /**
145 * Any access to this method should be protected in a synchronized
146 * block on the LongList object.
147 **/
148 public final long remove(final int from, final int count) {
149 if (count < 1 || from < 0) return -1;
150 if (from+count > size) return -1;
151
152 final long o = list[from];
153 final int oldsize = size;
154 size = size - count;
155
156 if (from == size) return o;
157
158 java.lang.System.arraycopy(list,from+count,list,from,
159 size-from);
160 return o;
161 }
162
163 /**
164 * Same behaviour than remove(int index) in {@link java.util.List}.
165 * Any access to this method should be protected in a synchronized
166 * block on the LongList object.
167 **/
168 public final long remove(final int index) {
169 if (index >= size) return -1;
170 final long o = list[index];
171 list[index]=0;
172 if (index == --size) return o;
173
174 java.lang.System.arraycopy(list,index+1,list,index,
175 size-index);
176 return o;
177 }
178
179 /**
180 * Same behaviour than the toArray(long[] a) method in
181 * {@link java.util.List}.
182 * Any access to this method should be protected in a synchronized
183 * block on the LongList object.
184 **/
185 public final long[] toArray(long[] a) {
186 java.lang.System.arraycopy(list,0,a,0,size);
187 return a;
188 }
189
190 /**
191 * Same behaviour than the toArray() method in
192 * {@link java.util.List}.
193 * Any access to this method should be protected in a synchronized
194 * block on the LongList object.
195 **/
196 public final long[] toArray() {
197 return toArray(new long[size]);
198 }
199
200 /**
201 * Resize the list. Increase its capacity by DELTA elements.
202 * Any call to this method must be protected by a synchronized
203 * block on this LongList.
204 **/
205 private final void resize() {
206 final long[] newlist = allocate(list.length + DELTA);
207 java.lang.System.arraycopy(list,0,newlist,0,size);
208 list = newlist;
209 }
210
211 /**
212 * Resize the list. Insure that the new length will be at
213 * least equal to <var>length</var>.
214 * @param length new minimal length requested.
215 * Any call to this method must be protected by a synchronized
216 * block on this LongList.
217 **/
218 private final void ensure(int length) {
219 if (list.length < length) {
220 final int min = list.length+DELTA;
221 length=(length<min)?min:length;
222 final long[] newlist = allocate(length);
223 java.lang.System.arraycopy(list,0,newlist,0,size);
224 list = newlist;
225 }
226 }
227
228 /**
229 * Allocate a new array of object of specified length.
230 **/
231 private final long[] allocate(final int length) {
232 return new long[length];
233 }
234
235}
236
237/**
238 * Oid Checker makes use of ACM to check each OID during the getnext process.
239 */
240class AcmChecker {
241
242
243 SnmpAccessControlModel model = null;
244 String principal = null;
245 int securityLevel = -1;
246 int version = -1;
247 int pduType = -1;
248 int securityModel = -1;
249 byte[] contextName = null;
250 SnmpEngineImpl engine = null;
251 LongList l = null;
252 AcmChecker(SnmpMibRequest req) {
253 engine = (SnmpEngineImpl) req.getEngine();
254 //We are in V3 architecture, ACM is in the picture.
255 if(engine != null) {
256 if(engine.isCheckOidActivated()) {
257 try {
258 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
259 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
260 SnmpMib.class.getName(),
261 "AcmChecker(SnmpMibRequest)",
262 "SNMP V3 Access Control to be done");
263 }
264 model = (SnmpAccessControlModel)
265 engine.getAccessControlSubSystem().
266 getModel(SnmpDefinitions.snmpVersionThree);
267 principal = req.getPrincipal();
268 securityLevel = req.getSecurityLevel();
269 pduType = req.getPdu().type;
270 version = req.getRequestPduVersion();
271 securityModel = req.getSecurityModel();
272 contextName = req.getAccessContextName();
273 l = new LongList();
274 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
275 final StringBuilder strb = new StringBuilder()
276 .append("Will check oid for : principal : ")
277 .append(principal)
278 .append("; securityLevel : ").append(securityLevel)
279 .append("; pduType : ").append(pduType)
280 .append("; version : ").append(version)
281 .append("; securityModel : ").append(securityModel)
282 .append("; contextName : ").append(contextName);
283 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
284 SnmpMib.class.getName(),
285 "AcmChecker(SnmpMibRequest)", strb.toString());
286 }
287
288 }catch(SnmpUnknownModelException e) {
289 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
290 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
291 SnmpMib.class.getName(),
292 "AcmChecker(SnmpMibRequest)",
293 "Unknown Model, no ACM check.");
294 }
295 }
296 }
297 }
298 }
299
300 void add(int index, long arc) {
301 if(model != null)
302 l.add(index, arc);
303 }
304
305 void remove(int index) {
306 if(model != null)
307 l.remove(index);
308 }
309
310 void add(final int at,final long[] src, final int from,
311 final int count) {
312 if(model != null)
313 l.add(at,src,from,count);
314 }
315
316 void remove(final int from, final int count) {
317 if(model != null)
318 l.remove(from,count);
319 }
320
321 void checkCurrentOid() throws SnmpStatusException {
322 if(model != null) {
323 SnmpOid oid = new SnmpOid(l.toArray());
324 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
325 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMib.class.getName(),
326 "checkCurrentOid", "Checking access for : " + oid);
327 }
328 model.checkAccess(version,
329 principal,
330 securityLevel,
331 pduType,
332 securityModel,
333 contextName,
334 oid);
335 }
336 }
337
338}
339
340/**
341 * Abstract class for representing an SNMP MIB.
342 * <P>
343 * When compiling a SNMP MIB, among all the classes generated by
344 * <CODE>mibgen</CODE>, there is one which extends <CODE>SnmpMib</CODE>
345 * for representing a whole MIB.
346 * <BR>The class is used by the SNMP protocol adaptor as the entry point in
347 * the MIB.
348 *
349 * <p>This generated class can be subclassed in your code in order to
350 * plug in your own specific behaviour.
351 * </p>
352 *
353 * <p><b>This API is a Sun Microsystems internal API and is subject
354 * to change without notice.</b></p>
355 */
356public abstract class SnmpMib extends SnmpMibAgent implements Serializable {
357
358 /**
359 * Default constructor.
360 * Initializes the OID tree.
361 */
362 public SnmpMib() {
363 root= new SnmpMibOid();
364 }
365
366
367 // --------------------------------------------------------------------
368 // POLYMORHIC METHODS
369 // --------------------------------------------------------------------
370
371 /**
372 * <p>
373 * This callback should return the OID associated to the group
374 * identified by the given <code>groupName</code>.
375 * </p>
376 *
377 * <p>
378 * This method is provided as a hook to plug-in some custom
379 * specific behavior. Although doing so is discouraged you might
380 * want to subclass this method in order to store & provide more metadata
381 * information (mapping OID <-> symbolic name) within the agent,
382 * or to "change" the root of the MIB OID by prefixing the
383 * defaultOid by an application dependant OID string, for instance.
384 * </p>
385 *
386 * <p>
387 * The default implementation of this method is to return the given
388 * <code>defaultOid</code>
389 * </p>
390 *
391 * @param groupName The java-ized name of the SNMP group.
392 * @param defaultOid The OID defined in the MIB for that group
393 * (in dot notation).
394 *
395 * @return The OID of the group identified by <code>groupName</code>,
396 * in dot-notation.
397 */
398 protected String getGroupOid(String groupName, String defaultOid) {
399 return defaultOid;
400 }
401
402 /**
403 * <p>
404 * This callback should return the ObjectName associated to the
405 * group identified by the given <code>groupName</code>.
406 * </p>
407 *
408 * <p>
409 * This method is provided as a hook to plug-in some custom
410 * specific behavior. You might want to override this method
411 * in order to provide a different object naming scheme than
412 * that proposed by default by <code>mibgen</code>.
413 * </p>
414 *
415 * <p>
416 * This method is only meaningful if the MIB is registered
417 * in the MBeanServer, otherwise, it will not be called.
418 * </p>
419 *
420 * <p>
421 * The default implementation of this method is to return an ObjectName
422 * built from the given <code>defaultName</code>.
423 * </p>
424 *
425 * @param name The java-ized name of the SNMP group.
426 * @param oid The OID returned by getGroupOid() - in dot notation.
427 * @param defaultName The name by default generated by <code>
428 * mibgen</code>
429 *
430 * @return The ObjectName of the group identified by <code>name</code>
431 */
432 protected ObjectName getGroupObjectName(String name, String oid,
433 String defaultName)
434 throws MalformedObjectNameException {
435 return new ObjectName(defaultName);
436 }
437
438 /**
439 * <p>
440 * Register an SNMP group and its metadata node in the MIB.
441 * </p>
442 *
443 * <p>
444 * This method is provided as a hook to plug-in some custom
445 * specific behavior. You might want to override this method
446 * if you want to set special links between the MBean, its metadata
447 * node, its OID or ObjectName etc..
448 * </p>
449 *
450 * <p>
451 * If the MIB is not registered in the MBeanServer, the <code>
452 * server</code> and <code>groupObjName</code> parameters will be
453 * <code>null</code>.<br>
454 * If the given group MBean is not <code>null</code>, and if the
455 * <code>server</code> and <code>groupObjName</code> parameters are
456 * not null, then this method will also automatically register the
457 * group MBean with the given MBeanServer <code>server</code>.
458 * </p>
459 *
460 * @param groupName The java-ized name of the SNMP group.
461 * @param groupOid The OID as returned by getGroupOid() - in dot
462 * notation.
463 * @param groupObjName The ObjectName as returned by getGroupObjectName().
464 * This parameter may be <code>null</code> if the
465 * MIB is not registered in the MBeanServer.
466 * @param node The metadata node, as returned by the metadata
467 * factory method for this group.
468 * @param group The MBean for this group, as returned by the
469 * MBean factory method for this group.
470 * @param server The MBeanServer in which the groups are to be
471 * registered. This parameter will be <code>null</code>
472 * if the MIB is not registered, otherwise it is a
473 * reference to the MBeanServer in which the MIB is
474 * registered.
475 *
476 */
477 protected void registerGroupNode(String groupName, String groupOid,
478 ObjectName groupObjName, SnmpMibNode node,
479 Object group, MBeanServer server)
480 throws NotCompliantMBeanException, MBeanRegistrationException,
481 InstanceAlreadyExistsException, IllegalAccessException {
482 root.registerNode(groupOid,node);
483 if (server != null && groupObjName != null && group != null)
484 server.registerMBean(group,groupObjName);
485 }
486
487 /**
488 * <p>
489 * Register an SNMP Table metadata node in the MIB.
490 * </p>
491 *
492 * <p>
493 * <b><i>
494 * This method is used internally and you should never need to
495 * call it directly.</i></b><br> It is used to establish the link
496 * between an SNMP table metadata node and its bean-like counterpart.
497 * <br>
498 * The group metadata nodes will create and register their
499 * underlying table metadata nodes in the MIB using this
500 * method. <br>
501 * The metadata nodes will be later retrieved from the MIB by the
502 * bean-like table objects using the getRegisterTableMeta() method.
503 * </p>
504 *
505 * @param name The java-ized name of the SNMP table.
506 * @param table The SNMP table metadata node - usually this
507 * corresponds to a <code>mibgen</code> generated
508 * object.
509 */
510 public abstract void registerTableMeta(String name, SnmpMibTable table);
511
512 /**
513 * Returns a registered SNMP Table metadata node.
514 *
515 * <p><b><i>
516 * This method is used internally and you should never need to
517 * call it directly.
518 * </i></b></p>
519 *
520 */
521 public abstract SnmpMibTable getRegisteredTableMeta(String name);
522
523 // --------------------------------------------------------------------
524 // PUBLIC METHODS
525 // --------------------------------------------------------------------
526
527 /**
528 * Processes a <CODE>get</CODE> operation.
529 *
530 **/
531 // Implements the method defined in SnmpMibAgent. See SnmpMibAgent
532 // for java-doc
533 //
534 public void get(SnmpMibRequest req) throws SnmpStatusException {
535
536 // Builds the request tree: creation is not allowed, operation
537 // is not atomic.
538
539 final int reqType = SnmpDefinitions.pduGetRequestPdu;
540 SnmpRequestTree handlers = getHandlers(req,false,false,reqType);
541
542 SnmpRequestTree.Handler h = null;
543 SnmpMibNode meta = null;
544
545 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
546 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMib.class.getName(),
547 "get", "Processing handlers for GET... ");
548 }
549
550 // For each sub-request stored in the request-tree, invoke the
551 // get() method.
552 for (Enumeration eh=handlers.getHandlers();eh.hasMoreElements();) {
553 h = (SnmpRequestTree.Handler) eh.nextElement();
554
555 // Gets the Meta node. It can be either a Group Meta or a
556 // Table Meta.
557 //
558 meta = handlers.getMetaNode(h);
559
560 // Gets the depth of the Meta node in the OID tree
561 final int depth = handlers.getOidDepth(h);
562
563 for (Enumeration rqs=handlers.getSubRequests(h);
564 rqs.hasMoreElements();) {
565
566 // Invoke the get() operation.
567 meta.get((SnmpMibSubRequest)rqs.nextElement(),depth);
568 }
569 }
570 }
571
572 /**
573 * Processes a <CODE>set</CODE> operation.
574 *
575 */
576 // Implements the method defined in SnmpMibAgent. See SnmpMibAgent
577 // for java-doc
578 //
579 public void set(SnmpMibRequest req) throws SnmpStatusException {
580
581 SnmpRequestTree handlers = null;
582
583 // Optimization: we're going to get the whole SnmpRequestTree
584 // built in the "check" method, so that we don't have to rebuild
585 // it here.
586 //
587 if (req instanceof SnmpMibRequestImpl)
588 handlers = ((SnmpMibRequestImpl)req).getRequestTree();
589
590 // Optimization didn't work: we have to rebuild the tree.
591 //
592 // Builds the request tree: creation is not allowed, operation
593 // is atomic.
594 //
595 final int reqType = SnmpDefinitions.pduSetRequestPdu;
596 if (handlers == null) handlers = getHandlers(req,false,true,reqType);
597 handlers.switchCreationFlag(false);
598 handlers.setPduType(reqType);
599
600 SnmpRequestTree.Handler h = null;
601 SnmpMibNode meta = null;
602
603 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
604 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMib.class.getName(),
605 "set", "Processing handlers for SET... ");
606 }
607
608 // For each sub-request stored in the request-tree, invoke the
609 // get() method.
610 for (Enumeration eh=handlers.getHandlers();eh.hasMoreElements();) {
611 h = (SnmpRequestTree.Handler) eh.nextElement();
612
613 // Gets the Meta node. It can be either a Group Meta or a
614 // Table Meta.
615 //
616 meta = handlers.getMetaNode(h);
617
618 // Gets the depth of the Meta node in the OID tree
619 final int depth = handlers.getOidDepth(h);
620
621 for (Enumeration rqs=handlers.getSubRequests(h);
622 rqs.hasMoreElements();) {
623
624 // Invoke the set() operation
625 meta.set((SnmpMibSubRequest)rqs.nextElement(),depth);
626 }
627 }
628 }
629
630 /**
631 * Checks if a <CODE>set</CODE> operation can be performed.
632 * If the operation cannot be performed, the method will raise a
633 * <CODE>SnmpStatusException</CODE>.
634 *
635 */
636 // Implements the method defined in SnmpMibAgent. See SnmpMibAgent
637 // for java-doc
638 //
639 public void check(SnmpMibRequest req) throws SnmpStatusException {
640
641 final int reqType = SnmpDefinitions.pduWalkRequest;
642 // Builds the request tree: creation is allowed, operation
643 // is atomic.
644 SnmpRequestTree handlers = getHandlers(req,true,true,reqType);
645
646 SnmpRequestTree.Handler h = null;
647 SnmpMibNode meta = null;
648
649 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
650 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMib.class.getName(),
651 "check", "Processing handlers for CHECK... ");
652 }
653
654 // For each sub-request stored in the request-tree, invoke the
655 // check() method.
656 for (Enumeration eh=handlers.getHandlers();eh.hasMoreElements();) {
657 h = (SnmpRequestTree.Handler) eh.nextElement();
658
659 // Gets the Meta node. It can be either a Group Meta or a
660 // Table Meta.
661 //
662 meta = handlers.getMetaNode(h);
663
664 // Gets the depth of the Meta node in the OID tree
665 final int depth = handlers.getOidDepth(h);
666
667 for (Enumeration rqs=handlers.getSubRequests(h);
668 rqs.hasMoreElements();) {
669
670 // Invoke the check() operation
671 meta.check((SnmpMibSubRequest)rqs.nextElement(),depth);
672 }
673 }
674
675 // Optimization: we're going to pass the whole SnmpRequestTree
676 // to the "set" method, so that we don't have to rebuild it there.
677 //
678 if (req instanceof SnmpMibRequestImpl) {
679 ((SnmpMibRequestImpl)req).setRequestTree(handlers);
680 }
681
682 }
683
684 /**
685 * Processes a <CODE>getNext</CODE> operation.
686 *
687 */
688 // Implements the method defined in SnmpMibAgent. See SnmpMibAgent
689 // for java-doc
690 //
691 public void getNext(SnmpMibRequest req) throws SnmpStatusException {
692 // Build the request tree for the operation
693 // The subrequest stored in the request tree are valid GET requests
694 SnmpRequestTree handlers = getGetNextHandlers(req);
695
696 SnmpRequestTree.Handler h = null;
697 SnmpMibNode meta = null;
698
699 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
700 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMib.class.getName(),
701 "getNext", "Processing handlers for GET-NEXT... ");
702 }
703
704 // Now invoke get() for each subrequest of the request tree.
705 for (Enumeration eh=handlers.getHandlers();eh.hasMoreElements();) {
706 h = (SnmpRequestTree.Handler) eh.nextElement();
707
708 // Gets the Meta node. It can be either a Group Meta or a
709 // Table Meta.
710 //
711 meta = handlers.getMetaNode(h);
712
713 // Gets the depth of the Meta node in the OID tree
714 int depth = handlers.getOidDepth(h);
715
716 for (Enumeration rqs=handlers.getSubRequests(h);
717 rqs.hasMoreElements();) {
718
719 // Invoke the get() operation
720 meta.get((SnmpMibSubRequest)rqs.nextElement(),depth);
721 }
722 }
723 }
724
725
726 /**
727 * Processes a <CODE>getBulk</CODE> operation.
728 * The method implements the <CODE>getBulk</CODE> operation by calling
729 * appropriately the <CODE>getNext</CODE> method.
730 *
731 */
732 // Implements the method defined in SnmpMibAgent. See SnmpMibAgent
733 // for java-doc
734 //
735 public void getBulk(SnmpMibRequest req, int nonRepeat, int maxRepeat)
736 throws SnmpStatusException {
737
738 getBulkWithGetNext(req, nonRepeat, maxRepeat);
739 }
740
741 /**
742 * Gets the root object identifier of the MIB.
743 * <P>In order to be accurate, the method should be called once the
744 * MIB is fully initialized (that is, after a call to <CODE>init</CODE>
745 * or <CODE>preRegister</CODE>).
746 *
747 * @return The root object identifier.
748 */
749 public long[] getRootOid() {
750
751 if( rootOid == null) {
752 Vector<Integer> list= new Vector<Integer>(10);
753
754 // Ask the tree to do the job !
755 //
756 root.getRootOid(list);
757
758 // Now format the result
759 //
760 rootOid= new long[list.size()];
761 int i=0;
762 for(Enumeration<Integer> e= list.elements(); e.hasMoreElements(); ) {
763 Integer val= e.nextElement();
764 rootOid[i++]= val.longValue();
765 }
766 }
767 return rootOid;
768
769 }
770
771 // --------------------------------------------------------------------
772 // PRIVATE METHODS
773 //---------------------------------------------------------------------
774
775 /**
776 * This method builds the temporary request-tree that will be used to
777 * perform the SNMP request associated with the given vector of varbinds
778 * `list'.
779 *
780 * @param req The SnmpMibRequest object holding the varbind list
781 * concerning this MIB.
782 * @param createflag Indicates whether the operation allow for creation
783 * of new instances (ie: it is a SET).
784 * @param atomic Indicates whether the operation is atomic or not.
785 * @param type Request type (from SnmpDefinitions).
786 *
787 * @return The request-tree where the original varbind list has been
788 * dispatched to the appropriate nodes.
789 */
790 private SnmpRequestTree getHandlers(SnmpMibRequest req,
791 boolean createflag, boolean atomic,
792 int type)
793 throws SnmpStatusException {
794
795 // Build an empty request tree
796 SnmpRequestTree handlers =
797 new SnmpRequestTree(req,createflag,type);
798
799 int index=0;
800 SnmpVarBind var = null;
801 final int ver= req.getVersion();
802
803 // For each varbind in the list finds its handling node.
804 for (Enumeration e= req.getElements(); e.hasMoreElements(); index++) {
805
806 var= (SnmpVarBind) e.nextElement();
807
808 try {
809 // Find the handling node for this varbind.
810 root.findHandlingNode(var,var.oid.longValue(false),
811 0,handlers);
812 } catch(SnmpStatusException x) {
813
814 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
815 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
816 SnmpMib.class.getName(),
817 "getHandlers",
818 "Couldn't find a handling node for " +
819 var.oid.toString());
820 }
821
822 // If the operation is atomic (Check/Set) or the version
823 // is V1 we must generate an exception.
824 //
825 if (ver == SnmpDefinitions.snmpVersionOne) {
826
827 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
828 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
829 SnmpMib.class.getName(),
830 "getHandlers", "\tV1: Throwing exception");
831 }
832
833 // The index in the exception must correspond to the
834 // SNMP index ...
835 //
836 final SnmpStatusException sse =
837 new SnmpStatusException(x, index + 1);
838 sse.initCause(x);
839 throw sse;
840 } else if ((type == SnmpDefinitions.pduWalkRequest) ||
841 (type == SnmpDefinitions.pduSetRequestPdu)) {
842 final int status =
843 SnmpRequestTree.mapSetException(x.getStatus(),ver);
844
845 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
846 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
847 SnmpMib.class.getName(),
848 "getHandlers", "\tSET: Throwing exception");
849 }
850
851 final SnmpStatusException sse =
852 new SnmpStatusException(status, index + 1);
853 sse.initCause(x);
854 throw sse;
855 } else if (atomic) {
856
857 // Should never come here...
858 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
859 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
860 SnmpMib.class.getName(),
861 "getHandlers", "\tATOMIC: Throwing exception");
862 }
863
864 final SnmpStatusException sse =
865 new SnmpStatusException(x, index + 1);
866 sse.initCause(x);
867 throw sse;
868 }
869
870 final int status =
871 SnmpRequestTree.mapGetException(x.getStatus(),ver);
872
873 if (status == SnmpStatusException.noSuchInstance) {
874
875 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
876 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
877 SnmpMib.class.getName(),
878 "getHandlers",
879 "\tGET: Registering noSuchInstance");
880 }
881
882 var.value= SnmpVarBind.noSuchInstance;
883
884 } else if (status == SnmpStatusException.noSuchObject) {
885 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
886 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
887 SnmpMib.class.getName(),
888 "getHandlers",
889 "\tGET: Registering noSuchObject");
890 }
891
892 var.value= SnmpVarBind.noSuchObject;
893
894 } else {
895
896 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
897 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
898 SnmpMib.class.getName(),
899 "getHandlers",
900 "\tGET: Registering global error: " + status);
901 }
902
903 final SnmpStatusException sse =
904 new SnmpStatusException(status, index + 1);
905 sse.initCause(x);
906 throw sse;
907 }
908 }
909 }
910 return handlers;
911 }
912
913 /**
914 * This method builds the temporary request-tree that will be used to
915 * perform the SNMP GET-NEXT request associated with the given vector
916 * of varbinds `list'.
917 *
918 * @param req The SnmpMibRequest object holding the varbind list
919 * concerning this MIB.
920 *
921 * @return The request-tree where the original varbind list has been
922 * dispatched to the appropriate nodes, and where the original
923 * OIDs have been replaced with the correct "next" OID.
924 */
925 private SnmpRequestTree getGetNextHandlers(SnmpMibRequest req)
926 throws SnmpStatusException {
927
928 // Creates an empty request tree, no entry creation is allowed (false)
929 SnmpRequestTree handlers = new
930 SnmpRequestTree(req,false,SnmpDefinitions.pduGetNextRequestPdu);
931
932 // Sets the getNext flag: if version=V2, status exception are
933 // transformed in endOfMibView
934 handlers.setGetNextFlag();
935
936 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
937 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMib.class.getName(),
938 "getGetNextHandlers", "Received MIB request : " + req);
939 }
940 AcmChecker checker = new AcmChecker(req);
941 int index=0;
942 SnmpVarBind var = null;
943 final int ver= req.getVersion();
944 SnmpOid original = null;
945 // For each varbind, finds the handling node.
946 // This function has the side effect of transforming a GET-NEXT
947 // request into a valid GET request, replacing the OIDs in the
948 // original GET-NEXT request with the OID of the first leaf that
949 // follows.
950 for (Enumeration e= req.getElements(); e.hasMoreElements(); index++) {
951
952 var = (SnmpVarBind) e.nextElement();
953 SnmpOid result = null;
954 try {
955 // Find the node handling the OID that follows the varbind
956 // OID. `result' contains this next leaf OID.
957 //ACM loop.
958 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
959 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
960 SnmpMib.class.getName(),
961 "getGetNextHandlers", " Next OID of : " + var.oid);
962 }
963 result = new SnmpOid(root.findNextHandlingNode
964 (var,var.oid.longValue(false),0,
965 0,handlers, checker));
966
967 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
968 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
969 SnmpMib.class.getName(),
970 "getGetNextHandlers", " is : " + result);
971 }
972 // We replace the varbind original OID with the OID of the
973 // leaf object we have to return.
974 var.oid = result;
975 } catch(SnmpStatusException x) {
976
977 // if (isDebugOn())
978 // debug("getGetNextHandlers",
979 // "Couldn't find a handling node for "
980 // + var.oid.toString());
981
982 if (ver == SnmpDefinitions.snmpVersionOne) {
983 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
984 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
985 SnmpMib.class.getName(),
986 "getGetNextHandlers",
987 "\tThrowing exception " + x.toString());
988 }
989 // The index in the exception must correspond to the
990 // SNMP index ...
991 //
992 throw new SnmpStatusException(x, index + 1);
993 }
994 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
995 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST,
996 SnmpMib.class.getName(),
997 "getGetNextHandlers",
998 "Exception : " + x.getStatus());
999 }
1000
1001 var.setSnmpValue(SnmpVarBind.endOfMibView);
1002 }
1003 }
1004 return handlers;
1005 }
1006
1007 // --------------------------------------------------------------------
1008 // PROTECTED VARIABLES
1009 // --------------------------------------------------------------------
1010
1011 /**
1012 * The top element in the Mib tree.
1013 * @serial
1014 */
1015 protected SnmpMibOid root;
1016
1017
1018 // --------------------------------------------------------------------
1019 // PRIVATE VARIABLES
1020 // --------------------------------------------------------------------
1021
1022 /**
1023 * The root object identifier of the MIB.
1024 */
1025 private transient long[] rootOid= null;
1026}