Package com.sun.jmx.snmp.daemon

Source Code of com.sun.jmx.snmp.daemon.SnmpSubRequestHandler$NonSyncVector

/*
* @(#)file      SnmpSubRequestHandler.java
* @(#)author    Sun Microsystems, Inc.
* @(#)version   4.38
* @(#)date      09/10/11
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*/


package com.sun.jmx.snmp.daemon;



// java import
//
import java.util.Vector;

// jmx imports
//
import com.sun.jmx.snmp.SnmpPdu;
import com.sun.jmx.snmp.SnmpVarBind;
import com.sun.jmx.snmp.SnmpDefinitions;
import com.sun.jmx.snmp.SnmpStatusException;
import com.sun.jmx.snmp.SnmpEngine;

// RI imports
//
import com.sun.jmx.trace.Trace;

// SNMP Runtime import
//
import com.sun.jmx.snmp.agent.SnmpMibAgent;
import com.sun.jmx.snmp.agent.SnmpMibRequest;
import com.sun.jmx.snmp.ThreadContext;
import com.sun.jmx.snmp.internal.SnmpIncomingRequest;

class SnmpSubRequestHandler implements SnmpDefinitions, Runnable {
   
    protected SnmpIncomingRequest incRequest = null;
    protected SnmpEngine engine = null;
    /**
     * V3 enabled Adaptor. Each Oid is added using updateRequest method.
     */
    protected SnmpSubRequestHandler(SnmpEngine engine,
            SnmpIncomingRequest incRequest,
            SnmpMibAgent agent,
            SnmpPdu req) {
        this(agent, req);
  init(engine, incRequest);
    }
   
    /**
     * V3 enabled Adaptor.
     */
    protected SnmpSubRequestHandler(SnmpEngine engine,
            SnmpIncomingRequest incRequest,
            SnmpMibAgent agent,
            SnmpPdu req,
            boolean nouse) {
        this(agent, req, nouse);
  init(engine, incRequest);
    }
    /**
     * SNMP V1/V2 . To be called with updateRequest.
     */
    protected SnmpSubRequestHandler(SnmpMibAgent agent, SnmpPdu req) {
       
        dbgTag = makeDebugTag();
        if (isTraceOn()) {
            trace("constructor", "creating instance for request " + String.valueOf(req.requestId));
        }
 
        version= req.version;
        type= req.type;
        this.agent= agent;
 
  // We get a ref on the pdu in order to pass it to SnmpMibRequest.
  reqPdu = req;
 
        //Pre-allocate room for storing varbindlist and translation table.
        //
        int length= req.varBindList.length;
        translation= new int[length];
        varBind= new NonSyncVector(length);
    }

    /**
     * SNMP V1/V2 The constuctor initialize the subrequest with the whole varbind list contained
     * in the original request.
     */
    protected SnmpSubRequestHandler(SnmpMibAgent agent,
            SnmpPdu req,
            boolean nouse) {
        this(agent,req);
   
        // The translation table is easy in this case ...
        //
        int max= translation.length;
        SnmpVarBind[] list= req.varBindList;
        for(int i=0; i < max; i++) {
            translation[i]= i;
            ((NonSyncVector)varBind).addNonSyncElement(list[i]);
        }
    }

    SnmpMibRequest createMibRequest(Vector vblist,
            int protocolVersion,
            Object userData) {

  // This is an optimization:
  //    The SnmpMibRequest created in the check() phase is
  //    reused in the set() phase.
  //
  if (type == pduSetRequestPdu && mibRequest != null)
      return mibRequest;
 
  //This is a request comming from an SnmpV3AdaptorServer.
  //Full power.
  SnmpMibRequest result = null;
  if(incRequest != null) {
      result = SnmpMibAgent.newMibRequest(engine,
            reqPdu,
            vblist,
            protocolVersion,
            userData,
            incRequest.getPrincipal(),
            incRequest.getSecurityLevel(),
            incRequest.getSecurityModel(),
            incRequest.getContextName(),
            incRequest.getAccessContext());
  } else {
      result = SnmpMibAgent.newMibRequest(reqPdu,
            vblist,
            protocolVersion,
            userData);
  }
  // If we're doing the check() phase, we store the SnmpMibRequest
  // so that we can reuse it in the set() phase.
  //
  if (type == pduWalkRequest)
      mibRequest = result;

  return result;
    }

