package org.zend.php.zendserver.deployment.ui.chrome; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.net.URISyntaxException; import org.zend.php.zendserver.deployment.ui.Activator; /** * Listens for requests on network socket and executes Eclipse commands. Request * to execute a command should contain command id in the request path last * segment. Parameters passed in request query will be provided in command * execution event. For example: * * http://127.0.0.1/org.zend.php.deployment.debug.OpenSshTunnel?container= * myContainer * * invokes org.zend.php.deploymentdebug.OpenSshTunnel with single param * "container". * */ public class SocketCommandListener { private Thread listeningThread; private static final int port = 28029; private CommandHandler handler = new CommandHandler(); public void start() { listeningThread = new Thread(new Runnable() { public void run() { ServerSocket serverSocket = null; try { serverSocket = openServerSocket(port); } catch (IOException ex) { Activator.log(ex); return; } try { serverLoop(serverSocket); } finally { try { serverSocket.close(); } catch (IOException ex) { Activator.log(ex); } } } }); listeningThread.start(); } protected ServerSocket openServerSocket(int port2) throws IOException { int tries = 3; IOException ex = null; while (tries > 0) { tries--; try { return new ServerSocket(port); } catch (IOException e) { ex = e; if (tries > 0) { try { Thread.sleep(5000); } catch (InterruptedException e1) { // ignore } } } } throw ex; } private void serverLoop(ServerSocket serverSocket) { while (true) { Socket clientSocket = null; BufferedReader in = null; PrintWriter out = null; try { clientSocket = serverSocket.accept(); out = new PrintWriter(clientSocket.getOutputStream(), true); in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); handleClientSocket(in, out); } catch (Throwable ex) { // eat all exceptions to protect server from falling Activator.log(ex); } finally { try { if (in != null) { in.close(); } if (out != null) { out.close(); } if (clientSocket != null) { clientSocket.close(); } } catch (IOException ex) { Activator.log(ex); } } } } private void handleClientSocket(BufferedReader in, PrintWriter out) throws IOException { HttpResponse response = new HttpResponse(out); try { HttpRequest request = readRequest(in); if (request == null) { return; } handler.handle(request, response); } catch (Throwable e) { response.setStatus(HttpResponse.ERROR); response.send(null); } } private HttpRequest readRequest(BufferedReader in) throws IOException, ParseError { HttpRequest httpRequest = new HttpRequest(); String request = in.readLine(); if (request == null) { return null; } int idx = request.indexOf(' '); if (idx == -1) { throw new ParseError(); } String method = request.substring(0, idx); httpRequest.setMethod(method); int idx2 = request.indexOf(' ', idx + 1); if (idx2 == -1) { throw new ParseError(); } String requestPath = request.substring(idx + 1, idx2); try { httpRequest.setRequest(requestPath); } catch (URISyntaxException e) { throw new ParseError(); } String inputLine; while (((inputLine = in.readLine()) != null) && (inputLine.length() > 0)) { int colon = inputLine.indexOf(':'); if (colon == -1) { throw new ParseError(); } String key = inputLine.substring(0, colon); String value = inputLine.substring(colon + 1).trim(); httpRequest.getHeaders().put(key, value); } StringBuilder body = new StringBuilder(); char[] buf = new char[4096]; int len; while (in.ready() && ((len = in.read(buf)) > 0)) { body.append(buf, 0, len); } httpRequest.setBody(body.toString()); return httpRequest; } public void stop() { if (listeningThread != null) { listeningThread.interrupt(); } } }