| package com.dy.common.mw.protocol; | 
|   | 
| import java.util.Collection; | 
| import java.util.HashMap; | 
|   | 
| 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; | 
|   | 
| public class PrefixedDataAvailableHandleImp implements PrefixedDataAvailableHandle { | 
|      | 
|     private static final Logger log = LogManager.getLogger(PrefixedDataAvailableHandleImp.class) ; | 
|      | 
|   | 
|     /** | 
|      * 在多线程环境中运行 | 
|      * 分析上线数据(网络连接后第一包数据)是否可获得 | 
|      * @param in IoBuffer | 
|      * @return PrefixedDataAvailableStatus | 
|      */ | 
|     public PrefixedDataAvailableStatus forOnLine(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 ; | 
|   | 
|                 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 ; | 
|                     } | 
|                 } | 
|                 if(pds == null){ | 
|                     //说明数据不属于任何协议,一般为Rtu数据出错,或网络攻击数据 | 
|                     byte[] preByte = new byte[remain]; | 
|                     in.get(preByte) ; | 
|                     in.position(0) ; | 
|                     log.error("上线第一包数据未找到对应的解析协议。数据是:" + ByteUtil.bytes2Hex(preByte, true)) ; | 
|                     //认为是完整包数据,后续读出,防止占用内存及死循环IO读数据 | 
|                     pds = new PrefixedDataAvailableStatus().rubbish(remain) ; | 
|                 } | 
|                 return pds ; | 
|             }catch(Exception e){ | 
|                 //处理过程中发生异常,上行数据就是垃圾数据了,后续以垃圾数据处理,即把数据从IO中取出来,以防止死循环IO读数据 | 
|                 return new PrefixedDataAvailableStatus().rubbish(remain) ; | 
|             } | 
|         } | 
|     } | 
|   | 
|     /** | 
|      * 在多线程环境中运行 | 
|      * 分析上行数据(网络连接后第二(包含)包以后数据)是否可获得 | 
|      * @param in IoBuffer | 
|      * @return PrefixedDataAvailableStatus | 
|      */ | 
|     public PrefixedDataAvailableStatus forUpData(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 ; | 
|   | 
|                 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 ; | 
|                     } | 
|                 } | 
|                 if(pds == null){ | 
|                     //说明数据不属于任何协议,一般为Rtu数据出错,或网络攻击数据 | 
|                     byte[] preByte = new byte[remain]; | 
|                     in.get(preByte) ; | 
|                     in.position(0) ; | 
|                     log.error("上行数据未找到对应的解析协议。数据是:" + ByteUtil.bytes2Hex(preByte, true)) ; | 
|                     //认为是完整包数据,后续读出,防止占用内存及死循环IO读数据 | 
|                     pds = new PrefixedDataAvailableStatus().rubbish(remain) ; | 
|                 } | 
|                 return pds ; | 
|             }catch(Exception e){ | 
|                 //处理过程中发生异常,上行数据就是垃圾数据了,后续以垃圾数据处理,即把数据从IO中取出来,以防止死循环IO读数据 | 
|                 return new PrefixedDataAvailableStatus().rubbish(remain) ; | 
|             } | 
|          }         | 
|     } | 
|      | 
|   | 
|   | 
|     /** | 
|      * 得到处理类对象 | 
|      * @param prority 优先级 | 
|      * @param set 集合 | 
|      * @return Object[] | 
|      * @throws Exception 异常 | 
|      */ | 
|     private Object[] getClassObjAndAnnotationVo(int prority, Collection<AnnotationPrefixedDataAvailableVo> set) throws Exception{ | 
|         PrefixedDataAvailable obj = null ; | 
|         AnnotationPrefixedDataAvailableVo rVo = null ; | 
|         for(AnnotationPrefixedDataAvailableVo vo : set){ | 
|             if(prority == vo.priority){ | 
|                 obj = PrefixedDataAvailablePool.getInstance(vo.clazz) ; | 
|                 rVo = vo ; | 
|                 break ; | 
|             } | 
|         } | 
|         return new Object[]{obj, rVo} ; | 
|     } | 
|   | 
| } |