|  |  | 
 |  |  | 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; | 
 |  |  | 
 |  |  | 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 { | 
 |  |  |     | 
 |  |  | 
 |  |  |     * @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]; | 
 |  |  | 
 |  |  |     * @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]; | 
 |  |  | 
 |  |  |       } | 
 |  |  |       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} ; | 
 |  |  |    } | 
 |  |  |  | 
 |  |  | } |