1 /*
2  * Copyright (C) 2018 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.config;
18 
19 import com.android.vts.entity.ApiCoverageEntity;
20 import com.android.vts.entity.BranchEntity;
21 import com.android.vts.entity.BuildTargetEntity;
22 import com.android.vts.entity.ApiCoverageExcludedEntity;
23 import com.android.vts.entity.CodeCoverageEntity;
24 import com.android.vts.entity.CoverageEntity;
25 import com.android.vts.entity.DeviceInfoEntity;
26 import com.android.vts.entity.HalApiEntity;
27 import com.android.vts.entity.ProfilingPointEntity;
28 import com.android.vts.entity.ProfilingPointRunEntity;
29 import com.android.vts.entity.ProfilingPointSummaryEntity;
30 import com.android.vts.entity.RoleEntity;
31 import com.android.vts.entity.TestAcknowledgmentEntity;
32 import com.android.vts.entity.TestCaseRunEntity;
33 import com.android.vts.entity.TestCoverageStatusEntity;
34 import com.android.vts.entity.TestEntity;
35 import com.android.vts.entity.TestPlanEntity;
36 import com.android.vts.entity.TestPlanRunEntity;
37 import com.android.vts.entity.TestRunEntity;
38 import com.android.vts.entity.TestStatusEntity;
39 import com.android.vts.entity.TestSuiteFileEntity;
40 import com.android.vts.entity.TestSuiteResultEntity;
41 import com.android.vts.entity.UserEntity;
42 import com.google.api.client.extensions.appengine.datastore.AppEngineDataStoreFactory;
43 import com.google.api.services.sheets.v4.SheetsScopes;
44 import com.googlecode.objectify.ObjectifyService;
45 
46 import java.util.Arrays;
47 import java.util.Collections;
48 import java.util.List;
49 import java.util.Optional;
50 import java.util.function.Supplier;
51 import java.util.stream.Stream;
52 import javax.servlet.ServletContext;
53 import javax.servlet.ServletContextEvent;
54 import javax.servlet.ServletContextListener;
55 import javax.servlet.annotation.WebListener;
56 import java.io.FileNotFoundException;
57 import java.io.IOException;
58 import java.io.InputStream;
59 import java.util.Properties;
60 import java.util.logging.Level;
61 import java.util.logging.Logger;
62 
63 /** The @WebListener annotation for registering a class as a listener of a web application. */
64 @WebListener
65 /**
66  * Initializing Objectify Service at the container start up before any web components like servlet
67  * get initialized.
68  */
69 public class ObjectifyListener implements ServletContextListener {
70 
71     private static final Logger logger = Logger.getLogger(ObjectifyListener.class.getName());
72 
73 
74     /** Global instance of the DataStoreFactory. */
75     private static final AppEngineDataStoreFactory DATA_STORE_FACTORY =
76             AppEngineDataStoreFactory.getDefaultInstance();
77 
78     /** Global instance of the scopes. */
79     private static final List<String> GOOGLE_API_SCOPES =
80             Collections.singletonList(SheetsScopes.SPREADSHEETS_READONLY);
81 
82     /**
83      * Receives notification that the web application initialization process is starting. This
84      * function will register Entity classes for objectify.
85      */
86     @Override
contextInitialized(ServletContextEvent servletContextEvent)87     public void contextInitialized(ServletContextEvent servletContextEvent) {
88         ObjectifyService.init();
89         ObjectifyService.register(BranchEntity.class);
90         ObjectifyService.register(BuildTargetEntity.class);
91 
92         ObjectifyService.register(HalApiEntity.class);
93         ObjectifyService.register(ApiCoverageEntity.class);
94         ObjectifyService.register(ApiCoverageExcludedEntity.class);
95         ObjectifyService.register(CodeCoverageEntity.class);
96         ObjectifyService.register(CoverageEntity.class);
97         ObjectifyService.register(DeviceInfoEntity.class);
98         ObjectifyService.register(TestCoverageStatusEntity.class);
99 
100         ObjectifyService.register(ProfilingPointEntity.class);
101         ObjectifyService.register(ProfilingPointRunEntity.class);
102         ObjectifyService.register(ProfilingPointSummaryEntity.class);
103 
104         ObjectifyService.register(TestEntity.class);
105         ObjectifyService.register(TestPlanEntity.class);
106         ObjectifyService.register(TestPlanRunEntity.class);
107         ObjectifyService.register(TestRunEntity.class);
108         ObjectifyService.register(TestCaseRunEntity.class);
109         ObjectifyService.register(TestStatusEntity.class);
110         ObjectifyService.register(TestSuiteFileEntity.class);
111         ObjectifyService.register(TestSuiteResultEntity.class);
112         ObjectifyService.register(TestAcknowledgmentEntity.class);
113         ObjectifyService.register(RoleEntity.class);
114         ObjectifyService.register(UserEntity.class);
115         ObjectifyService.begin();
116         logger.log(Level.INFO, "Value Initialized from context.");
117 
118         Properties systemConfigProp = new Properties();
119 
120         try {
121             InputStream defaultInputStream =
122                     ObjectifyListener.class
123                             .getClassLoader()
124                             .getResourceAsStream("config.properties");
125 
126             systemConfigProp.load(defaultInputStream);
127 
128             servletContextEvent
129                     .getServletContext()
130                     .setAttribute("systemConfigProp", systemConfigProp);
131             servletContextEvent
132                     .getServletContext()
133                     .setAttribute("dataStoreFactory", DATA_STORE_FACTORY);
134             servletContextEvent
135                     .getServletContext()
136                     .setAttribute("googleApiScopes", GOOGLE_API_SCOPES);
137 
138             String roleList = systemConfigProp.getProperty("user.roleList");
139             Supplier<Stream<String>> streamSupplier = () -> Arrays.stream(roleList.split(","));
140             this.createRoles(streamSupplier.get());
141 
142             String adminEmail = systemConfigProp.getProperty("user.adminEmail");
143             if (adminEmail.isEmpty()) {
144                 logger.log(Level.WARNING, "Admin email is not properly set. Check config file");
145             } else {
146                 String adminName = systemConfigProp.getProperty("user.adminName");
147                 String adminCompany = systemConfigProp.getProperty("user.adminCompany");
148                 Optional<String> roleName =
149                         streamSupplier.get().filter(r -> r.equals("admin")).findFirst();
150                 this.createAdminUser(adminEmail, adminName, adminCompany, roleName.orElse("admin"));
151             }
152         } catch (FileNotFoundException e) {
153             logger.log(Level.SEVERE, e.getMessage());
154         } catch (IOException e) {
155             logger.log(Level.SEVERE, e.getMessage());
156         }
157     }
158 
159     /** Receives notification that the ServletContext is about to be shut down. */
160     @Override
contextDestroyed(ServletContextEvent servletContextEvent)161     public void contextDestroyed(ServletContextEvent servletContextEvent) {
162         ServletContext servletContext = servletContextEvent.getServletContext();
163         logger.log(Level.INFO, "Value deleted from context.");
164     }
165 
createRoles(Stream<String> roleStream)166     private void createRoles(Stream<String> roleStream) {
167         roleStream
168                 .map(role -> role.trim())
169                 .forEach(
170                         roleName -> {
171                             RoleEntity roleEntity = new RoleEntity(roleName);
172                             roleEntity.save();
173                         });
174     }
175 
createAdminUser(String email, String name, String company, String role)176     private void createAdminUser(String email, String name, String company, String role) {
177         Optional<UserEntity> adminUserEntityOptional =
178                 Optional.ofNullable(UserEntity.getAdminUser(email));
179         if (adminUserEntityOptional.isPresent()) {
180             logger.log(Level.INFO, "The user is already registered.");
181         } else {
182             UserEntity userEntity = new UserEntity(email, name, company, role);
183             userEntity.setIsAdmin(true);
184             userEntity.save();
185             logger.log(Level.INFO, "The user is saved successfully.");
186         }
187     }
188 }
189