com.blade.route.RouteMatcher Maven / Gradle / Ivy
/**
* Copyright (c) 2015, biezhi 王爵 ([email protected])
*
* 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.blade.route;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.blade.web.http.HttpMethod;
import com.blade.web.http.Path;
/**
* Default Route Matcher
*
* @author biezhi
* @since 1.0
*/
public class RouteMatcher {
// private static final Logger LOGGER = Logger.getLogger(SampleRouteMatcher.class);
// Storage URL and route
private Map routes = null;
private Map interceptors = null;
// Storage Map Key
private Set routeKeys = null;
private List interceptorRoutes = new ArrayList();
public RouteMatcher(Routers routers) {
this.routes = routers.getRoutes();
this.interceptors = routers.getInterceptors();
this.routeKeys = routes.keySet();
Collection inters = interceptors.values();
if (null != inters && inters.size() > 0) {
this.interceptorRoutes.addAll(inters);
}
}
/**
* Find a route
* @param httpMethod httpMethod
* @param path request path
* @return return route object
*/
public Route getRoute(String httpMethod, String path) {
String cleanPath = parsePath(path);
String routeKey = path + "#" + httpMethod.toUpperCase();
Route route = routes.get(routeKey);
if(null != route){
return route;
}
route = routes.get(path + "#ALL");
if(null != route){
return route;
}
List matchRoutes = new ArrayList();
for(String key : routeKeys){
String[] keyArr = key.split("#");
HttpMethod routeMethod = HttpMethod.valueOf(keyArr[1]);
if (matchesPath(keyArr[0], cleanPath)) {
if (routeMethod == HttpMethod.ALL || HttpMethod.valueOf(httpMethod) == routeMethod) {
route = routes.get(key);
matchRoutes.add(route);
}
}
}
// Priority matching principle
giveMatch(path, matchRoutes);
return matchRoutes.size() > 0 ? matchRoutes.get(0) : null;
}
/**
* Find all in before of the interceptor
* @param path request path
* @return return interceptor list
*/
public List getBefore(String path) {
List befores = new ArrayList();
String cleanPath = parsePath(path);
for (Route route : interceptorRoutes) {
if(matchesPath(route.getPath(), cleanPath) && route.getHttpMethod() == HttpMethod.BEFORE){
befores.add(route);
}
}
giveMatch(path, befores);
return befores;
}
/**
* Find all in after of the interceptor
* @param path request path
* @return return interceptor list
*/
public List getAfter(String path) {
List afters = new ArrayList();
String cleanPath = parsePath(path);
for (Route route : interceptorRoutes) {
if(matchesPath(route.getPath(), cleanPath) && route.getHttpMethod() == HttpMethod.AFTER){
afters.add(route);
}
}
giveMatch(path, afters);
return afters;
}
/**
* Sort of path
* @param uri request uri
* @param routes route list
*/
private void giveMatch(final String uri, List routes) {
Collections.sort(routes, new Comparator() {
@Override
public int compare(Route o1, Route o2) {
if(o2.getPath().equals(uri)){
return o2.getPath().indexOf(uri);
}
return -1;
}
});
}
/**
* Matching path
*
* @param routePath route path
* @param pathToMatch match path
* @return return match is success
*/
private boolean matchesPath(String routePath, String pathToMatch) {
routePath = routePath.replaceAll(Path.VAR_REGEXP, Path.VAR_REPLACE);
return pathToMatch.matches("(?i)" + routePath);
}
/**
* Parse Path
*
* @param path route path
* @return return parsed path
*/
private String parsePath(String path) {
path = Path.fixPath(path);
try {
URI uri = new URI(path);
return uri.getPath();
} catch (URISyntaxException e) {
return null;
}
}
}