com.ca.dvs.app.dvs_servlet.misc.VirtualServiceBuilder.java Source code

Java tutorial

Introduction

Here is the source code for com.ca.dvs.app.dvs_servlet.misc.VirtualServiceBuilder.java

Source

/*******************************************************************************
 * Copyright (c) 2015 CA.  All rights reserved.
 *
 * This source file is licensed under the terms of the Eclipse Public License 1.0
 * For the full text of the EPL please see https://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/
package com.ca.dvs.app.dvs_servlet.misc;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import org.glassfish.jersey.internal.util.Base64;
import org.raml.model.Raml;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.ca.casd.utilities.commonUtils.CommonDefs;
import com.ca.casd.utilities.commonUtils.metadata.Metadata;
import com.ca.dvs.utilities.lisamar.LisaMarObject;
import com.ca.dvs.utilities.lisamar.LisaMarUtil;
import com.ca.dvs.utilities.raml.EDM;
import com.ca.dvs.utilities.raml.RamlUtil;
import com.ca.dvs.utilities.raml.VSI;
import com.ca.dvs.utilities.raml.WADL;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

/**
 * Build a CA LISA/DevTest virtual service from a RAML file
 * <p>
 * @author CA Technologies
 * @version 1
 */
public class VirtualServiceBuilder {

    VSEController vseCtrlr;
    LisaMarObject marObject;

    String strVsName = null;
    File fileMar = null;
    Response response = null;

    String vseServerUrl = "http://localhost:1505/api/Dcm/VSEs/VSE";
    String vseServicePortRange = "46001-46999";
    int vseServiceReadyWaitSeconds = 15;
    boolean generateServiceDocument = false;
    String authorization = null;

    public VirtualServiceBuilder(String vseServerUrl, String vseServicePortRange, int vseServiceReadyWaitSeconds,
            boolean generateServiceDocument, String authorization) throws Exception {

        if (null != vseServerUrl && !vseServerUrl.isEmpty()) {
            setVseServerUrl(vseServerUrl);
        }

        setAuthorization(authorization);

        this.vseCtrlr = new VSEController(getVseServerUrl(), getAuthorization());

        if (vseServiceReadyWaitSeconds > 0) {
            setVseServiceReadyWaitSeconds(vseServiceReadyWaitSeconds);
        }

        if (null != vseServicePortRange && !vseServicePortRange.isEmpty()) {
            setVseServicePortRange(vseServicePortRange);
        }

        setGenerateServiceDocument(generateServiceDocument);

    }

    /**
     * Get VSE controller, this object can retrieve VS name, port, base path, uri...etc
     * @return
     */
    public VSEController getVseController() {
        return this.vseCtrlr;
    }

    /**
     * Get File object of MAR file
     * @return
     */
    public File getMarFile() {
        return this.fileMar;
    }

    /**
     * Get response of the instance
     * @return
     */
    public Response getResponse() {
        return this.response;
    }

    /**
     * @return the vseServerUrl
     */
    public String getVseServerUrl() {
        return vseServerUrl;
    }

    /**
     * @param vseServerUrl the vseServerUrl to set
     */
    public void setVseServerUrl(String vseServerUrl) {
        this.vseServerUrl = vseServerUrl;
    }

    /**
     * @return the vseServicePortRange
     */
    public String getVseServicePortRange() {
        return vseServicePortRange;
    }

    /**
     * @param vseServicePortRange the vseServicePortRange to set
     */
    public void setVseServicePortRange(String vseServicePortRange) {
        this.vseServicePortRange = vseServicePortRange;
    }

    /**
     * @return the vseServiceReadyWaitSeconds
     */
    public int getVseServiceReadyWaitSeconds() {
        return vseServiceReadyWaitSeconds;
    }

    /**
     * @param vseServiceReadyWaitSeconds the vseServiceReadyWaitSeconds to set
     */
    public void setVseServiceReadyWaitSeconds(int vseServiceReadyWaitSeconds) {
        this.vseServiceReadyWaitSeconds = vseServiceReadyWaitSeconds;
    }

