com.ifengxue.http.proxy.Resolver Maven / Gradle / Ivy
/*
* Copyright 2019 https://www.ifengxue.com
*
* 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.ifengxue.http.proxy;
import com.ifengxue.http.annotation.Body;
import com.ifengxue.http.annotation.BodyType;
import com.ifengxue.http.annotation.Expensive;
import com.ifengxue.http.annotation.Header;
import com.ifengxue.http.annotation.Param;
import com.ifengxue.http.annotation.ParamHeader;
import com.ifengxue.http.annotation.QueryMap;
import com.ifengxue.http.annotation.QueryParam;
import com.ifengxue.http.codec.Codec;
import com.ifengxue.http.codec.CodecFactory;
import com.ifengxue.http.codec.JsonCodec;
import com.ifengxue.http.codec.XmlCodec;
import com.ifengxue.http.collection.MultiMap;
import com.ifengxue.http.collection.MultiValueMap;
import com.ifengxue.http.contract.Callback;
import com.ifengxue.http.contract.CallbackHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
class Resolver {
/**
* 解析参数
*/
static MultiMap resolveParameters(Map uriVariables) {
if (uriVariables == null) {
return new MultiValueMap<>();
}
MultiMap parameterMap = new MultiValueMap<>(uriVariables.size());
parameterMap.putAll(uriVariables);
return parameterMap;
}
/**
* 解析参数
*/
static MultiMap resolveParameters(Method method, Object[] args, BodyType bodyType) {
if (args == null || args.length == 0) {
return new MultiValueMap<>();
}
Parameter[] parameters = method.getParameters();
MultiMap parameterMap = new MultiValueMap<>(parameters.length);
for (int i = 0; i < parameters.length; i++) {
Parameter parameter = parameters[i];
// skip body annotation
if (parameter.isAnnotationPresent(Body.class)) {
continue;
}
// skip callback type
if (Callback.class.isAssignableFrom(parameter.getType())) {
continue;
}
// skip not param type param
if ((parameter.isAnnotationPresent(Header.class) || parameter.isAnnotationPresent(ParamHeader.class))
&& !parameter.isAnnotationPresent(Param.class)
&& !parameter.isAnnotationPresent(QueryParam.class)
&& !parameter.isAnnotationPresent(QueryMap.class)) {
continue;
}
if (parameter.isAnnotationPresent(Expensive.class) || parameter.isAnnotationPresent(QueryMap.class)) {
if (parameter.isAnnotationPresent(QueryMap.class)) {
if (!(args[i] instanceof Map)) {
throw new IllegalArgumentException("@QueryMap must annotated on Map type parameter.");
}
}
Codec codec = CodecFactory.findCodec(JsonCodec.class);
if (bodyType == BodyType.APPLICATION_XML) {
codec = CodecFactory.findCodec(XmlCodec.class);
}
codec.decode(args[i]).forEach((key, value) -> parameterMap
.put(key, Optional.ofNullable(value).orElse(null)));
} else if (parameter.isAnnotationPresent(QueryParam.class)) {
QueryParam queryParam = parameter.getAnnotation(QueryParam.class);
parameterMap.put(queryParam.name(), args[i]);
} else {
Param param = parameter.getAnnotation(Param.class);
String parameterName = Optional.ofNullable(param).map(Param::value)
.orElse(parameter.getName());
parameterMap.put(parameterName, args[i]);
}
}
return parameterMap;
}
/**
* 解析请求头
*/
static Map resolveHeaders(Method method) {
Map headerMap = new HashMap<>();
for (Header header : method.getDeclaringClass().getAnnotationsByType(Header.class)) {
headerMap.put(header.name(), header.value());
}
for (Header header : method.getAnnotationsByType(Header.class)) {
headerMap.put(header.name(), header.value());
}
return headerMap;
}
/**
* 解析参数中的请求头
*/
static Map resolveParamHeaders(Method method, Object[] args) {
if (args == null) {
return Collections.emptyMap();
}
Parameter[] parameters = method.getParameters();
Map headerMap = new HashMap<>(args.length);
for (int i = 0; i < parameters.length; i++) {
Parameter parameter = parameters[i];
if (!parameter.isAnnotationPresent(ParamHeader.class)) {
continue;
}
ParamHeader header = parameter.getAnnotation(ParamHeader.class);
headerMap.put(header.name(), String.valueOf(args[i]));
}
return headerMap;
}
/**
* 解析参数中的查询参数名称
*/
static Set resolveQueryParameterNames(Method method, Object[] args) {
Set names = Collections.emptySet();
for (int i = 0; i < method.getParameters().length; i++) {
Parameter parameter = method.getParameters()[i];
if (parameter.isAnnotationPresent(QueryParam.class)) {
if (names.isEmpty()) {
names = new LinkedHashSet<>();
}
QueryParam queryParam = parameter.getAnnotation(QueryParam.class);
names.add(queryParam.name());
} else if (parameter.isAnnotationPresent(QueryMap.class)) {
if (names.isEmpty()) {
names = new LinkedHashSet<>();
}
if (args[i] != null) {
for (Object name : ((Map) args[i]).keySet()) {
names.add(name.toString());
}
}
}
}
return names;
}
/**
* 解析请求body
*/
public static Object resolveBody(Method method, Object[] args) {
if (args == null) {
return null;
}
Parameter[] parameters = method.getParameters();
int bodyIndex = -1;
for (int i = 0; i < parameters.length; i++) {
Parameter parameter = parameters[i];
if (parameter.isAnnotationPresent(Body.class)) {
if (bodyIndex >= 0) {
throw new IllegalArgumentException(method.getName() + " contains more than one @Body");
}
bodyIndex = i;
}
}
return bodyIndex >= 0 ? args[bodyIndex] : null;
}
/**
* 查找callback
*/
public static CallbackHandler findCallbackHandler(Method method, Object[] args) {
if (args == null || args.length == 0) {
return null;
}
Parameter[] parameters = method.getParameters();
int callbackIndex = -1;
for (int i = 0; i < parameters.length; i++) {
Parameter parameter = parameters[i];
if (Callback.class.isAssignableFrom(parameter.getType())) {
if (callbackIndex >= 0) {
throw new IllegalArgumentException(method.getName() + " contains more than one Callback parameter");
}
callbackIndex = i;
}
}
if (callbackIndex >= 0 && args[callbackIndex] == null) {
throw new IllegalArgumentException("Callback can not be null");
}
return callbackIndex >= 0 ? new CallbackHandler((Callback) args[callbackIndex], parameters[callbackIndex])
: null;
}
}