| /******************************************************************************* |
| * Copyright (c) 2006, 2008 Steffen Pingel and others. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * https://www.eclipse.org/legal/epl-2.0 |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Steffen Pingel - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.mylyn.trac.tests.support; |
| |
| import java.io.BufferedReader; |
| import java.io.BufferedWriter; |
| import java.io.EOFException; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.InputStreamReader; |
| import java.io.InterruptedIOException; |
| import java.io.OutputStream; |
| import java.io.OutputStreamWriter; |
| import java.net.ServerSocket; |
| import java.net.Socket; |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.StringTokenizer; |
| |
| public class TestProxy implements Runnable { |
| |
| public static final String NOT_FOUND = "HTTP/1.1 404 Not Found"; |
| |
| private int listenPort; |
| |
| private Message request; |
| |
| private Message response; |
| |
| private Thread runner; |
| |
| private IOException exception; |
| |
| private volatile boolean stopped = false; |
| |
| public TestProxy(int listenPort) { |
| this.listenPort = listenPort; |
| } |
| |
| public TestProxy() { |
| } |
| |
| public synchronized int getListenPort() throws InterruptedException { |
| while (listenPort == 0) { |
| wait(); |
| } |
| return listenPort; |
| } |
| |
| public void start() { |
| runner = new Thread(this, "TestProxy :" + listenPort); |
| runner.start(); |
| } |
| |
| public int startAndWait() throws InterruptedException { |
| start(); |
| int port = getListenPort(); |
| // wait for socket to enter accept call |
| Thread.sleep(100); |
| return port; |
| } |
| |
| public void run() { |
| ServerSocket serverSocket = null; |
| try { |
| serverSocket = new ServerSocket(listenPort); |
| synchronized (this) { |
| listenPort = serverSocket.getLocalPort(); |
| notifyAll(); |
| } |
| while (!stopped) { |
| Socket socket = serverSocket.accept(); |
| try { |
| Message request = readMessage(socket.getInputStream()); |
| setRequest(request); |
| |
| Message response = waitForResponse(); |
| writeMessage(response, socket.getOutputStream()); |
| } finally { |
| try { |
| socket.close(); |
| } catch (IOException e1) { |
| } |
| } |
| } |
| } catch (InterruptedIOException e) { |
| } catch (IOException e) { |
| setException(e); |
| } catch (InterruptedException e) { |
| } finally { |
| if (serverSocket != null) { |
| try { |
| serverSocket.close(); |
| } catch (IOException e) { |
| } |
| } |
| } |
| |
| } |
| |
| private void writeMessage(Message message, OutputStream out) throws IOException { |
| BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out)); |
| writer.write(message.toString()); |
| } |
| |
| private synchronized void setException(IOException exception) { |
| this.exception = exception; |
| notifyAll(); |
| } |
| |
| public synchronized void checkForException() throws IOException { |
| if (exception != null) { |
| throw exception; |
| } |
| } |
| |
| private Message readMessage(InputStream in) throws IOException { |
| BufferedReader reader = new BufferedReader(new InputStreamReader(in)); |
| Message message = null; |
| String line; |
| while ((line = reader.readLine()) != null) { |
| if (line.length() == 0) { |
| if (message == null) { |
| throw new IOException("Incomplete message"); |
| } |
| return message; |
| } |
| |
| if (message == null) { |
| message = new Message(line); |
| } else { |
| StringTokenizer t = new StringTokenizer(line, ":"); |
| message.headers.put(t.nextToken(), t.nextToken().trim()); |
| } |
| } |
| throw new EOFException(); |
| } |
| |
| public void stop() { |
| stopped = true; |
| runner.interrupt(); |
| try { |
| runner.join(500); |
| } catch (InterruptedException e) { |
| } |
| } |
| |
| public Message getRequest() { |
| return request; |
| } |
| |
| public synchronized Message waitForRequest() throws InterruptedException { |
| while (request == null) { |
| wait(); |
| } |
| return request; |
| } |
| |
| public synchronized Message waitForResponse() throws InterruptedException { |
| while (response == null) { |
| wait(); |
| } |
| return response; |
| } |
| |
| public synchronized void setResponse(Message response) { |
| this.response = response; |
| notifyAll(); |
| } |
| |
| public synchronized void setResponse(String response) { |
| this.response = new Message(response); |
| notifyAll(); |
| } |
| |
| public synchronized void setRequest(Message request) { |
| this.request = request; |
| notifyAll(); |
| } |
| |
| public static class Message { |
| |
| public Message(String request) { |
| this.request = request; |
| } |
| |
| public String request; |
| |
| public Map<String, String> headers = new HashMap<String, String>(); |
| |
| @Override |
| public String toString() { |
| StringBuilder sb = new StringBuilder(); |
| sb.append(request); |
| sb.append("\n"); |
| if (headers != null) { |
| for (String key : headers.keySet()) { |
| sb.append(key + ": " + headers.get(key)); |
| sb.append("\n"); |
| } |
| } |
| sb.append("\n"); |
| return sb.toString(); |
| } |
| |
| public String getMethod() { |
| int i = request.indexOf(" "); |
| return (i != -1) ? request.substring(0, i) : request; |
| } |
| |
| } |
| |
| public static void main(String[] args) { |
| TestProxy proxy = new TestProxy(8080); |
| proxy.start(); |
| try { |
| proxy.setResponse(new Message("404 / HTTP 1.1")); |
| try { |
| System.out.println(proxy.waitForRequest()); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| } finally { |
| proxy.stop(); |
| } |
| |
| } |
| |
| } |