Java tutorial
/* * This file is part of SpaceRTK (http://SpaceRTK.xereo.net/). * * SpaceRTK 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. * * SpaceRTK 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.spacertk; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketTimeoutException; import java.net.URLDecoder; import java.util.List; import me.neatmonster.spacemodule.api.InvalidArgumentsException; import me.neatmonster.spacemodule.api.UnhandledActionException; import me.neatmonster.spacertk.utilities.Utilities; import me.neatmonster.spacertk.utilities.ZIP; import org.json.simple.JSONValue; /** * Listens and accepts requests from the panel */ public class PanelListener extends Thread { /** * 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 (SpaceRTK.getInstance().actionsManager.contains(method)) return SpaceRTK.getInstance().actionsManager.execute(method, arguments.toArray()); } 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 (SpaceRTK.getInstance().actionsManager.contains(methods.toArray()[i].toString())) result.add(SpaceRTK.getInstance().actionsManager.execute(methods.toArray()[i].toString(), args.toArray())); } 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(SpaceRTK.getInstance().rPort, SO_BACKLOG, SpaceRTK.getInstance().bindAddress); serverSocket.setSoTimeout(SO_TIMEOUT); } catch (IOException e) { e.printStackTrace(); return; } while (!serverSocket.isClosed()) { try { final Socket clientSocket = serverSocket.accept(); new PanelListener(clientSocket); } catch (SocketTimeoutException e) { // Do nothing. } catch (Exception e) { if (!e.getMessage().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 + SpaceRTK.getInstance().salt))) { if (string.startsWith("call?method=DOWNLOAD_WORLD")) { final boolean wasRunning = RemoteToolkit.isRunning(); if (wasRunning) RemoteToolkit.hold(); final File file = new File(string.split("\"")[1] + ".zip"); ZIP.zip(file, new File(string.split("\"")[1])); if (file.exists()) { final FileInputStream fileInputStream = new FileInputStream(file); final byte[] fileData = new byte[65536]; int length; output.println("HTTP/1.1 200 OK"); output.println("Content-Type: application/force-download; name=" + file.getName()); output.println("Content-Transfer-Encoding: binary"); output.println("Content-Length:" + file.length()); output.println("Content-Disposition: attachment; filename=" + file.getName()); output.println("Expires: 0"); output.println("Cache-Control: no-cache, must-revalidate"); output.println("Pragma: no-cache"); while ((length = fileInputStream.read(fileData)) > 0) output.print(new String(fileData, 0, length)); fileInputStream.close(); } else output.println(Utilities.addHeader(null)); if (wasRunning) RemoteToolkit.unhold(); } else { 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 + SpaceRTK.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 { if (serverSocket != null) serverSocket.close(); } }