net.ymate.platform.webmvc.RequestMeta Maven / Gradle / Ivy
/*
* Copyright 2007-2017 the original author or authors.
*
* 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 net.ymate.platform.webmvc;
import net.ymate.platform.core.util.ClassUtils;
import net.ymate.platform.webmvc.annotation.*;
import net.ymate.platform.webmvc.base.Type;
import org.apache.commons.lang.StringUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* 控制器请求映射元数据描述
*
* @author 刘镇 ([email protected]) on 2012-12-10 下午10:59:14
* @version 1.0
*/
@ParameterEscape
public class RequestMeta {
private static final Map, Map> __CLASS_PARAMETER_METAS;
static {
__CLASS_PARAMETER_METAS = new ConcurrentHashMap, Map>();
}
private final List __methodParameterMetas;
private final Class> targetClass;
private final String name;
private final String mapping;
private Class extends IRequestProcessor> processor;
private Class extends IResponseErrorProcessor> errorProcessor;
private final Method method;
private final List methodParamNames;
private final boolean singleton;
private ResponseCache responseCache;
/**
* 参数转义注解, 若未设置则该值为null
*/
private ParameterEscape parameterEscape;
private ResponseView responseView;
private ResponseBody responseBody;
private final Set responseHeaders;
private final Set allowMethods;
private final Map allowHeaders;
private final Map allowParams;
public RequestMeta(IWebMvc owner, Class> targetClass, Method method) throws Exception {
this.targetClass = targetClass;
this.method = method;
//
this.allowMethods = new HashSet();
this.allowHeaders = new HashMap();
this.allowParams = new HashMap();
//
Controller _controller = targetClass.getAnnotation(Controller.class);
this.name = StringUtils.defaultIfBlank(_controller.name(), targetClass.getName());
this.singleton = _controller.singleton();
//
this.responseCache = method.getAnnotation(ResponseCache.class);
if (this.responseCache == null) {
this.responseCache = targetClass.getAnnotation(ResponseCache.class);
if (this.responseCache == null) {
this.responseCache = targetClass.getPackage().getAnnotation(ResponseCache.class);
}
}
//
this.parameterEscape = method.getAnnotation(ParameterEscape.class);
if (this.parameterEscape == null) {
this.parameterEscape = targetClass.getAnnotation(ParameterEscape.class);
if (this.parameterEscape == null) {
this.parameterEscape = targetClass.getPackage().getAnnotation(ParameterEscape.class);
if (this.parameterEscape == null && owner.getModuleCfg().isParameterEscapeMode()) {
this.parameterEscape = this.getClass().getAnnotation(ParameterEscape.class);
}
}
}
if (this.parameterEscape != null && this.parameterEscape.skiped()) {
this.parameterEscape = null;
}
//
this.responseView = method.getAnnotation(ResponseView.class);
if (this.responseView == null) {
this.responseView = targetClass.getAnnotation(ResponseView.class);
if (this.responseView == null) {
this.responseView = targetClass.getPackage().getAnnotation(ResponseView.class);
}
}
//
this.responseBody = method.getAnnotation(ResponseBody.class);
if (this.responseBody == null) {
this.responseBody = targetClass.getAnnotation(ResponseBody.class);
if (this.responseBody == null) {
this.responseBody = targetClass.getPackage().getAnnotation(ResponseBody.class);
}
}
//
this.responseHeaders = new HashSet();
ResponseHeader _respHeader = targetClass.getPackage().getAnnotation(ResponseHeader.class);
if (_respHeader != null) {
Collections.addAll(this.responseHeaders, _respHeader.value());
}
_respHeader = targetClass.getAnnotation(ResponseHeader.class);
if (_respHeader != null) {
Collections.addAll(this.responseHeaders, _respHeader.value());
}
_respHeader = method.getAnnotation(ResponseHeader.class);
if (_respHeader != null) {
Collections.addAll(this.responseHeaders, _respHeader.value());
}
//
RequestMapping _reqMapping = targetClass.getPackage().getAnnotation(RequestMapping.class);
String _root = null;
if (_reqMapping != null) {
_root = _reqMapping.value();
__doSetAllowValues(_reqMapping);
}
_reqMapping = targetClass.getAnnotation(RequestMapping.class);
if (_reqMapping != null) {
_root = __doBuildRequestMapping(_root, _reqMapping);
__doSetAllowValues(_reqMapping);
}
_reqMapping = method.getAnnotation(RequestMapping.class);
__doSetAllowValues(_reqMapping);
//
if (this.allowMethods.isEmpty()) {
this.allowMethods.add(Type.HttpMethod.GET);
}
//
this.mapping = __doBuildRequestMapping(_root, _reqMapping);
//
RequestProcessor _reqProcessor = method.getAnnotation(RequestProcessor.class);
if (_reqProcessor == null) {
_reqProcessor = targetClass.getAnnotation(RequestProcessor.class);
if (_reqProcessor == null) {
_reqProcessor = targetClass.getPackage().getAnnotation(RequestProcessor.class);
}
}
if (_reqProcessor != null) {
this.processor = _reqProcessor.value();
}
//
ResponseErrorProcessor _errorProcessor = method.getAnnotation(ResponseErrorProcessor.class);
if (_errorProcessor == null) {
_errorProcessor = targetClass.getAnnotation(ResponseErrorProcessor.class);
if (_errorProcessor == null) {
_errorProcessor = targetClass.getPackage().getAnnotation(ResponseErrorProcessor.class);
}
}
if (_errorProcessor != null) {
this.errorProcessor = _errorProcessor.value();
}
//
Map _targetClassParameterMetas = __CLASS_PARAMETER_METAS.get(targetClass);
if (_targetClassParameterMetas == null) {
ClassUtils.BeanWrapper> _wrapper = ClassUtils.wrapper(targetClass);
if (_wrapper != null) {
_targetClassParameterMetas = new HashMap();
//
for (String _fieldName : _wrapper.getFieldNames()) {
if (!_targetClassParameterMetas.containsKey(_fieldName)) {
ParameterMeta _meta = new ParameterMeta(this, _wrapper.getField(_fieldName));
if (_meta.isParamField()) {
_targetClassParameterMetas.put(_fieldName, _meta);
}
}
}
__CLASS_PARAMETER_METAS.put(targetClass, _targetClassParameterMetas);
}
}
//
this.__methodParameterMetas = new ArrayList();
this.methodParamNames = Arrays.asList(ClassUtils.getMethodParamNames(method));
if (!this.methodParamNames.isEmpty()) {
Class>[] _paramTypes = method.getParameterTypes();
Annotation[][] _paramAnnotations = method.getParameterAnnotations();
for (int _idx = 0; _idx < this.methodParamNames.size(); _idx++) {
ParameterMeta _meta = new ParameterMeta(this, _paramTypes[_idx], this.methodParamNames.get(_idx), _paramAnnotations[_idx]);
if (_meta.isParamField()) {
this.__methodParameterMetas.add(_meta);
}
}
}
}
private void __doSetAllowValues(RequestMapping requestMapping) {
this.allowMethods.addAll(Arrays.asList(requestMapping.method()));
for (String _header : requestMapping.header()) {
String[] _headerParts = StringUtils.split(StringUtils.trimToEmpty(_header), "=");
if (_headerParts.length == 2) {
this.allowHeaders.put(_headerParts[0].trim(), _headerParts[1].trim());
}
}
for (String _param : requestMapping.param()) {
String[] _paramParts = StringUtils.split(StringUtils.trimToEmpty(_param), "=");
if (_paramParts.length == 2) {
this.allowParams.put(_paramParts[0].trim(), _paramParts[1].trim());
}
}
}
private String __doBuildRequestMapping(String root, RequestMapping requestMapping) {
StringBuilder _mappingSB = new StringBuilder(__doCheckMappingSeparator(root));
String _mapping = requestMapping.value();
if (StringUtils.isBlank(_mapping)) {
_mappingSB.append("/").append(method.getName());
} else {
_mappingSB.append(__doCheckMappingSeparator(_mapping));
}
return _mappingSB.toString();
}
private String __doCheckMappingSeparator(String mapping) {
if (StringUtils.isBlank(mapping)) {
return "";
}
if (!mapping.startsWith("/")) {
mapping = "/".concat(mapping);
}
if (mapping.endsWith("/")) {
mapping = mapping.substring(0, mapping.length() - 1);
}
return mapping;
}
public Class> getTargetClass() {
return targetClass;
}
public String getMapping() {
return mapping;
}
public Class extends IRequestProcessor> getProcessor() {
return processor;
}
public Class extends IResponseErrorProcessor> getErrorProcessor() {
return errorProcessor;
}
public Method getMethod() {
return method;
}
public List getMethodParamNames() {
return Collections.unmodifiableList(methodParamNames);
}
public String getName() {
return name;
}
public boolean isSingleton() {
return singleton;
}
public ResponseCache getResponseCache() {
return responseCache;
}
public ParameterEscape getParameterEscape() {
return parameterEscape;
}
public ResponseView getResponseView() {
return responseView;
}
public ResponseBody getResponseBody() {
return responseBody;
}
public Set getResponseHeaders() {
return Collections.unmodifiableSet(responseHeaders);
}
/**
* @param method 方法名称
* @return 判断是否允许method方式的HTTP请求,若允许的请求方式集合为空,则默认不限制
*/
public boolean allowHttpMethod(Type.HttpMethod method) {
// 若允许的请求方式集合为空,则默认不限制
return this.allowMethods.isEmpty() || this.allowMethods.contains(method);
}
public Set getAllowMethods() {
return Collections.unmodifiableSet(allowMethods);
}
public Map getAllowHeaders() {
return Collections.unmodifiableMap(allowHeaders);
}
public Map getAllowParams() {
return Collections.unmodifiableMap(allowParams);
}
public Collection getClassParameterMetas() {
return Collections.unmodifiableCollection(__CLASS_PARAMETER_METAS.get(targetClass).values());
}
public List getMethodParameterMetas() {
return Collections.unmodifiableList(__methodParameterMetas);
}
}