    void setUserData(Object userData) {
  data = userData;
    }

    public void run() {
   
        try {
      final ThreadContext oldContext =
    ThreadContext.push("SnmpUserData",data);
      try {
    switch(type) {
    case pduGetRequestPdu:
        // Invoke a get operation
        //
        if (isTraceOn()) {
      trace("run", "[" + Thread.currentThread() +
            "]:get operation on " + agent.getMibName());
        }
   
        agent.get(createMibRequest(varBind,version,data));
        break;
 
    case pduGetNextRequestPdu:
        if (isTraceOn()) {
      trace("run", "[" + Thread.currentThread() +
            "]:getNext operation on " + agent.getMibName());
        }
        //#ifdef DEBUG
        agent.getNext(createMibRequest(varBind,version,data));
        break;
       
    case pduSetRequestPdu:
        if (isTraceOn()) {
      trace("run", "[" + Thread.currentThread() +
            "]:set operation on " + agent.getMibName());
        }
        agent.set(createMibRequest(varBind,version,data));
        break;
       
    case pduWalkRequest:
        if (isTraceOn()) {
      trace("run", "[" + Thread.currentThread() +
            "]:check operation on " + agent.getMibName());
        }
        agent.check(createMibRequest(varBind,version,data));
        break;
       
    default:
        if (isDebugOn()) {
      debug("run", "[" + Thread.currentThread() +
            "]:unknown operation (" +  type + ") on " +
            agent.getMibName());
        }
        errorStatus= snmpRspGenErr;
        errorIndex= 1;
        break;
       
    }// end of switch
   
      } finally {
    ThreadContext.restore(oldContext);
      }
  } catch(SnmpStatusException x) {
      errorStatus = x.getStatus() ;
      errorIndex=  x.getErrorIndex();
      if (isDebugOn()) {
    debug("run", "[" + Thread.currentThread() +
          "]:an Snmp error occured during the operation");
    debug("run", x);
      }
  }
  catch(Exception x) {
      errorStatus = SnmpDefinitions.snmpRspGenErr ;
      if (isTraceOn()) {
    trace("run", "[" + Thread.currentThread() +
          "]:a generic error occured during the operation");
      }
      if (isDebugOn()) {
    debug("run", "Error is: " + x);
    debug("run", x);
      }
  }
  if (isTraceOn()) {
      trace("run", "[" + Thread.currentThread() +
      "]:operation completed");
  }
    }
   
