co.uk.mattredmond.basewatcher.handlers.APIHandler.java Source code

Java tutorial

Introduction

Here is the source code for co.uk.mattredmond.basewatcher.handlers.APIHandler.java

Source

/**
 * Copyright (C) 2014 Matt Redmond and BaseWatcher contributors.
 *
 * This file is part of BaseWatcher.
 *
 * BaseWatcher is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * BaseWatcher 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with BaseWatcher. If not, see <http://www.gnu.org/licenses/>.
 */

package co.uk.mattredmond.basewatcher.handlers;

import co.uk.mattredmond.basewatcher.BaseWatcher;
import co.uk.mattredmond.basewatcher.reference.Errors;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import scala.util.parsing.json.JSONObject;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.LinkedHashMap;

// TODO Write a caching system for commands to the server if network connection drops

public class APIHandler {
    public static String ApiKey; // Unique user API Key
    private static String _url; // API URL
    private static Boolean error; // If any errors occur with the API
    private static String defaultApiKey = "0000"; // Default key to ignore
    private static LinkedHashMap<String, JSONObject> commands; // Store for commands if the network drops

    public APIHandler() {
        error = false;
        commands = new LinkedHashMap<String, JSONObject>();

        if (!ApiKey.equals(defaultApiKey) && !ApiKey.equals("")) { // Check the ApiKey that has been set isn't the default one
            this._url = "http://0.0.0.0:8080/api/v1"; // TODO REMOVE

            if (validUrl()) {
                // Validate the ApiKey against the database online
                this.APIPost(prepJson(new HashMap<String, String>() {
                    {
                        put("ApiKey", ApiKey);
                    }
                }), APIEndpoints.validateApiKey);

                if (!error) {
                    // Start the users session
                    this.APIPost(prepJson(new HashMap<String, String>() {
                        {
                            put("ApiKey", ApiKey);
                        }
                    }), APIEndpoints.startSession);
                }
            } else {
                BaseWatcher.logger.error(Errors.INVALID_URL);
            }
        } else {
            BaseWatcher.logger.error(Errors.NO_API_KEY_PROVIDED);
        }
    }

    /**
     * GET operation to the API
     *
     * @param endpoint API endpoint to hit
     * @return JsonObject Response from the server in a JSON format
     */
    public JsonObject APIGet(APIEndpoints endpoint) {
        String completeUrl = urlPrep(endpoint);

        String resp = netty(completeUrl, "", "GET"); // Perform the GET operation

        if (resp != null) {
            JsonObject response = parseJson(resp);

            if (response != null) {
                return response;
            }

        } else {
            BaseWatcher.logger.error(Errors.SERVER_OR_NETWORK_ISSUE);
            error = true;
            return null;
        }

        return null;
    }

    /**
     * POST operation using the API
     *
     * @param data Data (JSON String) to send to the server
     * @param endpoint API endpoint to hit
     * @return JsonObject Response from the server in a JSON format
     */
    public JsonObject APIPost(String data, APIEndpoints endpoint) {
        String completeUrl = urlPrep(endpoint); // Endpoint to hit

        String resp = netty(completeUrl, data, "POST"); // Perform the POST operation

        if (resp != null) {
            JsonObject response = parseJson(resp);

            if (response != null) {
                return response;
            }

        } else {
            BaseWatcher.logger.error(Errors.SERVER_OR_NETWORK_ISSUE);
            error = true;
            return null;
        }

        return null;
    }

    /**
     * Connection method to the API
     *
     * @param url URL to hit
     * @param data Data to pass to the API
     * @param reqMethod POST / GET
     * @return String Responded data from the server
     */
    private String netty(String url, String data, String reqMethod) {
        String serverData = "";

        try {
            URL _url = new URL(url);

            HttpURLConnection httpConnection = (HttpURLConnection) _url.openConnection();
            httpConnection.setDoOutput(true);
            httpConnection.setRequestMethod(reqMethod);

            // Only if we are doing a POST execution do we need to add content to the payload
            if (reqMethod.toLowerCase().equals("post")) {
                httpConnection.setRequestProperty("Content-Type", "application/json");

                OutputStream outputStream = httpConnection.getOutputStream();
                outputStream.write(data.getBytes());
                outputStream.flush();
            }

            BufferedReader responseBuffer = new BufferedReader(
                    new InputStreamReader((httpConnection.getInputStream())));

            // Output from server
            String output;
            while ((output = responseBuffer.readLine()) != null) {
                serverData = output;
            }

            httpConnection.disconnect(); // Close the connection

            return serverData;
        } catch (Exception e) {
            error = true;
            BaseWatcher.logger.error("There was an issue with the " + reqMethod + " operation.");
            return null;
        }
    }

    /**
     * Parsing of the returned JSON from the server
     *
     * @param rawJson Raw JSON string from server
     */
    private JsonObject parseJson(String rawJson) {
        JsonObject rawObject = new Gson().fromJson(rawJson, JsonObject.class);
        JsonObject baseWatcherObject = rawObject.get("BaseWatcher").getAsJsonObject();
        JsonObject dataInner = baseWatcherObject.get("data").getAsJsonObject();

        if (dataInner.has("error")) {
            BaseWatcher.logger.error(dataInner.get("error").getAsString());
            return null;
        } else {
            return dataInner;
        }
    }

    /**
     * Prepares the URL to be the proper format
     *
     * @param endpoint Endpoint to hit
     * @return String
     */
    private String urlPrep(APIEndpoints endpoint) {
        return _url + "/" + endpoint;
    }

    /**
     * Converts a HashMap to a JSON string for easier JSON building
     *
     * @param data HashMap of data points to convert to JSON
     * @return String
     */
    public String prepJson(HashMap<String, String> data) {
        return new Gson().toJsonTree(data, HashMap.class).getAsJsonObject().toString();
    }

    /**
     * Validates the URL being used. Simple ping / pong
     *
     * @return boolean
     */
    private boolean validUrl() {
        JsonObject ping = APIGet(APIEndpoints.ping);

        if (ping != null) {
            if (ping.has("ping")) {
                return true;
            }
        } else {
            return false;
        }

        return false;
    }

    /**
     * Check if the user is online before trying to perform a POST or GET operation
     *
     * @return boolean
     */
    private boolean isOnline() {
        if (true) {
            return true;
        }

        return false;
    }

    private void cacheCommands(String date, JSONObject data) {
        commands.put(date, data);
    }
}