abstractions.AbstractWorker.java Source code

Java tutorial

Introduction

Here is the source code for abstractions.AbstractWorker.java

Source

/*
 * This file is part of cBackup, network equipment configuration backup tool
 * Copyright (C) 2017, Oegs apligins, Imants ernovs, Dmitrijs Galo?kins
 *
 * cBackup is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package abstractions;

import api.ApiCaller;
import api.ApiRequest;
import api.ApiRequestMethods;
import api.ApiResponse;

/*
 * gson
 */
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;

/*
 * md5
 */
import javax.xml.bind.DatatypeConverter;
import java.lang.reflect.Type;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import java.util.*;
import java.util.concurrent.Callable;

/**
 * Abstract class for all workers
 * @noinspection WeakerAccess
 */
public abstract class AbstractWorker extends AbstractCoreUnit implements Callable<Boolean> {

    protected Map<String, String> credentials;
    protected Map<String, Map<String, String>> jobs;
    protected Map<String, DTOVariableConvertResult> variables = new HashMap<>();
    protected Gson gson = new Gson();

    /*
     * Worker result DTO
     */
    protected DTOWorkerResult workerResult = new DTOWorkerResult();

    /**
     * Main worker thread-callable method
     *
     * @return Boolean - returns true|false for Task stats
     */
    public Boolean call() {

        /*if(!this.isActionRequired()) {
        return true;
        }*/ // todo implement (for save)

        // checking data, critical for factories
        if (!this.checkFactoryData()) {
            return false;
        }

        // Getting credentials
        if (!this.getCredentials()) {
            return false;
        }

        // Getting Job list
        if (!this.processJobs()) {
            return false;
        }

        // Executing jobs
        if (!this.executeJobs()) {
            return false;
        }

        // Check for data saving required
        if (!this.isSetResultRequired()) {
            return true;
        }

        // Setting worker result
        return this.setResult();

    }

    /**
     * Checking data, critical for factories
     *
     * @return Boolean
     */
    protected Boolean checkFactoryData() {

        String nodeVendor = this.coordinates.get("nodeVendor");
        String nodeModel = this.coordinates.get("nodeModel");

        if (nodeVendor == null || nodeVendor.length() == 0) {
            String noVendorMessage = "Task " + this.coordinates.get("taskName") + ", node "
                    + this.coordinates.get("nodeId") + ": empty device vendor.";
            this.logMessage("WARNING", "NODE GET CREDENTIALS", noVendorMessage);
            return false;
        }

        if (nodeModel == null || nodeModel.length() == 0) {
            String noModelMessage = "Task " + this.coordinates.get("taskName") + ", node "
                    + this.coordinates.get("nodeId") + ": empty device vendor.";
            this.logMessage("WARNING", "NODE GET CREDENTIALS", noModelMessage);
            return false;
        }

        return true;
    }

    /**
     * Get node credentials
     *
     * @return Boolean - result of get-parse node credentials
     */
    protected Boolean getCredentials() {
        /*
         * Getting credentials Json
         */
        Map<String, String> params = new HashMap<>();
        params.put("node_id", this.coordinates.get("nodeId"));

        ApiRequest getCredentials = new ApiRequest(coordinates).setRequestMethod(ApiRequestMethods.GET)
                .setApiMethod("v1/core/get-node-credentials").setParams(params);

        ApiResponse credentialsResponse = ApiCaller.request(getCredentials);

        if (!credentialsResponse.success) {

            /*
             * Log record
             * Can't get node credentials
             */
            String getCredMessage = "Task " + this.coordinates.get("taskName") + ", node "
                    + this.coordinates.get("nodeId") + ": can't get credentials from API.";
            this.logBadResponse("WARNING", "NODE GET CREDENTIALS", getCredMessage, credentialsResponse);
            return false;

        }

        /*
         * Parsing credentials Json to map
         * Writing parse result
         */
        String credentialsJson = credentialsResponse.response;

        Type credentialsType = new TypeToken<HashMap<String, String>>() {
        }.getType();

        try {

            this.credentials = gson.fromJson(credentialsJson, credentialsType);

        } catch (JsonSyntaxException e) {
            String parseCredMessage = "Task " + this.coordinates.get("taskName") + ", node "
                    + this.coordinates.get("nodeId") + ": can't parse credentials JSON.";
            this.logException("WARNING", "NODE PARSE CREDENTIALS", parseCredMessage, e);
            return false;
        }

        return true;
    }

    /**
     * Get job list
     * Set job list to this.jobs
     *
     * @return Boolean - job list get result
     */
    protected Boolean processJobs() {
        /*
         * Getting credentials Json
         */
        Map<String, String> params = new HashMap<>();
        params.put("worker_id", this.coordinates.get("workerId"));

        ApiRequest getCredentials = new ApiRequest(coordinates).setRequestMethod(ApiRequestMethods.GET)
                .setApiMethod("v1/core/get-jobs").setParams(params);

        ApiResponse jobsResponse = ApiCaller.request(getCredentials);

        if (!jobsResponse.success) {

            /*
             * Log record
             * Can't get node credentials
             */
            String getCredMessage = "Task " + this.coordinates.get("taskName") + ", node "
                    + this.coordinates.get("nodeId") + ": can't get jobs from api.";
            this.logBadResponse("WARNING", "NODE GET JOBS", getCredMessage, jobsResponse);
            return false;

        }

        /*
         * Parsing credentials Json to map
         * Writing parse result
         */
        String jobsJson = jobsResponse.response;

        Type jobsType = new TypeToken<TreeMap<String, HashMap<String, String>>>() {
        }.getType();

        try {

            this.jobs = gson.fromJson(jobsJson, jobsType);

        } catch (JsonSyntaxException e) {
            String parseCredMessage = "Task " + this.coordinates.get("taskName") + ", node "
                    + this.coordinates.get("nodeId") + ": can't parse jobs JSON.";
            this.logException("WARNING", "NODE PARSE JOBS", parseCredMessage, e);
            return false;

        }

        /*
         * Empty job list
         */
        if (this.jobs.size() == 0) {
            String jobsCountMessage = "Task " + this.coordinates.get("taskName") + ", node "
                    + this.coordinates.get("nodeId") + ": empty jobs list.";
            this.logMessage("WARNING", "NODE GET JOBS", jobsCountMessage);
            return false;
        }

        return true;
    }

