SNMP4J でトラップ受信

SNMP4J トラップ受信をGoogle guice で動かせるようにしてみた。

import java.io.IOException;
import org.apache.log4j.Logger;
import org.snmp4j.CommandResponder;
import org.snmp4j.MessageDispatcherImpl;
import org.snmp4j.Snmp;
import org.snmp4j.mp.MPv1;
import org.snmp4j.mp.MPv2c;
import org.snmp4j.mp.MPv3;
import org.snmp4j.security.SecurityModels;
import org.snmp4j.security.SecurityProtocols;
import org.snmp4j.security.USM;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.MultiThreadedMessageDispatcher;
import org.snmp4j.util.ThreadPool;
import com.google.inject.Inject;
/**
 * SNMP トラップ受信.
 * コンストラクタSNMP受信するIP,受信スレッド数、CommandResponderインスタンスを指定する。
 * 特別なアノテーションにより、SNMP受信するIP,受信スレッド数の、
 * Google guice インジェクトを次のように約束されている。
 *   @Inject public SnmpTrapReceiver(@SnmpIPaddress       String ip
 *                                  ,@SnmpRecvThreadnum   int threadNum
 *                                  ,CommandResponder     commandResponder)
 * よって、任意のModule で、annotatedWith で、@SnmpIPaddress , @SnmpRecvThreadnum に対して
 * インジェクトするものを作成するか、または、SnmpTrapReceiveModule を使用するかである。
 */

public final class SnmpTrapReceiver{
   private String recvIP;
   private int threadNum = 2;
   private CommandResponder commandResponder;
   private Snmp snmp = null;
   private ThreadPool threadPool;

   private Logger logger;
   /**
    * コンストラクタ
    * @param ip トラップ受信するIPアドレス
    * @param threadNum 受信スレッドの数
    * @param commandResponder CommandResponder実装インスタンス
    */

   @Inject
   public SnmpTrapReceiver(@SnmpIPaddress String ip
                          ,@SnmpRecvThreadnum int threadNum
                          ,CommandResponder commandResponder){
      this.recvIP = ip;
      this.threadNum = threadNum;
      this.commandResponder = commandResponder;
      this.logger = Logger.getLogger(this.getClass());
   }

   /**
    * 受信開始.
    * CommandResponder実装インスタンスがスレッドとして待機
    * @throws IOException
    */

   public void start() throws IOException{
      // port 162 をバインド
      this.threadPool = ThreadPool.create("SnmpTrapReceiver",this.threadNum);
      MultiThreadedMessageDispatcher dispatcher 
      = new MultiThreadedMessageDispatcher(this.threadPool,new MessageDispatcherImpl());
      org.snmp4j.smi.Address listenAddress 
      = GenericAddress.parse(System.getProperty("snmp4j.listenAddress","udp:"+this.recvIP+"/162"));
      this.snmp = new Snmp(dispatcher,new DefaultUdpTransportMapping*1;

      this.snmp.getMessageDispatcher().addMessageProcessingModel(new MPv1());
      this.snmp.getMessageDispatcher().addMessageProcessingModel(new MPv2c());
      this.snmp.getMessageDispatcher().addMessageProcessingModel(new MPv3());
      USM usm = new USM(SecurityProtocols.getInstance(),
      new OctetString(MPv3.createLocalEngineID()),0);
      SecurityModels.getInstance().addSecurityModel(usm);
      this.snmp.addCommandResponder(this.commandResponder);
      this.snmp.listen();

      this.logger.debug("## SnmpTrapReceiver  "+this.recvIP+"/162  listen");
   }
   /**
    * 受信終了
    * 受信スレッド終了、ポートを閉じる。
    */

   public void end(){
      this.threadPool.cancel();
      try{
      this.snmp.close();
      }catch(IOException e){
         this.logger.error("## IOException : "+e.getMessage(),e);
      }finally{
         this.logger.debug("## SnmpTrapReceiver  close");
      }
   }
}
------------------------------------------------
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.google.inject.BindingAnnotation;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.PARAMETER})
@BindingAnnotation
public @interface SnmpIPaddress{
}

