Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.fastchar.core.FastDispatcher Maven / Gradle / Ivy
package com.fastchar.core;
import com.fastchar.annotation.*;
import com.fastchar.asm.FastParameter;
import com.fastchar.asm.FastMethodRead;
import com.fastchar.exception.FastActionException;
import com.fastchar.exception.FastWebException;
import com.fastchar.interfaces.IFastInterceptor;
import com.fastchar.interfaces.IFastRootInterceptor;
import com.fastchar.out.FastOut;
import com.fastchar.utils.FastMethodUtils;
import com.fastchar.utils.FastStringUtils;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
@SuppressWarnings("unchecked")
public final class FastDispatcher {
private static final Map FAST_ROUTE_MAP = new HashMap<>();
private static final Set resolved = new HashSet<>();
static void initDispatcher() {
FastEngine.instance().getInterceptors().sortRootInterceptor();
resolved.clear();
}
public static List getClassRoutes(Class targetClass) throws Exception {
FastAction fastAction = targetClass.newInstance();
FastMethodRead parameterConverter = new FastMethodRead();
List lineNumber = parameterConverter.getMethodLineNumber(targetClass, "getRoute");
String classRoute = fastAction.getRoute();
if (FastStringUtils.isEmpty(classRoute)) {
int line = 1;
if (lineNumber.size() > 0) {
line = lineNumber.get(0).getLastLine();
}
throw new FastActionException(FastChar.getLocal().getInfo("Action_Error1") +
"\n\tat " + new StackTraceElement(targetClass.getName(), "getRoute",
targetClass.getSimpleName() + ".java", line)
);
}
List classRoutes = new ArrayList<>();
classRoutes.add(classRoute);
if (targetClass.isAnnotationPresent(AFastRoute.class)) {
AFastRoute fastRoute = targetClass.getAnnotation(AFastRoute.class);
if (fastRoute.head()) {
classRoutes.clear();
for (String s : fastRoute.value()) {
String route = FastStringUtils.stripEnd(s, "/") + "/" +
FastStringUtils.stripStart(classRoute, "/");
if (classRoutes.contains(route)) {
continue;
}
classRoutes.add(route);
}
} else {
for (String route : fastRoute.value()) {
if (classRoutes.contains(route)) {
continue;
}
classRoutes.add(route);
}
}
}
return classRoutes;
}
public static List getClassMethodRoutes(Class targetClass, String declaredMethodName) throws Exception {
return getClassMethodRoutes(targetClass, targetClass.getDeclaredMethod(declaredMethodName));
}
public static List getClassMethodRoutes(Class targetClass, Method declaredMethod) throws Exception {
List classMethodRoutes = new ArrayList<>();
if (Modifier.isStatic(declaredMethod.getModifiers())) {
return classMethodRoutes;
}
if (Modifier.isTransient(declaredMethod.getModifiers())) {
return classMethodRoutes;
}
if (Modifier.isAbstract(declaredMethod.getModifiers())) {
return classMethodRoutes;
}
if (!Modifier.isPublic(declaredMethod.getModifiers())) {
return classMethodRoutes;
}
if (declaredMethod.getName().equalsIgnoreCase("getRoute")) {
return classMethodRoutes;
}
List classRoutes = getClassRoutes(targetClass);
List methodRoutes = new ArrayList<>();
methodRoutes.add(declaredMethod.getName());
if (declaredMethod.isAnnotationPresent(AFastRoute.class)) {
AFastRoute fastRoute = declaredMethod.getAnnotation(AFastRoute.class);
if (fastRoute.head()) {
methodRoutes.clear();
for (String s : fastRoute.value()) {
String route = FastStringUtils.stripEnd(s, "/") + "/" + declaredMethod.getName();
if (methodRoutes.contains(route)) {
continue;
}
methodRoutes.add(route);
}
} else {
for (String route : fastRoute.value()) {
if (methodRoutes.contains(route)) {
continue;
}
methodRoutes.add(route);
}
}
}
for (String route : classRoutes) {
if (FastStringUtils.isEmpty(route)) continue;
route = FastStringUtils.stripEnd(route, "/") + "/";
for (String methodRoute : methodRoutes) {
if (FastStringUtils.isEmpty(methodRoute)) continue;
String classMethodRoute = route + FastStringUtils.strip(methodRoute, "/");
if (classMethodRoutes.contains(classMethodRoute)) {
continue;
}
classMethodRoutes.add(classMethodRoute);
}
}
return classMethodRoutes;
}
static boolean actionResolver(Class actionClass) throws Exception {
if (FastChar.getServletContext() == null) {
return false;
}
if (resolved.contains(actionClass.getName())) {
return true;
}
resolved.add(actionClass.getName());
Class defaultOut = FastEngine.instance().getActions().getDefaultOut();
FastMethodRead parameterConverter = new FastMethodRead();
if (actionClass.isAnnotationPresent(AFastAction.class)) {
AFastAction annotation = actionClass.getAnnotation(AFastAction.class);
if (!annotation.value()) {//被禁止
return false;
}
}
if (actionClass.isAnnotationPresent(AFastResponse.class)) {
AFastResponse response = actionClass.getAnnotation(AFastResponse.class);
defaultOut = FastOut.convertType(response.value());
}
Method[] declaredMethods = actionClass.getDeclaredMethods();
Map methodCount = new HashMap<>();
for (Method declaredMethod : declaredMethods) {
if (Modifier.isStatic(declaredMethod.getModifiers())) {
continue;
}
if (Modifier.isTransient(declaredMethod.getModifiers())) {
continue;
}
if (Modifier.isAbstract(declaredMethod.getModifiers())) {
continue;
}
if (!Modifier.isPublic(declaredMethod.getModifiers())) {
continue;
}
if (!methodCount.containsKey(declaredMethod.getName())) {
methodCount.put(declaredMethod.getName(), 0);
}
methodCount.put(declaredMethod.getName(), methodCount.get(declaredMethod.getName()) + 1);
List lines = new ArrayList<>();
List parameter = parameterConverter.getParameter(declaredMethod, lines);
List classMethodRoutes = getClassMethodRoutes(actionClass, declaredMethod);
for (String classMethodRoute : classMethodRoutes) {
FastRoute fastRoute = new FastRoute();
fastRoute.actionClass = actionClass;
fastRoute.method = declaredMethod;
fastRoute.firstMethodLineNumber = lines.get(methodCount.get(declaredMethod.getName()) - 1).getFirstLine() - 1;
fastRoute.lastMethodLineNumber = lines.get(methodCount.get(declaredMethod.getName()) - 1).getLastLine();
fastRoute.methodParameter = parameter;
fastRoute.route = classMethodRoute;
if (actionClass.isAnnotationPresent(AFastPriority.class)) {
AFastPriority annotation = actionClass.getAnnotation(AFastPriority.class);
fastRoute.priority = annotation.value();
}
if (FastMethodUtils.isOverride(declaredMethod)) {
fastRoute.priority = Math.max(AFastPriority.P_NORMAL, fastRoute.priority);
}
if (declaredMethod.isAnnotationPresent(AFastPriority.class)) {
AFastPriority annotation = declaredMethod.getAnnotation(AFastPriority.class);
fastRoute.priority = annotation.value();
}
if (declaredMethod.isAnnotationPresent(AFastResponse.class)) {
AFastResponse annotation = declaredMethod.getAnnotation(AFastResponse.class);
defaultOut = FastOut.convertType(annotation.value());
}
fastRoute.returnOut = defaultOut;
initInterceptor(null, fastRoute, 0);
initInterceptor(actionClass, fastRoute, 1);
initInterceptor(declaredMethod, fastRoute, 2);
if (FAST_ROUTE_MAP.containsKey(classMethodRoute)) {
FastRoute existFastRoute = FAST_ROUTE_MAP.get(classMethodRoute);
StackTraceElement newStack = new StackTraceElement(actionClass.getName(), fastRoute.getMethod().getName(),
actionClass.getSimpleName() + ".java", fastRoute.firstMethodLineNumber);
StackTraceElement currStack = new StackTraceElement(existFastRoute.getActionClass().getName(), existFastRoute.getMethod().getName(),
existFastRoute.getActionClass().getSimpleName() + ".java", existFastRoute.firstMethodLineNumber);
if (fastRoute.getPriority() == existFastRoute.getPriority()) {
throw new FastActionException(FastChar.getLocal().getInfo("Action_Error2", "'" + classMethodRoute + "'") +
"\n\tat " + newStack +
"\n\tat " + currStack
);
}
if (fastRoute.getPriority() > existFastRoute.getPriority()) {
FastChar.getLog().warn(FastAction.class, FastChar.getLog().warnStyle(FastChar.getLocal().getInfo("Action_Error3", "'" + classMethodRoute + "'", newStack)));
} else {
FastChar.getLog().warn(FastAction.class, FastChar.getLog().warnStyle(FastChar.getLocal().getInfo("Action_Error3", "'" + classMethodRoute + "'", currStack)));
continue;
}
}
fastRoute.sortInterceptors();
FAST_ROUTE_MAP.put(classMethodRoute, fastRoute);
if (FastChar.getConstant().isLogRoute()) {
FastChar.getLog().info(actionClass, classMethodRoute);
}
}
}
if (FastAction.class.isAssignableFrom(actionClass.getSuperclass())) {
if (actionClass.getSuperclass() != FastAction.class) {
actionResolver((Class) actionClass.getSuperclass());
}
}
return true;
}
private static void initInterceptor(GenericDeclaration target, FastRoute fastRoute, int index) throws Exception {
FastMethodRead read = new FastMethodRead();
if (target != null) {
AFastBefore beforeInterceptor = null;
AFastAfter afterInterceptor = null;
if (target instanceof Class) {
beforeInterceptor = ((Class) target).getAnnotation(AFastBefore.class);
afterInterceptor = ((Class) target).getAnnotation(AFastAfter.class);
} else if (target instanceof Method) {
beforeInterceptor = ((Method) target).getAnnotation(AFastBefore.class);
afterInterceptor = ((Method) target).getAnnotation(AFastAfter.class);
}
if (beforeInterceptor != null) {
for (Class aClass : beforeInterceptor.value()) {
List lineNumber = read.getMethodLineNumber(aClass, "onInterceptor");
FastRoute.RouteInterceptor routeInterceptor = new FastRoute.RouteInterceptor();
routeInterceptor.index = index;
routeInterceptor.priority = beforeInterceptor.priority();
routeInterceptor.interceptorClass = aClass;
if (lineNumber.size() > 0) {
routeInterceptor.firstMethodLineNumber = lineNumber.get(0).getFirstLine();
routeInterceptor.lastMethodLineNumber = lineNumber.get(0).getLastLine();
}
fastRoute.addBeforeInterceptor(routeInterceptor);
}
}
if (afterInterceptor != null) {
for (Class aClass : afterInterceptor.value()) {
List lineNumber = read.getMethodLineNumber(aClass, "onInterceptor");
FastRoute.RouteInterceptor routeInterceptor = new FastRoute.RouteInterceptor();
routeInterceptor.index = index;
routeInterceptor.priority = afterInterceptor.priority();
routeInterceptor.interceptorClass = aClass;
if (lineNumber.size() > 0) {
routeInterceptor.firstMethodLineNumber = lineNumber.get(0).getFirstLine();
routeInterceptor.lastMethodLineNumber = lineNumber.get(0).getLastLine();
}
fastRoute.addAfterInterceptor(routeInterceptor);
}
}
} else {
List> beforeInterceptors = FastEngine.instance().getInterceptors().getBeforeInterceptors(fastRoute.getRoute());
for (FastInterceptors.InterceptorInfo beforeInterceptor : beforeInterceptors) {
List lineNumber = read.getMethodLineNumber(beforeInterceptor.getInterceptor(), "onInterceptor");
FastRoute.RouteInterceptor routeInterceptor = new FastRoute.RouteInterceptor();
routeInterceptor.index = index;
routeInterceptor.priority = beforeInterceptor.getPriority();
routeInterceptor.interceptorClass = beforeInterceptor.getInterceptor();
if (lineNumber.size() > 0) {
routeInterceptor.firstMethodLineNumber = lineNumber.get(0).getFirstLine();
routeInterceptor.lastMethodLineNumber = lineNumber.get(0).getLastLine();
}
fastRoute.addBeforeInterceptor(routeInterceptor);
}
List> afterInterceptors = FastEngine.instance().getInterceptors().getAfterInterceptors(fastRoute.getRoute());
for (FastInterceptors.InterceptorInfo afterInterceptor : afterInterceptors) {
List lineNumber = read.getMethodLineNumber(afterInterceptor.getInterceptor(), "onInterceptor");
FastRoute.RouteInterceptor routeInterceptor = new FastRoute.RouteInterceptor();
routeInterceptor.index = index;
routeInterceptor.priority = afterInterceptor.getPriority();
routeInterceptor.interceptorClass = afterInterceptor.getInterceptor();
if (lineNumber.size() > 0) {
routeInterceptor.firstMethodLineNumber = lineNumber.get(0).getFirstLine();
routeInterceptor.lastMethodLineNumber = lineNumber.get(0).getLastLine();
}
fastRoute.addAfterInterceptor(routeInterceptor);
}
}
}
private FilterChain filterChain;
private HttpServletRequest request;
private HttpServletResponse response;
private String contentUrl;
private List> rootInterceptor;
private int interceptorIndex = -1;
private FastAction forwarder;
public FastDispatcher(HttpServletRequest request, HttpServletResponse response) {
this(null, request, response);
}
public FastDispatcher(FilterChain filterChain, HttpServletRequest request, HttpServletResponse response) {
this.filterChain = filterChain;
this.request = request;
this.response = response;
this.init();
}
private void init() {
String requestUrl = request.getRequestURL().toString();
this.contentUrl = FastUrlParser.getContentPath(requestUrl);
this.rootInterceptor = FastEngine.instance().getInterceptors().getRootInterceptors(contentUrl);
this.interceptorIndex = -1;
}
public FilterChain getFilterChain() {
return filterChain;
}
public HttpServletRequest getRequest() {
return request;
}
public HttpServletResponse getResponse() {
return response;
}
public String getContentUrl() {
return contentUrl;
}
public FastDispatcher setContentUrl(String contentUrl) {
this.contentUrl = contentUrl;
return this;
}
public FastAction getForwarder() {
return forwarder;
}
public FastDispatcher setForwarder(FastAction forwarder) {
this.forwarder = forwarder;
return this;
}
/**
* 验证路径是否可被转发到FastChar
*
* @param contentPath
* @return
*/
private boolean validateUrl(String contentPath) {
List excludeUrls = FastChar.getActions().getExcludeUrls();
for (String excludeUrl : excludeUrls) {
if (FastStringUtils.matches(excludeUrl, contentPath)) {
return false;
}
}
File localFile = new File(FastChar.getPath().getWebRootPath(), contentPath);
if (localFile.exists()) {//存在于webroot下
return false;
}
return true;
}
public void invoke() throws FastWebException {
try {
interceptorIndex++;
if (interceptorIndex < rootInterceptor.size()) {
IFastRootInterceptor interceptor = rootInterceptor.get(interceptorIndex).newInstance();
interceptor.onInterceptor(request, response, this);
return;
}
Date inTime = new Date();
List parse = FastUrlParser.parse(contentUrl);
for (int i = 0; i < parse.size(); i++) {
FastUrl fastUrl = parse.get(i);
if (FAST_ROUTE_MAP.containsKey(fastUrl.getMethodRoute())) {
FastRoute fastRoute = FAST_ROUTE_MAP.get(fastUrl.getMethodRoute()).copy();
fastRoute.inTime = inTime;
fastRoute.request = request;
fastRoute.response = response;
fastRoute.fastUrl = fastUrl;
fastRoute.forwarder = forwarder;
fastRoute.rootInterceptor = rootInterceptor;
fastRoute.stackTraceElements.addAll(Arrays.asList(Thread.currentThread().getStackTrace()));
fastRoute.invoke();
return;
}
if (FAST_ROUTE_MAP.containsKey(fastUrl.getMethodRouteIndex())) {
FastRoute fastRoute = FAST_ROUTE_MAP.get(fastUrl.getMethodRouteIndex()).copy();
fastRoute.inTime = inTime;
fastRoute.request = request;
fastRoute.response = response;
fastRoute.fastUrl = fastUrl;
fastRoute.forwarder = forwarder;
fastRoute.rootInterceptor = rootInterceptor;
fastRoute.stackTraceElements.addAll(Arrays.asList(Thread.currentThread().getStackTrace()));
fastRoute.invoke();
return;
}
if (i == 0) {
if (!validateUrl(contentUrl)) {
doFilter();
return;
}
}
}
contentUrl = FastStringUtils.stripEnd(contentUrl, "/");
if (contentUrl.lastIndexOf(".") > 0) {
doFilter();
return;
}
FastRoute fastRoute404 = new FastRoute();
fastRoute404.inTime = inTime;
fastRoute404.route = contentUrl;
FastAction fastErrorAction = new FastAction() {
@Override
public String getRoute() {
return null;
}
};
fastRoute404.fastAction = fastErrorAction;
fastErrorAction.fastRoute = fastRoute404;
fastErrorAction.request = request;
fastErrorAction.response = response;
fastErrorAction.fastUrl = new FastUrl();
fastErrorAction.response404("the route '" + contentUrl + "' not found!");
} catch (Exception e) {
throw new FastWebException(e);
}
}
private void doFilter() throws Exception {
if (this.filterChain != null) {
this.filterChain.doFilter(this.request, this.response);
}
}
}