zhubaomin
2025-04-07 1a2b07f01ba4616fd9e894dddf474b56d020158c
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/PrefixedDataAvailableHandleImp.java
@@ -3,6 +3,7 @@
import java.util.Collection;
import java.util.HashMap;
import com.dy.common.mw.channel.tcp.TcpIoSessionAttrIdIsRtuAddr;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.mina.core.buffer.IoBuffer;
@@ -10,6 +11,7 @@
import com.dy.common.util.ByteUtil;
import com.dy.common.mw.channel.tcp.PrefixedDataAvailableHandle;
import com.dy.common.mw.channel.tcp.PrefixedDataAvailableStatus;
import org.apache.mina.core.session.IoSession;
public class PrefixedDataAvailableHandleImp implements PrefixedDataAvailableHandle {
   
@@ -22,43 +24,63 @@
    * @param in IoBuffer
    * @return PrefixedDataAvailableStatus
    */
   public PrefixedDataAvailableStatus forOnLine(IoBuffer in){
   public PrefixedDataAvailableStatus forOnLine(IoSession ioSession, IoBuffer in){
       int remain = in.remaining() ;
       if(remain == 0){
          return new PrefixedDataAvailableStatus().breaked() ;
       }else{
          try{
             PrefixedDataAvailableStatus pds = null ;
             HashMap<String, AnnotationPrefixedDataAvailableVo> prefixedDataAvailableMap = ProtocolCache.getPrefixedDataAvailableMap() ;
             Collection<AnnotationPrefixedDataAvailableVo> set = prefixedDataAvailableMap.values() ;
             if(set.size() == 0){
                throw new Exception("上线数据完整性检查时,得到的协议完整性检查类集合为空。") ;
             }
             int priority = ProtocolConstant.firstPriority ;
            PrefixedDataAvailableStatus pds = null ;
            PrefixedDataAvailable pda = null ;
             while(true){
                Object[] objs = this.getClassObjAndAnnotationVo(priority, set) ;
                PrefixedDataAvailable pda = (PrefixedDataAvailable)objs[0] ;
                if(pda == null && priority == ProtocolConstant.firstPriority){
                   throw new Exception("上线数据完整性检查时,未得到优先级为" + priority + "上线数据完整性检查类!") ;
                }else if(pda == null){
                   //说明上线数据完整性检查类集合已经遍历完了。
                   break ;
                }
                //处理完整性检查
                pds = pda.forOnLine(in, remain, ((AnnotationPrefixedDataAvailableVo)objs[1]).onLineDataMinLength, ((AnnotationPrefixedDataAvailableVo)objs[1]).errorMaxLength) ;
                //用完对象后,放回池中
                PrefixedDataAvailablePool.freeInstance(((AnnotationPrefixedDataAvailableVo)objs[1]).clazz, pda);
                if(pds == null){
                  //说明不是对应的协议数据,需要另外的协议来处理上线
                  //循环继续
                  priority++ ;
               }else{
                  //停止循环,返回结果
                  break ;
            //从会话缓存得到上次上行数据确定的协议
            String protocolName = (String) ioSession.getAttribute(TcpIoSessionAttrIdIsRtuAddr.sessionArrProtocolName) ;
             Short protocolVersion = (Short) ioSession.getAttribute(TcpIoSessionAttrIdIsRtuAddr.sessionArrProtocolVersion) ;
             //由会话中的协议得到处理类
            //利用缓存的协议,进而对不符合协议的上行数据也能用该协议处理了,例如RTU采用不同数据协议的嵌入式软件升级协议
            //即RTU第一包数据确定下来协议,后面数据都用这个协议处理,那么数据可以变化了,可以不符合第一包数据遵守的协议了
            Object[] objs =  this.getClassObjAndAnnotationVo(protocolName, protocolVersion) ;
            if(objs != null && objs[0] != null && objs[1] != null){
               pda = (PrefixedDataAvailable)objs[0] ;
               //处理完整性检查
               pds = pda.forOnLine(ioSession, in, remain, ((AnnotationPrefixedDataAvailableVo)objs[1]).onLineDataMinLength, ((AnnotationPrefixedDataAvailableVo)objs[1]).errorMaxLength) ;
               //用完对象后,放回池中
               PrefixedDataAvailablePool.freeInstance(objs[0].getClass(), pda);
            }
            if(pds == null){
               //如果会话中缓存的协议未能正确处理
               HashMap<String, AnnotationPrefixedDataAvailableVo> prefixedDataAvailableMap = ProtocolCache.getPrefixedDataAvailableMap() ;
               Collection<AnnotationPrefixedDataAvailableVo> set = prefixedDataAvailableMap.values() ;
               if(set.size() == 0){
                  throw new Exception("上线数据完整性检查时,得到的协议完整性检查类集合为空。") ;
               }
             }
               int priority = ProtocolConstant.firstPriority ;
               while(true){
                  objs = this.getClassObjAndAnnotationVo(priority, set) ;
                  pda = (PrefixedDataAvailable)objs[0] ;
                  if(pda == null && priority == ProtocolConstant.firstPriority){
                     throw new Exception("上线数据完整性检查时,未得到优先级为" + priority + "上线数据完整性检查类!") ;
                  }else if(pda == null){
                     //说明上线数据完整性检查类集合已经遍历完了。
                     break ;
                  }
                  //处理完整性检查
                  pds = pda.forOnLine(ioSession, in, remain, ((AnnotationPrefixedDataAvailableVo)objs[1]).onLineDataMinLength, ((AnnotationPrefixedDataAvailableVo)objs[1]).errorMaxLength) ;
                  //用完对象后,放回池中
                  //2024-11-25下面一行进行了修改
                  //PrefixedDataAvailablePool.freeInstance(((AnnotationPrefixedDataAvailableVo)objs[1]).clazz, pda);
                  PrefixedDataAvailablePool.freeInstance(objs[0].getClass(), pda);
                  if(pds == null){
                     //说明不是对应的协议数据,需要另外的协议来处理上线
                     //循环继续
                     priority++ ;
                  }else{
                     //停止循环,返回结果
                     break ;
                  }
               }
            }
             if(pds == null){
                //说明数据不属于任何协议,一般为Rtu数据出错,或网络攻击数据
                byte[] preByte = new byte[remain];
@@ -82,43 +104,59 @@
    * @param in IoBuffer
    * @return PrefixedDataAvailableStatus
    */
   public PrefixedDataAvailableStatus forUpData(IoBuffer in){
   public PrefixedDataAvailableStatus forUpData(IoSession ioSession, IoBuffer in){
      int remain = in.remaining() ;
       if(remain == 0){
          return new PrefixedDataAvailableStatus().breaked() ;
       }else{
          try{
            PrefixedDataAvailableStatus pds = null ;
             HashMap<String, AnnotationPrefixedDataAvailableVo> prefixedDataAvailableMap = ProtocolCache.getPrefixedDataAvailableMap() ;
             Collection<AnnotationPrefixedDataAvailableVo> set = prefixedDataAvailableMap.values() ;
             if(set.size() == 0){
                throw new Exception("上线数据完整性检查时,得到的协议集合为空。") ;
             }
             int prority = ProtocolConstant.firstPriority ;
            PrefixedDataAvailableStatus pds = null ;
            PrefixedDataAvailable pda = null ;
             while(true){
                Object[] objs = this.getClassObjAndAnnotationVo(prority, set) ;
                PrefixedDataAvailable pda = (PrefixedDataAvailable)objs[0] ;
                if(pda == null && prority == ProtocolConstant.firstPriority){
                   throw new Exception("上线数据完整性检查时,未得到优先级为" + prority + "上线数据完整性检查类!") ;
                }else if(pda == null){
                   //说明上线数据完整性检查类集合已经遍历完了。
                   break ;
                }
                //处理完整性检查
                 pds = pda.forUpData(in, remain, ((AnnotationPrefixedDataAvailableVo)objs[1]).headMinLength, ((AnnotationPrefixedDataAvailableVo)objs[1]).errorMaxLength) ;
                 //用完对象后,放回池中
                 PrefixedDataAvailablePool.freeInstance(objs[0].getClass(), pda);
                 if(pds == null){
                   //说明不是对应的协议数据,需要另外的协议来处理上线
                   //循环继续
                   prority++ ;
                }else{
                   //停止循环,返回结果
                   break ;
                }
              }
            //从会话缓存得到上次上行数据确定的协议
            String protocolName = (String) ioSession.getAttribute(TcpIoSessionAttrIdIsRtuAddr.sessionArrProtocolName) ;
            Short protocolVersion = (Short) ioSession.getAttribute(TcpIoSessionAttrIdIsRtuAddr.sessionArrProtocolVersion) ;
            //由会话中的协议得到处理类
            Object[] objs =  this.getClassObjAndAnnotationVo(protocolName, protocolVersion) ;
            if(objs != null && objs[0] != null && objs[1] != null){
               pda = (PrefixedDataAvailable)objs[0] ;
               //处理完整性检查
               pds = pda.forOnLine(ioSession, in, remain, ((AnnotationPrefixedDataAvailableVo)objs[1]).onLineDataMinLength, ((AnnotationPrefixedDataAvailableVo)objs[1]).errorMaxLength) ;
               //用完对象后,放回池中
               PrefixedDataAvailablePool.freeInstance(objs[0].getClass(), pda);
            }
            if(pds == null) {
               //如果会话中缓存的协议未能正确处理
               HashMap<String, AnnotationPrefixedDataAvailableVo> prefixedDataAvailableMap = ProtocolCache.getPrefixedDataAvailableMap() ;
               Collection<AnnotationPrefixedDataAvailableVo> set = prefixedDataAvailableMap.values() ;
               if(set.size() == 0){
                  throw new Exception("上线数据完整性检查时,得到的协议集合为空。") ;
               }
               int priority = ProtocolConstant.firstPriority ;
               while(true){
                  objs = this.getClassObjAndAnnotationVo(priority, set) ;
                  pda = (PrefixedDataAvailable)objs[0] ;
                  if(pda == null && priority == ProtocolConstant.firstPriority){
                     throw new Exception("上线数据完整性检查时,未得到优先级为" + priority + "上线数据完整性检查类!") ;
                  }else if(pda == null){
                     //说明上线数据完整性检查类集合已经遍历完了。
                     break ;
                  }
                  //处理完整性检查
                  pds = pda.forUpData(ioSession, in, remain, ((AnnotationPrefixedDataAvailableVo)objs[1]).headMinLength, ((AnnotationPrefixedDataAvailableVo)objs[1]).errorMaxLength) ;
                  //用完对象后,放回池中
                  PrefixedDataAvailablePool.freeInstance(objs[0].getClass(), pda);
                  if(pds == null){
                     //说明不是对应的协议数据,需要另外的协议来处理上线
                     //循环继续
                     priority++ ;
                  }else{
                     //停止循环,返回结果
                     break ;
                  }
               }
            }
              if(pds == null){
                 //说明数据不属于任何协议,一般为Rtu数据出错,或网络攻击数据
                 byte[] preByte = new byte[remain];
@@ -157,5 +195,21 @@
      }
      return new Object[]{obj, rVo} ;
   }
   /**
    * 得到处理类对象
    * @param protocolName 通信协议名称
    * @param protocolVersion 通信协议版本号
    * @return Object[]
    * @throws Exception 异常
    */
   private Object[] getClassObjAndAnnotationVo(String protocolName, Short protocolVersion) throws Exception{
      PrefixedDataAvailable obj = null ;
      AnnotationPrefixedDataAvailableVo rVo = null ;
      if(protocolName != null && !protocolName.trim().equals("") && protocolVersion != null){
         rVo =  ProtocolCache.getAnnotationPrefixedDataAvailable(protocolName, protocolVersion) ;
         obj = PrefixedDataAvailablePool.getInstance(rVo.clazz) ;
      }
      return new Object[]{obj, rVo} ;
   }
}