io.crnk.rs.internal.JaxrsModule Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of crnk-rs Show documentation
Show all versions of crnk-rs Show documentation
JSON API framework for Java
package io.crnk.rs.internal;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.SecurityContext;
import io.crnk.core.engine.information.repository.RepositoryAction;
import io.crnk.core.engine.information.repository.RepositoryAction.RepositoryActionType;
import io.crnk.core.module.Module;
import io.crnk.legacy.repository.information.DefaultResourceRepositoryInformationProvider;
public class JaxrsModule implements Module {
private static final String ID_ACTION_PARAMETER = "{id}";
private SecurityContext securityContext;
public JaxrsModule(SecurityContext securityContext) {
this.securityContext = securityContext;
}
@Override
public void setupModule(ModuleContext context) {
context.addRepositoryInformationBuilder(new JaxrsResourceRepositoryInformationProvider());
context.addExceptionMapper(new WebApplicationExceptionMapper());
if (securityContext != null) {
context.addSecurityProvider(new JaxrsSecurityProvider(securityContext));
}
}
@Override
public String getModuleName() {
return "jaxrs";
}
public static class JaxrsResourceRepositoryInformationProvider extends DefaultResourceRepositoryInformationProvider {
@Override
protected Map buildActions(Class extends Object> repositoryClass) {
HashMap actions = new HashMap<>();
// search for annotated methods on classes and interfaces
// since annotations are no inherited
setupClass(actions, repositoryClass);
for (Class> interfaceClass : repositoryClass.getInterfaces()) {
setupClass(actions, interfaceClass);
}
return actions;
}
private void setupClass(HashMap actions, Class extends Object> repositoryClass) {
for (Method method : repositoryClass.getMethods()) {
setupMethod(actions, method);
}
}
private void setupMethod(HashMap actions, Method method) {
Path pathAnnotation = method.getAnnotation(Path.class);
boolean isJaxRs = isJaxRsMethod(method);
if (pathAnnotation != null) {
String path = normPath(pathAnnotation.value());
String[] pathElements = path.split("\\/");
checkPathElements(method, pathElements);
RepositoryActionType actionType = pathElements[0].equals(ID_ACTION_PARAMETER) ? RepositoryActionType.RESOURCE
: RepositoryActionType.REPOSITORY;
String name = pathElements[pathElements.length - 1];
RepositoryAction action = new JaxrsRepositoryAction(name, actionType);
actions.put(name, action);
}
else if (isJaxRs) {
throw new IllegalStateException("JAXRS actions must be annotated with @Path: " + method);
}
}
/**
* There are some strict roles to follow to be a valid action
*
* @param method holding the @Path annotation
* @param pathElements of this method
*/
private void checkPathElements(Method method, String[] pathElements) {
if (pathElements.length == 0 || pathElements.length == 1 && pathElements[0].isEmpty()) {
throw new IllegalStateException("@Path value must not be empty: " + method);
}
if (pathElements.length > 2) {
throw new IllegalStateException("@Path value must not contain more than two elements: " + method);
}
if (pathElements.length == 1 && pathElements[0].equals(ID_ACTION_PARAMETER)) {
throw new IllegalStateException("single element in @Path cannot be {id}, add action name: " + method);
}
if (pathElements.length == 2 && !pathElements[0].equals(ID_ACTION_PARAMETER)) {
throw new IllegalStateException(
"for two elements in @Path the first one must be {id}, the second the action name: " + method);
}
}
private boolean isJaxRsMethod(Method method) {
Path pathAnnotation = method.getAnnotation(Path.class);
boolean isGet = method.getAnnotation(GET.class) != null;
boolean isPost = method.getAnnotation(POST.class) != null;
boolean isPut = method.getAnnotation(PUT.class) != null;
boolean isDelete = method.getAnnotation(DELETE.class) != null;
if (isGet || isPost || isPut || isDelete) {
return true;
}
if (pathAnnotation != null) {
return true;
}
return hasJaxRsMethodParameters(method);
}
private boolean hasJaxRsMethodParameters(Method method) {
Annotation[][] parameterAnnotationsArray = method.getParameterAnnotations();
for (int paramIndex = 0; paramIndex < parameterAnnotationsArray.length; paramIndex++) {
Annotation[] parameterAnnotations = parameterAnnotationsArray[paramIndex];
for (Annotation parameterAnnotation : parameterAnnotations) {
if (parameterAnnotation instanceof PathParam || parameterAnnotation instanceof QueryParam) {
return true;
}
}
}
return false;
}
private String normPath(String path) {
String normPath = path;
if (normPath.startsWith("/")) {
normPath = normPath.substring(1);
}
if (normPath.endsWith("/")) {
normPath = normPath.substring(0, normPath.length() - 1);
}
return normPath;
}
}
public static class JaxrsRepositoryAction implements RepositoryAction {
private String name;
private RepositoryActionType actionType;
public JaxrsRepositoryAction(String name, RepositoryActionType actionType) {
this.name = name;
this.actionType = actionType;
}
@Override
public String getName() {
return name;
}
@Override
public RepositoryActionType getActionType() {
return actionType;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy