/** {@inheritDoc} */
  public PDU processPdu(PDU pdu) throws SnmpToolkitException {
    Log log = LogFactory.getLog(this.getClass());

    // 応答用のPDUを生成する
    PDU retPdu = new PDU();
    retPdu.setType(PDU.RESPONSE);

    // 要求のリクエストIDを取得し、応答PDUにセットする
    Integer32 requestID = pdu.getRequestID();
    retPdu.setRequestID(requestID);

    // SNMP4J用の型変換オブジェクト
    SnmpVariableHelper varHelper = new Snmp4jVariableHelper();

    // AgentServiceからAgentを取得する
    Agent agent = this.agentService_.getAgent();

    // 要求PDUのVarbindを走査する
    int varCount = 0;
    List<?> reqVarbinds = pdu.getVariableBindings();
    for (Object reqVarbindObj : reqVarbinds) {
      varCount++;

      // 要求されているOIDを取得する
      VariableBinding reqVarbind = (VariableBinding) reqVarbindObj;
      OID oid = reqVarbind.getOid();

      // GETNEXTでない場合は、指定されたOIDそのものを取得しようとする
      // GETNEXTの場合は、指定されたOID配下で最も近いオブジェクトを探す
      boolean exact = (pdu.getType() != PDU.GETNEXT);
      SnmpVarbind foundVarbind = agent.findObject(oid.toString(), exact);
      if (foundVarbind == null) {
        // Varbindが見つからなかった場合はnoSuchNameを返す
        log.warn("varbind is not found. oid=" + oid.toString());

        retPdu.setErrorStatus(SnmpConstants.SNMP_ERROR_NO_SUCH_NAME);
        retPdu.setErrorIndex(varCount);

        Variable retObject = new Null();
        VariableBinding retVarbind = new VariableBinding(oid, retObject);
        retPdu.add(retVarbind);
        break;
      }

      // READ-WRITEでなければエラー応答を返す
      String accessibility = foundVarbind.getAccessibility();
      if (accessibility.equals(SnmpVarbind.ACCESSIBILITY_NOT_ACCESSIBLE) == true) {
        log.warn("varbind is not accessible. accessibility=" + accessibility);

        retPdu.setErrorStatus(SnmpConstants.SNMP_ERROR_NO_ACCESS);
        retPdu.setErrorIndex(varCount);

        Variable retObject = new Null();
        VariableBinding retVarbind = new VariableBinding(oid, retObject);
        retPdu.add(retVarbind);
        break;
      }

      try {
        // 正常の応答を返す
        retPdu.setErrorStatus(SnmpConstants.SNMP_ERROR_SUCCESS);
        retPdu.setErrorIndex(0);

        log.debug("varbind is found: " + foundVarbind.toString());
        String typeStr = foundVarbind.getType();
        Object retValueObj = foundVarbind.getValue();
        Variable retObject = (Variable) varHelper.createAsnObject(retValueObj, typeStr);

        OID retOID = new OID(foundVarbind.getOid());
        VariableBinding retVarbind = new VariableBinding(retOID, retObject);
        retPdu.add(retVarbind);
      } catch (Exception exception) {
        log.warn("exception occured", exception);

        // 未知のエラーを示す応答PDUを作成する
        retPdu.setErrorStatus(SnmpConstants.SNMP_ERROR_GENERAL_ERROR);
        retPdu.setErrorIndex(varCount);

        if (foundVarbind != null) {
          OID retOID = new OID(foundVarbind.getOid());
          Variable retObject = new Null();
          VariableBinding retVarbind = new VariableBinding(retOID, retObject);
          retPdu.add(retVarbind);
        }
      }
    }
    return retPdu;
  }