liurunyu
6 天以前 7aab004601e77890b158f19d1735594a8326feaa
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/AnnotationScan.java
New file
@@ -0,0 +1,292 @@
package com.dy.common.mw.protocol;
import java.util.Collection;
import java.util.HashMap;
import java.util.Set;
import com.dy.common.util.NumUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.reflections.Reflections;
/**
 * 扫描:
 *   协议驱动类
 *   上行数据完整性检查类(断包粘包检查)
 *   上线数据(连接后第一包数据)处理类(识别协议及终端地址)
 * @author Administrator
 *
 */
@SuppressWarnings("unused")
public class AnnotationScan {
   private static final Logger log = LogManager.getLogger(AnnotationScan.class);
   private static String scanRootPackage = "com.dy.common.mw.protocol" ;
   private static AnnotationScan instance ;
   private AnnotationScan(){
   }
   /**
    * 得到唯一实例,
    * 并在生成唯一实例时,扫描注解类
    * @return AnnotationScan
    * @throws Exception 异常
    */
   public static AnnotationScan getIntance()throws Exception{
      if(instance == null){
         instance = new AnnotationScan() ;
         instance.scanEndpointAnnotations();
      }
      return instance ;
   }
   /**
    * 扫描出注解的类
    * @throws ClassNotFoundException 异常
    * @throws Exception 异常
    */
   private void scanEndpointAnnotations() throws Exception {
      Reflections reflections = new Reflections(scanRootPackage); // 指定包名
      Set<Class<?>> driverClasses = reflections.getTypesAnnotatedWith(AnnotationDriver.class);
      if (driverClasses != null && driverClasses.size() > 0) {
         String protocolName;
         short protocolVersion;
         String key ;
         int priority;
         int onLineDataMinLength;
         int headMinLength;
         HashMap<String, AnnotationDriverVo> driverMap = ProtocolCache.getDriverMap();
         HashMap<String, AnnotationPrefixedDataAvailableVo> prefixedDataAvailableMap = ProtocolCache.getPrefixedDataAvailableMap();
         HashMap<String, AnnotationOnLineVo> onLineMap = ProtocolCache.getOnLineMap();
         for (Class<?> clazz : driverClasses) {
            AnnotationDriver ann = clazz.getAnnotation(AnnotationDriver.class);
            if (ann != null) {
               if (ann.enable()) {
                  protocolName = ann.name();
                  protocolVersion = ann.version() ;
                  if(protocolName == null || protocolName.trim().equals("")){
                     throw new Exception("严重错误,协议驱动名称注解值为空字符串");
                  }
                  if(protocolVersion == -1){
                     throw new Exception("严重错误,协议驱动版本号未配置");
                  }
                  key = protocolName + protocolVersion ;
                  if (driverMap.containsKey(key)) {
                     throw new Exception("严重错误,协议驱动(名称+版本号)" + key + "出现了重复注解!");
                  }
                  driverMap.put(key, new AnnotationDriverVo(clazz));
               }
            }
         }
         Set<Class<?>> prefixedClass = reflections.getTypesAnnotatedWith(AnnotationPrefixedDataAvailable.class);
         for (Class<?> clazz : prefixedClass) {
            AnnotationPrefixedDataAvailable ann = clazz.getAnnotation(AnnotationPrefixedDataAvailable.class);
            if (ann != null) {
               if (ann.enable()) {
                  protocolName = ann.protocolName();
                  if (!(protocolName.trim().equals(""))) {
                     if (prefixedDataAvailableMap.containsKey(protocolName)) {
                        throw new Exception("严重错误, 上行数据完整性检查所配协议驱动" + protocolName + "出现了重复注解!");
                     }
                  } else {
                     throw new Exception("严重错误,上行数据完整性检查所配协议驱动注解值为空字符串");
                  }
                  protocolVersion = ann.protocolVersion();
                  if (protocolVersion == -1) {
                     throw new Exception("严重错误, 上行数据完整性检查所配协议版本号未配置");
                  }
                  priority = ann.priority();
                  if (priority == 0) {
                     throw new Exception("严重错误, 上行数据完整性检查所配优先级注解不能为0");
                  }
                  if (isRepeatPrefixedDataAvailablePriority(priority, prefixedDataAvailableMap)) {
                     throw new Exception("严重错误, 上行数据完整性检查所配优先级注解(priority)数值" + priority + "重复");
                  }
                  onLineDataMinLength = ann.onLineDataMinLength();
                  /*气象协议为0
                  if(onLineDataMinLength == 0){
                     throw new Exception("严重错误, 上行数据完整性检查所配上线数据最小长度注解不能为0") ;
                  }
                  */
                  headMinLength = ann.headMinLength();
                  /*气象协议为0
                  if(headMinLength == 0){
                     throw new Exception("严重错误, 上行数据完整性检查所配上报数据的头部最小长度注解不能为0") ;
                  }
                  */
                  key = protocolName + protocolVersion ;
                  prefixedDataAvailableMap.put(key, new AnnotationPrefixedDataAvailableVo(clazz, protocolName, protocolVersion, priority, onLineDataMinLength, headMinLength, ProtocolConstant.errorMaxLength));
               }
            }
         }
         Set<Class<?>> onLineClass = reflections.getTypesAnnotatedWith(AnnotationOnLine.class);
         for (Class<?> clazz : onLineClass) {
            AnnotationOnLine ann = clazz.getAnnotation(AnnotationOnLine.class);
            if (ann != null) {
               if (ann.enable()) {
                  protocolName = ann.protocolName();
                  if (!(protocolName.trim().equals(""))) {
                     if (onLineMap.containsKey(protocolName)) {
                        throw new Exception("严重错误, 上线数据分析所配协议驱动" + protocolName + "出现了重复注解!");
                     }
                  } else {
                     throw new Exception("严重错误,上线数据分析所配协议驱动注解值为空字符串");
                  }
                  protocolVersion = ann.protocolVersion();
                  if (protocolVersion == -1) {
                     throw new Exception("严重错误, 上线数据分析所配协议版本号未配置");
                  }
                  priority = ann.priority();
                  if (priority == 0) {
                     throw new Exception("严重错误, 上线数据分析所配优先级注解不能为0");
                  }
                  if (isRepeatOnLinePriority(priority, onLineMap)) {
                     throw new Exception("严重错误, 上线数据分析所配优先级注解(priority)数值" + priority + "重复");
                  }
                  key = protocolName + protocolVersion ;
                  onLineMap.put(key, new AnnotationOnLineVo(clazz, protocolName, protocolVersion, priority));
               }
            }
         }
         //进行验证
         String error = this.hasErrorInDriver(driverMap);
         if (error != null) {
            throw new Exception(error);
         } else {
            error = this.hasErrorInPrefixedDataAvailable(driverMap, prefixedDataAvailableMap);
            if (error != null) {
               throw new Exception(error);
            } else {
               error = this.hasErrorInOnLine(driverMap, onLineMap);
               if (error != null) {
                  throw new Exception(error);
               }
            }
         }
      } else {
         throw new Exception("严重错误, 扫描协议相关注解所得到类型集合为空,扫描根路径是" + scanRootPackage);
      }
   }
   /**
    * 检查优先级重复
    * @param priority 优先级
    * @return 结果
    */
   private boolean isRepeatPrefixedDataAvailablePriority(int priority, HashMap<String, AnnotationPrefixedDataAvailableVo> prefixedDataAvailableMap){
      Collection<AnnotationPrefixedDataAvailableVo> col = prefixedDataAvailableMap.values();
      for(AnnotationPrefixedDataAvailableVo vo : col){
         if(vo.priority == priority){
            return true ;
         }
      }
      return false ;
   }
   /**
    * 检查优先级重复
    * @param priority 优先级
    * @return 结果
    */
   private boolean isRepeatOnLinePriority(int priority, HashMap<String, AnnotationOnLineVo> onLineMap){
      Collection<AnnotationOnLineVo> col = onLineMap.values();
      for(AnnotationOnLineVo vo : col){
         if(vo.priority == priority){
            return true ;
         }
      }
      return false ;
   }
   private String hasErrorInDriver(HashMap<String, AnnotationDriverVo> driverMap){
      if(driverMap.size() == 0){
         return "严重错误,未注解任何协议驱动" ;
      }
      return null ;
   }
   private String hasErrorInPrefixedDataAvailable(HashMap<String, AnnotationDriverVo> driverMap,
                                       HashMap<String, AnnotationPrefixedDataAvailableVo> prefixedDataAvailableMap){
      Collection<AnnotationPrefixedDataAvailableVo> col = prefixedDataAvailableMap.values();
      for(AnnotationPrefixedDataAvailableVo vo : col){
         if(!driverMap.containsKey(vo.protocolName + vo.protocolVersion)){
            return "严重错误,上行数据完整性检查所配驱动名称(" + (vo.protocolName + vo.protocolVersion) + ")在协议驱动中未配置" ;
         }
      }
      int[] prioritys = new int[prefixedDataAvailableMap.size()] ;
      int count = 0 ;
      col = prefixedDataAvailableMap.values();
      for(AnnotationPrefixedDataAvailableVo vo : col){
         prioritys[count++] = vo.priority ;
      }
      NumUtil.sort(prioritys, true) ;
      int firstPriority = prioritys[0] ;
      if(ProtocolConstant.firstPriority != firstPriority){
         return "严重错误,上行数据完整性检查所配优先级必须从 " + ProtocolConstant.firstPriority + " 开始" ;
      }
      int  prePriority = prioritys[0] ;
      int  nextPriority;
      if(prioritys.length > 1){
         for(int i = 1 ; i < prioritys.length; i++){
            nextPriority = prioritys[i] ;
            if(nextPriority - prePriority != 1){
               return "严重错误,上行数据完整性检查所配各个优先级必须相差1" ;
            }else{
               prePriority = nextPriority ;
            }
         }
      }
      return null ;
   }
   private String hasErrorInOnLine(HashMap<String, AnnotationDriverVo> driverMap,
                           HashMap<String, AnnotationOnLineVo> onLineMap){
      Collection<AnnotationOnLineVo> col = onLineMap.values();
      for(AnnotationOnLineVo vo : col){
         if(!driverMap.containsKey(vo.protocolName + vo.protocolVersion)){
            return "严重错误,上线数据分析所配驱动名称(" + (vo.protocolName + vo.protocolVersion) + ")在协议驱动中未配置" ;
         }
      }
      int[] prioritys = new int[onLineMap.size()] ;
      int count = 0 ;
      col = onLineMap.values();
      for(AnnotationOnLineVo vo : col){
         prioritys[count++] = vo.priority ;
      }
      NumUtil.sort(prioritys, true) ;
      int firstPriority = prioritys[0] ;
      if(ProtocolConstant.firstPriority != firstPriority){
         return "严重错误,上线数据分析所配优先级必须从 " + ProtocolConstant.firstPriority + " 开始" ;
      }
      int  prePriority = prioritys[0] ;
      int  nextPriority;
      if(prioritys.length > 1){
         for(int i = 1 ; i < prioritys.length; i++){
            nextPriority = prioritys[i] ;
            if(nextPriority - prePriority != 1){
               return "严重错误,上线数据分析所配各个优先级必须相差1" ;
            }else{
               prePriority = nextPriority ;
            }
         }
      }
      return null ;
   }
}