PageRenderTime 92ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/src/main/java/edu/cmu/ds/pbolar/privacymonitor/server/PrivacyMontiorController.java

https://bitbucket.org/PranavBolar/privacymonitor_server
Java | 184 lines | 111 code | 25 blank | 48 comment | 6 complexity | 06c569719b8df98787ef24f60cbcf4df MD5 | raw file
  1. package edu.cmu.ds.pbolar.privacymonitor.server;
  2. import com.google.gson.Gson;
  3. import com.mongodb.MongoClient;
  4. import com.mongodb.MongoClientURI;
  5. import com.mongodb.client.MongoCollection;
  6. import com.mongodb.client.MongoDatabase;
  7. import edu.cmu.ds.pbolar.privacymonitor.server.entity.ClientRequest;
  8. import edu.cmu.ds.pbolar.privacymonitor.server.entity.ClientResponse;
  9. import edu.cmu.ds.pbolar.privacymonitor.server.model.AzureImageFeaturizer;
  10. import edu.cmu.ds.pbolar.privacymonitor.server.model.Constant;
  11. import java.io.IOException;
  12. import java.nio.charset.StandardCharsets;
  13. import javax.servlet.RequestDispatcher;
  14. import javax.servlet.ServletException;
  15. import javax.servlet.annotation.WebServlet;
  16. import javax.servlet.http.HttpServlet;
  17. import javax.servlet.http.HttpServletRequest;
  18. import javax.servlet.http.HttpServletResponse;
  19. import org.bson.Document;
  20. /**
  21. *
  22. * @author pbolar
  23. */
  24. @WebServlet(name = "PrivacyMonitorServlet", urlPatterns = {"/analyze", "/dashboard"}, loadOnStartup = 0)
  25. public class PrivacyMontiorController extends HttpServlet {
  26. public static final String MONGO_COLLECTION_ATTR = "logs-collection";
  27. private final String ANALYZE_PATH = "/analyze";
  28. private final String DASHBOARD_PATH = "/dashboard";
  29. private final String DASHBOARD_JSP = "dashboard.jsp";
  30. private final String COLLECTION_ID = "privacy-monitor-logs";
  31. private Gson gson;
  32. private AzureImageFeaturizer azImageFeaturizer;
  33. private MongoCollection<Document> logs;
  34. private MongoClient mongoClient;
  35. @Override
  36. public void init() throws ServletException {
  37. gson = new Gson();
  38. azImageFeaturizer = new AzureImageFeaturizer(gson);
  39. // Connecting to the MongoDB database instance at mLab
  40. MongoClientURI uri = new MongoClientURI(Constant.getMLabURI());
  41. mongoClient = new MongoClient(uri);
  42. MongoDatabase db = mongoClient.getDatabase(uri.getDatabase());
  43. logs = db.getCollection(COLLECTION_ID);
  44. }
  45. /**
  46. * Processes both GETs and POSTs, assigning requests to appropriate handlers
  47. *
  48. * @param request Incoming request
  49. * @param response Outgoing response
  50. * @param isPost Boolean, true if HTTP POST was used as the request
  51. * @throws ServletException
  52. * @throws IOException
  53. */
  54. private void processRequest(HttpServletRequest request, HttpServletResponse response, boolean isPost)
  55. throws ServletException, IOException {
  56. switch (request.getServletPath()) {
  57. case ANALYZE_PATH:
  58. // ignore GETs on this path
  59. if (isPost) {
  60. analyzeClientRequest(request, response);
  61. }
  62. break;
  63. case DASHBOARD_PATH:
  64. serveDashboard(request, response);
  65. break;
  66. }
  67. }
  68. /**
  69. * Processes requests from mobile clients for image analysis
  70. *
  71. * @param req
  72. * @param resp
  73. * @throws ServletException
  74. * @throws IOException
  75. */
  76. private void analyzeClientRequest(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  77. // Start a new logging session
  78. Document log = new Document().append(Constant.MDB_TIMESTAMP_KEY, System.nanoTime());
  79. // What sort of content-type is this?
  80. String contentType = getContentType(req);
  81. if (!contentType.equals(Constant.JSON_MIME)) {
  82. // We only support JSON!
  83. String responseJson = getJsonMessage("This Content-Type (" + req.getContentType() + ") is not accepted.");
  84. buildResponse(resp, HttpServletResponse.SC_NOT_ACCEPTABLE, Constant.JSON_MIME, responseJson);
  85. return;
  86. }
  87. // Deserialize the JSON
  88. ClientRequest request = getClientRequest(req);
  89. System.out.println(request);
  90. // Get the model to talk to Azure about this picture
  91. log.append(Constant.MDB_PHONE_KEY, request.getPhoneModel());
  92. ClientResponse response = azImageFeaturizer.analyzeImage(request, log);
  93. // Everything looking good?
  94. if (response.getStatus() == HttpServletResponse.SC_OK) {
  95. String responseJson = gson.toJson(response, ClientResponse.class);
  96. // Send this back to the client
  97. buildResponse(resp, HttpServletResponse.SC_OK, Constant.JSON_MIME, responseJson);
  98. } else {
  99. // Send an error
  100. buildResponse(resp, response.getStatus(), Constant.JSON_MIME, getJsonMessage(response.getMessage()));
  101. }
  102. // Store document in the DB
  103. logs.insertOne(log);
  104. System.out.println("---------------- COMPLETED WITH STATUS [" +response.getStatus() +"] ----------------");
  105. }
  106. /**
  107. *
  108. * @param req
  109. * @return Marshalled version of the client request JSON
  110. * @throws IOException
  111. */
  112. private ClientRequest getClientRequest(HttpServletRequest req) throws IOException {
  113. StringBuilder jsonBuilder = req.getReader().lines()
  114. .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append);
  115. return gson.fromJson(jsonBuilder.toString(), ClientRequest.class);
  116. }
  117. /**
  118. * Responds to requests for the dashboard web page
  119. *
  120. * @param req
  121. * @param resp
  122. * @throws ServletException
  123. * @throws IOException
  124. */
  125. private void serveDashboard(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  126. req.setAttribute(MONGO_COLLECTION_ATTR, logs);
  127. RequestDispatcher resultView = req.getRequestDispatcher(DASHBOARD_JSP);
  128. resultView.forward(req, resp);
  129. }
  130. @Override
  131. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  132. System.out.println("---------------- NEW POST REQUEST FROM " + req.getRemoteAddr() + " ----------------");
  133. this.processRequest(req, resp, true);
  134. }
  135. @Override
  136. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  137. this.processRequest(req, resp, false);
  138. }
  139. private void buildResponse(HttpServletResponse resp, int status, String mime, String payload) throws IOException {
  140. resp.setStatus(status);
  141. resp.setContentType(mime);
  142. resp.setContentLength(payload.length());
  143. resp.setCharacterEncoding(StandardCharsets.UTF_8.name());
  144. resp.getWriter().append(payload).flush();
  145. }
  146. @Override
  147. public void destroy() {
  148. mongoClient.close();
  149. }
  150. private String getJsonMessage(String message) {
  151. return "{\"message\":\"" + message + "\"}";
  152. }
  153. private String getContentType(HttpServletRequest req) {
  154. String[] contentTypeParts = req.getContentType().split(";");
  155. // contentTypeParts[1] => MIME
  156. // contentTypeParts[1] => Charset
  157. return contentTypeParts[0].trim();
  158. }
  159. }