1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you 5 * may not use this file except in compliance with the License. You may 6 * obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 13 * implied. See the License for the specific language governing 14 * permissions and limitations under the License. 15 */ 16 17 package com.android.vts.api; 18 19 import com.android.vts.entity.TestAcknowledgmentEntity; 20 import com.android.vts.util.DatastoreHelper; 21 import com.google.appengine.api.datastore.DatastoreFailureException; 22 import com.google.appengine.api.datastore.DatastoreService; 23 import com.google.appengine.api.datastore.DatastoreServiceFactory; 24 import com.google.appengine.api.datastore.DatastoreTimeoutException; 25 import com.google.appengine.api.datastore.Entity; 26 import com.google.appengine.api.datastore.Key; 27 import com.google.appengine.api.datastore.KeyFactory; 28 import com.google.appengine.api.datastore.Query; 29 import com.google.appengine.api.datastore.Transaction; 30 import com.google.appengine.api.users.User; 31 import com.google.appengine.api.users.UserService; 32 import com.google.appengine.api.users.UserServiceFactory; 33 import com.google.gson.Gson; 34 import com.google.gson.JsonObject; 35 import com.google.gson.JsonParser; 36 import java.io.BufferedReader; 37 import java.io.IOException; 38 import java.io.PrintWriter; 39 import java.util.ArrayList; 40 import java.util.ConcurrentModificationException; 41 import java.util.List; 42 import java.util.logging.Level; 43 import java.util.logging.Logger; 44 import javax.servlet.http.HttpServlet; 45 import javax.servlet.http.HttpServletRequest; 46 import javax.servlet.http.HttpServletResponse; 47 48 /** Servlet for handling requests to fetch test acknowledgments. */ 49 public class TestAcknowledgmentRestServlet extends HttpServlet { 50 protected static final Logger logger = 51 Logger.getLogger(TestAcknowledgmentRestServlet.class.getName()); 52 53 /** Read all test acknowledgments. */ 54 @Override doGet(HttpServletRequest request, HttpServletResponse response)55 public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { 56 DatastoreService datastore = DatastoreServiceFactory.getDatastoreService(); 57 58 Query ackQuery = new Query(TestAcknowledgmentEntity.KIND); 59 List<JsonObject> testAcks = new ArrayList<>(); 60 for (Entity ackEntity : 61 datastore.prepare(ackQuery).asIterable(DatastoreHelper.getLargeBatchOptions())) { 62 TestAcknowledgmentEntity ack = TestAcknowledgmentEntity.fromEntity(ackEntity); 63 if (ack == null) continue; 64 testAcks.add(ack.toJson()); 65 } 66 response.setContentType("application/json"); 67 PrintWriter writer = response.getWriter(); 68 writer.print(new Gson().toJson(testAcks)); 69 writer.flush(); 70 } 71 72 /** Create a test acknowledgment. */ 73 @Override doPost(HttpServletRequest request, HttpServletResponse response)74 public void doPost(HttpServletRequest request, HttpServletResponse response) 75 throws IOException { 76 UserService userService = UserServiceFactory.getUserService(); 77 if (!userService.isUserAdmin()) { 78 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); 79 return; 80 } 81 User currentUser = userService.getCurrentUser(); 82 DatastoreService datastore = DatastoreServiceFactory.getDatastoreService(); 83 84 StringBuilder sb = new StringBuilder(); 85 BufferedReader br = new BufferedReader(request.getReader()); 86 String str; 87 while ((str = br.readLine()) != null) { 88 sb.append(str); 89 } 90 JsonObject json; 91 try { 92 json = new JsonParser().parse(sb.toString()).getAsJsonObject(); 93 } catch (IllegalStateException e) { 94 response.setStatus(HttpServletResponse.SC_BAD_REQUEST); 95 return; 96 } 97 TestAcknowledgmentEntity ack = TestAcknowledgmentEntity.fromJson(currentUser, json); 98 Transaction txn = datastore.beginTransaction(); 99 try { 100 Key key = datastore.put(ack.toEntity()); 101 txn.commit(); 102 103 response.setContentType("application/json"); 104 PrintWriter writer = response.getWriter(); 105 writer.print(new Gson().toJson(KeyFactory.keyToString(key))); 106 writer.flush(); 107 } catch (ConcurrentModificationException 108 | DatastoreFailureException 109 | DatastoreTimeoutException e) { 110 txn.rollback(); 111 response.setStatus(HttpServletResponse.SC_BAD_REQUEST); 112 return; 113 } finally { 114 if (txn.isActive()) { 115 logger.log(Level.WARNING, "Transaction rollback forced acknowledgment post."); 116 txn.rollback(); 117 response.setStatus(HttpServletResponse.SC_BAD_REQUEST); 118 return; 119 } 120 } 121 response.setStatus(HttpServletResponse.SC_OK); 122 } 123 124 /** Remove a test acknowledgment. */ 125 @Override doDelete(HttpServletRequest request, HttpServletResponse response)126 public void doDelete(HttpServletRequest request, HttpServletResponse response) 127 throws IOException { 128 UserService userService = UserServiceFactory.getUserService(); 129 if (!userService.isUserAdmin()) { 130 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); 131 return; 132 } 133 DatastoreService datastore = DatastoreServiceFactory.getDatastoreService(); 134 String stringKey = request.getPathInfo(); 135 if (stringKey == null) { 136 response.setStatus(HttpServletResponse.SC_BAD_REQUEST); 137 return; 138 } 139 if (stringKey.startsWith("/")) { 140 stringKey = stringKey.substring(1); 141 } 142 Key key = KeyFactory.stringToKey(stringKey); 143 if (!key.getKind().equals(TestAcknowledgmentEntity.KIND)) { 144 response.setStatus(HttpServletResponse.SC_BAD_REQUEST); 145 return; 146 } 147 datastore.delete(key); 148 response.setStatus(HttpServletResponse.SC_OK); 149 } 150 } 151