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