com.epam.wilma.extras.shortcircuit.ShortCircuitResponseInformationFileHandler.java Source code

Java tutorial

Introduction

Here is the source code for com.epam.wilma.extras.shortcircuit.ShortCircuitResponseInformationFileHandler.java

Source

package com.epam.wilma.extras.shortcircuit;
/*==========================================================================
Copyright 2013-2016 EPAM Systems
    
This file is part of Wilma.
    
Wilma is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
    
Wilma is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with Wilma.  If not, see <http://www.gnu.org/licenses/>.
===========================================================================*/

import com.epam.wilma.common.helper.FileFactory;
import com.epam.wilma.common.helper.UniqueIdGenerator;
import com.epam.wilma.webapp.config.servlet.stub.upload.helper.FileOutputStreamFactory;
import org.apache.commons.codec.binary.Base64;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * This class provides file save and load utility for {@link ShortCircuitResponseInformation}.
 *
 * @author tkohegyi
 */
class ShortCircuitResponseInformationFileHandler {

    private static final Object SHORT_CIRCUIT_MAP_GUARD = ShortCircuitChecker.getShortCircuitMapGuard();
    private static final Map<String, ShortCircuitResponseInformation> SHORT_CIRCUIT_MAP = ShortCircuitChecker
            .getShortCircuitMap();
    private final Logger logger = LoggerFactory.getLogger(ShortCircuitResponseInformationFileHandler.class);

    /**
     * Saves the map to a folder, to preserve it for later use.
     *
     * @param httpServletResponse is the response object
     * @return with the response body - that is a json info about the result of the call
     */
    String savePreservedMessagesFromMap(String path, FileFactory fileFactory,
            FileOutputStreamFactory fileOutputStreamFactory, HttpServletResponse httpServletResponse) {
        String response = null;
        String filenamePrefix = "sc" + UniqueIdGenerator.getNextUniqueId() + "_";
        if (!SHORT_CIRCUIT_MAP.isEmpty()) {
            String[] keySet = SHORT_CIRCUIT_MAP.keySet().toArray(new String[SHORT_CIRCUIT_MAP.size()]);
            for (String entryKey : keySet) {
                ShortCircuitResponseInformation information = SHORT_CIRCUIT_MAP.get(entryKey);
                if (information != null) { //save only the cached files
                    //save this into file, folder is in folder variable
                    String filename = path + filenamePrefix + UniqueIdGenerator.getNextUniqueId() + ".json";
                    File file = fileFactory.createFile(filename);
                    try {
                        saveMapObject(fileOutputStreamFactory, file, entryKey, information);
                    } catch (IOException e) {
                        String message = "Cache save failed at file: " + filename + ", with message: "
                                + e.getLocalizedMessage();
                        logger.info("ShortCircuit: " + message);
                        response = "{ \"resultsFailure\": \"" + message + "\" }";
                        httpServletResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                        break;
                    }
                }
            }
        }
        if (response == null) {
            String message = "Cache saved as: " + path + filenamePrefix + "*.json files";
            response = "{ \"resultsSuccess\": \"" + message + "\" }";
            httpServletResponse.setStatus(HttpServletResponse.SC_OK);
            logger.info("ShortCircuit: " + message);
        }
        return response;
    }

    private void saveMapObject(FileOutputStreamFactory fileOutputStreamFactory, File file, String entryKey,
            ShortCircuitResponseInformation information) throws IOException {
        // if file does not exists, then create it
        if (!file.exists()) {
            if (file.getParentFile() != null) {
                file.getParentFile().mkdirs();
            }
            file.createNewFile();
        }
        FileOutputStream fos = fileOutputStreamFactory.createFileOutputStream(file);
        fos.write(("{\n  \"Key\": \"" + entryKey + "\",\n").getBytes());
        fos.write(("  \"ResponseCode\": " + information.getStatusCode() + ",\n").getBytes());
        fos.write(("  \"ContentType\": \"" + information.getContentType() + "\",\n").getBytes());
        Map<String, String> headers = information.getHeaders();
        if (headers != null) {
            fos.write("  \"Headers\": [".getBytes());
            int j = 1;
            for (String key : headers.keySet()) {
                fos.write(("    { \"" + key + "\": \"" + encodeString(headers.get(key)) + "\" }").getBytes());
                if (j != headers.size()) {
                    fos.write(",".getBytes());
                }
                fos.write("\n".getBytes());
                j++;
            }
            fos.write("  ],\n".getBytes());
        }
        fos.write("  \"Body\": ".getBytes());
        String myBody = new JSONObject().put("Body", encodeString(information.getBody())).toString();
        fos.write((myBody + "\n}").getBytes());
        fos.close();
    }

