All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.virtualan.controller.VirtualServiceController Maven / Gradle / Ivy

There is a newer version: 3.1.0
Show newest version
/*
 *
 * Copyright 2018 Virtualan Contributors (https://virtualan.io)
 *
 * 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 io.virtualan.controller;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import io.virtualan.core.VirtualParameterizedUtil;
import io.virtualan.core.model.*;

import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;


import io.virtualan.core.util.Converter;
import io.virtualan.core.util.rule.RuleEvaluator;
import io.virtualan.core.util.rule.ScriptExecutor;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

import io.virtualan.core.InvalidMockResponseException;
import io.virtualan.core.VirtualServiceInfo;
import io.virtualan.core.VirtualServiceUtil;
import io.virtualan.requestbody.RequestBodyTypes;
import io.virtualan.service.VirtualService;


/**
 * This is a entry point to to record mock data in the Virtualan.
 *
 * Virtualan-UI and Virtualan-OpenAPI would interact through this web services.
 *
 * @author Elan Thangamani
 *
 **/
@RestController("virtualServiceController")
public class VirtualServiceController {

    private static final Logger log = LoggerFactory.getLogger(VirtualServiceController.class);
    public static final String VS_REQUEST_BODY_MISMATCH = "VS_REQUEST_BODY_MISMATCH";

    @Value("${virtualan.script.enabled:false}")
    private boolean scriptEnabled;


    @Autowired
    private RuleEvaluator ruleEvaluator;

    @Autowired
    private ScriptExecutor scriptExecutor;

    @Autowired
    private Converter converter;

    @Autowired
    private VirtualParameterizedUtil virtualParameterizedUtil;

    @Autowired
    private VirtualService virtualService;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private MessageSource messageSource;


    Locale locale = LocaleContextHolder.getLocale();

    @Autowired
    private VirtualServiceUtil virtualServiceUtil;

