package codeine.servlet; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.lang.reflect.Type; import javax.inject.Inject; import javax.inject.Provider; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import org.eclipse.jetty.http.HttpStatus; import codeine.model.Constants; import codeine.permissions.IUserWithPermissions; import codeine.permissions.UserPermissionsGetter; import codeine.servlet.manage_statistics.ManageStatisticsCollector; import codeine.utils.ExceptionUtils; import codeine.utils.ServletUtils; import codeine.utils.exceptions.InShutdownException; import codeine.utils.exceptions.UnAuthorizedException; import codeine.utils.network.RequestUtils; import com.google.common.net.HttpHeaders; import com.google.gson.Gson; public abstract class AbstractServlet extends HttpServlet{ private static final Logger log = Logger.getLogger(AbstractServlet.class); private static final long serialVersionUID = 1L; @Inject private Gson gson; @Inject private UserPermissionsGetter permissionsManager; @Inject private ManageStatisticsCollector manageStatisticsCollector; @Inject private Provider<RequestBodyReader> requestBodyReaderProvider; @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { beforeRequest(request, response); if (!checkPermissions(request)) { throw newUnauthrizedException(request); } myGet(request, response); } catch (Exception e) { handleError(e, response); } } private void beforeRequest(HttpServletRequest request, HttpServletResponse response) { manageStatisticsCollector().userAccess(getUser(request), request.getPathInfo(), request); } private UnAuthorizedException newUnauthrizedException(HttpServletRequest request) { return new UnAuthorizedException(getUser(request) + " not authorized for url " + request.getRequestURI()); } @Override protected final void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { beforeRequest(request, response); if (!checkPermissions(request)) { throw newUnauthrizedException(request); } myPut(request, response); } catch (Exception e) { handleError(e, response); } } @Override protected final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { beforeRequest(request, response); if (!checkPermissions(request)) { throw newUnauthrizedException(request); } myPost(request, response); } catch (Exception e) { handleError(e, response); } } @Override protected final void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { beforeRequest(request, response); if (!checkPermissions(request)) { throw newUnauthrizedException(request); } myDelete(request, response); } catch (Exception e) { handleError(e, response); } } protected abstract boolean checkPermissions(HttpServletRequest request) ; protected void myDelete(HttpServletRequest request, HttpServletResponse response) { writeNotFound(request, response); } protected void myPut(HttpServletRequest request, HttpServletResponse response) { writeNotFound(request, response); } protected void handleError(Exception e, HttpServletResponse response) { log.warn("Error in servlet", e); ApiError error; if (e instanceof UnAuthorizedException) { response.setStatus(HttpStatus.UNAUTHORIZED_401); error = new ApiError("UNAUTHORIZED Request","Please provide API Token",e.getMessage()); //getWriter(response).write("UNAUTHORIZED Request, please provide API Token"); } else if (e instanceof IllegalArgumentException){ error = new ApiError("Bad request","Please check api help",e.getMessage()); response.setStatus(HttpStatus.BAD_REQUEST_400); } else if (e instanceof InShutdownException){ error = new ApiError("Cannot execute","Preparing for shutdown",e.getMessage()); response.setStatus(HttpStatus.FORBIDDEN_403); } else { error = new ApiError("Internal Server Error",e.getMessage() ,e.getMessage()); response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR_500); } getWriter(response).write(gson().toJson(error)); } protected void writeNotFound(HttpServletRequest request, HttpServletResponse response) { response.setStatus(HttpStatus.METHOD_NOT_ALLOWED_405); PrintWriter writer = getWriter(response); writer.write("Codeine dosen't support this action"); } protected void myPost(HttpServletRequest request, HttpServletResponse response) { writeNotFound(request, response); } protected void myGet(HttpServletRequest request, HttpServletResponse response) { writeNotFound(request, response); } protected final PrintWriter getWriter(HttpServletResponse response) { return ServletUtils.getWriter(response); } protected Gson gson(){ return gson; } protected final <T> T readBodyJson(HttpServletRequest request, Class<T> clazz) { return gson().fromJson(readBody(request), clazz); } protected final <T> T readBodyJson(HttpServletRequest request, Type listType) { return gson().fromJson(readBody(request), listType); } protected final void writeResponseJson(HttpServletResponse response, Object json) { gson().toJson(json, getWriter(response)); } protected final void writeResponseGzipJson(Object json, HttpServletRequest request, HttpServletResponse response) { if (Constants.RequestHeaders.NO_ZIP.equals(request.getHeader(Constants.RequestHeaders.NO_ZIP))) { log.debug("will not compress"); writeResponseJson(response, json); return; } try { try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(getGzipStream(response), response.getCharacterEncoding()))) { gson().toJson(json, writer); } } catch (IOException e) { throw ExceptionUtils.asUnchecked(e); } } private ServletResponseGZIPOutputStream getGzipStream(HttpServletResponse response) throws IOException { response.addHeader(HttpHeaders.CONTENT_ENCODING, "gzip"); return new ServletResponseGZIPOutputStream(response.getOutputStream()); } protected String readBody(HttpServletRequest request) { return requestBodyReaderProvider.get().readBody(request); } protected final boolean canReadProject(HttpServletRequest request) { String projectName = getParameter(request, Constants.UrlParameters.PROJECT_NAME); return getUser(request).canRead(projectName); } protected IUserWithPermissions getUser(HttpServletRequest request) { return permissionsManager.user(request); } protected final boolean canCommandProject(HttpServletRequest request) { String projectName = getParameter(request, Constants.UrlParameters.PROJECT_NAME); return getUser(request).canCommand(projectName); } protected final boolean canConfigureProject(HttpServletRequest request) { String projectName = getParameter(request, Constants.UrlParameters.PROJECT_NAME); return getUser(request).canConfigure(projectName); } protected final boolean isAdministrator(HttpServletRequest request) { return getUser(request).isAdministrator(); } protected final String projectName(HttpServletRequest request) { return getParameter(request, Constants.UrlParameters.PROJECT_NAME); } public static final void setNoCache(HttpServletResponse response) { response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1. response.setHeader("Pragma", "no-cache"); // HTTP 1.0. response.setDateHeader("Expires", 0); // Proxies. } protected String getParameter(HttpServletRequest request, String parameter) { return RequestUtils.getParameter(request, parameter); } public ManageStatisticsCollector manageStatisticsCollector() { return manageStatisticsCollector; } }