    /**
     * Check for data saving required
     * Getting old data hash, comparing with new hash
     *
     * @return Boolean
     */
    protected Boolean isSetResultRequired() {
        // noinspection UnusedAssignment
        Boolean required = true;
        String oldHash;
        String allData = "";
        // noinspection UnusedAssignment
        String newHash = "";

        if (this.coordinates.get("put") == null) {
            required = false;
        } else {

            /*
             * Getting old hash
             */
            Map<String, String> params = new HashMap<>();
            params.put("task_name", this.coordinates.get("taskName"));
            params.put("node_id", this.coordinates.get("nodeId"));

            ApiRequest getCredentials = new ApiRequest(coordinates).setRequestMethod(ApiRequestMethods.GET)
                    .setApiMethod("v1/core/get-hash").setParams(params);

            ApiResponse hashResponse = ApiCaller.request(getCredentials);

            if (!hashResponse.success) {

                /*
                 * Log record
                 * Can't get old hash
                 */
                String getCredMessage = "Task " + this.coordinates.get("taskName") + ", node "
                        + this.coordinates.get("nodeId") + ": can't get old hash from API.";
                this.logBadResponse("ERROR", "WORKER SEND RESULT", getCredMessage, hashResponse);
                return false;
            }

            /*
             * Parsing old hash Json to string
             * Writing parse result
             */
            String hashJson = hashResponse.response;

            Type hashType = new TypeToken<String>() {
            }.getType();

            try {

                oldHash = gson.fromJson(hashJson, hashType);

            } catch (JsonSyntaxException e) {
                String parseCredMessage = "Task " + this.coordinates.get("taskName") + ", node "
                        + this.coordinates.get("nodeId") + ": can't parse old hash JSON.";
                this.logException("WARNING", "WORKER SEND RESULT", parseCredMessage, e);
                return false;
            }

            // Calculating new hash
            // Get a set of the entries
            Set resultDataSet = this.workerResult.data.entrySet();

            // Get an iterator
            Iterator it = resultDataSet.iterator();

            // Concatenating all new data
            // noinspection WhileLoopReplaceableByForEach
            while (it.hasNext()) {
                Map.Entry result = (Map.Entry) it.next();
                allData += result.getValue();
            }

            // Getting new hash
            try {

                MessageDigest md = MessageDigest.getInstance("MD5");
                md.update(allData.getBytes()); // todo test getBytes("UTF-8")
                byte[] digest = md.digest();
                newHash = DatatypeConverter.printHexBinary(digest).toUpperCase();

            } catch (NoSuchAlgorithmException e) {
                String parseCredMessage = "Task " + this.coordinates.get("taskName") + ", node "
                        + this.coordinates.get("nodeId") + ": can't get new md5 hash from result.";
                this.logException("ERROR", "WORKER SEND RESULT", parseCredMessage, e);
                return false;
            }

            this.workerResult.hash = newHash;

            required = oldHash == null || !oldHash.equals(newHash);

        }

        if (required) {
            return true;
        } else {
            String saveNotRequiredMessage = "Task " + this.coordinates.get("taskName") + ", node "
                    + this.coordinates.get("nodeId") + ": worker success. Result saving is not required.";
            this.logMessage("INFO", "WORKER SEND RESULT", saveNotRequiredMessage);
            return false;
        }
    }

    /**
     * Sending worker result to API
     *
     * @return Boolean
     */
    protected Boolean setResult() {

        String message;

        /*
         * No result save required
         */
        if (this.coordinates.get("put") == null) {
            return true;
        }

        /*
         * Target database table is not set
         */
        if (this.coordinates.get("put").equals("db")
                && (this.coordinates.get("table") == null || this.coordinates.get("table").length() == 0)) {
            message = "Task " + this.coordinates.get("taskName") + ", node " + this.coordinates.get("nodeId")
                    + ": destination db table is not set.";
            this.logMessage("WARNING", "WORKER SEND RESULT", message);
            return false;
        }

        /*
         * Sending worker result POST
         */
        ApiRequest log = new ApiRequest(this.coordinates).setRequestMethod(ApiRequestMethods.POST)
                .setApiMethod("v1/core/set-worker-result").setPostJson(this.gson.toJson(this.workerResult));

        ApiResponse setResultResponse = ApiCaller.request(log);

        /*
         * Logging
         */
        if (!setResultResponse.success) {
            message = "Task " + this.coordinates.get("taskName") + ", node " + this.coordinates.get("nodeId")
                    + ": set result via API is failed.";
            this.logBadResponse("ERROR", "WORKER SEND RESULT", message, setResultResponse);
            return false;
        } else {
            message = "Task " + this.coordinates.get("taskName") + ", node " + this.coordinates.get("nodeId")
                    + ": worker success. Result is successfully saved.";
            this.logMessage("INFO", "WORKER SEND RESULT", message);
            return true;
        }

    }

    /**
     * Executing all commands(this.jobs).
     * Setting execution results to this.workerResult
     * Returning success.
     *
     * @return Boolean - success of jobs execution
     */
    protected abstract Boolean executeJobs();

}