Skip to content

Commit

Permalink
#4 : EntryPointScannerclass refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
Gmugra committed Jan 21, 2021
1 parent e93d118 commit 99d0a55
Show file tree
Hide file tree
Showing 21 changed files with 126 additions and 120 deletions.
22 changes: 11 additions & 11 deletions core/src/main/java/net/cactusthorn/routing/RoutingConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public Object ddefault() {
}
}

private List<Class<?>> entryPointClasses;
private List<Class<?>> resourceClasses;

private ConvertersHolder convertersHolder;

Expand All @@ -64,15 +64,15 @@ public Object ddefault() {
private RoutingConfig(
ComponentProvider componentProvider,
ConvertersHolder convertersHolder,
List<Class<?>> entryPointClasses,
List<Class<?>> resourceClasses,
List<BodyWriter> bodyWriters,
List<BodyReader> bodyReaders,
Map<ConfigProperty, Object> configProperties,
ParametersValidator validator,
String applicationPath) {
this.componentProvider = componentProvider;
this.convertersHolder = convertersHolder;
this.entryPointClasses = entryPointClasses;
this.resourceClasses = resourceClasses;
this.bodyWriters = bodyWriters;
this.bodyReaders = bodyReaders;
this.configProperties = configProperties;
Expand All @@ -89,8 +89,8 @@ public ConvertersHolder convertersHolder() {
return convertersHolder;
}

public List<Class<?>> entryPointClasses() {
return entryPointClasses;
public List<Class<?>> resourceClasses() {
return resourceClasses;
}

public List<BodyWriter> bodyWriters() {
Expand Down Expand Up @@ -123,7 +123,7 @@ public static final class Builder {

private final ConvertersHolder convertersHolder = new ConvertersHolder();

private final List<Class<?>> entryPointClasses = new ArrayList<>();
private final List<Class<?>> resourceClasses = new ArrayList<>();

private final List<BodyWriter> bodyWriters = new ArrayList<>();

Expand Down Expand Up @@ -158,13 +158,13 @@ public Builder addConverter(Class<?> clazz, Converter converter) {
return this;
}

public Builder addEntryPoint(Class<?> entryPoint) {
entryPointClasses.add(entryPoint);
public Builder addResource(Class<?> resource) {
resourceClasses.add(resource);
return this;
}

public Builder addEntryPoint(Collection<Class<?>> entryPoints) {
entryPointClasses.addAll(entryPoints);
public Builder addResource(Collection<Class<?>> resources) {
resourceClasses.addAll(resources);
return this;
}

Expand Down Expand Up @@ -217,7 +217,7 @@ public RoutingConfig build() {

Map<ConfigProperty, Object> unmodifiableConfigProperties = Collections.unmodifiableMap(configProperties);

return new RoutingConfig(componentProvider, convertersHolder, Collections.unmodifiableList(entryPointClasses),
return new RoutingConfig(componentProvider, convertersHolder, Collections.unmodifiableList(resourceClasses),
unmodifiableBodyWriters, unmodifiableBodyReaders, unmodifiableConfigProperties, validator, applicationPath);
}
}
Expand Down
45 changes: 23 additions & 22 deletions core/src/main/java/net/cactusthorn/routing/RoutingServlet.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@
import javax.ws.rs.core.Response.StatusType;
import javax.ws.rs.ext.MessageBodyWriter;

import net.cactusthorn.routing.EntryPointScanner.EntryPoint;
import net.cactusthorn.routing.RoutingConfig.ConfigProperty;
import net.cactusthorn.routing.body.writer.BodyWriter;
import net.cactusthorn.routing.body.writer.MessageBodyHeadersWriter;
import net.cactusthorn.routing.invoke.MethodInvoker.ReturnObjectInfo;
import net.cactusthorn.routing.resource.ResourceScanner;
import net.cactusthorn.routing.resource.ResourceScanner.Resource;
import net.cactusthorn.routing.PathTemplate.PathValues;

public class RoutingServlet extends HttpServlet {
Expand All @@ -32,7 +33,7 @@ public class RoutingServlet extends HttpServlet {

private static final Logger LOG = Logger.getLogger(RoutingServlet.class.getName());

private transient Map<String, List<EntryPoint>> allEntryPoints;
private transient Map<String, List<Resource>> allResources;
private transient ServletContext servletContext;
private transient RoutingConfig routingConfig;
private transient String responseCharacterEncoding;
Expand All @@ -53,8 +54,8 @@ public void init() throws ServletException {
routingConfig.bodyReaders().forEach(r -> r.init(servletContext, routingConfig));
routingConfig.validator().ifPresent(v -> v.init(servletContext, routingConfig.provider()));

EntryPointScanner scanner = new EntryPointScanner(routingConfig);
allEntryPoints = scanner.scan();
ResourceScanner scanner = new ResourceScanner(routingConfig);
allResources = scanner.scan();
}

@Override //
Expand All @@ -67,78 +68,78 @@ protected void service(HttpServletRequest req, HttpServletResponse resp) throws
}

protected void doPatch(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
process(req, resp, allEntryPoints.get(HttpMethod.PATCH));
process(req, resp, allResources.get(HttpMethod.PATCH));
}

@Override //
protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
process(req, resp, allEntryPoints.get(HttpMethod.HEAD));
process(req, resp, allResources.get(HttpMethod.HEAD));
}

@Override //
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
process(req, resp, allEntryPoints.get(HttpMethod.POST));
process(req, resp, allResources.get(HttpMethod.POST));
}

@Override //
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
process(req, resp, allEntryPoints.get(HttpMethod.PUT));
process(req, resp, allResources.get(HttpMethod.PUT));
}

@Override //
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
process(req, resp, allEntryPoints.get(HttpMethod.DELETE));
process(req, resp, allResources.get(HttpMethod.DELETE));
}

@Override //
protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
process(req, resp, allEntryPoints.get(HttpMethod.OPTIONS));
process(req, resp, allResources.get(HttpMethod.OPTIONS));
}

@Override //
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
process(req, resp, allEntryPoints.get(HttpMethod.GET));
process(req, resp, allResources.get(HttpMethod.GET));
}

private void process(HttpServletRequest req, HttpServletResponse resp, List<EntryPoint> entryPoints) throws IOException {
private void process(HttpServletRequest req, HttpServletResponse resp, List<Resource> resources) throws IOException {
String contentType = contentType(req);
if (req.getCharacterEncoding() == null) {
req.setCharacterEncoding(defaultRequestCharacterEncoding);
}
String path = getPath(contentType, req);
if (entryPoints.isEmpty()) {
if (resources.isEmpty()) {
resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Not Found");
return;
}
List<MediaType> accept = Http.parseAccept(req.getHeaders(HttpHeaders.ACCEPT));
boolean matchContentTypeFail = false;
boolean matchAcceptFail = false;
for (EntryPoint entryPoint : entryPoints) {
PathValues pathValues = entryPoint.parse(path);
for (Resource resource : resources) {
PathValues pathValues = resource.parse(path);
if (pathValues != null) {
if (!entryPoint.matchUserRole(req)) {
if (!resource.matchUserRole(req)) {
resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Forbidden");
return;
}
try {
if (!entryPoint.matchContentType(contentType)) {
if (!resource.matchContentType(contentType)) {
matchContentTypeFail = true;
continue;
}
Optional<MediaType> producesMediaType = entryPoint.matchAccept(accept);
Optional<MediaType> producesMediaType = resource.matchAccept(accept);
if (!producesMediaType.isPresent()) {
matchAcceptFail = true;
continue;
}
Response result = entryPoint.invoke(req, resp, servletContext, pathValues);
Response result = resource.invoke(req, resp, servletContext, pathValues);
//It could be that in resource method Response object was created manually and media-type was set,
//and this media-type do not match request Accept-header.
//In this case -> response error at ones.
if (!matchAccept(accept, result)) {
resp.sendError(HttpServletResponse.SC_NOT_ACCEPTABLE, "Not acceptable");
return;
}
produce(resp, entryPoint, result, producesMediaType.get());
produce(resp, resource, result, producesMediaType.get());
} catch (WebApplicationException wae) {
resp.sendError(wae.getResponse().getStatus(), wae.getMessage());
} catch (Exception e) {
Expand Down Expand Up @@ -177,7 +178,7 @@ private String getPath(String contentType, HttpServletRequest req) {
return path;
}

private void produce(HttpServletResponse resp, EntryPoint entryPoint, Response result, MediaType producesMediaType) throws IOException {
private void produce(HttpServletResponse resp, Resource resource, Response result, MediaType producesMediaType) throws IOException {

StatusType status = result.getStatusInfo();
resp.setStatus(status.getStatusCode());
Expand All @@ -196,7 +197,7 @@ private void produce(HttpServletResponse resp, EntryPoint entryPoint, Response r
resp.setCharacterEncoding(responseMediaType.getParameters().get(MediaType.CHARSET_PARAMETER));
resp.setContentType(new MediaType(responseMediaType.getType(), responseMediaType.getSubtype()).toString());

ReturnObjectInfo info = entryPoint.returnObjectInfo().withEntity(result.getEntity());
ReturnObjectInfo info = resource.returnObjectInfo().withEntity(result.getEntity());

MessageBodyHeadersWriter writer = new MessageBodyHeadersWriter(resp, findBodyWriter(responseMediaType, info));

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package net.cactusthorn.routing;
package net.cactusthorn.routing.resource;

import java.lang.reflect.Method;
import java.util.Collections;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package net.cactusthorn.routing;
package net.cactusthorn.routing.resource;

import java.lang.reflect.Method;

import javax.ws.rs.Path;

import net.cactusthorn.routing.PathTemplate;
import net.cactusthorn.routing.RoutingInitializationException;

public final class PathTemplateParser {

PathTemplate create(Method method, String classPath) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package net.cactusthorn.routing;
package net.cactusthorn.routing.resource;

import java.lang.reflect.Method;
import java.util.ArrayList;
Expand All @@ -8,6 +8,8 @@
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import net.cactusthorn.routing.Http;

public final class ProducesParser {

List<MediaType> produces(Class<?> clazz) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package net.cactusthorn.routing;
package net.cactusthorn.routing.resource;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
Expand All @@ -17,19 +17,22 @@

import net.cactusthorn.routing.annotation.Template;
import net.cactusthorn.routing.annotation.UserRoles;
import net.cactusthorn.routing.PathTemplate;
import net.cactusthorn.routing.RoutingConfig;
import net.cactusthorn.routing.Templated;
import net.cactusthorn.routing.PathTemplate.PathValues;
import net.cactusthorn.routing.invoke.MethodInvoker;
import net.cactusthorn.routing.invoke.MethodInvoker.ReturnObjectInfo;

public class EntryPointScanner {
public class ResourceScanner {

private static final ConsumesParser CONSUMES_PARSER = new ConsumesParser();
private static final PathTemplateParser PATHTEMPLATE_PARSER = new PathTemplateParser();
private static final ProducesParser PRODUCES_PARSER = new ProducesParser();

public static final class EntryPoint {
public static final class Resource {

private static final Comparator<EntryPoint> COMPARATOR = (o1, o2) -> PathTemplate.COMPARATOR.compare(o1.pathTemplate,
private static final Comparator<Resource> COMPARATOR = (o1, o2) -> PathTemplate.COMPARATOR.compare(o1.pathTemplate,
o2.pathTemplate);

private PathTemplate pathTemplate;
Expand All @@ -39,7 +42,7 @@ public static final class EntryPoint {
private String template;
private Set<String> userRoles;

private EntryPoint(PathTemplate pathTemplate, String template, List<MediaType> producesMediaTypes,
private Resource(PathTemplate pathTemplate, String template, List<MediaType> producesMediaTypes,
Set<MediaType> consumesMediaTypes, MethodInvoker methodInvoker, Set<String> userRoles) {
this.pathTemplate = pathTemplate;
this.producesMediaTypes = producesMediaTypes;
Expand Down Expand Up @@ -119,15 +122,15 @@ public boolean matchContentType(String contenttype) {

private RoutingConfig routingConfig;

public EntryPointScanner(RoutingConfig routingConfig) {
public ResourceScanner(RoutingConfig routingConfig) {
this.routingConfig = routingConfig;
}

public Map<String, List<EntryPoint>> scan() {
public Map<String, List<Resource>> scan() {

Map<String, List<EntryPoint>> entryPoints = createMap();
Map<String, List<Resource>> resources = createMap();

for (Class<?> clazz : routingConfig.entryPointClasses()) {
for (Class<?> clazz : routingConfig.resourceClasses()) {

String classPath = PATHTEMPLATE_PARSER.prepare(routingConfig.applicationPath(), clazz.getAnnotation(Path.class));
Set<MediaType> classConsumesMediaTypes = CONSUMES_PARSER.consumes(clazz);
Expand All @@ -153,19 +156,19 @@ public Map<String, List<EntryPoint>> scan() {

Set<String> userRoles = findUserRoles(method);

EntryPoint entryPoint = new EntryPoint(pathTemplate, template, producesMediaTypes, consumesMediaTypes,
Resource resource = new Resource(pathTemplate, template, producesMediaTypes, consumesMediaTypes,
methodInvoker, userRoles);
entryPoints.get(httpMethod).add(entryPoint);
resources.get(httpMethod).add(resource);
}
}
}
}

for (Map.Entry<String, List<EntryPoint>> entry : entryPoints.entrySet()) {
Collections.sort(entry.getValue(), EntryPoint.COMPARATOR);
for (Map.Entry<String, List<Resource>> entry : resources.entrySet()) {
Collections.sort(entry.getValue(), Resource.COMPARATOR);
}

return entryPoints;
return resources;
}

private String findTemplate(Method method) {
Expand Down Expand Up @@ -195,11 +198,11 @@ private String getHttpMethod(Annotation annotation) {
return null;
}

private Map<String, List<EntryPoint>> createMap() {
Map<String, List<EntryPoint>> entryPoints = new HashMap<>();
private Map<String, List<Resource>> createMap() {
Map<String, List<Resource>> resources = new HashMap<>();
for (String method : HTTP_METHODS) {
entryPoints.put(method, new ArrayList<>());
resources.put(method, new ArrayList<>());
}
return entryPoints;
return resources;
}
}
Loading

0 comments on commit 99d0a55

Please sign in to comment.