1 /*
   2  * Copyright (c) 1998, 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.Enumeration;
  36 
  37 // jmx imports
  38 //
  39 import javax.management.MBeanServer;
  40 import javax.management.MBeanRegistration;
  41 import javax.management.ObjectName;
  42 import javax.management.InstanceNotFoundException;
  43 import javax.management.ServiceNotFoundException;
  44 import javax.management.ReflectionException;
  45 import javax.management.MBeanException;
  46 import com.sun.jmx.snmp.SnmpVarBind;
  47 import com.sun.jmx.snmp.SnmpDefinitions;
  48 import com.sun.jmx.snmp.SnmpStatusException;
  49 import com.sun.jmx.snmp.SnmpPdu;
  50 import com.sun.jmx.snmp.SnmpOid;
  51 import com.sun.jmx.snmp.SnmpEngine;
  52 
  53 /**
  54  * Abstract class for representing an SNMP agent.
  55  *
  56  * The class is used by the SNMP protocol adaptor as the entry point in
  57  * the SNMP agent to query.
  58  *
  59  * <p><b>This API is a Sun Microsystems internal API  and is subject
  60  * to change without notice.</b></p>
  61  */
  62 @SuppressWarnings("serial") // JDK implementation class
  63 public abstract class SnmpMibAgent
  64     implements SnmpMibAgentMBean, MBeanRegistration, Serializable {
  65 
  66     /**
  67      * Default constructor.
  68      */
  69     public SnmpMibAgent() {
  70     }
  71 
  72     // ---------------------------------------------------------------------
  73     // PUBLIC METHODS
  74     //----------------------------------------------------------------------
  75 
  76     /**
  77      * Initializes the MIB (with no registration of the MBeans into the
  78      * MBean server).
  79      *
  80      * @exception IllegalAccessException The MIB can not be initialized.
  81      */
  82     public abstract void init() throws IllegalAccessException;
  83 
  84     /**
  85      * Initializes the MIB but each single MBean representing the MIB
  86      * is inserted into the MBean server.
  87      *
  88      * @param server The MBean server to register the service with.
  89      * @param name The object name.
  90      *
  91      * @return The name of the SNMP MIB registered.
  92      *
  93      * @exception java.lang.Exception
  94      */
  95     @Override
  96     public abstract ObjectName preRegister(MBeanServer server,
  97                                            ObjectName name)
  98         throws java.lang.Exception;
  99 
 100     /**
 101      * Not used in this context.
 102      */
 103     @Override
 104     public void postRegister (Boolean registrationDone) {
 105     }
 106 
 107     /**
 108      * Not used in this context.
 109      */
 110     @Override
 111     public void preDeregister() throws java.lang.Exception {
 112     }
 113 
 114     /**
 115      * Not used in this context.
 116      */
 117     @Override
 118     public void postDeregister() {
 119     }
 120 
 121     /**
 122      * Processes a <CODE>get</CODE> operation.
 123      * This method must update the SnmpVarBinds contained in the
 124      * <var>{@link SnmpMibRequest} req</var> parameter.
 125      *
 126      * @param req The SnmpMibRequest object holding the list of variable to
 127      *            be retrieved. This list is composed of
 128      *            <CODE>SnmpVarBind</CODE> objects.
 129      *
 130      * @exception SnmpStatusException An error occurred during the operation.
 131      */
 132     @Override
 133     public abstract void get(SnmpMibRequest req)
 134         throws SnmpStatusException;
 135 
 136     /**
 137      * Processes a <CODE>getNext</CODE> operation.
 138      * This method must update the SnmpVarBinds contained in the
 139      * <var>{@link SnmpMibRequest} req</var> parameter.
 140      *
 141      * @param req The SnmpMibRequest object holding the list of
 142      *            OIDs from which the next variables should be retrieved.
 143      *            This list is composed of <CODE>SnmpVarBind</CODE> objects.
 144      *
 145      * @exception SnmpStatusException An error occurred during the operation.
 146      */
 147     @Override
 148     public abstract void getNext(SnmpMibRequest req)
 149         throws SnmpStatusException;
 150 
 151     /**
 152      * Processes a <CODE>getBulk</CODE> operation.
 153      * This method must update the SnmpVarBinds contained in the
 154      * <var>{@link SnmpMibRequest} req</var> parameter.
 155      *
 156      * @param req The SnmpMibRequest object holding the list of variable to
 157      *            be retrieved. This list is composed of
 158      *            <CODE>SnmpVarBind</CODE> objects.
 159      *
 160      * @param nonRepeat The number of variables, starting with the first
 161      *    variable in the variable-bindings, for which a single
 162      *    lexicographic successor is requested.
 163      *
 164      * @param maxRepeat The number of lexicographic successors requested
 165      *    for each of the last R variables. R is the number of variables
 166      *    following the first <CODE>nonRepeat</CODE> variables for which
 167      *    multiple lexicographic successors are requested.
 168      *
 169      * @exception SnmpStatusException An error occurred during the operation.
 170      */
 171     @Override
 172     public abstract void getBulk(SnmpMibRequest req, int nonRepeat,
 173                                  int maxRepeat)
 174         throws SnmpStatusException;
 175 
 176     /**
 177      * Processes a <CODE>set</CODE> operation.
 178      * This method must update the SnmpVarBinds contained in the
 179      * <var>{@link SnmpMibRequest} req</var> parameter.
 180      * This method is called during the second phase of the SET two-phase
 181      * commit.
 182      *
 183      * @param req The SnmpMibRequest object holding the list of variable to
 184      *            be set. This list is composed of
 185      *            <CODE>SnmpVarBind</CODE> objects.
 186      *
 187      * @exception SnmpStatusException An error occurred during the operation.
 188      *            Throwing an exception in this method will break the
 189      *            atomicity of the SET operation. Care must be taken so that
 190      *            the exception is thrown in the {@link #check(SnmpMibRequest)}
 191      *            method instead.
 192      */
 193     @Override
 194     public abstract void set(SnmpMibRequest req)
 195         throws SnmpStatusException;
 196 
 197 
 198     /**
 199      * Checks if a <CODE>set</CODE> operation can be performed.
 200      * If the operation can not be performed, the method should throw an
 201      * <CODE>SnmpStatusException</CODE>.
 202      * This method is called during the first phase of the SET two-phase
 203      * commit.
 204      *
 205      * @param req The SnmpMibRequest object holding the list of variable to
 206      *            be set. This list is composed of
 207      *            <CODE>SnmpVarBind</CODE> objects.
 208      *
 209      * @exception SnmpStatusException The <CODE>set</CODE> operation
 210      *    cannot be performed.
 211      */
 212     @Override
 213     public abstract void check(SnmpMibRequest req)
 214         throws SnmpStatusException;
 215 
 216     /**
 217      * Gets the root object identifier of the MIB.
 218      * <P>The root object identifier is the object identifier uniquely
 219      * identifying the MIB.
 220      *
 221      * @return The root object identifier.
 222      */
 223     public abstract long[] getRootOid();
 224 
 225     // ---------------------------------------------------------------------
 226     // GETTERS AND SETTERS
 227     // ---------------------------------------------------------------------
 228 
 229     /**
 230      * Gets the reference to the MBean server in which the SNMP MIB is
 231      * registered.
 232      *
 233      * @return The MBean server or null if the MIB is not registered in any
 234      *     MBean server.
 235      */
 236     @Override
 237     public MBeanServer getMBeanServer() {
 238         return server;
 239     }
 240 
 241     /**
 242      * Gets the reference to the SNMP protocol adaptor to which the MIB is
 243      * bound.
 244      *
 245      * @return The SNMP MIB handler.
 246      */
 247     @Override
 248     public SnmpMibHandler getSnmpAdaptor() {
 249         return adaptor;
 250     }
 251 
 252     /**
 253      * Sets the reference to the SNMP protocol adaptor through which the MIB
 254      * will be SNMP accessible and add this new MIB in the SNMP MIB handler.
 255      *
 256      * @param stack The SNMP MIB handler.
 257      */
 258     @Override
 259     public void setSnmpAdaptor(SnmpMibHandler stack) {
 260         if (adaptor != null) {
 261             adaptor.removeMib(this);
 262         }
 263         adaptor = stack;
 264         if (adaptor != null) {
 265             adaptor.addMib(this);
 266         }
 267     }
 268 
 269      /**
 270      * Sets the reference to the SNMP protocol adaptor through which the MIB
 271      * will be SNMP accessible and add this new MIB in the SNMP MIB handler.
 272      * This method is to be called to set a specific agent to a specific OID. This can be useful when dealing with MIB overlapping.
 273      * Some OID can be implemented in more than one MIB. In this case, the OID nearest the agent will be used on SNMP operations.
 274      * @param stack The SNMP MIB handler.
 275      * @param oids The set of OIDs this agent implements.
 276      *
 277      * @since 1.5
 278      */
 279     @Override
 280     public void setSnmpAdaptor(SnmpMibHandler stack, SnmpOid[] oids) {
 281         if (adaptor != null) {
 282             adaptor.removeMib(this);
 283         }
 284         adaptor = stack;
 285         if (adaptor != null) {
 286             adaptor.addMib(this, oids);
 287         }
 288     }
 289 
 290     /**
 291      * Sets the reference to the SNMP protocol adaptor through which the MIB
 292      * will be SNMP accessible and adds this new MIB in the SNMP MIB handler.
 293      * Adds a new contextualized MIB in the SNMP MIB handler.
 294      *
 295      * @param stack The SNMP MIB handler.
 296      * @param contextName The MIB context name. If null is passed, will be registered in the default context.
 297      *
 298      * @exception IllegalArgumentException If the parameter is null.
 299      *
 300      * @since 1.5
 301      */
 302     @Override
 303     public void setSnmpAdaptor(SnmpMibHandler stack, String contextName) {
 304         if (adaptor != null) {
 305             adaptor.removeMib(this, contextName);
 306         }
 307         adaptor = stack;
 308         if (adaptor != null) {
 309             adaptor.addMib(this, contextName);
 310         }
 311     }
 312     /**
 313      * Sets the reference to the SNMP protocol adaptor through which the MIB
 314      * will be SNMP accessible and adds this new MIB in the SNMP MIB handler.
 315      * Adds a new contextualized MIB in the SNMP MIB handler.
 316      *
 317      * @param stack The SNMP MIB handler.
 318      * @param contextName The MIB context name. If null is passed, will be registered in the default context.
 319      * @param oids The set of OIDs this agent implements.
 320      * @exception IllegalArgumentException If the parameter is null.
 321      *
 322      * @since 1.5
 323      */
 324     @Override
 325     public void setSnmpAdaptor(SnmpMibHandler stack,
 326                                String contextName,
 327                                SnmpOid[] oids) {
 328         if (adaptor != null) {
 329             adaptor.removeMib(this, contextName);
 330         }
 331         adaptor = stack;
 332         if (adaptor != null) {
 333             adaptor.addMib(this, contextName, oids);
 334         }
 335     }
 336 
 337     /**
 338      * Gets the object name of the SNMP protocol adaptor to which the MIB
 339      * is bound.
 340      *
 341      * @return The name of the SNMP protocol adaptor.
 342      */
 343     @Override
 344     public ObjectName getSnmpAdaptorName() {
 345         return adaptorName;
 346     }
 347 
 348     /**
 349      * Sets the reference to the SNMP protocol adaptor through which the MIB
 350      * will be SNMP accessible and add this new MIB in the SNMP MIB handler
 351      * associated to the specified <CODE>name</CODE>.
 352      *
 353      * @param name The name of the SNMP protocol adaptor.
 354      *
 355      * @exception InstanceNotFoundException The SNMP protocol adaptor does
 356      *     not exist in the MBean server.
 357      *
 358      * @exception ServiceNotFoundException This SNMP MIB is not registered
 359      *     in the MBean server or the requested service is not supported.
 360      */
 361     @Override
 362     public void setSnmpAdaptorName(ObjectName name)
 363         throws InstanceNotFoundException, ServiceNotFoundException {
 364 
 365         if (server == null) {
 366             throw new ServiceNotFoundException(mibName + " is not registered in the MBean server");
 367         }
 368         // First remove the reference on the old adaptor server.
 369         //
 370         if (adaptor != null) {
 371             adaptor.removeMib(this);
 372         }
 373 
 374         // Then update the reference to the new adaptor server.
 375         //
 376         Object[] params = {this};
 377         String[] signature = {"com.sun.jmx.snmp.agent.SnmpMibAgent"};
 378         try {
 379             adaptor = (SnmpMibHandler)(server.invoke(name, "addMib", params,
 380                                                      signature));
 381         } catch (InstanceNotFoundException e) {
 382             throw new InstanceNotFoundException(name.toString());
 383         } catch (ReflectionException e) {
 384             throw new ServiceNotFoundException(name.toString());
 385         } catch (MBeanException e) {
 386             // Should never occur...
 387         }
 388 
 389         adaptorName = name;
 390     }
 391     /**
 392      * Sets the reference to the SNMP protocol adaptor through which the MIB
 393      * will be SNMP accessible and add this new MIB in the SNMP MIB handler
 394      * associated to the specified <CODE>name</CODE>.
 395      * This method is to be called to set a specific agent to a specific OID. This can be useful when dealing with MIB overlapping.
 396      * Some OID can be implemented in more than one MIB. In this case, the OID nearer agent will be used on SNMP operations.
 397      * @param name The name of the SNMP protocol adaptor.
 398      * @param oids The set of OIDs this agent implements.
 399      * @exception InstanceNotFoundException The SNMP protocol adaptor does
 400      *     not exist in the MBean server.
 401      *
 402      * @exception ServiceNotFoundException This SNMP MIB is not registered
 403      *     in the MBean server or the requested service is not supported.
 404      *
 405      * @since 1.5
 406      */
 407     @Override
 408     public void setSnmpAdaptorName(ObjectName name, SnmpOid[] oids)
 409         throws InstanceNotFoundException, ServiceNotFoundException {
 410 
 411         if (server == null) {
 412             throw new ServiceNotFoundException(mibName + " is not registered in the MBean server");
 413         }
 414         // First remove the reference on the old adaptor server.
 415         //
 416         if (adaptor != null) {
 417             adaptor.removeMib(this);
 418         }
 419 
 420         // Then update the reference to the new adaptor server.
 421         //
 422         Object[] params = {this, oids};
 423         String[] signature = {"com.sun.jmx.snmp.agent.SnmpMibAgent",
 424         oids.getClass().getName()};
 425         try {
 426             adaptor = (SnmpMibHandler)(server.invoke(name, "addMib", params,
 427                                                      signature));
 428         } catch (InstanceNotFoundException e) {
 429             throw new InstanceNotFoundException(name.toString());
 430         } catch (ReflectionException e) {
 431             throw new ServiceNotFoundException(name.toString());
 432         } catch (MBeanException e) {
 433             // Should never occur...
 434         }
 435 
 436         adaptorName = name;
 437     }
 438     /**
 439      * Sets the reference to the SNMP protocol adaptor through which the MIB
 440      * will be SNMP accessible and add this new MIB in the SNMP MIB handler
 441      * associated to the specified <CODE>name</CODE>.
 442      *
 443      * @param name The name of the SNMP protocol adaptor.
 444      * @param contextName The MIB context name. If null is passed, will be registered in the default context.
 445      * @exception InstanceNotFoundException The SNMP protocol adaptor does
 446      *     not exist in the MBean server.
 447      *
 448      * @exception ServiceNotFoundException This SNMP MIB is not registered
 449      *     in the MBean server or the requested service is not supported.
 450      *
 451      * @since 1.5
 452      */
 453     @Override
 454     public void setSnmpAdaptorName(ObjectName name, String contextName)
 455         throws InstanceNotFoundException, ServiceNotFoundException {
 456 
 457         if (server == null) {
 458             throw new ServiceNotFoundException(mibName + " is not registered in the MBean server");
 459         }
 460 
 461         // First remove the reference on the old adaptor server.
 462         //
 463         if (adaptor != null) {
 464             adaptor.removeMib(this, contextName);
 465         }
 466 
 467         // Then update the reference to the new adaptor server.
 468         //
 469         Object[] params = {this, contextName};
 470         String[] signature = {"com.sun.jmx.snmp.agent.SnmpMibAgent", "java.lang.String"};
 471         try {
 472             adaptor = (SnmpMibHandler)(server.invoke(name, "addMib", params,
 473                                                      signature));
 474         } catch (InstanceNotFoundException e) {
 475             throw new InstanceNotFoundException(name.toString());
 476         } catch (ReflectionException e) {
 477             throw new ServiceNotFoundException(name.toString());
 478         } catch (MBeanException e) {
 479             // Should never occur...
 480         }
 481 
 482         adaptorName = name;
 483     }
 484 
 485     /**
 486      * Sets the reference to the SNMP protocol adaptor through which the MIB
 487      * will be SNMP accessible and add this new MIB in the SNMP MIB handler
 488      * associated to the specified <CODE>name</CODE>.
 489      *
 490      * @param name The name of the SNMP protocol adaptor.
 491      * @param contextName The MIB context name. If null is passed, will be registered in the default context.
 492      * @param oids The set of OIDs this agent implements.
 493      * @exception InstanceNotFoundException The SNMP protocol adaptor does
 494      *     not exist in the MBean server.
 495      *
 496      * @exception ServiceNotFoundException This SNMP MIB is not registered
 497      *     in the MBean server or the requested service is not supported.
 498      *
 499      * @since 1.5
 500      */
 501     @Override
 502     public void setSnmpAdaptorName(ObjectName name,
 503                                    String contextName, SnmpOid[] oids)
 504         throws InstanceNotFoundException, ServiceNotFoundException {
 505 
 506         if (server == null) {
 507             throw new ServiceNotFoundException(mibName + " is not registered in the MBean server");
 508         }
 509 
 510         // First remove the reference on the old adaptor server.
 511         //
 512         if (adaptor != null) {
 513             adaptor.removeMib(this, contextName);
 514         }
 515 
 516         // Then update the reference to the new adaptor server.
 517         //
 518         Object[] params = {this, contextName, oids};
 519         String[] signature = {"com.sun.jmx.snmp.agent.SnmpMibAgent", "java.lang.String", oids.getClass().getName()};
 520         try {
 521             adaptor = (SnmpMibHandler)(server.invoke(name, "addMib", params,
 522                                                      signature));
 523         } catch (InstanceNotFoundException e) {
 524             throw new InstanceNotFoundException(name.toString());
 525         } catch (ReflectionException e) {
 526             throw new ServiceNotFoundException(name.toString());
 527         } catch (MBeanException e) {
 528             // Should never occur...
 529         }
 530 
 531         adaptorName = name;
 532     }
 533 
 534     /**
 535      * Indicates whether or not the MIB module is bound to a SNMP protocol
 536      * adaptor.
 537      * As a reminder, only bound MIBs can be accessed through SNMP protocol
 538      * adaptor.
 539      *
 540      * @return <CODE>true</CODE> if the MIB module is bound,
 541      *         <CODE>false</CODE> otherwise.
 542      */
 543     @Override
 544     public boolean getBindingState() {
 545         if (adaptor == null)
 546             return false;
 547         else
 548             return true;
 549     }
 550 
 551     /**
 552      * Gets the MIB name.
 553      *
 554      * @return The MIB name.
 555      */
 556     @Override
 557     public String getMibName() {
 558         return mibName;
 559     }
 560 
 561     /**
 562      * This is a factory method for creating new SnmpMibRequest objects.
 563      * @param reqPdu The received PDU.
 564      * @param vblist   The vector of SnmpVarBind objects in which the
 565      *        MIB concerned by this request is involved.
 566      * @param version  The protocol version of the SNMP request.
 567      * @param userData User allocated contextual data.
 568      *
 569      * @return A new SnmpMibRequest object.
 570      *
 571      * @since 1.5
 572      **/
 573     public static SnmpMibRequest newMibRequest(SnmpPdu reqPdu,
 574                                                Vector<SnmpVarBind> vblist,
 575                                                int version,
 576                                                Object userData)
 577     {
 578         return new SnmpMibRequestImpl(null,
 579                                       reqPdu,
 580                                       vblist,
 581                                       version,
 582                                       userData,
 583                                       null,
 584                                       SnmpDefinitions.noAuthNoPriv,
 585                                       getSecurityModel(version),
 586                                       null,null);
 587     }
 588     /**
 589      * This is a factory method for creating new SnmpMibRequest objects.
 590      * @param engine The local engine.
 591      * @param reqPdu The received pdu.
 592      * @param vblist The vector of SnmpVarBind objects in which the
 593      *        MIB concerned by this request is involved.
 594      * @param version The protocol version of the SNMP request.
 595      * @param userData User allocated contextual data.
 596      *
 597      * @return A new SnmpMibRequest object.
 598      *
 599      * @since 1.5
 600      **/
 601     public static SnmpMibRequest newMibRequest(SnmpEngine engine,
 602                                                SnmpPdu reqPdu,
 603                                                Vector<SnmpVarBind> vblist,
 604                                                int version,
 605                                                Object userData,
 606                                                String principal,
 607                                                int securityLevel,
 608                                                int securityModel,
 609                                                byte[] contextName,
 610                                                byte[] accessContextName) {
 611         return new SnmpMibRequestImpl(engine,
 612                                       reqPdu,
 613                                       vblist,
 614                                       version,
 615                                       userData,
 616                                       principal,
 617                                       securityLevel,
 618                                       securityModel,
 619                                       contextName,
 620                                       accessContextName);
 621     }
 622     // ---------------------------------------------------------------------
 623     // PACKAGE METHODS
 624     // ---------------------------------------------------------------------
 625 
 626     /**
 627      * Processes a <CODE>getBulk</CODE> operation using call to
 628      * <CODE>getNext</CODE>.
 629      * The method implements the <CODE>getBulk</CODE> operation by calling
 630      * appropriately the <CODE>getNext</CODE> method.
 631      *
 632      * @param req The SnmpMibRequest containing the variable list to be
 633      *        retrieved.
 634      *
 635      * @param nonRepeat The number of variables, starting with the first
 636      *    variable in the variable-bindings, for which a single lexicographic
 637      *    successor is requested.
 638      *
 639      * @param maxRepeat The number of lexicographic successors
 640      *    requested for each of the last R variables. R is the number of
 641      *    variables following the first nonRepeat variables for which
 642      *    multiple lexicographic successors are requested.
 643      *
 644      * @return The variable list containing returned values.
 645      *
 646      * @exception SnmpStatusException An error occurred during the operation.
 647      */
 648     void getBulkWithGetNext(SnmpMibRequest req, int nonRepeat, int maxRepeat)
 649         throws SnmpStatusException {
 650         final Vector<SnmpVarBind> list = req.getSubList();
 651 
 652         // RFC 1905, Section 4.2.3, p14
 653         final int L = list.size() ;
 654         final int N = Math.max(Math.min(nonRepeat, L), 0) ;
 655         final int M = Math.max(maxRepeat, 0) ;
 656         final int R = L - N ;
 657 
 658         // Let's build the varBindList for the response pdu
 659         //
 660         // int errorStatus = SnmpDefinitions.snmpRspNoError ;
 661         // int errorIndex = 0 ;
 662         if (L != 0) {
 663 
 664             // Non-repeaters and first row of repeaters
 665             //
 666             getNext(req);
 667 
 668             // Now the remaining repeaters
 669             //
 670             Vector<SnmpVarBind> repeaters= splitFrom(list, N);
 671             SnmpMibRequestImpl repeatedReq =
 672                 new SnmpMibRequestImpl(req.getEngine(),
 673                                        req.getPdu(),
 674                                        repeaters,
 675                                        SnmpDefinitions.snmpVersionTwo,
 676                                        req.getUserData(),
 677                                        req.getPrincipal(),
 678                                        req.getSecurityLevel(),
 679                                        req.getSecurityModel(),
 680                                        req.getContextName(),
 681                                        req.getAccessContextName());
 682             for (int i = 2 ; i <= M ; i++) {
 683                 getNext(repeatedReq);
 684                 concatVector(req, repeaters);
 685             }
 686         }
 687     }
 688 
 689 
 690     // ---------------------------------------------------------------------
 691     // PRIVATE METHODS
 692     // ---------------------------------------------------------------------
 693 
 694     /**
 695      * This method creates a new Vector which does not contain the first
 696      * element up to the specified limit.
 697      *
 698      * @param original The original vector.
 699      * @param limit The limit.
 700      */
 701     private Vector<SnmpVarBind> splitFrom(Vector<SnmpVarBind> original, int limit) {
 702 
 703         int max= original.size();
 704         Vector<SnmpVarBind> result= new Vector<>(max - limit);
 705         int i= limit;
 706 
 707         // Ok the loop looks a bit strange. But in order to improve the
 708         // perf, we try to avoid reference to the limit variable from
 709         // within the loop ...
 710         //
 711         for(Enumeration<SnmpVarBind> e= original.elements(); e.hasMoreElements(); --i) {
 712             SnmpVarBind var= e.nextElement();
 713             if (i >0)
 714                 continue;
 715             result.addElement(new SnmpVarBind(var.oid, var.value));
 716         }
 717         return result;
 718     }
 719 
 720     private void concatVector(SnmpMibRequest req, Vector<SnmpVarBind> source) {
 721         for(Enumeration<SnmpVarBind> e= source.elements(); e.hasMoreElements(); ) {
 722             SnmpVarBind var= e.nextElement();
 723             // We need to duplicate the SnmpVarBind otherwise it is going
 724             // to be overloaded by the next get Next ...
 725             req.addVarBind(new SnmpVarBind(var.oid, var.value));
 726         }
 727     }
 728 
 729     private static int getSecurityModel(int version) {
 730         switch(version) {
 731         case SnmpDefinitions.snmpVersionOne:
 732             return SnmpDefinitions.snmpV1SecurityModel;
 733         default:
 734             return SnmpDefinitions.snmpV2SecurityModel;
 735         }
 736     }
 737 
 738     // ---------------------------------------------------------------------
 739     // PROTECTED VARIABLES
 740     // ---------------------------------------------------------------------
 741 
 742     /**
 743      * The object name of the MIB.
 744      * @serial
 745      */
 746     protected String mibName;
 747 
 748     /**
 749      * The reference to the MBean server.
 750      * @serial
 751      */
 752     protected MBeanServer server;
 753 
 754     // ---------------------------------------------------------------------
 755     // PRIVATE VARIABLES
 756     // ---------------------------------------------------------------------
 757 
 758     /**
 759      * The object name of the SNMP protocol adaptor.
 760      * @serial
 761      */
 762     private ObjectName adaptorName;
 763 
 764     /**
 765      * The reference to the SNMP stack.
 766      */
 767     private transient SnmpMibHandler adaptor;
 768 }