1/*******************************************************************************
2 * Copyright (c) 2009, 2015 Mountainminds GmbH & Co. KG and Contributors
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 *    Marc R. Hoffmann - initial API and implementation
10 *
11 *******************************************************************************/
12package org.jacoco.agent.rt.internal.output;
13
14import java.io.IOException;
15import java.io.InterruptedIOException;
16import java.net.InetAddress;
17import java.net.ServerSocket;
18import java.net.Socket;
19import java.net.SocketAddress;
20import java.net.SocketException;
21import java.nio.channels.ServerSocketChannel;
22
23/**
24 * Emulation of a {@link ServerSocket} for testing purposes without any physical
25 * tcp/ip connections.
26 */
27public class MockServerSocket extends ServerSocket {
28
29	private final Object lock = new Object();
30
31	private boolean closed;
32
33	private Socket connection;
34
35	private boolean inAccept;
36
37	public MockServerSocket() throws IOException {
38		super();
39		closed = false;
40		inAccept = false;
41	}
42
43	/**
44	 * Establishes a new mock connection. This method blocks until the other end
45	 * of the connection has been accepted.
46	 *
47	 * @return remote end of the mock connection
48	 */
49	public Socket connect() throws Exception {
50		synchronized (lock) {
51			final MockSocketConnection c = new MockSocketConnection();
52			connection = c.getSocketA();
53			lock.notifyAll();
54			while (connection != null) {
55				lock.wait();
56			}
57			return c.getSocketB();
58		}
59	}
60
61	/**
62	 * Blocks until another thread calls the {@link #accept()} method.
63	 */
64	public void waitForAccept() throws Exception {
65		synchronized (lock) {
66			while (!inAccept) {
67				lock.wait();
68			}
69		}
70
71	}
72
73	@Override
74	public void close() throws IOException {
75		synchronized (lock) {
76			closed = true;
77			lock.notifyAll();
78		}
79	}
80
81	@Override
82	public boolean isClosed() {
83		return closed;
84	}
85
86	@Override
87	public Socket accept() throws IOException {
88		synchronized (lock) {
89			inAccept = true;
90			lock.notifyAll();
91			try {
92				while (connection == null) {
93					if (closed) {
94						throw new SocketException("socket closed");
95					}
96					lock.wait();
97				}
98				return connection;
99			} catch (InterruptedException e) {
100				throw new InterruptedIOException();
101			} finally {
102				connection = null;
103				inAccept = false;
104				lock.notifyAll();
105			}
106		}
107	}
108
109	// unsupported server socket methods:
110
111	@Override
112	public void bind(SocketAddress endpoint, int backlog) throws IOException {
113		throw new AssertionError();
114	}
115
116	@Override
117	public void bind(SocketAddress endpoint) throws IOException {
118		throw new AssertionError();
119	}
120
121	@Override
122	public ServerSocketChannel getChannel() {
123		throw new AssertionError();
124	}
125
126	@Override
127	public InetAddress getInetAddress() {
128		throw new AssertionError();
129	}
130
131	@Override
132	public int getLocalPort() {
133		throw new AssertionError();
134	}
135
136	@Override
137	public SocketAddress getLocalSocketAddress() {
138		throw new AssertionError();
139	}
140
141	@Override
142	public synchronized int getReceiveBufferSize() throws SocketException {
143		throw new AssertionError();
144	}
145
146	@Override
147	public boolean getReuseAddress() throws SocketException {
148		throw new AssertionError();
149	}
150
151	@Override
152	public synchronized int getSoTimeout() throws IOException {
153		throw new AssertionError();
154	}
155
156	@Override
157	public boolean isBound() {
158		throw new AssertionError();
159	}
160
161	@Override
162	public void setPerformancePreferences(int connectionTime, int latency,
163			int bandwidth) {
164		throw new AssertionError();
165	}
166
167	@Override
168	public synchronized void setReceiveBufferSize(int size)
169			throws SocketException {
170		throw new AssertionError();
171	}
172
173	@Override
174	public void setReuseAddress(boolean on) throws SocketException {
175		throw new AssertionError();
176	}
177
178	@Override
179	public synchronized void setSoTimeout(int timeout) throws SocketException {
180		throw new AssertionError();
181	}
182
183	@Override
184	public String toString() {
185		throw new AssertionError();
186	}
187
188}
189