/* * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.arialyy.compiler; import com.arialyy.annotations.Download; import com.arialyy.annotations.DownloadGroup; import com.arialyy.annotations.TaskEnum; import com.arialyy.annotations.Upload; import java.lang.annotation.Annotation; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.annotation.processing.RoundEnvironment; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; import javax.lang.model.util.Elements; /** * Created by lyy on 2017/9/6. * 构建代理文件的参数获取工具 */ class ParamObtainUtil { private Map mMethodParams = new HashMap<>(); private Elements mElementUtil; ParamObtainUtil(Elements elements) { mElementUtil = elements; } /** * 获取搜索到的代理方法参数 */ Map getMethodParams() { return mMethodParams; } /** * 查找并保存扫描到的方法 */ void saveMethod(TaskEnum taskEnum, RoundEnvironment roundEnv, Class annotationClazz, int annotationType) { for (Element element : roundEnv.getElementsAnnotatedWith(annotationClazz)) { ElementKind kind = element.getKind(); if (kind == ElementKind.METHOD) { ExecutableElement method = (ExecutableElement) element; TypeElement classElement = (TypeElement) method.getEnclosingElement(); PackageElement packageElement = mElementUtil.getPackageOf(classElement); String methodName = method.getSimpleName().toString(); String className = method.getEnclosingElement().toString(); //全类名 String key = className + taskEnum.proxySuffix; ProxyClassParam proxyEntity = mMethodParams.get(key); MethodInfo methodInfo = new MethodInfo(); methodInfo.methodName = methodName; methodInfo.params = (List) method.getParameters(); if (taskEnum == TaskEnum.M3U8_PEER) { checkM3U8PeerMethod(method, methodInfo.params); } else { checkTaskMethod(taskEnum, method, annotationClazz, methodInfo.params); } if (proxyEntity == null) { proxyEntity = new ProxyClassParam(); proxyEntity.taskEnums = new HashSet<>(); proxyEntity.packageName = packageElement.getQualifiedName().toString(); proxyEntity.className = classElement.getSimpleName().toString(); proxyEntity.proxyClassName = proxyEntity.className + taskEnum.proxySuffix; proxyEntity.mainTaskEnum = taskEnum; if (taskEnum == TaskEnum.DOWNLOAD_GROUP_SUB || taskEnum == TaskEnum.DOWNLOAD_GROUP) { proxyEntity.subTaskEnum = EntityInfo.DOWNLOAD; } mMethodParams.put(key, proxyEntity); } proxyEntity.taskEnums.add(taskEnum); if (proxyEntity.methods.get(taskEnum) == null) { proxyEntity.methods.put(taskEnum, new HashMap, MethodInfo>()); } proxyEntity.methods.get(taskEnum).put(annotationClazz, methodInfo); proxyEntity.keyMappings.put(methodName, getValues(taskEnum, method, annotationType)); } } } /** * 获取注解的内容 */ private Set getValues(TaskEnum taskEnum, ExecutableElement method, int annotationType) { String[] keys = null; switch (taskEnum) { case DOWNLOAD: keys = ValuesUtil.getDownloadValues(method, annotationType); break; case UPLOAD: keys = ValuesUtil.getUploadValues(method, annotationType); break; case DOWNLOAD_GROUP: keys = ValuesUtil.getDownloadGroupValues(method, annotationType); break; case DOWNLOAD_GROUP_SUB: keys = ValuesUtil.getDownloadGroupSubValues(method, annotationType); break; case M3U8_PEER: keys = ValuesUtil.getM3U8PeerValues(method, annotationType); break; } return keys == null ? null : convertSet(keys); } /** * 检查m3u8注解方法参数 */ private void checkM3U8PeerMethod(ExecutableElement method, List params) { String methodName = method.getSimpleName().toString(); String className = method.getEnclosingElement().toString(); Set modifiers = method.getModifiers(); if (modifiers.contains(Modifier.PRIVATE)) { throw new IllegalAccessError(String.format("%s.%s, 不能为private方法", className, methodName)); } if (params.size() != 3 || !params.get(0).asType().toString().equals(String.class.getName()) || !params.get(1).asType().toString().equals(String.class.getName()) || !params.get(2).asType().toString().equals("int")) { throw new IllegalArgumentException( String.format("%s.%s 的参数错误,该方法需要的参数为:String, String, int", className, methodName)); } } /** * 检查任务注解的相关参数,如果被注解的方法为private或参数不合法或参数错误,停止任务 */ private void checkTaskMethod(TaskEnum taskEnum, ExecutableElement method, Class annotationClazz, List params) { String methodName = method.getSimpleName().toString(); String className = method.getEnclosingElement().toString(); Set modifiers = method.getModifiers(); if (modifiers.contains(Modifier.PRIVATE)) { throw new IllegalAccessError(String.format("%s.%s, 不能为private方法", className, methodName)); } if (taskEnum == TaskEnum.DOWNLOAD_GROUP_SUB) { if (isFailAnnotation(annotationClazz)) { if (params.size() < 2 || params.size() > 3) { throw new IllegalArgumentException( String.format("%s.%s参数错误, 参数只能是两个或三个,第一个参数是:%s,第二个参数是:%s,第三个参数(可选)是:%s", className, methodName, getCheckParams(taskEnum), getCheckSubParams(taskEnum), Exception.class.getSimpleName())); } if (params.size() == 2 && (!params.get(0).asType().toString().equals(getCheckParams(taskEnum)) || !params.get(1).asType().toString().equals(getCheckSubParams(taskEnum)))) { throw new IllegalArgumentException( String.format("%s.%s参数错误, 参数只能是两个或三个,第一个参数是:%s,第二个参数是:%s,第三个参数(可选)是:%s", className, methodName, getCheckParams(taskEnum), getCheckSubParams(taskEnum), Exception.class.getSimpleName())); } if (params.size() == 3 && (!params.get(0).asType().toString().equals(getCheckParams(taskEnum)) || !params.get(1).asType().toString().equals(getCheckSubParams(taskEnum)) || !params.get(2).asType().toString().equals(Exception.class.getName()))) { throw new IllegalArgumentException( String.format("%s.%s参数错误, 参数只能是两个或三个,第一个参数是:%s,第二个参数是:%s,第三个参数(可选)是:%s", className, methodName, getCheckParams(taskEnum), getCheckSubParams(taskEnum), Exception.class.getSimpleName())); } } else { if (params.size() == 2 && (!params.get(0).asType().toString().equals(getCheckParams(taskEnum)) || !params.get(1).asType().toString().equals(getCheckSubParams(taskEnum)))) { throw new IllegalArgumentException( String.format("%s.%s参数错误, 参数只能是两个或三个,第一个参数是:%s,第二个参数是:%s", className, methodName, getCheckParams(taskEnum), getCheckSubParams(taskEnum))); } } } else { if (isFailAnnotation(annotationClazz)) { if (params.size() < 1 || params.size() > 2) { throw new IllegalArgumentException( String.format("%s.%s参数错误, 参数只能有一个或两个,第一个参数是:%s,第二个参数(可选)是:%s", className, methodName, getCheckParams(taskEnum), Exception.class.getSimpleName())); } if (params.size() == 1 && (!params.get(0).asType().toString().equals(getCheckParams(taskEnum)))) { throw new IllegalArgumentException( String.format("%s.%s参数错误, 参数只能有一个或两个,第一个参数是:%s,第二个参数(可选)是:%s", className, methodName, getCheckParams(taskEnum), Exception.class.getSimpleName())); } if (params.size() == 2 && (!params.get(0).asType().toString().equals(getCheckParams(taskEnum)) || !params.get(1).asType().toString().equals(Exception.class.getName()))) { throw new IllegalArgumentException( String.format("%s.%s参数错误, 参数只能有一个或两个,第一个参数是:%s,第二个参数(可选)是:%s", className, methodName, getCheckParams(taskEnum), Exception.class.getSimpleName())); } } else { if (params.size() != 1 && !params.get(0).asType().toString().equals(getCheckParams(taskEnum))) { throw new IllegalArgumentException( String.format("%s.%s参数错误, 参数只能有一个,且参数必须是:%s", className, methodName, getCheckParams(taskEnum))); } } } } /** * 判断是否是任务失败的回调注解 * * @return {@code true}是任务失败的回调注解 */ private boolean isFailAnnotation(Class annotationClazz) { return annotationClazz == Download.onTaskFail.class || annotationClazz == DownloadGroup.onTaskFail.class || annotationClazz == DownloadGroup.onSubTaskFail.class || annotationClazz == Upload.onTaskFail.class; } /** * 字符串数组转set * * @param keys 注解中查到的key */ private Set convertSet(final String[] keys) { if (keys == null || keys.length == 0) { return null; } if (keys[0].isEmpty()) return null; Set set = new HashSet<>(); Collections.addAll(set, keys); return set; } private String getCheckParams(TaskEnum taskEnum) { return taskEnum.pkg + "." + taskEnum.className; } /** * 检查任务组子任务第二个参数 */ private String getCheckSubParams(TaskEnum taskEnum) { if (taskEnum == TaskEnum.DOWNLOAD_GROUP_SUB) { return EntityInfo.DOWNLOAD.pkg + "." + EntityInfo.DOWNLOAD.className; } return ""; } }