--------------------------------------------------
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.google.inject.BindingAnnotation;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.PARAMETER})
@BindingAnnotation
public @interface SnmpRecvThreadnum{
}

-----------------------------------------------
import org.snmp4j.CommandResponder;
import com.google.inject.AbstractModule;
/**
 * SNMPトラップ受信バインド定義.
 */

public class SnmpTrapReceiveModule extends AbstractModule{
   private String recvIP;
   private int threadNum;
   private Class<? extends CommandResponder> cls;
   /**
    * コンストラクタ
    * @param recvIP SNMP受信のアドレス
    * @param threadNum SNMP受信スレッド数
    * @param cls CommandResponder実装クラス
    */

   public SnmpTrapReceiveModule(String recvIP,int threadNum,Class<? extends CommandResponder> cls){
      this.recvIP = recvIP;
      this.threadNum = threadNum;
      this.cls = cls;
   }
   /*
    * @see com.google.inject.AbstractModule#configure()
    */

   @Override
   protected void configure(){
      binder().bind(String.class).annotatedWith(SnmpIPaddress.class).toInstance(this.recvIP);
      binder().bind(int.class).annotatedWith(SnmpRecvThreadnum.class).toInstance(this.threadNum);
      try{
      binder().bind(CommandResponder.class).toInstance(this.cls.newInstance());
      }catch(Exception e){
         throw new RuntimeException(e);
      }
   }

}
===============================================
import java.util.Iterator;
import java.util.Vector;
import org.apache.log4j.Logger;
import org.snmp4j.CommandResponder;
import org.snmp4j.CommandResponderEvent;
import org.snmp4j.PDUv1;
import org.snmp4j.smi.VariableBinding;
/**
 * CommandResponder サンプル
 */

public class CommandResponderSample implements CommandResponder{
   private Logger logger;

   public CommandResponderSample(){
      this.logger = Logger.getLogger(this.getClass());
   }

   /*
    * @see org.snmp4j.CommandResponder#processPdu(org.snmp4j.CommandResponderEvent)
    */

   @Override
   public void processPdu(CommandResponderEvent event){

      // 受信した内容を表示する
      StringBuffer sb = new StringBuffer("## recv CommandResponderEvent\n");
      sb.append("\t"+"PDU toString   = "+event.getPDU().toString()+"\n");

      PDUv1 pduv1 = (PDUv1)event.getPDU();

      sb.append("\t"+"PDUv1.toString = "         +pduv1.toString()+"\n");
      sb.append("\t"+"PDUv1.getAgentAddress   = "+pduv1.getAgentAddress()+"\n");
      sb.append("\t"+"PDUv1.getEnterprise()   = "+pduv1.getEnterprise()+"\n");
      sb.append("\t"+"PDUv1.getGenericTrap()  = "+pduv1.getGenericTrap()+"\n");
      sb.append("\t"+"PDUv1.getSpecificTrap() = "+pduv1.getSpecificTrap()+"\n");

      Vector vars = event.getPDU().getVariableBindings();
      for(Iterator<?> it=vars.iterator();it.hasNext();){
         VariableBinding v = (VariableBinding)it.next();

         sb.append("\t"+"---------------------------------------------\n");
         sb.append("\t"+"VariableBinding.getOid()      = "+v.getOid()+"\n");
         sb.append("\t"+"VariableBinding.getVariable() = "+v.getVariable()+"\n");
         sb.append("\t"+"VariableBinding.toString()    = ["+v.toString()+"]"+"\n");
      }
      this.logger.info(sb.toString());
   }
}
===========================================
実行は、
Injector injector = Guice.createInjector(
new SnmpTrapReceiveModule(recvIP,threadNum,CommandResponderSample.class));
SnmpTrapReceiver snmpTrapReceiver = injector.getInstance(SnmpTrapReceiver.class);

snmpTrapReceiver.start();

*1:UdpAddress)listenAddress