summaryrefslogtreecommitdiff
path: root/src/main/java/com/android/vts/job/VtsSpreadSheetSyncServlet.java
blob: 45726d9d495bdd7397560c4ad928432b3f68c8f5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License. You may
 * obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

package com.android.vts.job;

import com.android.vts.entity.ApiCoverageExcludedEntity;
import com.android.vts.entity.DashboardEntity;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.appengine.datastore.AppEngineDataStoreFactory;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.sheets.v4.Sheets;
import com.google.api.services.sheets.v4.model.ValueRange;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

/** Job to sync excluded API data in google spreadsheet with datastore's entity. */
public class VtsSpreadSheetSyncServlet extends BaseJobServlet {

    protected static final Logger logger =
            Logger.getLogger(VtsSpreadSheetSyncServlet.class.getName());

    private static final String APPLICATION_NAME = "VTS Dashboard";
    private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();

    private String CREDENTIALS_KEY_FILE = "";

    /** GoogleClientSecrets for GoogleAuthorizationCodeFlow Builder */
    private GoogleClientSecrets clientSecrets;

    /** This is the ID of google spreadsheet. */
    private String SPREAD_SHEET_ID = "";

    /** This is the range to read of google spreadsheet. */
    private String SPREAD_SHEET_RANGE = "";

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        super.init(servletConfig);

        try {
            CREDENTIALS_KEY_FILE = systemConfigProp.getProperty("api.coverage.keyFile");
            SPREAD_SHEET_ID = systemConfigProp.getProperty("api.coverage.spreadSheetId");
            SPREAD_SHEET_RANGE = systemConfigProp.getProperty("api.coverage.spreadSheetRange");

            InputStream keyFileInputStream =
                    this.getClass()
                            .getClassLoader()
                            .getResourceAsStream("keys/" + CREDENTIALS_KEY_FILE);
            InputStreamReader keyFileStreamReader = new InputStreamReader(keyFileInputStream);

            this.clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, keyFileStreamReader);
        } catch (IOException ioe) {
            logger.log(Level.SEVERE, ioe.getMessage());
        } catch (Exception exception) {
            logger.log(Level.SEVERE, exception.getMessage());
        }
    }

    /**
     * Creates an authorized Credential object.
     *
     * @param HTTP_TRANSPORT The network HTTP Transport.
     * @param appEngineDataStoreFactory The credential will be persisted using the Google App Engine
     *     Data Store API.
     * @param SCOPES Scopes are strings that enable access to particular resources, such as user
     *     data.
     * @return An authorized Credential object.
     * @throws IOException If the credentials.json file cannot be found.
     */
    private Credential getCredentials(
            final NetHttpTransport HTTP_TRANSPORT,
            final AppEngineDataStoreFactory appEngineDataStoreFactory,
            final List<String> SCOPES)
            throws IOException {

        // Build flow and trigger user authorization request.
        GoogleAuthorizationCodeFlow flow =
                new GoogleAuthorizationCodeFlow.Builder(
                                HTTP_TRANSPORT, JSON_FACTORY, this.clientSecrets, SCOPES)
                        .setDataStoreFactory(appEngineDataStoreFactory)
                        .setAccessType("offline")
                        .build();
        LocalServerReceiver localServerReceiver = new LocalServerReceiver();
        return new AuthorizationCodeInstalledApp(flow, localServerReceiver).authorize("user");
    }

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {

        try {
            // Build a new authorized API client service.
            final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
            final AppEngineDataStoreFactory appEngineDataStoreFactory =
                    (AppEngineDataStoreFactory)
                            request.getServletContext().getAttribute("dataStoreFactory");
            final List<String> googleApiScopes =
                    (List<String>) request.getServletContext().getAttribute("googleApiScopes");

            Sheets service =
                    new Sheets.Builder(
                                    HTTP_TRANSPORT,
                                    JSON_FACTORY,
                                    getCredentials(
                                            HTTP_TRANSPORT,
                                            appEngineDataStoreFactory,
                                            googleApiScopes))
                            .setApplicationName(APPLICATION_NAME)
                            .build();

            ValueRange valueRange =
                    service.spreadsheets()
                            .values()
                            .get(SPREAD_SHEET_ID, SPREAD_SHEET_RANGE)
                            .execute();

            List<ApiCoverageExcludedEntity> apiCoverageExcludedEntities = new ArrayList<>();
            List<List<Object>> values = valueRange.getValues();
            if (values == null || values.isEmpty()) {
                logger.log(Level.WARNING, "No data found in google spreadsheet.");
            } else {
                for (List row : values) {
                    ApiCoverageExcludedEntity apiCoverageExcludedEntity =
                            new ApiCoverageExcludedEntity(
                                    row.get(0).toString(),
                                    row.get(1).toString(),
                                    row.get(2).toString(),
                                    row.get(3).toString(),
                                    row.get(4).toString());
                    apiCoverageExcludedEntities.add(apiCoverageExcludedEntity);
                }
            }

            DashboardEntity.saveAll(apiCoverageExcludedEntities, MAX_ENTITY_SIZE_PER_TRANSACTION);

        } catch (GeneralSecurityException gse) {
            logger.log(Level.SEVERE, gse.getMessage());
        }
    }
}