RouteInterceptor -> Add possibility to associate an interceptor with specific Route(s)
This commit is contained in:
parent
9cedf6898f
commit
f47551fc6f
5 changed files with 111 additions and 0 deletions
72
src/dev/peerat/framework/RouteBinder.java
Normal file
72
src/dev/peerat/framework/RouteBinder.java
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
package dev.peerat.framework;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
|
||||||
|
public class RouteBinder{
|
||||||
|
|
||||||
|
//TODO interceptor -------> bind to a specific route, no all routes ? or both. Could be interesting for somes cases !
|
||||||
|
|
||||||
|
private Class<?>[] types;
|
||||||
|
private int[] bindMethod;
|
||||||
|
private int parameterCount;
|
||||||
|
|
||||||
|
public RouteBinder(){}
|
||||||
|
|
||||||
|
public void bind(Class<?>... types){
|
||||||
|
if(this.types == null){
|
||||||
|
this.types = types;
|
||||||
|
this.parameterCount = this.types.length;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Class<?>[] copy = new Class[this.types.length+types.length];
|
||||||
|
System.arraycopy(this.types, 0, copy, 0, this.types.length);
|
||||||
|
System.arraycopy(types, 0, copy, this.types.length, types.length);
|
||||||
|
this.types = copy;
|
||||||
|
this.parameterCount = this.types.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bindIndexes(Method method){
|
||||||
|
Class<?>[] parameters = method.getParameterTypes();
|
||||||
|
this.bindMethod = new int[4+(types == null ? 0 : types.length)];
|
||||||
|
this.bindMethod[0] = findIndex(parameters, Matcher.class);
|
||||||
|
this.bindMethod[1] = findIndex(parameters, Context.class);
|
||||||
|
this.bindMethod[2] = findIndex(parameters, HttpReader.class);
|
||||||
|
this.bindMethod[3] = findIndex(parameters, HttpWriter.class);
|
||||||
|
if(this.types == null) return;
|
||||||
|
for(int i = 0; i < this.types.length; i++){
|
||||||
|
this.bindMethod[4+i] = findIndex(parameters, this.types[i]);
|
||||||
|
}
|
||||||
|
this.types = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getParameterCount(){
|
||||||
|
return this.parameterCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] bindMethod(Method method, Matcher matcher, Context context, HttpReader reader, HttpWriter writer, Object[] objects){
|
||||||
|
Object[] result = new Object[method.getParameterCount()];
|
||||||
|
setElement(result, bindMethod[0], matcher);
|
||||||
|
setElement(result, bindMethod[1], context);
|
||||||
|
setElement(result, bindMethod[2], reader);
|
||||||
|
setElement(result, bindMethod[3], writer);
|
||||||
|
for(int i = 0; i < objects.length; i++){
|
||||||
|
setElement(result, bindMethod[4+i], objects[i]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setElement(Object[] array, int position, Object element){
|
||||||
|
if(position < 0) return;
|
||||||
|
array[position] = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int findIndex(Class<?>[] array, Class<?> type){
|
||||||
|
for(int i = 0; i < array.length; i++){
|
||||||
|
Class<?> clazz = array[i];
|
||||||
|
if(type.isAssignableFrom(clazz)) return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
10
src/dev/peerat/framework/RouteFilter.java
Normal file
10
src/dev/peerat/framework/RouteFilter.java
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
package dev.peerat.framework;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public interface RouteFilter{
|
||||||
|
|
||||||
|
boolean accept(Method method, Route route, Pattern pattern);
|
||||||
|
|
||||||
|
}
|
|
@ -27,6 +27,12 @@ public class RouteMapper<U extends User>{
|
||||||
if(this.calls != null) this.calls = new int[length];
|
if(this.calls != null) this.calls = new int[length];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addInterceptor(RouteFilter filter, RouteInterceptor interceptor){
|
||||||
|
for(RouteState state : this.states){
|
||||||
|
if(filter.accept(state.getMethod(), state.getRoute(), state.getPattern())) state.addInterceptor(interceptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void bind(RouteFilter filter, Class<?>... types){
|
public void bind(RouteFilter filter, Class<?>... types){
|
||||||
for(RouteState state : this.states){
|
for(RouteState state : this.states){
|
||||||
if(filter.accept(state.getMethod(), state.getRoute(), state.getPattern())) state.getBinder().bind(types);
|
if(filter.accept(state.getMethod(), state.getRoute(), state.getPattern())) state.getBinder().bind(types);
|
||||||
|
@ -77,6 +83,12 @@ public class RouteMapper<U extends User>{
|
||||||
for(RouteInterceptor interceptor : interceptors){
|
for(RouteInterceptor interceptor : interceptors){
|
||||||
if(!interceptor.intercept(matcher, context, reader, writer, target.getMethod(), params)) return true;
|
if(!interceptor.intercept(matcher, context, reader, writer, target.getMethod(), params)) return true;
|
||||||
}
|
}
|
||||||
|
List<RouteInterceptor> localInterceptors = target.getInterceptors();
|
||||||
|
if(localInterceptors != null){
|
||||||
|
for(RouteInterceptor interceptor : localInterceptors){
|
||||||
|
if(!interceptor.intercept(matcher, context, reader, writer, target.getMethod(), params)) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
Object[] inv = target.getBinder().bindMethod(target.getMethod(), matcher, context, reader, writer, params);
|
Object[] inv = target.getBinder().bindMethod(target.getMethod(), matcher, context, reader, writer, params);
|
||||||
target.getMethod().invoke(target.getInstance(), inv);
|
target.getMethod().invoke(target.getInstance(), inv);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package dev.peerat.framework;
|
package dev.peerat.framework;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@ -11,6 +13,7 @@ public class RouteState {
|
||||||
private Route route;
|
private Route route;
|
||||||
private Pattern pattern;
|
private Pattern pattern;
|
||||||
private RouteBinder binder;
|
private RouteBinder binder;
|
||||||
|
private List<RouteInterceptor> interceptors; //TODO concat interceptors ??
|
||||||
|
|
||||||
public RouteState(Object instance, Method method, Route route){
|
public RouteState(Object instance, Method method, Route route){
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
|
@ -29,6 +32,15 @@ public class RouteState {
|
||||||
return matcher.matches() ? matcher : null;
|
return matcher.matches() ? matcher : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addInterceptor(RouteInterceptor interceptor){
|
||||||
|
if(this.interceptors == null) this.interceptors = new ArrayList<>();
|
||||||
|
this.interceptors.add(interceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<RouteInterceptor> getInterceptors(){
|
||||||
|
return this.interceptors;
|
||||||
|
}
|
||||||
|
|
||||||
public Route getRoute(){
|
public Route getRoute(){
|
||||||
return this.route;
|
return this.route;
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,6 +135,11 @@ public class Router<U extends User>{
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Router<U> addInterceptor(RouteFilter filter, RouteInterceptor interceptor){
|
||||||
|
for(RouteMapper<U> mapper : this.mappers) mapper.addInterceptor(filter, interceptor);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Router<U> bind(RouteFilter filter, Class<?>... types){
|
public Router<U> bind(RouteFilter filter, Class<?>... types){
|
||||||
for(RouteMapper<U> mapper : this.mappers) mapper.bind(filter, types);
|
for(RouteMapper<U> mapper : this.mappers) mapper.bind(filter, types);
|
||||||
return this;
|
return this;
|
||||||
|
|
Loading…
Add table
Reference in a new issue