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.
net.codestory.http.routes.RouteCollection Maven / Gradle / Ivy
/**
* Copyright (C) 2013-2014 [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 net.codestory.http.routes;
import net.codestory.http.Configuration;
import net.codestory.http.Context;
import net.codestory.http.Request;
import net.codestory.http.Response;
import net.codestory.http.compilers.CompilerFacade;
import net.codestory.http.convert.TypeConvert;
import net.codestory.http.extensions.Extensions;
import net.codestory.http.filters.Filter;
import net.codestory.http.filters.PayloadSupplier;
import net.codestory.http.injection.IocAdapter;
import net.codestory.http.injection.Singletons;
import net.codestory.http.io.Resources;
import net.codestory.http.misc.Env;
import net.codestory.http.payload.Payload;
import net.codestory.http.payload.PayloadWriter;
import net.codestory.http.templating.Site;
import java.lang.reflect.Method;
import java.util.Deque;
import java.util.LinkedList;
import java.util.function.Supplier;
import static net.codestory.http.annotations.AnnotationHelper.parseAnnotations;
import static net.codestory.http.constants.Methods.*;
import static net.codestory.http.payload.Payload.*;
import static net.codestory.http.routes.UriParser.paramsCount;
public class RouteCollection implements Routes {
protected final Env env;
protected final Resources resources;
protected final CompilerFacade compilers;
protected final Site site;
protected final Deque routes;
protected final Deque> filters;
protected IocAdapter iocAdapter;
protected Extensions extensions;
public RouteCollection(Env env) {
this.env = env;
this.resources = new Resources(env);
this.compilers = new CompilerFacade(env, resources);
this.site = new Site(env, resources);
this.routes = new LinkedList<>();
this.filters = new LinkedList<>();
this.iocAdapter = new Singletons();
this.extensions = Extensions.DEFAULT;
}
public void configure(Configuration configuration) {
configuration.configure(this);
installExtensions();
addStaticRoutes(env.prodMode());
}
private void installExtensions() {
TypeConvert.configureOrReplaceMapper(mapper -> extensions.configureOrReplaceObjectMapper(mapper, env));
extensions.configureCompilers(compilers, env);
}
private void addStaticRoutes(boolean prodMode) {
routes.add(new WebJarsRoute(prodMode));
routes.add(new StaticRoute(prodMode, resources, compilers));
if (!prodMode) {
routes.add(new SourceMapRoute(resources, compilers));
routes.add(new SourceRoute(resources));
}
}
public PayloadWriter createPayloadWriter(Request request, Response response) {
return extensions.createPayloadWriter(request, response, env, site, resources, compilers);
}
public Context createContext(Request request, Response response) {
return extensions.createContext(request, response, iocAdapter, site);
}
@Override
public RouteCollection setExtensions(Extensions extensions) {
this.extensions = extensions;
return this;
}
@Override
public RouteCollection setIocAdapter(IocAdapter iocAdapter) {
this.iocAdapter = iocAdapter;
return this;
}
@Override
public RouteCollection filter(Class extends Filter> filterClass) {
filters.addFirst(() -> iocAdapter.get(filterClass));
return this;
}
@Override
public RouteCollection filter(Filter filter) {
filters.addFirst(() -> filter);
return this;
}
@Override
public RouteCollection add(Class> resourceType) {
addResource("", resourceType, () -> iocAdapter.get(resourceType));
return this;
}
@Override
public RouteCollection add(String urlPrefix, Class> resourceType) {
addResource(urlPrefix, resourceType, () -> iocAdapter.get(resourceType));
return this;
}
@Override
public RouteCollection add(Object resource) {
addResource("", resource.getClass(), () -> resource);
return this;
}
@Override
public RouteCollection add(String urlPrefix, Object resource) {
addResource(urlPrefix, resource.getClass(), () -> resource);
return this;
}
protected void addResource(String urlPrefix, Class> type, Supplier resource) {
parseAnnotations(urlPrefix, type, (httpMethod, uri, method) -> addResource(httpMethod, method, resource, uri));
}
protected void addResource(String httpMethod, Method method, Supplier resource, String uriPattern) {
int methodParamsCount = method.getParameterCount();
int uriParamsCount = paramsCount(uriPattern);
if (methodParamsCount < uriParamsCount) {
throw new IllegalArgumentException("Expected at least" + uriParamsCount + " parameters in " + uriPattern);
}
add(httpMethod, uriPattern, new ReflectionRoute(resource, method));
}
@Override
public RouteCollection get(String uriPattern, Object payload) {
get(uriPattern, () -> payload);
return this;
}
@Override
public RouteCollection get(String uriPattern, NoParamRoute route) {
add(GET, checkParametersCount(uriPattern, 0), route);
return this;
}
@Override
public RouteCollection get(String uriPattern, NoParamRouteWithContext route) {
add(GET, checkParametersCount(uriPattern, 0), route);
return this;
}
@Override
public RouteCollection get(String uriPattern, OneParamRoute route) {
add(GET, checkParametersCount(uriPattern, 1), route);
return this;
}
@Override
public RouteCollection get(String uriPattern, TwoParamsRoute route) {
add(GET, checkParametersCount(uriPattern, 2), route);
return this;
}
@Override
public RouteCollection get(String uriPattern, ThreeParamsRoute route) {
add(GET, checkParametersCount(uriPattern, 3), route);
return this;
}
@Override
public RouteCollection get(String uriPattern, FourParamsRoute route) {
add(GET, checkParametersCount(uriPattern, 4), route);
return this;
}
@Override
public RouteCollection options(String uriPattern, Object payload) {
options(uriPattern, () -> payload);
return this;
}
@Override
public RouteCollection options(String uriPattern, NoParamRoute route) {
add(OPTIONS, checkParametersCount(uriPattern, 0), route);
return this;
}
@Override
public RouteCollection options(String uriPattern, NoParamRouteWithContext route) {
add(OPTIONS, checkParametersCount(uriPattern, 0), route);
return this;
}
@Override
public RouteCollection options(String uriPattern, OneParamRoute route) {
add(OPTIONS, checkParametersCount(uriPattern, 1), route);
return this;
}
@Override
public RouteCollection options(String uriPattern, TwoParamsRoute route) {
add(OPTIONS, checkParametersCount(uriPattern, 2), route);
return this;
}
@Override
public RouteCollection options(String uriPattern, ThreeParamsRoute route) {
add(OPTIONS, checkParametersCount(uriPattern, 3), route);
return this;
}
@Override
public RouteCollection options(String uriPattern, FourParamsRoute route) {
add(OPTIONS, checkParametersCount(uriPattern, 4), route);
return this;
}
@Override
public RouteCollection head(String uriPattern, Object payload) {
head(uriPattern, () -> payload);
return this;
}
@Override
public RouteCollection head(String uriPattern, NoParamRoute route) {
add(HEAD, checkParametersCount(uriPattern, 0), route);
return this;
}
@Override
public RouteCollection head(String uriPattern, NoParamRouteWithContext route) {
add(HEAD, checkParametersCount(uriPattern, 0), route);
return this;
}
@Override
public RouteCollection head(String uriPattern, OneParamRoute route) {
add(HEAD, checkParametersCount(uriPattern, 1), route);
return this;
}
@Override
public RouteCollection head(String uriPattern, TwoParamsRoute route) {
add(HEAD, checkParametersCount(uriPattern, 2), route);
return this;
}
@Override
public RouteCollection head(String uriPattern, ThreeParamsRoute route) {
add(HEAD, checkParametersCount(uriPattern, 3), route);
return this;
}
@Override
public RouteCollection head(String uriPattern, FourParamsRoute route) {
add(HEAD, checkParametersCount(uriPattern, 4), route);
return this;
}
@Override
public RouteCollection post(String uriPattern, NoParamRoute route) {
add(POST, checkParametersCount(uriPattern, 0), route);
return this;
}
@Override
public RouteCollection post(String uriPattern, NoParamRouteWithContext route) {
add(POST, checkParametersCount(uriPattern, 0), route);
return this;
}
@Override
public RouteCollection post(String uriPattern, OneParamRoute route) {
add(POST, checkParametersCount(uriPattern, 1), route);
return this;
}
@Override
public RouteCollection post(String uriPattern, TwoParamsRoute route) {
add(POST, checkParametersCount(uriPattern, 2), route);
return this;
}
@Override
public RouteCollection post(String uriPattern, ThreeParamsRoute route) {
add(POST, checkParametersCount(uriPattern, 3), route);
return this;
}
@Override
public RouteCollection post(String uriPattern, FourParamsRoute route) {
add(POST, checkParametersCount(uriPattern, 4), route);
return this;
}
@Override
public RouteCollection put(String uriPattern, NoParamRoute route) {
add(PUT, checkParametersCount(uriPattern, 0), route);
return this;
}
@Override
public RouteCollection put(String uriPattern, NoParamRouteWithContext route) {
add(PUT, checkParametersCount(uriPattern, 0), route);
return this;
}
@Override
public RouteCollection put(String uriPattern, OneParamRoute route) {
add(PUT, checkParametersCount(uriPattern, 1), route);
return this;
}
@Override
public RouteCollection put(String uriPattern, TwoParamsRoute route) {
add(PUT, checkParametersCount(uriPattern, 2), route);
return this;
}
@Override
public RouteCollection put(String uriPattern, ThreeParamsRoute route) {
add(PUT, checkParametersCount(uriPattern, 3), route);
return this;
}
@Override
public RouteCollection put(String uriPattern, FourParamsRoute route) {
add(PUT, checkParametersCount(uriPattern, 4), route);
return this;
}
@Override
public RouteCollection delete(String uriPattern, NoParamRoute route) {
add(DELETE, checkParametersCount(uriPattern, 0), route);
return this;
}
@Override
public RouteCollection delete(String uriPattern, NoParamRouteWithContext route) {
add(DELETE, checkParametersCount(uriPattern, 0), route);
return this;
}
@Override
public RouteCollection delete(String uriPattern, OneParamRoute route) {
add(DELETE, checkParametersCount(uriPattern, 1), route);
return this;
}
@Override
public RouteCollection delete(String uriPattern, TwoParamsRoute route) {
add(DELETE, checkParametersCount(uriPattern, 2), route);
return this;
}
@Override
public RouteCollection delete(String uriPattern, ThreeParamsRoute route) {
add(DELETE, checkParametersCount(uriPattern, 3), route);
return this;
}
@Override
public RouteCollection delete(String uriPattern, FourParamsRoute route) {
add(DELETE, checkParametersCount(uriPattern, 4), route);
return this;
}
@Override
public RouteCollection catchAll(Object payload) {
catchAll(() -> payload);
return this;
}
@Override
public RouteCollection catchAll(NoParamRoute route) {
routes.add(new CatchAllRoute(route));
return this;
}
@Override
public RouteCollection catchAll(NoParamRouteWithContext route) {
routes.add(new CatchAllRoute(route));
return this;
}
@Override
public RoutesWithPattern with(String uriPattern) {
return new RoutesWithPattern(this, uriPattern);
}
protected RouteCollection add(String method, String uriPattern, AnyRoute route) {
routes.add(new RouteWrapper(method, uriPattern, route));
return this;
}
public Payload apply(Context context) throws Exception {
String uri = context.uri();
if (uri == null) {
return notFound();
}
PayloadSupplier payloadSupplier = () -> {
Payload response = notFound();
for (Route route : routes) {
if (route.matchUri(uri)) {
if (route.matchMethod(context.method())) {
return route.apply(uri, context);
}
response = methodNotAllowed();
} else if (!uri.endsWith("/") && route.matchUri(uri + '/')) {
if (route.matchMethod(context.method())) {
return seeOther(uri + '/');
}
response = methodNotAllowed();
}
}
return response;
};
for (Supplier filterSupplier : filters) {
Filter filter = filterSupplier.get();
if (filter.matches(uri, context)) {
PayloadSupplier nextFilter = payloadSupplier;
payloadSupplier = () -> filter.apply(uri, context, nextFilter);
}
}
return payloadSupplier.get();
}
protected String checkParametersCount(String uriPattern, int count) {
if (paramsCount(uriPattern) != count) {
String error = (count == 1) ? "1 parameter" : count + " parameters";
throw new IllegalArgumentException("Expected " + error + " in " + uriPattern);
}
return uriPattern;
}
}