de.craftolution.craftoplugin4.modules.bot.BotConnection.java Source code

Java tutorial

Introduction

Here is the source code for de.craftolution.craftoplugin4.modules.bot.BotConnection.java

Source

/*
 * This file is part of CraftoPlugin, licensed under the MIT License (MIT).
 *
 * Copyright (c) 2017 CraftolutionDE <https://craftolution.de>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * Website: http://craftolution.de/
 * Contact: support@craftolution.de
 */
package de.craftolution.craftoplugin4.modules.bot;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;

import com.google.gson.Gson;
import com.google.gson.JsonObject;

import de.craftolution.craftoplugin4.modules.bot.packets.BotPacket;
import de.craftolution.craftoplugin4.modules.bot.result.Result;
import de.craftolution.craftoplugin4.modules.bot.result.ResultBotResponse;
import de.craftolution.craftoplugin4.modules.bot.packets.ResultPacket;
import de.craftolution.craftoplugin4.modules.bot.util.NoConnectionException;
import de.craftolution.craftoplugin4.services.config.Config;
import de.craftolution.craftoplugin4.services.config.ConfigService;
import de.craftolution.craftoplugin4.services.messenger.interfaces.Loggable;
import de.craftolution.craftoplugin4.services.module.Component;
import de.craftolution.craftoplugin4.services.task.annotations.TaskHandler;

/**
 * TODO: File description for BotConnection.java
 *
 * @author Fear837, Pingebam
 * @since 20.04.2017
 * @see <a href="https://github.com/Craftolution">Craftolution on Github</a>
 */
public class BotConnection extends Component implements Loggable {

    private final BotModule module;
    private final Gson gson = new Gson();

    private InetAddress address;
    private int port;

    private Socket socket;
    private DataInputStream input;
    private DataOutputStream output;
    private boolean listening;

    public BotConnection(BotModule module) {
        this.module = module;
    }

    @Override
    protected void onEnable() throws Exception {
        Config config = ConfigService.instance().get().getOrCreateConfig(this.module);
        this.address = InetAddress.getByName(config.getString("address"));
        this.port = config.getInt("port");

        try {
            this.connect();
        } catch (ConnectException e) {
            report("Failed to connect to " + address + " on port " + port + "...", e);
        }
    }

    @Override
    protected void onDisable() throws Exception {
        this.disconnect();
    }

    boolean isConnected() {
        return this.socket != null && !this.socket.isClosed() && this.socket.isConnected()
                && !this.socket.isInputShutdown() && !this.socket.isOutputShutdown();
    }

    void connect() throws IOException {
        if (isConnected()) {
            return;
        }

        info("Connecting to %s:%s...", this.address, this.port);

        this.socket = new Socket(this.address, this.port);
        this.socket.setKeepAlive(true);

        this.input = new DataInputStream(this.socket.getInputStream());
        this.output = new DataOutputStream(this.socket.getOutputStream());
        this.listening = true;
    }

    void disconnect() {
        info("Disconnecting...");

        this.listening = false;

        if (this.socket != null) {
            try {
                this.socket.shutdownInput();
            } catch (IOException e) {
            }
            try {
                this.socket.shutdownOutput();
            } catch (IOException e) {
            }
            try {
                this.socket.close();
            } catch (IOException e) {
            }
            this.socket = null;
        }

        if (this.input != null) {
            try {
                this.input.close();
            } catch (IOException e) {
            }
            this.input = null;
        }

        if (this.output != null) {
            try {
                this.output.close();
            } catch (IOException e) {
            }
            this.output = null;
        }

    }

    void send(int packetId, String platform, String packetType, JsonObject packetContent)
            throws IOException, NoConnectionException {
        if (!this.isConnected()) {
            throw new NoConnectionException();
        }

        JsonObject root = new JsonObject();
        root.addProperty("platform", platform);
        root.addProperty("packetType", packetType);
        root.addProperty("packetId", packetId);
        root.add("content", packetContent);

        byte[] packet = root.toString().getBytes();

        ByteBuffer buffer = ByteBuffer.allocate(4 + packet.length).putInt(packet.length).put(packet);

        this.output.write(buffer.array());
        this.output.flush();
    }

    void send(BotPacket packet) throws IOException, NoConnectionException {
        this.send(packet.getId(), packet.getPlatform(), packet.getType(), packet.getContent());
    }

    @TaskHandler(name = "BotConnectionListenerTask", delay = 20, async = true)
    public void onTask() throws IOException {
        if (!isConnected() || !this.listening || this.input.available() <= 4) {
            return;
        }

        int packetLength = this.input.readInt();
        byte[] packet = new byte[packetLength];
        this.input.read(packet);

        this.parse(packet);
    }

    private void parse(byte[] packet) {
        String string = new String(packet, Charset.forName("UTF8"));

        JsonObject root = gson.fromJson(string, JsonObject.class);

        String packetType = root.get("packetType").getAsString();
        String platform = root.get("platform").getAsString();
        int packetId = root.get("packetId").getAsInt();
        JsonObject content = root.getAsJsonObject("content").getAsJsonObject();

        if (packetType.equals("result")) {
            ResultPacket resultPacket = new ResultPacket(packetId, platform, packetType, content);
            Result result = Result.parse(resultPacket);
            ResultBotResponse response = new ResultBotResponse(result);

            this.module.craftobot.scheduleResponse(response);
        }
    }

}