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 ; 
 | 
    } 
 | 
} 
 |