    private ObjectMapper getObjectMapper() {
        objectMapper.findAndRegisterModules();
        objectMapper.setSerializationInclusion(Include.NON_NULL);

        return objectMapper.enable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE,
            DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
            // ,DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES
        );
    }


    public VirtualService getVirtualService() {
        return virtualService;
    }

    public void setVirtualService(VirtualService virtualService) {
        this.virtualService = virtualService;
    }

    public VirtualServiceInfo getVirtualServiceInfo() {
        return virtualServiceUtil.getVirtualServiceInfo();
    }

    @Value("${virtualan.application.name:Mock Service}")
    private String applicationName;

    @GetMapping(value = "/virtualservices/app-name")
    public String applicationName() {
        return "{\"appName\":\"" + applicationName + "\"}";
    }

    @GetMapping(value = "/virtualservices/load")
    public Map> listAllMockLoadRequest()
        throws InstantiationException, IllegalAccessException, ClassNotFoundException,
        IOException {
        return virtualServiceUtil.getVirtualServiceInfo() != null ? virtualServiceUtil.getVirtualServiceInfo().loadVirtualServices(scriptEnabled)
            : new HashMap<>();
    }


    @GetMapping(value = "/virtualservices")
    public ResponseEntity> listAllMockLoadRequests() {
        final List mockRestLoadRequests = virtualService.findAllMockRequests();
        if (mockRestLoadRequests.isEmpty()) {
            return new ResponseEntity<>(HttpStatus.NO_CONTENT);
        }
        List response =
            mockRestLoadRequests.stream().map(x  -> converter.convertAsJson(x)).collect(Collectors.toList());
        return new ResponseEntity<>(response, HttpStatus.OK);
    }

    @GetMapping(value = "/virtualservices/{id}",
        produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity getMockLoadRequest(@PathVariable("id") long id){
        VirtualServiceRequest mockLoadRequest = virtualService.findById(id);
        if (mockLoadRequest == null) {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
        mockLoadRequest = converter.convertAsJson(mockLoadRequest);
        return new ResponseEntity<>(mockLoadRequest, HttpStatus.OK);
    }

    @PostMapping(value = "/virtualservices")
    public ResponseEntity createMockRequest(
        @RequestBody VirtualServiceRequest virtualServiceRequest) {
        try {
            if( !scriptEnabled && virtualServiceRequest.getType() != null && (ResponseProcessType.SCRIPT.toString().equalsIgnoreCase(virtualServiceRequest.getType().toString())
                    || ResponseProcessType.RULE.toString().equalsIgnoreCase(virtualServiceRequest.getType().toString()))) {
                return new ResponseEntity<>(
                        "{\"message\":\""+messageSource.getMessage("VS_VALIDATION_FAILURE_REJECT", null, locale)+"\"}",
                        null, HttpStatus.BAD_REQUEST);
            } else if (virtualServiceRequest.getType() == null) {
                virtualServiceRequest.setType(ResponseProcessType.RESPONSE.toString());
            }

            converter.convertJsonAsString(virtualServiceRequest);
            virtualServiceRequest.setRequestType(RequestType.REST.toString());
            validateExpectedInput(virtualServiceRequest);
            // find the operationId for the given Request. It required for the Automation test cases
            virtualServiceUtil.findOperationIdForService(virtualServiceRequest);
            if ("PARAMS".equalsIgnoreCase(virtualServiceRequest.getType())) {
                Map response = virtualParameterizedUtil.handleParameterizedRequest(virtualServiceRequest);
                if(!response.isEmpty()) {
                    final VirtualServiceStatus virtualServiceStatus = new VirtualServiceStatus(
                        messageSource.getMessage("VS_PARAMS_DATA_ALREADY_EXISTS", null, locale));
                    virtualServiceRequest = converter.convertAsJson(virtualServiceRequest);
                    virtualServiceStatus.setVirtualServiceRequest(virtualServiceRequest);
                    virtualServiceStatus.setResponseParam( response);
                    return new ResponseEntity<>(virtualServiceStatus,
                        HttpStatus.BAD_REQUEST);
                }
            } else {

                ResponseEntity responseEntity = validateRequestBody(virtualServiceRequest);
                if (responseEntity != null) {
                    return responseEntity;
                } else {
                    responseEntity = validateResponseBody(virtualServiceRequest);
                    if (responseEntity != null) {
                        return responseEntity;
                    }
                }
                responseEntity = virtualServiceUtil
                    .checkIfServiceDataAlreadyExists(virtualServiceRequest);

                if (responseEntity != null) {
                    return responseEntity;
                }
            }
            VirtualServiceRequest mockTransferObject = virtualService.saveMockRequest(virtualServiceRequest);
            mockTransferObject = converter.convertAsJson(mockTransferObject);
            mockTransferObject.setMockStatus(
                new VirtualServiceStatus(messageSource.getMessage("VS_SUCCESS", null, locale)));
            return new ResponseEntity<>(mockTransferObject, HttpStatus.CREATED);

        } catch (final Exception e) {
            return new ResponseEntity(new VirtualServiceStatus(
                messageSource.getMessage("VS_UNEXPECTED_ERROR", null, locale) + e.getMessage()),
                HttpStatus.BAD_REQUEST);
        }
    }





    private ResponseEntity validateResponseBody(VirtualServiceRequest mockLoadRequest) {
        try {
            virtualServiceUtil.isMockResponseBodyValid(mockLoadRequest);
        } catch (NoSuchMessageException | InvalidMockResponseException e) {
            return new ResponseEntity(new VirtualServiceStatus(
                messageSource.getMessage("VS_RESPONSE_BODY_MISMATCH", null, locale)
                    + e.getMessage()),
                HttpStatus.BAD_REQUEST);
        }
        return null;
    }

    private ResponseEntity validateRequestBody(VirtualServiceRequest virtualServiceRequest) {

        if (virtualServiceUtil.getVirtualServiceInfo() != null) {
            final Class inputObjectType = virtualServiceUtil.getVirtualServiceInfo().getInputType(virtualServiceRequest);
            if (inputObjectType == null && (virtualServiceRequest.getInput() == null
                || virtualServiceRequest.getInput().toString().length() == 0)) {
                return null;
            } else if (virtualServiceRequest.getInput() != null
                && virtualServiceRequest.getInput().toString().length() > 0 && inputObjectType != null) {
                return getResponseEntity(virtualServiceRequest, inputObjectType);
            }
        }


        return null;
    }

    private ResponseEntity getResponseEntity(VirtualServiceRequest virtualServiceRequest,
        Class inputObjectType) {
        final io.virtualan.requestbody.RequestBody requestBody =
            new io.virtualan.requestbody.RequestBody();
        requestBody.setObjectMapper(getObjectMapper());
        requestBody.setInputRequest(virtualServiceRequest.getInput().toString());
        requestBody.setInputObjectType(inputObjectType);
        Object object = getInputObject(inputObjectType, requestBody);
        if (object == null) {
            return new ResponseEntity(
                new VirtualServiceStatus(messageSource
                    .getMessage(VS_REQUEST_BODY_MISMATCH, null, locale)),
                HttpStatus.BAD_REQUEST);
        }

        if ("RULE".equalsIgnoreCase(virtualServiceRequest.getType())) {
            return getRuleEntity(virtualServiceRequest, inputObjectType,
                requestBody);

        } else if ("SCRIPT".equalsIgnoreCase(virtualServiceRequest.getType())) {
            return getScriptResponseEntity(virtualServiceRequest,
                inputObjectType, requestBody);
        }
        return null;
    }

    private ResponseEntity getScriptResponseEntity(VirtualServiceRequest virtualServiceRequest,
        Class inputObjectType, io.virtualan.requestbody.RequestBody requestBody) {
        try {
            MockServiceRequest mockServiceRequest = new MockServiceRequest();
            Object inputObject = getInputObject(inputObjectType, requestBody);
            mockServiceRequest.setInput(inputObject);
            mockServiceRequest.setParams(Converter.converter(virtualServiceRequest.getAvailableParams()));
            MockResponse mockResponse = new MockResponse();
            mockResponse = scriptExecutor.executeScript (mockServiceRequest, mockResponse, virtualServiceRequest.getRule());
            if(mockResponse == null){
                return new ResponseEntity(
                    new VirtualServiceStatus("Its not a valid mock response setup!!! Verify the script? ", messageSource
                        .getMessage(VS_REQUEST_BODY_MISMATCH, null, locale)),
                    HttpStatus.BAD_REQUEST);
            }
        } catch (Exception e) {
            return new ResponseEntity(
                new VirtualServiceStatus(e.getMessage(), messageSource
                    .getMessage(VS_REQUEST_BODY_MISMATCH, null, locale)),
                HttpStatus.BAD_REQUEST);
        }
        return null;
    }

    private ResponseEntity getRuleEntity(VirtualServiceRequest virtualServiceRequest,
        Class inputObjectType, io.virtualan.requestbody.RequestBody requestBody) {
        try {
            MockServiceRequest mockServiceRequest = new MockServiceRequest();
            Object  object = getInputObject(inputObjectType, requestBody);
            mockServiceRequest.setInput(object);
            mockServiceRequest.setParams(Converter.converter(virtualServiceRequest.getAvailableParams()));
            ruleEvaluator.expressionEvaluatorForMockCreation(mockServiceRequest, virtualServiceRequest.getRule());
        } catch (Exception e) {
            return new ResponseEntity(
                new VirtualServiceStatus(e.getMessage(), messageSource
                    .getMessage(VS_REQUEST_BODY_MISMATCH, null, locale)),
                HttpStatus.BAD_REQUEST);
        }
        return null;
    }

    private Object getInputObject(Class inputObjectType,
        io.virtualan.requestbody.RequestBody requestBody) {
        Object object;
        try {
            object = RequestBodyTypes.fromString(inputObjectType.getTypeName())
                .getValidMockRequestBody(requestBody);
        } catch (NoSuchMessageException | IOException e) {
            object = null;
        }
        return object;
    }


    private ResponseEntity validateExpectedInput(VirtualServiceRequest mockLoadRequest) {
        if (mockLoadRequest.getHttpStatusCode() == null || mockLoadRequest.getMethod() == null || mockLoadRequest.getType() == null
            || mockLoadRequest.getUrl() == null) {
            return new ResponseEntity(
                new VirtualServiceStatus(
                    messageSource.getMessage("VS_CREATE_MISSING_INFO", null, locale)),
                HttpStatus.BAD_REQUEST);
        }
        return null;
    }

    @PutMapping(value = "/virtualservices/{id}")
    public ResponseEntity updateMockRequest(@PathVariable("id") long id,
        @RequestBody VirtualServiceRequest mockLoadRequest) {

        final VirtualServiceRequest currentMockLoadRequest = virtualService.findById(id);
        if (currentMockLoadRequest == null) {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }

        // find the operationId for the given Request. It required for the Automation test cases
        virtualServiceUtil.findOperationIdForService(mockLoadRequest);

        currentMockLoadRequest.setInput(mockLoadRequest.getInput());
        currentMockLoadRequest.setOutput(mockLoadRequest.getOutput());
        currentMockLoadRequest.setOperationId(mockLoadRequest.getOperationId());

        virtualService.updateMockRequest(currentMockLoadRequest);
        return new ResponseEntity<>(currentMockLoadRequest, HttpStatus.OK);
    }


    @DeleteMapping(value = "/virtualservices/{id}")
    public ResponseEntity deleteMockRequest(@PathVariable("id") long id) {
        final VirtualServiceRequest mockLoadRequest = virtualService.findById(id);
        if (mockLoadRequest == null) {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
        virtualService.deleteMockRequestById(id);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }


    @GetMapping(value = "/api-catalogs")
    public ResponseEntity> readCatalog() {
        final Set fileList = new HashSet<>();
        List lists  = Arrays.asList("classpath:META-INF/resources/yaml/*/", "classpath:META-INF/resources/wsdl/*/");
        fileList.add("VirtualService");
        for(String pathName  :  lists){
            try {
                final Resource[] resources = getCatalogList(pathName);
                for (final Resource file : resources) {
                    final String[] names = file.toString().split("/");
                    if (names.length > 1) {
                        fileList.add(names[names.length - 2]);
                    }
                }
            }catch (Exception e){
                log.error("api-catalogs : {}" , e.getMessage());
            }
        }
        if (fileList.isEmpty()) {
            log.error("Api-catalogs List was not available : ");
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        } else {
            return new ResponseEntity<>(new LinkedList<>(fileList.stream().sorted().collect(
                Collectors.toList())), HttpStatus.OK);
        }
    }


    @GetMapping(value = "/api-catalogs/{name}")
    public ResponseEntity> readCatalog(@PathVariable("name") String name) {
        final List fileList = new LinkedList<>();
        try {
            if("VirtualService".equalsIgnoreCase(name)){
                fileList.add("virtualservices.yaml");
            }

            for (final Resource file : getCatalogs(name)) {
                fileList.add(file.getFilename());
            }

        } catch (final IOException e) {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
        if (fileList.isEmpty()) {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        } else {
            return new ResponseEntity<>(fileList, HttpStatus.OK);
        }
    }


    private Resource[] getCatalogs(String name) throws IOException {
        final ClassLoader classLoader = MethodHandles.lookup().getClass().getClassLoader();
        final PathMatchingResourcePatternResolver resolver =
            new PathMatchingResourcePatternResolver(classLoader);
        return resolver.getResources("classpath:META-INF/resources/**/" + name + "/*.*");
    }
    private Resource[] getCatalogList(String path) throws IOException {
        final ClassLoader classLoader = MethodHandles.lookup().getClass().getClassLoader();

        final PathMatchingResourcePatternResolver resolver =
            new PathMatchingResourcePatternResolver(classLoader);
        return resolver.getResources(path);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy