me.neatmonster.spacebukkit.PanelListener.java Source code

Java tutorial

Introduction

Here is the source code for me.neatmonster.spacebukkit.PanelListener.java

Source

/*
 * This file is part of SpaceBukkit (http://spacebukkit.xereo.net/).
 *
 * SpaceBukkit is free software: you can redistribute it and/or modify it under the terms of the
 * Attribution-NonCommercial-ShareAlike Unported (CC BY-NC-SA) license as published by the Creative Common organization,
 * either version 3.0 of the license, or (at your option) any later version.
 *
 * SpaceBukkit 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 Attribution-NonCommercial-ShareAlike
 * Unported (CC BY-NC-SA) license for more details.
 *
 * You should have received a copy of the Attribution-NonCommercial-ShareAlike Unported (CC BY-NC-SA) license along with
 * this program. If not, see <http://creativecommons.org/licenses/by-nc-sa/3.0/>.
 */
package me.neatmonster.spacebukkit;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.*;
import java.util.List;

import me.neatmonster.spacebukkit.events.RequestEvent;
import me.neatmonster.spacebukkit.utilities.Utilities;
import me.neatmonster.spacemodule.api.InvalidArgumentsException;
import me.neatmonster.spacemodule.api.UnhandledActionException;

import org.bukkit.Bukkit;
import org.json.simple.JSONValue;
import java.lang.reflect.Field;

/**
 * Listens and accepts requests from the panel
 */
public class PanelListener extends Thread {

    private boolean running = true;

    /**
     * Interprets a raw command from the panel
     * @param string input from panel
     * @return result of the action
     * @throws InvalidArgumentsException Thrown when the wrong arguments are used by the panel
     * @throws UnhandledActionException Thrown when there is no handler for the action
     */
    @SuppressWarnings("unchecked")
    private static Object interpret(final String string)
            throws InvalidArgumentsException, UnhandledActionException {
        final int indexOfMethod = string.indexOf("?method=");
        final int indexOfArguments = string.indexOf("&args=");
        final int indexOfKey = string.indexOf("&key=");
        final String method = string.substring(indexOfMethod + 8, indexOfArguments);
        final String argumentsString = string.substring(indexOfArguments + 6, indexOfKey);
        final List<Object> arguments = (List<Object>) JSONValue.parse(argumentsString);
        try {
            if (SpaceBukkit.getInstance().actionsManager.contains(method))
                return SpaceBukkit.getInstance().actionsManager.execute(method, arguments.toArray());
            else {
                final RequestEvent event = new RequestEvent(method, arguments.toArray());
                Bukkit.getPluginManager().callEvent(event);
                return JSONValue.toJSONString(event.getResult());
            }
        } catch (final InvalidArgumentsException e) {
            e.printStackTrace();
        } catch (final UnhandledActionException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Interprets a raw command from the panel (multiple)
     * @param string input from panel
     * @return result of the action
     * @throws InvalidArgumentsException Thrown when the wrong arguments are used by the panel
     * @throws UnhandledActionException Thrown when there is no handler for the action
     */
    @SuppressWarnings("unchecked")
    private static Object interpretm(final String string)
            throws InvalidArgumentsException, UnhandledActionException {
        final int indexOfMethod = string.indexOf("?method=");
        final int indexOfArguments = string.indexOf("&args=");
        final int indexOfKey = string.indexOf("&key=");
        final String methodString = string.substring(indexOfMethod + 8, indexOfArguments);
        final String argumentsString = string.substring(indexOfArguments + 6, indexOfKey);
        final List<Object> methods = (List<Object>) JSONValue.parse(methodString);
        final List<Object> arguments = (List<Object>) JSONValue.parse(argumentsString);
        final List<Object> result = (List<Object>) JSONValue.parse("[]");
        for (int i = 0; i < methods.size(); i++) {
            String argsString = arguments.toArray()[i].toString();
            List<Object> args = (List<Object>) JSONValue.parse(argsString);
            try {
                if (SpaceBukkit.getInstance().actionsManager.contains(methods.toArray()[i].toString()))
                    result.add(SpaceBukkit.getInstance().actionsManager.execute(methods.toArray()[i].toString(),
                            args.toArray()));
                else {
                    final RequestEvent event = new RequestEvent(methods.toArray()[i].toString(), args.toArray());
                    Bukkit.getPluginManager().callEvent(event);
                    result.add(JSONValue.toJSONString(event.getResult()));
                }
            } catch (final InvalidArgumentsException e) {
                result.add(null);
                e.printStackTrace();
            } catch (final UnhandledActionException e) {
                result.add(null);
                e.printStackTrace();
            }

        }
        return result;
    }

    private static final int SO_BACKLOG = 128;
    private static final int SO_TIMEOUT = 30000; //30 seconds
    private final int mode;
    private ServerSocket serverSocket = null;
    private Socket socket;

    /**
     * Creates a new panel listener, listening for connections from a panel
     */
    public PanelListener() {
        mode = 0;
        start();
    }

    /**
     * Creates a new panel listener, listening for input from the socket
     * @param socket Socket to listen on
     */
    public PanelListener(final Socket socket) {
        mode = 1;
        this.socket = socket;
        start();
    }

    /**
     * Gets the mode the panel listener is in
     * 0 = Listening for opening connection from a panel
     * 1 = Listening for input from a socket
     * @return mode panel is in
     */
    public int getMode() {
        return mode;
    }

    @Override
    public void run() {
        if (mode == 0) {

            try {
                serverSocket = new ServerSocket(SpaceBukkit.getInstance().port, SO_BACKLOG,
                        SpaceBukkit.getInstance().bindAddress);
                serverSocket.setSoTimeout(SO_TIMEOUT);
            } catch (IOException e) {
                e.printStackTrace();
                return;
            }

            while (running && !serverSocket.isClosed()) {
                try {
                    final Socket clientSocket = serverSocket.accept();
                    new PanelListener(clientSocket);
                } catch (SocketTimeoutException e) {
                    // Do nothing.
                } catch (IOException e) {
                    if (!e.getMessage().toLowerCase().contains("socket closed"))
                        e.printStackTrace();
                }
            }
        } else {
            try {
                final BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String string = input.readLine();
                if (string == null) {
                    return;
                }
                string = URLDecoder.decode(string, "UTF-8");
                string = string.substring(5, string.length() - 9);
                final PrintWriter output = new PrintWriter(socket.getOutputStream());
                if (string.startsWith("call") && string.contains("?method=") && string.contains("&args=")) {
                    final String method = string.substring(12, string.indexOf("&args="));
                    if (string.contains("&key=" + Utilities.crypt(method + SpaceBukkit.getInstance().salt))) {
                        final Object result = interpret(string);
                        if (result != null)
                            try {
                                output.println(Utilities.addHeader(JSONValue.toJSONString(result)));
                            } catch (OutOfMemoryError e) {
                                System.gc();
                                output.println(Utilities.addHeader(null));
                            }
                        else
                            output.println(Utilities.addHeader(null));
                    } else
                        output.println(Utilities.addHeader("Incorrect Salt supplied. Access denied!"));
                } else if (string.startsWith("multiple") && string.contains("?method=")
                        && string.contains("&args=")) {
                    final String method = string.substring(16, string.indexOf("&args="));
                    if (string.contains("&key=" + Utilities.crypt(method + SpaceBukkit.getInstance().salt))) {
                        final Object result = interpretm(string);
                        if (result != null)
                            try {
                                output.println(Utilities.addHeader(JSONValue.toJSONString(result)));
                            } catch (OutOfMemoryError e) {
                                System.gc();
                                output.println(Utilities.addHeader(null));
                            }
                        else
                            output.println(Utilities.addHeader(null));
                    } else
                        output.println(Utilities.addHeader("Incorrect Salt supplied. Access denied!"));
                } else if (string.startsWith("ping"))
                    output.println(Utilities.addHeader("Pong!"));
                else
                    output.println(Utilities.addHeader(null));
                output.flush();
                input.close();
                output.close();
            } catch (final Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * Gracefully stops the listener
     * @throws IOException If the socket cannot be closed
     */
    public void stopServer() throws IOException {
        running = false;
        if (serverSocket != null) {
            serverSocket.close();
        }
    }

    public static String dump(Object object) {
        Field[] fields = object.getClass().getDeclaredFields();
        StringBuilder sb = new StringBuilder();
        sb.append(object.getClass().getSimpleName()).append('{');

        boolean firstRound = true;

        for (Field field : fields) {
            if (!firstRound) {
                sb.append(", ");
            }
            firstRound = false;
            field.setAccessible(true);
            try {
                final Object fieldObj = field.get(object);
                final String value;
                if (null == fieldObj) {
                    value = "null";
                } else {
                    value = fieldObj.toString();
                }
                sb.append(field.getName()).append('=').append('\'').append(value).append('\'');
            } catch (IllegalAccessException ignore) {
                //this should never happen
            }

        }

        sb.append('}');
        return sb.toString();
    }
}