/******************************************************************************* * Copyright 2015 Software Evolution and Architecture Lab, University of Zurich * * 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 eu.cloudwave.wp5.feedbackhandler.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import eu.cloudwave.wp5.common.constants.Headers; import eu.cloudwave.wp5.common.constants.Params; import eu.cloudwave.wp5.common.constants.Urls; import eu.cloudwave.wp5.common.dto.AccessTokenDto; import eu.cloudwave.wp5.common.dto.ApplicationDto; import eu.cloudwave.wp5.common.dto.model.MetricContainingProcedureExecutionDto; import eu.cloudwave.wp5.common.error.RequestException; import eu.cloudwave.wp5.feedbackhandler.model.db.DbApplication; import eu.cloudwave.wp5.feedbackhandler.model.db.DbCostApplication; import eu.cloudwave.wp5.feedbackhandler.model.factories.ApplicationFactory; import eu.cloudwave.wp5.feedbackhandler.service.MonitoringDataService; @RestController public class MonitoringController extends AbstractBaseRestController { private static final String SPACE = " "; private static final String ERROR_MSG__APP_ID_CONTAINS_SPACES = "The application ID may not contain spaces."; private static final String ERROR_MSG__APP_ID_ALREADY_EXISTS = "The chosen application ID already exists. Please choose another one"; @Autowired private ApplicationFactory applicationFactory; @Autowired private MonitoringDataService monitoringDataService; @RequestMapping(value = Urls.MONITORING__DATA, method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE) @ResponseStatus(HttpStatus.OK) public Boolean data( @RequestHeader(Headers.ACCESS_TOKEN) final String accessToken, @RequestHeader(Headers.APPLICATION_ID) final String applicationId, @RequestBody final MetricContainingProcedureExecutionDto procedureExecutionDto) { final DbApplication application = handleUnauthorized(applicationId, accessToken); // TODO: remove print // ProcedureExecutionPrinter.print(procedureExecutionDto, false); monitoringDataService.persist(application, procedureExecutionDto); return true; } @RequestMapping(Urls.MONITORING__REGISTER) @ResponseStatus(HttpStatus.OK) public AccessTokenDto register(@RequestParam(value = Params.APPLICATION_ID, required = true) final String applicationId) { sampleLogger.info("Request to " + Urls.MONITORING__REGISTER); checkApplicationId(applicationId); final DbApplication application = applicationFactory.create(applicationId); applicationRepository.save(application); return new AccessTokenDto(application.getAccessToken()); } @RequestMapping(Urls.MONITORING__LOGIN) @ResponseStatus(HttpStatus.OK) public ApplicationDto login(@RequestHeader(Headers.ACCESS_TOKEN) final String accessToken, @RequestHeader(Headers.APPLICATION_ID) final String applicationId) { sampleLogger.info("Request to " + Urls.MONITORING__LOGIN); final DbCostApplication app = handleUnauthorizedCostApplication(applicationId, accessToken); return new ApplicationDto(app.getApplicationId(), app.getAccessToken(), app.getInstances(), app.getPricePerInstanceInUSD(), app.getMaxRequestsPerInstancePerSecond()); } @RequestMapping(Urls.MONITORING__APPLICATION) @ResponseStatus(HttpStatus.OK) public ApplicationDto application( @RequestHeader(Headers.ACCESS_TOKEN) final String accessToken, @RequestHeader(Headers.APPLICATION_ID) final String applicationId, @RequestHeader(value = Headers.REQUESTED_APPLICATION_ID, required = false) final String requestedApplicationId) { sampleLogger.info(applicationId + " sends request to " + Urls.MONITORING__APPLICATION + " of " + requestedApplicationId); DbCostApplication application = handleUnauthorizedCostApplication(applicationId, accessToken); if (requestedApplicationId != null) { // try to find requested application with given id application = applicationRepository.findOneCostApplication(requestedApplicationId); // does the requested application exist? if (application == null) throwRequestedApplicationIdNotFoundException(); } return new ApplicationDto(application.getApplicationId(), application.getAccessToken(), application.getInstances(), application.getPricePerInstanceInUSD(), application.getMaxRequestsPerInstancePerSecond()); } @RequestMapping(value = Urls.MONITORING__UPDATE, method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE) @ResponseStatus(HttpStatus.OK) public void data(@RequestBody final ApplicationDto updatedApplication) { sampleLogger.info("Request to " + Urls.MONITORING__UPDATE); handleUnauthorized(updatedApplication.getApplicationId(), updatedApplication.getAccessToken()); final DbCostApplication application = applicationRepository.findOneCostApplication(updatedApplication.getApplicationId()); application.setInstances(updatedApplication.getInstances()); application.setMaxRequestsPerInstancePerSecond(updatedApplication.getMaxRequestsPerInstancePerSecond()); application.setPricePerInstanceInUSD(updatedApplication.getPricePerInstanceInUSD()); applicationRepository.save(application); } @RequestMapping(Urls.MONITORING__APPLICATIONS) @ResponseStatus(HttpStatus.OK) public ApplicationDto[] applications(@RequestHeader(Headers.ACCESS_TOKEN) final String accessToken, @RequestHeader(Headers.APPLICATION_ID) final String applicationId) { sampleLogger.info("Request to " + Urls.MONITORING__APPLICATIONS); // Keep in mind: any registered application is able to get a list of all other registered applications // This only makes sense in the context of prototyping and demo applications handleUnauthorized(applicationId, accessToken); List<? extends DbCostApplication> allApplications = applicationRepository.findAllCostApplications(); // create DTO and return as array return allApplications.stream() .map(app -> new ApplicationDto(app.getApplicationId(), app.getAccessToken(), app.getInstances(), app.getPricePerInstanceInUSD(), app.getMaxRequestsPerInstancePerSecond())) .toArray(size -> new ApplicationDto[size]); } private void checkApplicationId(final String applicationId) { if (applicationId.contains(SPACE)) { throw new RequestException(ERROR_MSG__APP_ID_CONTAINS_SPACES); } else if (applicationRepository.findOne(applicationId) != null) { throw new RequestException(ERROR_MSG__APP_ID_ALREADY_EXISTS); } } }