package foundation.route; import java.net.URLDecoder; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Set; import javax.servlet.http.HttpServletRequest; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import foundation.util.MapList; import foundation.util.Util; public class RouteTable { protected static Logger logger; private static RouteTable instance; private static String contextPath; private static int contextLength; private static HashMap resourceTypeMap; private static URIRouteMap resourceURIMap; private static HashMapvirtualPathResourceMap; private static MapList controlerMap; private static OperationSet freeCallSet; private static MapList allRouteMap; private static AuthorizeURIRoute authorizeURIRoute; private static TimeOutRoute timeOutRoute; private static InvalidUserRightRoute invalidUserRightRoute; private static ServerErrorRoute serverErrorRoute; private static NotExistsRoute notExistsRoute; static { logger = LogManager.getLogger(RouteTable.class); } public static synchronized RouteTable createInstance(String contextPath) { if (instance == null) { instance = new RouteTable(contextPath); } return instance; } private RouteTable(String context) { init(context); } private void init(String context) { //1. context contextPath = context; contextLength = context.length(); //2. resourceTypeMap = new HashMap(); resourceURIMap = new URIRouteMap(); virtualPathResourceMap = new HashMap(); controlerMap = new MapList(); freeCallSet = new OperationSet(); allRouteMap = new MapList(); //3. authorizeURIRoute = new AuthorizeURIRoute(); timeOutRoute = new TimeOutRoute("root/login.html"); invalidUserRightRoute = new InvalidUserRightRoute(); serverErrorRoute = new ServerErrorRoute(); notExistsRoute = new NotExistsRoute(); //4. allRouteMap.add("*", authorizeURIRoute); allRouteMap.add("*", timeOutRoute); allRouteMap.add("*", invalidUserRightRoute); allRouteMap.add("*", serverErrorRoute); allRouteMap.add("*", notExistsRoute); } public static RouteNavigator matchRoute(HttpServletRequest request) { String uri = request.getRequestURI(); String path; try { path = URLDecoder.decode(uri, "UTF-8"); } catch (Exception e) { e.printStackTrace(); path = uri; } //1. replace root from context path int pos_root = path.lastIndexOf("/root/"); path = pos_root >= 0 ? contextPath + path.substring(pos_root + 5) : path; //2. delete parameters int pos_end = path.indexOf("?"); if (pos_end <= 0) { pos_end = path.length(); } path = path.substring(contextLength, pos_end); //3. get suffix int pos_dot = path.lastIndexOf("."); String suffix = null; if (pos_dot > 0) { suffix = path.substring(pos_dot); } //4. match NavigatorCreator navigatorCreator = new NavigatorCreator(request); doMatchRoute(uri, path, suffix, navigatorCreator); return navigatorCreator.getNavigator(); } private static void doMatchRoute(String uri, String path, String suffix, NavigatorCreator navigatorCreator) { Route route = null; //1 resource by suffix if (suffix != null) { suffix = suffix.toLowerCase(); route = resourceTypeMap.get(suffix); if (route != null) { navigatorCreator.onResourceTypeMatch(uri, path, suffix, route, false); return; } } //2 resource by URI String[] segments = createSegements(path); String page = segments[segments.length - 1]; route = resourceURIMap.get(page); if (route != null) { navigatorCreator.onResourceURIMatch(uri, path, suffix, route, false); return; } //3. virtual path resource route = virtualPathResourceMap.get(path); if (route != null) { VirtualPathRoute virtualRoute = (VirtualPathRoute) route; navigatorCreator.onVirtualPathMatch(uri, virtualRoute.getTarget(), suffix, route, false); return; } //4. controller if (segments.length >= 2) { Operation operation = new Operation(segments); route = controlerMap.get(operation.getObject()); if (route != null) { boolean authorizeSensitive = !freeCallSet.contains(operation); navigatorCreator.onControllerMatch(uri, path, operation, route, authorizeSensitive); return; } } //5. not exists navigatorCreator.onNoMatch(uri, suffix, path); return; } private static String[] createSegements(String path) { if (path.charAt(0) == '/') { path = path.substring(1); } return path.toLowerCase().split("/"); } public static void addFreeVisitResourceType(String type) { if (Util.isEmpty(type)) { return; } Route route = new FreeTypeRoute(type); String from = route.getFrom(); resourceTypeMap.put(from, route); allRouteMap.add(type, route); } public static void appendFreeVisitResource(String uri) { if (Util.isEmpty(uri)) { return; } Route route = new FreeURIRoute(uri); String from = route.getFrom(); resourceURIMap.add(from, route); allRouteMap.add(uri, route); } public static void appendVirtualPath(String from, String target) { VirtualPathRoute route = new VirtualPathRoute(from, target); virtualPathResourceMap.put(from, route); allRouteMap.add(from, route); } public static void appendFreeVisitCall(String call) { if (Util.isEmpty(call)) { return; } call = call.toLowerCase(); freeCallSet.add(call); } public static void appendCallableClass(String path, String classname) throws Exception { try { ControllerRoute route = new ControllerRoute(path, classname); String from = route.getFrom(); controlerMap.add(from, route); allRouteMap.add(path, route); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static List getRouteList() { return allRouteMap.getItemList(); } public static List getFreeResourceTypeRouteList() { List result = new ArrayList(); Set keys = resourceTypeMap.keySet(); for (String key: keys) { result.add(resourceTypeMap.get(key)); } return result; } public static List getFreeResourceURIRouteList() { List result = new ArrayList(); Set keys = resourceURIMap.keySet(); for (String key: keys) { result.add(resourceURIMap.get(key)); } return result; } public static List getAuthorizedControlerRouteList() { List result = new ArrayList(); Set keys = controlerMap.keySet(); for (String key: keys) { result.add(controlerMap.get(key)); } return result; } public static List getSpecializedRouteList() { List result = new ArrayList(); result.add(authorizeURIRoute); result.add(invalidUserRightRoute); result.add(timeOutRoute); result.add(serverErrorRoute); result.add(notExistsRoute); return result; } public static List getControlerList() { return controlerMap.getItemList(); } public static ControllerRoute getControler(String name) { return controlerMap.get(name); } public static Route getTimeOutRoute() { return timeOutRoute; } public static Route getNotExistsRoute() { return notExistsRoute; } public static ServerErrorRoute getServerErrorRoute() { return serverErrorRoute; } public static InvalidUserRightRoute getInvalidUserRightRoute() { return invalidUserRightRoute; } }