diff --git a/src/dev/peerat/framework/RouteCachable.java b/src/dev/peerat/framework/RouteCachable.java new file mode 100644 index 0000000..f551a54 --- /dev/null +++ b/src/dev/peerat/framework/RouteCachable.java @@ -0,0 +1,61 @@ +package dev.peerat.framework; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +public class RouteCachable{ + + private List interceptors; + private Map> localInterceptors; + private Map[]> types; + + public RouteCachable(){ + this.interceptors = new ArrayList<>(); + this.localInterceptors = new HashMap<>(); + this.types = new HashMap<>(); + } + + public void addInterceptor(RouteMapper[] mappers, RouteInterceptor interceptor){ + this.interceptors.add(interceptor); + for(RouteMapper mapper : mappers) mapper.addInterceptor(interceptor); + } + + public void addInterceptor(RouteMapper[] mappers, RouteFilter filter, RouteInterceptor interceptor){ + List list = this.localInterceptors.get(filter); + if(list == null){ + list = new ArrayList<>(); + this.localInterceptors.put(filter, list); + } + list.add(interceptor); + + for(RouteMapper mapper : mappers) mapper.addInterceptor(filter, interceptor); + } + + public void bind(RouteMapper[] mappers, RouteFilter filter, Class... types){ + Class[] array = this.types.get(filter); + Class[] copy; + if(array == null){ + copy = types; + }else{ + copy = new Class[array.length+types.length]; + System.arraycopy(array, 0, copy, 0, array.length); + System.arraycopy(types, 0, copy, array.length, types.length); + } + this.types.put(filter, copy); + + for(RouteMapper mapper : mappers) mapper.bind(filter, types); + } + + public void registerRoute(RouteState route){ + if(!this.interceptors.isEmpty()) route.addInterceptors(this.interceptors); + for(Entry> entry : this.localInterceptors.entrySet()){ + if(entry.getKey().accept(route.getMethod(), route.getRoute(), route.getPattern())) route.addInterceptors(entry.getValue()); + } + for(Entry[]> entry : this.types.entrySet()){ + if(entry.getKey().accept(route.getMethod(), route.getRoute(), route.getPattern())) route.getBinder().bind(entry.getValue()); + } + } +} diff --git a/src/dev/peerat/framework/RouteMapper.java b/src/dev/peerat/framework/RouteMapper.java index d9fc465..cfff5af 100644 --- a/src/dev/peerat/framework/RouteMapper.java +++ b/src/dev/peerat/framework/RouteMapper.java @@ -20,11 +20,19 @@ public class RouteMapper{ this.states = new RouteState[0]; } - public void register(Object instance, Method method, Route route){ + public RouteState register(Object instance, Method method, Route route){ int length = states.length+1; method.setAccessible(true); - this.states = addElement(states, new RouteState[length], new RouteState(instance, method, route)); + RouteState state = new RouteState(instance, method, route); + this.states = addElement(states, new RouteState[length], state); if(this.calls != null) this.calls = new int[length]; + return state; + } + + public void addInterceptor(RouteInterceptor interceptor){ + for(RouteState state : this.states){ + state.addInterceptor(interceptor); + } } public void addInterceptor(RouteFilter filter, RouteInterceptor interceptor){ @@ -48,7 +56,7 @@ public class RouteMapper{ this.dif = 2; } - public boolean exec(Context context, HttpReader reader, HttpWriter writer, List interceptors) throws Exception{ + public boolean exec(Context context, HttpReader reader, HttpWriter writer) throws Exception{ RouteState target = null; Matcher matcher = null; @@ -80,9 +88,6 @@ public class RouteMapper{ } if(target != null){ Object[] params = new Object[target.getBinder().getParameterCount()]; - for(RouteInterceptor interceptor : interceptors){ - if(!interceptor.intercept(matcher, context, reader, writer, target.getMethod(), params)) return true; - } List localInterceptors = target.getInterceptors(); if(localInterceptors != null){ for(RouteInterceptor interceptor : localInterceptors){ @@ -90,7 +95,9 @@ public class RouteMapper{ } } Object[] inv = target.getBinder().bindMethod(target.getMethod(), matcher, context, reader, writer, params); - target.getMethod().invoke(target.getInstance(), inv); + Object result = target.getMethod().invoke(target.getInstance(), inv); + if(result == null) return true; + //TODO MAP OBJECT TO RESPONSE return true; } return false; diff --git a/src/dev/peerat/framework/RouteState.java b/src/dev/peerat/framework/RouteState.java index 32adcfe..4964763 100644 --- a/src/dev/peerat/framework/RouteState.java +++ b/src/dev/peerat/framework/RouteState.java @@ -2,6 +2,7 @@ package dev.peerat.framework; import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -37,6 +38,11 @@ public class RouteState { this.interceptors.add(interceptor); } + public void addInterceptors(Collection interceptors){ + if(this.interceptors == null) this.interceptors = new ArrayList<>(interceptors); + else this.interceptors.addAll(interceptors); + } + public List getInterceptors(){ return this.interceptors; } diff --git a/src/dev/peerat/framework/Router.java b/src/dev/peerat/framework/Router.java index d17839a..3dbb153 100644 --- a/src/dev/peerat/framework/Router.java +++ b/src/dev/peerat/framework/Router.java @@ -22,7 +22,7 @@ public class Router{ private Locker logger; private Locker exceptions; private RouteMapper[] mappers; - private List interceptors; + private RouteCachable cachable; private Response noFileFound; private Authenticator auth; private String[][] headers; @@ -33,8 +33,8 @@ public class Router{ this.exceptions = new Locker<>(); int types = RequestType.values().length; this.mappers = new RouteMapper[types]; - this.interceptors = new ArrayList<>(); for(RequestType type : RequestType.values()) this.mappers[type.ordinal()] = new RouteMapper<>(this); + this.cachable = new RouteCachable(); this.headers = new String[types][0]; } @@ -58,7 +58,8 @@ public class Router{ Response.class.getDeclaredMethods()[0].getParameterTypes()); Route route = method.getAnnotation(Route.class); - this.mappers[route.type().ordinal()].register(response, method, route); + RouteState state = this.mappers[route.type().ordinal()].register(response, method, route); + this.cachable.registerRoute(state); System.out.println("Registered route "+method+" ["+route.type()+" "+route.path()+"]"); }catch(Exception e){ throw new IllegalArgumentException(e); @@ -82,7 +83,8 @@ public class Router{ instance = constructors[0].newInstance(injector.apply(constructors[0])); } - this.mappers[route.type().ordinal()].register(instance, method, route); + RouteState state = this.mappers[route.type().ordinal()].register(instance, method, route); + this.cachable.registerRoute(state); System.out.println("Registered route "+method+" ["+route.type()+" "+route.path()+"]"); } @@ -131,17 +133,17 @@ public class Router{ } public Router addInterceptor(RouteInterceptor interceptor){ - this.interceptors.add(interceptor); + this.cachable.addInterceptor(mappers, interceptor); return this; } public Router addInterceptor(RouteFilter filter, RouteInterceptor interceptor){ - for(RouteMapper mapper : this.mappers) mapper.addInterceptor(filter, interceptor); + this.cachable.addInterceptor(mappers, filter, interceptor); return this; } public Router bind(RouteFilter filter, Class... types){ - for(RouteMapper mapper : this.mappers) mapper.bind(filter, types); + this.cachable.bind(mappers, filter, types); return this; } @@ -163,7 +165,7 @@ public class Router{ } void exec(Context context, HttpReader reader, HttpWriter writer) throws Exception{ - if(this.mappers[context.getType().ordinal()].exec(context, reader, writer, this.interceptors)) return; + if(this.mappers[context.getType().ordinal()].exec(context, reader, writer)) return; if(noFileFound != null) noFileFound.exec(null, context, reader, writer); }