    /**
     * @return the generateServiceDocument
     */
    public boolean isGenerateServiceDocument() {
        return generateServiceDocument;
    }

    /**
     * @param generateServiceDocument the generateServiceDocument to set
     */
    public void setGenerateServiceDocument(boolean generateServiceDocument) {
        this.generateServiceDocument = generateServiceDocument;
    }

    /**
     * @return the authorization
     */
    public String getAuthorization() {
        return authorization;
    }

    /**
     * @param authorization the authorization to set
     */
    public void setAuthorization(String authorization) {
        this.authorization = authorization;
    }

    /**
     * Set to process RAML file
     * @param raml
     * @param ramlParentFile
     * @return
     * @throws Exception 
     */
    public Response setInputFile(Raml raml, File ramlParentFile, boolean isRest) throws Exception {
        strVsName = null;
        fileMar = null;
        response = null;
        if (isRest)
            createRestVsMar(raml, ramlParentFile);
        else
            createVsMar(raml, ramlParentFile);
        deployVsMar(this.fileMar, this.strVsName);
        cleanUp();
        return this.response;
    }

    /**
     * Set to process WADL file
     * @param wadl
     * @return
     */
    public Response setInputFile(WADL wadl) {
        strVsName = null;
        fileMar = null;
        response = null;

        //createVsMar(wadl);
        //deployVsMar(this.fileMar, this.strVsName);
        //cleanUp();
        return this.response;
    }

    /**
     * Set to process metadata
     * @param metadata
     * @return
     */
    public Response setInputFile(Metadata metadata) {
        strVsName = null;
        fileMar = null;
        response = null;

        //createVsMar(metadata);
        //deployVsMar(this.fileMar, this.strVsName);
        //cleanUp();
        return this.response;
    }

    /**
     * Generate mar file from RAML for Odata service
     * @param raml
     * @param ramlParentFile
     * @throws Exception 
     */
    private void createVsMar(Raml raml, File ramlParentFile) throws Exception {

        try {

            // Generate the AEDM from the RAML
            Document docAEDM = null;
            EDM edm = new EDM(raml);
            docAEDM = edm.getDocument();
            String odataVersion = CommonDefs.VALUE_ODATA_VERSION_4;

            Map<String, Map<String, Object>> sampleData = RamlUtil.getSampleData(raml, ramlParentFile);

            // Get base URL and port from RAML
            String strVsBaseURL = raml.getBasePath();

            // Get seed port from RAML
            URI uri = new URI(raml.getBaseUri());
            int intRamlPort = uri.getPort();

            //Get current Virtual Service list from LISA
            HashMap<String, VSE> vseList = this.vseCtrlr.getVseList();

            // get Alias name from AEDM
            String strAlias = getDocumentAliasNameParser(docAEDM);

            // set a valid service name
            this.strVsName = vseCtrlr.getNewServiceName(strAlias, vseList);

            // Get a valid free port
            int intVsPort = vseCtrlr.getAvailablePort(intRamlPort, getVseServicePortRange(), vseList);

            // Generate MAR          
            //LisaMarObject marObject = LisaMarUtil.generateLiasMar(docAEDM, strVsName, strVsBaseURL, String.valueOf(intVsPort));      
            this.marObject = LisaMarUtil.generateLisaMar(docAEDM, strVsName, strVsBaseURL,
                    String.valueOf(intVsPort), odataVersion, sampleData);
            String strPathMar = marObject.getLisafile();

            // set fileMar
            this.fileMar = new File(strPathMar);

        } catch (Exception e) {
            String msg = String.format("Failed to create MAR file - %s", e.getMessage());
            throw new Exception(msg, e.getCause());
        }
    }

