| package com.dy.common.mw.protocol; | 
|   | 
| import java.net.URI; | 
| import java.net.URL; | 
| import java.util.Collection; | 
| import java.util.HashMap; | 
| import java.util.List; | 
|   | 
| import com.dy.common.util.ClassScan; | 
| import com.dy.common.util.NumUtil; | 
|   | 
| /** | 
|  * 扫描: | 
|  *   协议驱动类 | 
|  *   上行数据完整性检查类(断包粘包检查) | 
|  *   上线数据(连接后第一包数据)处理类(识别协议及终端地址) | 
|  * @author Administrator | 
|  * | 
|  */ | 
| @SuppressWarnings("unused") | 
| public class AnnotationScan { | 
|      | 
|     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{ | 
|         ClassLoader load = this.getClass().getClassLoader() ; | 
|          | 
|         if(!scanRootPackage.endsWith(".")){ | 
|             scanRootPackage += "." ; | 
|         } | 
|         URL url = AnnotationScan.class.getResource("/" + scanRootPackage.replace('.', '/')); | 
|         if(url != null){ | 
|             String urlStr = url.toString() ; | 
|             if(urlStr != null){ | 
|                 URI uri = new URI(url.toString()); | 
|   | 
|                 List<String> classNames = new ClassScan().searchClassFromUrl(new URI[]{uri}, scanRootPackage) ; | 
|                 if(classNames != null && classNames.size() > 0){ | 
|                     String protocolName ; | 
|                     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(String cName : classNames){ | 
|                         String className = cName.substring(0,  cName.lastIndexOf('.')) ; | 
|                         Class<?> clazz = load.loadClass(className) ; | 
|                         if(clazz.isAnnotationPresent(AnnotationDriver.class)){ | 
|                             AnnotationDriver ann = clazz.getAnnotation(AnnotationDriver.class) ; | 
|                             if(ann != null){ | 
|                                 protocolName = ann.name() ; | 
|                                 if(!(protocolName.trim().equals(""))){ | 
|                                     if(driverMap.containsKey(protocolName)){ | 
|                                         throw new Exception("严重错误,协议驱动名称" + protocolName + "出现了重复注解!") ; | 
|                                     } | 
|                                     driverMap.put(protocolName, new AnnotationDriverVo(clazz)) ; | 
|                                 }else{ | 
|                                     throw new Exception("严重错误,协议驱动名称注解值为空字符串") ; | 
|                                 } | 
|                             } | 
|                         } | 
|   | 
|   | 
|                         if(clazz.isAnnotationPresent(AnnotationPrefixedDataAvailable.class)){ | 
|                             AnnotationPrefixedDataAvailable ann = clazz.getAnnotation(AnnotationPrefixedDataAvailable.class) ; | 
|                             if(ann != null){ | 
|                                 protocolName = ann.protocolName() ; | 
|                                 if(!(protocolName.trim().equals(""))){ | 
|                                     if(prefixedDataAvailableMap.containsKey(protocolName)){ | 
|                                         throw new Exception("严重错误, 上行数据完整性检查所配协议驱动" + protocolName + "出现了重复注解!") ; | 
|                                     } | 
|                                 }else{ | 
|                                     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") ; | 
|                         } | 
|                         */ | 
|   | 
|                                 prefixedDataAvailableMap.put(protocolName, new AnnotationPrefixedDataAvailableVo(clazz, protocolName, priority, onLineDataMinLength, headMinLength, ProtocolConstant.errorMaxLength)) ; | 
|                             } | 
|                         } | 
|   | 
|                         if(clazz.isAnnotationPresent(AnnotationOnLine.class)){ | 
|                             AnnotationOnLine ann = clazz.getAnnotation(AnnotationOnLine.class) ; | 
|                             if(ann != null){ | 
|                                 protocolName = ann.protocolName() ; | 
|                                 if(!(protocolName.trim().equals(""))){ | 
|                                     if(onLineMap.containsKey(protocolName)){ | 
|                                         throw new Exception("严重错误, 上线数据分析所配协议驱动" + protocolName + "出现了重复注解!") ; | 
|                                     } | 
|                                 }else{ | 
|                                     throw new Exception("严重错误,上线数据分析所配协议驱动注解值为空字符串") ; | 
|                                 } | 
|   | 
|                                 priority = ann.priority() ; | 
|                                 if(priority == 0){ | 
|                                     throw new Exception("严重错误, 上线数据分析所配优先级注解不能为0") ; | 
|                                 } | 
|                                 if(isRepeatOnLinePriority(priority, onLineMap)){ | 
|                                     throw new Exception("严重错误, 上线数据分析所配优先级注解(priority)数值" + priority + "重复") ; | 
|                                 } | 
|   | 
|                                 onLineMap.put(protocolName, new AnnotationOnLineVo(clazz, protocolName, 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)){ | 
|                 return "严重错误,上行数据完整性检查所配驱动名称(" + vo.protocolName + ")在协议驱动中未配置" ; | 
|             } | 
|         } | 
|          | 
|         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)){ | 
|                 return "严重错误,上线数据分析所配驱动名称(" + vo.protocolName + ")在协议驱动中未配置" ; | 
|             } | 
|         } | 
|          | 
|         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 ; | 
|     } | 
| } |