package com.github.nyrkovalex.ironadmin.core.servlet;
import com.github.nyrkovalex.ironadmin.core.AdminContext;
import com.github.nyrkovalex.ironadmin.core.defaults.DefaultAdminContext;
import com.github.nyrkovalex.ironadmin.core.pages.Page;
import com.github.nyrkovalex.ironadmin.core.pages.PageContext;
import com.github.nyrkovalex.ironadmin.core.pages.PageRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Optional;
public class AdminDispatcherServlet extends HttpServlet {
private static final Logger LOG = LoggerFactory.getLogger(AdminDispatcherServlet.class);
static final String CONTEXT_CLASS_PARAMETER_NAME = "context-class";
static final String PAGE_CONTEXT_ATTR = "ia-page-context";
private AdminContext adminContext;
@Override
public void init(ServletConfig config) throws ServletException {
String contextClassName = config.getInitParameter(CONTEXT_CLASS_PARAMETER_NAME);
if (contextClassName == null || contextClassName.isEmpty()) {
this.adminContext = DefaultAdminContext.instance();
} else {
this.adminContext = loadContextForClassName(contextClassName);
}
super.init(config);
}
private static AdminContext loadContextForClassName(String className) throws ServletException {
try {
Class<?> contextClass = loadClass(className);
return createInstance(contextClass);
} catch (IllegalArgumentException e) {
throw new ServletException("Wrong context class name provided: " + className, e);
}
}
private static AdminContext createInstance(Class<?> contextClass) {
try {
return (AdminContext) contextClass.newInstance();
} catch (IllegalAccessException | InstantiationException e) {
throw new IllegalArgumentException(String.format("Could not instantiate %s", contextClass.getName()), e);
} catch (ClassCastException e) {
throw new IllegalArgumentException(
String.format("%s does not implement %s", contextClass.getName(), AdminContext.class.getName()), e);
}
}
private static Class<?> loadClass(String className) {
Class<?> contextClass;
try {
contextClass = Class.forName(className);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Cannot find class for name " + className, e);
}
return contextClass;
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
LOG.debug("Got request to " + req.getRequestURI());
PageRequest request = getPageRequest(req);
Optional<Page> page = adminContext.pageRegistry().pageFor(request.pageUrl());
if (page.isPresent()) {
req.setAttribute(PAGE_CONTEXT_ATTR, page.get().pageContextForRequest(request));
super.service(req, resp);
return;
}
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
}
private PageRequest getPageRequest(HttpServletRequest req) {
String requestURI = req.getRequestURI();
String withoutServletPath = requestURI.replace(req.getServletPath() + "/", "");
String[] splitted = withoutServletPath.split("/");
String pageUrl = "/" + (splitted.length > 0 ? splitted[0] : "");
String entityId = "" + (splitted.length > 1 ? splitted[1] : "");
return new PageRequest(pageUrl, entityId.isEmpty() ? Optional.empty() : Optional.of(entityId));
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PageContext context = (PageContext) req.getAttribute(PAGE_CONTEXT_ATTR);
adminContext.templateResolver().resolvePageTemplate(req.getServletPath(), context, resp.getWriter());
resp.setStatus(HttpServletResponse.SC_OK);
}
public AdminContext getAdminContext() {
return adminContext;
}
}