    /**
     * Load the map from a folder, and create a new map from it.
     *
     * @param path is the folder to be used, under Wilma's message folder.
     */
    void loadPreservedMessagesToMap(String path) {
        //Map<String, ShortCircuitResponseInformation> newShortCircuitMap = new HashMap<>();

        File folderFile = new File(path);
        File[] listOfFiles = folderFile.listFiles();
        if (listOfFiles != null) {
            for (int i = 0; i < listOfFiles.length; i++) {
                if (listOfFiles[i].isFile() && listOfFiles[i].getName().endsWith(".json")) {
                    try {
                        ShortCircuitResponseInformation mapObject = loadMapObject(listOfFiles[i].getAbsolutePath());
                        if (mapObject != null) {
                            synchronized (SHORT_CIRCUIT_MAP_GUARD) {
                                SHORT_CIRCUIT_MAP.put(mapObject.getHashCode(), mapObject);
                            }
                        }
                    } catch (JSONException e) {
                        logger.info("Cannot load JSON file to Short Circuit map: "
                                + listOfFiles[i].getAbsolutePath() + ", error:" + e.getLocalizedMessage());
                    }
                }
            }
        }
    }

    private ShortCircuitResponseInformation loadMapObject(String fileName) {
        ShortCircuitResponseInformation result = null;
        File file = new File(fileName);
        if (file.exists()) {
            //load the file
            String fileContent = loadFileToString(fileName);
            if (fileContent != null) {
                JSONObject obj = new JSONObject(fileContent);
                String hashKey = obj.getString("Key");
                int responseCode = obj.getInt("ResponseCode");
                String contentType = obj.getString("ContentType");
                String body = decodeString(obj.getJSONObject("Body").getString("Body"));
                JSONArray headerArray = obj.getJSONArray("Headers");
                ShortCircuitResponseInformation information = null;
                if (hashKey != null && contentType != null && body != null) {
                    information = new ShortCircuitResponseInformation(Long.MAX_VALUE);
                    information.setHashCode(hashKey);
                    information.setStatusCode(responseCode);
                    information.setContentType(contentType);
                    information.setBody(body);
                }
                if (headerArray != null && information != null) {
                    Map<String, String> headers = new HashMap<>();
                    for (int i = 0; i < headerArray.length(); i++) {
                        JSONObject o = headerArray.getJSONObject(i);
                        Iterator j = o.keys();
                        while (j.hasNext()) {
                            String key = (String) j.next();
                            headers.put(key, decodeString(o.getString(key)));
                        }
                    }
                    information.setHeaders(headers);
                }
                result = information;
            }
        }
        return result;
    }

    private String loadFileToString(final String fileName) {
        String text;
        try {
            //CHECKSTYLE OFF - ignoring new String() error, as this is the most effective implementation
            text = new String(Files.readAllBytes(Paths.get(fileName)), StandardCharsets.UTF_8);
            //CHECKSTYLE ON
        } catch (IOException e) {
            //cannot read a file
            text = null;
        }
        return text;
    }

    private String encodeString(final String toBeEncoded) {
        //CHECKSTYLE OFF - ignoring new String() error, as this is the most effective implementation
        return new String(Base64.encodeBase64(toBeEncoded.getBytes()));
        //CHECKSTYLE ON
    }

    private String decodeString(final String toBeDecoded) {
        //CHECKSTYLE OFF - ignoring new String() error, as this is the most effective implementation
        return new String(Base64.decodeBase64(toBeDecoded.getBytes()));
        //CHECKSTYLE ON
    }
}