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