    /**
     * Generate mar file from RAML for Rest service
     * @param raml
     * @param ramlParentFile
     * @throws Exception 
     */
    private void createRestVsMar(Raml raml, File ramlParentFile) throws Exception {

        try {

            // Get base URL and port from RAML
            String strVsBaseURL = raml.getBasePath();

            // Get seed port from RAML
            URI uri = new URI(raml.getBaseUri());
            int intRamlPort = uri.getPort();

            //Get current Virtual Service list from LISA
            HashMap<String, VSE> vseList = this.vseCtrlr.getVseList();

            // get service name from raml
            String strAlias = raml.getTitle().replaceAll("\\s", "");

            // set a valid service name
            this.strVsName = vseCtrlr.getNewServiceName(strAlias, vseList);

            // Get a valid free port
            int intVsPort = vseCtrlr.getAvailablePort(intRamlPort, getVseServicePortRange(), vseList);

            // Generate a VSI from raml
            VSI vsi = new VSI(raml, ramlParentFile, isGenerateServiceDocument());
            Document vsidoc = vsi.getDocument();

            // Generate MAR          
            this.marObject = LisaMarUtil.generateRestLisaMar(strVsName, strVsBaseURL, String.valueOf(intVsPort),
                    vsidoc, vsi.getOperationsList(raml.getResources()));
            String strPathMar = marObject.getLisafile();

            // set fileMar
            this.fileMar = new File(strPathMar);

        } catch (Exception e) {
            String msg = String.format("Failed to create MAR file - %s", e.getMessage());
            throw new Exception(msg, e.getCause());
        }
    }

    /**
     * Deploy MAR to VSE and generate response to the newly VS URI
     * @param fileMar
     * @param strVsName
     * @throws Exception 
     */
    private void deployVsMar(File fileMar, String strVsName) throws Exception {

        try {

            // Deploy MAR
            this.vseCtrlr.deployMar(fileMar);
        } catch (Exception e) {
            String msg = String.format("Failed to deploy a virtual service from MAR file - %s", e.getMessage());
            throw new Exception(msg, e.getCause());
        }

        try {
            // Validate newly deployed service   
            // success - form response body containing URL to new service (LISA Host, base URL, port)
            // fail - form response body containing error message
            Thread.sleep(getVseServiceReadyWaitSeconds() * 1000); // wait to check status of the VS
            VirtualService vs = vseCtrlr.getVirtualService(strVsName);
            if (vs.getStatus() == 2) {

                // form actions URLs hash map
                Map<String, Object> mapActions = formActionURIs(vs.getServiceCtrlUri());

                // form messages hash map
                Map<String, Object> mapMsg = new LinkedHashMap<String, Object>();
                Map<String, Object> mapMsgWarn = new LinkedHashMap<String, Object>();
                Map<String, Object> mapMsgErr = new LinkedHashMap<String, Object>();
                Map<String, Object> mapSvcWarnCreateMar = this.marObject.getWarnings();
                Map<String, Object> mapSvcErrCreateMar = this.marObject.getErrors();

                if (mapSvcWarnCreateMar.size() > 0)
                    mapMsgWarn.put("createMarFile", mapSvcWarnCreateMar);
                if (mapSvcErrCreateMar.size() > 0)
                    mapMsgErr.put("createMarFile", mapSvcErrCreateMar);

                mapMsg.put("serviceWarnings", mapMsgWarn);
                mapMsg.put("serviceErrors", mapMsgErr);

                // put into map for response
                Map<String, Object> map = new LinkedHashMap<String, Object>();
                map.put("serviceName", vs.getName());
                map.put("serviceUrl", vs.getServiceUri().toString());
                map.put("actions", mapActions);
                map.put("messages", mapMsg);

                GsonBuilder gsonBuilder = new GsonBuilder();
                gsonBuilder.setPrettyPrinting();
                gsonBuilder.serializeNulls();
                Gson gson = gsonBuilder.create();

                this.response = Response.status(Status.OK).entity(gson.toJson(map)).build();

            } else {
                this.response = Response.status(Status.INTERNAL_SERVER_ERROR)
                        .entity(String.format("Service name '%s' is deployed but failed to start", strVsName))
                        .build();
            }

        } catch (Exception e) {
            String msg = String.format("Service name '%s' is deployed but failed to start - %s", strVsName,
                    e.getMessage());
            throw new Exception(msg, e.getCause());
        }
    }

    /**
     * Method to clean up afterward
     * @throws Exception 
     */
    public void cleanUp() throws Exception {
        // Delete Mar file
        try {
            Files.deleteIfExists(this.fileMar.toPath());
        } catch (IOException e) {
            String msg = String.format("Failed to delete MAR file: %s - %s", this.fileMar.getPath(),
                    e.getMessage());
            throw new Exception(msg, e.getCause());
        }
    }

    /**
     * Get schema alias name. However if alias name is not presented, use last segment of namespace 
     * @param doc
     * @return
     */
    private String getDocumentAliasNameParser(Document doc) {
        String strAlias = null;

        doc.getDocumentElement().normalize();
        NodeList nList = doc.getElementsByTagName("Schema");
        Node nNode = nList.item(0);
        if (nNode.getNodeType() == Node.ELEMENT_NODE) {
            strAlias = ((Element) nNode).getAttribute("Alias");
        }

        if (strAlias == null || strAlias.isEmpty()) {
            if (nNode.getNodeType() == Node.ELEMENT_NODE) {
                String strNameSpace = ((Element) nNode).getAttribute("Namespace");
                if (strNameSpace != null && !strNameSpace.isEmpty())
                    strAlias = strNameSpace.substring(strNameSpace.lastIndexOf("\\.") + 1);
            }
        }
        return strAlias;
    }

    public Map<String, Object> formActionURIs(URI svcCtrlUri) throws Exception {
        BufferedReader in = null;
        try {
            String strActions = "actions";
            URL url = new URL(svcCtrlUri + "/" + strActions);

            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setRequestProperty("Content-Type", "application/vnd.ca.lisaInvoke.vseList+xml");

            if (getAuthorization() != null) {
                String encodedPswd = Base64.encodeAsString(getAuthorization());
                conn.setRequestProperty("Authorization", "Basic " + encodedPswd);
            }

            // Get the response from VSE of specific VM actions
            int responseCode = conn.getResponseCode();

            if (responseCode >= 200 && responseCode <= 300) {
                in = new BufferedReader(new InputStreamReader(conn.getInputStream()));

                String inputLine;
                StringBuffer response = new StringBuffer();

                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                //in.close();

                //convert the response to xml doc
                Document doc = vseCtrlr.readXmlString(response.toString());

                //get the list of actions nodelist
                NodeList virtualSvcNList = doc.getElementsByTagName("Link");
                Map<String, Object> mapActionsUri = new LinkedHashMap<String, Object>();
                for (int i = 0; i < virtualSvcNList.getLength(); i++) {
                    Node node = virtualSvcNList.item(i);
                    String strRel = ((Element) node).getAttribute("rel");
                    String strHref = ((Element) node).getAttribute("href");

                    if (strRel != null && !strRel.isEmpty() && strHref != null && !strHref.isEmpty())
                        mapActionsUri.put(strRel, strHref);
                }

                // last, add control URI to the map
                mapActionsUri.put("control", svcCtrlUri.toString());

                return mapActionsUri;

            } else {

                StringBuffer sbError = new StringBuffer();

                sbError.append(
                        String.format("Error getting list action from virtual service at uri: %s - ", svcCtrlUri));

                try {
                    sbError.append(VSEController.getLisaErrorResponse(conn.getErrorStream()));
                } catch (Exception ex) {
                    sbError.append(String.format("response code: %s", Integer.toString(responseCode)));
                }

                throw new Exception(sbError.toString(), null);

            }

        } catch (Exception e) {
            throw e;
        } finally {
            if (in != null)
                in.close();
        }
    }

}