    // -------------------------------------------------------------
    //
    // This function does a best-effort to map global error status
    // to SNMP v1 valid global error status.
    //
    // An SnmpStatusException can contain either:
    // <li> v2 local error codes (that should be stored in the varbind)</li>
    // <li> v2 global error codes </li>
    // <li> v1 global error codes </li>
    //
    // v2 local error codes (noSuchInstance, noSuchObject) are
    // transformed in a global v1 snmpRspNoSuchName error.
    //
    // v2 global error codes are transformed in the following way:
    //   
    //    If the request was a GET/GETNEXT then either
    //         snmpRspNoSuchName or snmpRspGenErr is returned.
    //
    //    Otherwise:
    //      snmpRspNoAccess, snmpRspInconsistentName
    //               => snmpRspNoSuchName
    //      snmpRspAuthorizationError, snmpRspNotWritable, snmpRspNoCreation
    //               => snmpRspReadOnly  (snmpRspNoSuchName for GET/GETNEXT)
    //      snmpRspWrong*
    //               => snmpRspBadValue  (snmpRspNoSuchName for GET/GETNEXT)
    //      snmpRspResourceUnavailable, snmpRspRspCommitFailed,
    //      snmpRspUndoFailed
    //                  => snmpRspGenErr
    //
    // -------------------------------------------------------------
    //
    static final int mapErrorStatusToV1(int errorStatus, int reqPduType) {
  // Map v2 codes onto v1 codes
  //
        if (errorStatus == SnmpDefinitions.snmpRspNoError)
            return SnmpDefinitions.snmpRspNoError;

        if (errorStatus == SnmpDefinitions.snmpRspGenErr)
            return SnmpDefinitions.snmpRspGenErr;

        if (errorStatus == SnmpDefinitions.snmpRspNoSuchName)
            return SnmpDefinitions.snmpRspNoSuchName;
 
  if ((errorStatus == SnmpStatusException.noSuchInstance) ||
      (errorStatus == SnmpStatusException.noSuchObject)   ||
      (errorStatus == SnmpDefinitions.snmpRspNoAccess)    ||
      (errorStatus == SnmpDefinitions.snmpRspInconsistentName) ||
      (errorStatus == SnmpDefinitions.snmpRspAuthorizationError)){
     
      return SnmpDefinitions.snmpRspNoSuchName;
     
  } else if ((errorStatus ==
        SnmpDefinitions.snmpRspAuthorizationError)         ||
       (errorStatus == SnmpDefinitions.snmpRspNotWritable)) {
     
      if (reqPduType == SnmpDefinitions.pduWalkRequest)
    return SnmpDefinitions.snmpRspReadOnly;
      else
    return SnmpDefinitions.snmpRspNoSuchName;
     
  } else if ((errorStatus == SnmpDefinitions.snmpRspNoCreation)) {
     
    return SnmpDefinitions.snmpRspNoSuchName;

  } else if ((errorStatus == SnmpDefinitions.snmpRspWrongType)      ||
       (errorStatus == SnmpDefinitions.snmpRspWrongLength)    ||
       (errorStatus == SnmpDefinitions.snmpRspWrongEncoding||
       (errorStatus == SnmpDefinitions.snmpRspWrongValue)     ||
       (errorStatus == SnmpDefinitions.snmpRspWrongLength)    ||
       (errorStatus ==
        SnmpDefinitions.snmpRspInconsistentValue)) {
     
      if ((reqPduType == SnmpDefinitions.pduSetRequestPdu) ||
    (reqPduType == SnmpDefinitions.pduWalkRequest))
    return SnmpDefinitions.snmpRspBadValue;
      else
    return SnmpDefinitions.snmpRspNoSuchName;
     
  } else if ((errorStatus ==
        SnmpDefinitions.snmpRspResourceUnavailable) ||
       (errorStatus ==
        SnmpDefinitions.snmpRspCommitFailed)        ||
       (errorStatus == SnmpDefinitions.snmpRspUndoFailed)) {
     
      return SnmpDefinitions.snmpRspGenErr;
     
  }

  // At this point we should have a V1 error code
  //
  if (errorStatus == SnmpDefinitions.snmpRspTooBig)
      return SnmpDefinitions.snmpRspTooBig;

  if( (errorStatus == SnmpDefinitions.snmpRspBadValue) ||
      (errorStatus == SnmpDefinitions.snmpRspReadOnly)) {
      if ((reqPduType == SnmpDefinitions.pduSetRequestPdu) ||
    (reqPduType == SnmpDefinitions.pduWalkRequest))
    return errorStatus;
      else
    return SnmpDefinitions.snmpRspNoSuchName;
  }

  // We have a snmpRspGenErr, or something which is not defined
  // in RFC1905 => return a snmpRspGenErr
  //
  return SnmpDefinitions.snmpRspGenErr;

    }

    // -------------------------------------------------------------
    //
    // This function does a best-effort to map global error status
    // to SNMP v2 valid global error status.
    //
    // An SnmpStatusException can contain either:
    // <li> v2 local error codes (that should be stored in the varbind)</li>
    // <li> v2 global error codes </li>
    // <li> v1 global error codes </li>
    //
    // v2 local error codes (noSuchInstance, noSuchObject)
    // should not raise this level: they should have been stored in the
    // varbind earlier. If they, do there is nothing much we can do except
    // to transform them into:
    // <li> a global snmpRspGenErr (if the request is a GET/GETNEXT) </li>
    // <li> a global snmpRspNoSuchName otherwise. </li>
    //
    // v2 global error codes are transformed in the following way:
    //   
    //    If the request was a GET/GETNEXT then snmpRspGenErr is returned.
    //    (snmpRspGenErr is the only global error that is expected to be
    //     raised by a GET/GETNEXT request).
    //
    //    Otherwise the v2 code itself is returned
    //
    // v1 global error codes are transformed in the following way:
    //
    //      snmpRspNoSuchName
    //               => snmpRspNoAccess  (snmpRspGenErr for GET/GETNEXT)
    //      snmpRspReadOnly
    //               => snmpRspNotWritable (snmpRspGenErr for GET/GETNEXT)
    //      snmpRspBadValue
    //               => snmpRspWrongValue  (snmpRspGenErr for GET/GETNEXT)
    //
    // -------------------------------------------------------------
    //
    static final int mapErrorStatusToV2(int errorStatus, int reqPduType) {
  // Map v1 codes onto v2 codes
  //
        if (errorStatus == SnmpDefinitions.snmpRspNoError)
            return SnmpDefinitions.snmpRspNoError;

        if (errorStatus == SnmpDefinitions.snmpRspGenErr)
            return SnmpDefinitions.snmpRspGenErr;

        if (errorStatus == SnmpDefinitions.snmpRspTooBig)
            return SnmpDefinitions.snmpRspTooBig;

  // For get / getNext / getBulk the only global error
  // (PDU-level) possible is genErr.
  //
  if ((reqPduType != SnmpDefinitions.pduSetRequestPdu) &&
      (reqPduType != SnmpDefinitions.pduWalkRequest)) {
      if(errorStatus == SnmpDefinitions.snmpRspAuthorizationError)
    return errorStatus;
      else
    return SnmpDefinitions.snmpRspGenErr;
  }

  // Map to noSuchName
  //  if ((errorStatus == SnmpDefinitions.snmpRspNoSuchName) ||
  //   (errorStatus == SnmpStatusException.noSuchInstance) ||
  //  (errorStatus == SnmpStatusException.noSuchObject))
  //  return SnmpDefinitions.snmpRspNoSuchName;

  // SnmpStatusException.noSuchInstance and
  // SnmpStatusException.noSuchObject can't happen...

  if (errorStatus == SnmpDefinitions.snmpRspNoSuchName)
      return SnmpDefinitions.snmpRspNoAccess;

  // Map to notWritable
   if (errorStatus == SnmpDefinitions.snmpRspReadOnly)
    return SnmpDefinitions.snmpRspNotWritable;

  // Map to wrongValue
   if (errorStatus == SnmpDefinitions.snmpRspBadValue)
      return SnmpDefinitions.snmpRspWrongValue;
 
  // Other valid V2 codes
  if ((errorStatus == SnmpDefinitions.snmpRspNoAccess) ||
      (errorStatus == SnmpDefinitions.snmpRspInconsistentName) ||
      (errorStatus == SnmpDefinitions.snmpRspAuthorizationError) ||
      (errorStatus == SnmpDefinitions.snmpRspNotWritable) ||
      (errorStatus == SnmpDefinitions.snmpRspNoCreation) ||
      (errorStatus == SnmpDefinitions.snmpRspWrongType) ||
      (errorStatus == SnmpDefinitions.snmpRspWrongLength) ||
      (errorStatus == SnmpDefinitions.snmpRspWrongEncoding) ||
      (errorStatus == SnmpDefinitions.snmpRspWrongValue) ||
      (errorStatus == SnmpDefinitions.snmpRspWrongLength) ||
      (errorStatus == SnmpDefinitions.snmpRspInconsistentValue) ||
      (errorStatus == SnmpDefinitions.snmpRspResourceUnavailable) ||
      (errorStatus == SnmpDefinitions.snmpRspCommitFailed) ||
      (errorStatus == SnmpDefinitions.snmpRspUndoFailed))
      return errorStatus;

  // Ivalid V2 code => genErr
  return SnmpDefinitions.snmpRspGenErr;
    }
   
    static final int mapErrorStatus(int errorStatus,
            int protocolVersion,
            int reqPduType) {
        if (errorStatus == SnmpDefinitions.snmpRspNoError)
            return SnmpDefinitions.snmpRspNoError;
 
        // Too bad, an error occurs ... we need to translate it ...
        //
  if (protocolVersion == SnmpDefinitions.snmpVersionOne)
      return mapErrorStatusToV1(errorStatus,reqPduType);
        if (protocolVersion == SnmpDefinitions.snmpVersionTwo ||
      protocolVersion == SnmpDefinitions.snmpVersionThree)
      return mapErrorStatusToV2(errorStatus,reqPduType);
 
        return SnmpDefinitions.snmpRspGenErr;
    }

    /**
     * The method returns the error status of the operation.
     * The method takes into account the protocol version.
     */
    protected int getErrorStatus() {
        if (errorStatus == snmpRspNoError)
            return snmpRspNoError;
     
        return mapErrorStatus(errorStatus,version,type);
    }
   
    /**
     * The method returns the error index as a position in the var bind list.
     * The value returned by the method corresponds to the index in the original
     * var bind list as received by the SNMP protocol adaptor.
     */
    protected int getErrorIndex() {
        if  (errorStatus == snmpRspNoError)
            return -1;
   
        // An error occurs. We need to be carefull because the index
        // we are getting is a valid SNMP index (so range starts at 1).
        // FIX ME: Shall we double-check the range here ?
        // The response is : YES :
        if ((errorIndex == 0) || (errorIndex == -1))
            errorIndex = 1;
 
        return translation[errorIndex -1];
    }
 
    /**
     * The method updates the varbind list of the subrequest.
     */
    protected  void updateRequest(SnmpVarBind var, int pos) {
        int size= varBind.size();
        translation[size]= pos;
        varBind.addElement(var);
    }
 
    /**
     * The method updates a given var bind list with the result of a
     * previsouly invoked operation.
     * Prior to calling the method, one must make sure that the operation was
     * successful. As such the method getErrorIndex or getErrorStatus should be
     * called.
     */
    protected void updateResult(SnmpVarBind[] result) {
 
  if (result == null) return;
        final int max=varBind.size();
  final int len=result.length;
        for(int i= 0; i< max ; i++) {
      // bugId 4641694: must check position in order to avoid
      //       ArrayIndexOutOfBoundException
      final int pos=translation[i];
      if (pos < len) {
    result[pos] =
        (SnmpVarBind)((NonSyncVector)varBind).elementAtNonSync(i);
      } else {
    debug("updateResult","Position `"+pos+"' is out of bound...");
      }
        }
    }

    private void init(SnmpEngine engine,
          SnmpIncomingRequest incRequest) {
  this.incRequest = incRequest;
  this.engine = engine; 
    }
   
    protected boolean isTraceOn() {
        return Trace.isSelected(Trace.LEVEL_TRACE, Trace.INFO_ADAPTOR_SNMP);
    }

    protected void trace(String clz, String func, String info) {
        Trace.send(Trace.LEVEL_TRACE, Trace.INFO_ADAPTOR_SNMP, clz, func, info);
    }

    protected void trace(String func, String info) {
        trace(dbgTag, func, info);
    }
   
    protected boolean isDebugOn() {
        return Trace.isSelected(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP);
    }

    protected void debug(String clz, String func, String info) {
        Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP, clz, func, info);
    }

    protected void debug(String func, Throwable t) {
        Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP, dbgTag, func, t);
    }

    protected void debug(String func, String info) {
        debug(dbgTag, func, info);
    }
   
    protected String makeDebugTag() {
        return "SnmpSubRequestHandler";
    }
   
    // PRIVATE VARIABLES
    //------------------

    protected String dbgTag = null;
   
    /**
     * Store the protocol version to handle
     */
    protected int version= snmpVersionOne;

    /**
     * Store the operation type. Remember if the type is Walk, it means
     * that we have to invoke the check method ...
     */
    protected int type= 0;

    /**
     * Agent directly handled by the sub-request handler.
     */
    protected SnmpMibAgent agent;

    /**
     * Error status.
     */
    protected int errorStatus= snmpRspNoError;
 
    /**
     * Index of error.
     * A value of -1 means no error.
     */
    protected int errorIndex= -1;
 
    /**
     * The varbind list specific to the current sub request.
     * The vector must contain object of type SnmpVarBind.
     */
    protected Vector varBind;
 
    /**
     * The array giving the index translation between the content of
     * <VAR>varBind</VAR> and the varbind list as specified in the request.
     */
    protected int[] translation;

    /**
     * Contextual object allocated by the SnmpUserDataFactory.
     **/
    protected Object data;

    /**
     * The SnmpMibRequest that will be passed to the agent.
     *
     **/
    private   SnmpMibRequest mibRequest = null;
   
    /**
     * The SnmpPdu that will be passed to the request.
     *
     **/
    private   SnmpPdu reqPdu = null;
   
    // All the methods of the Vector class are synchronized.
    // Synchronization is a very expensive operation. In our case it is not always
    // required...
    //
    class NonSyncVector extends Vector {
   
        public NonSyncVector(int size) {
            super(size);
        }
   
        final void addNonSyncElement(Object obj) {
            ensureCapacity(elementCount + 1);
            elementData[elementCount++] = obj;
        }
   
        final Object elementAtNonSync(int index) {
            return elementData[index];
        }
    };
}
TOP

Related Classes of com.sun.jmx.snmp.daemon.SnmpSubRequestHandler$NonSyncVector

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.