1 /******************************************************************************* 2 * Copyright (c) 2009, 2018 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 *******************************************************************************/ 12 package org.jacoco.agent.rt.internal.output; 13 14 import java.io.IOException; 15 import java.io.InputStream; 16 import java.io.InterruptedIOException; 17 import java.io.OutputStream; 18 import java.net.InetAddress; 19 import java.net.Socket; 20 import java.net.SocketAddress; 21 import java.net.SocketException; 22 import java.net.SocketImpl; 23 import java.nio.channels.SocketChannel; 24 import java.util.Queue; 25 import java.util.concurrent.ConcurrentLinkedQueue; 26 27 /** 28 * Simulates two connected {@link Socket} objects. No physical connection is 29 * established for this. The behavior includes the (inconsistent) exception 30 * messages have been derived from Sun JDK 1.5.0_18-b02. 31 */ 32 public class MockSocketConnection { 33 34 private final MockSocket socketA; 35 36 private final MockSocket socketB; 37 38 public MockSocketConnection() throws SocketException { 39 socketA = new MockSocket(); 40 socketB = new MockSocket(); 41 socketA.connect(socketB); 42 } 43 44 public MockSocket getSocketA() { 45 return socketA; 46 } 47 48 public MockSocket getSocketB() { 49 return socketB; 50 } 51 52 class MockSocket extends Socket { 53 54 private MockSocket other; 55 56 private boolean closed; 57 58 private final Queue<Byte> buffer = new ConcurrentLinkedQueue<Byte>(); 59 60 private final OutputStream out = new OutputStream() { 61 62 @Override 63 public void write(int b) throws IOException { 64 if (closed) { 65 throw new SocketException("Socket closed"); 66 } 67 synchronized (other.buffer) { 68 other.buffer.add(Byte.valueOf((byte) b)); 69 other.buffer.notifyAll(); 70 } 71 } 72 }; 73 74 private final InputStream in = new InputStream() { 75 76 @Override 77 public int read() throws IOException { 78 synchronized (buffer) { 79 try { 80 while (true) { 81 if (closed) { 82 throw new SocketException("socket closed"); 83 } 84 if (other.closed) { 85 return -1; 86 } 87 final Byte b = buffer.poll(); 88 buffer.notifyAll(); 89 if (b != null) { 90 return 0xff & b.intValue(); 91 } 92 buffer.wait(); 93 } 94 } catch (InterruptedException e) { 95 throw new InterruptedIOException(); 96 } 97 } 98 } 99 100 @Override 101 public int available() throws IOException { 102 synchronized (buffer) { 103 return buffer.size(); 104 } 105 } 106 107 }; 108 109 private MockSocket() throws SocketException { 110 super((SocketImpl) null); 111 closed = false; 112 } 113 114 private void connect(MockSocket other) { 115 this.other = other; 116 other.other = this; 117 } 118 119 public void waitUntilInputBufferIsEmpty() throws InterruptedException { 120 synchronized (buffer) { 121 while (!closed && !buffer.isEmpty()) { 122 buffer.wait(); 123 } 124 } 125 } 126 127 // socket methods with mocking behavior: 128 129 @Override 130 public OutputStream getOutputStream() throws IOException { 131 if (isClosed()) { 132 throw new SocketException("Socket is closed"); 133 } 134 return out; 135 } 136 137 @Override 138 public InputStream getInputStream() throws IOException { 139 if (isClosed()) { 140 throw new SocketException("Socket is closed"); 141 } 142 return in; 143 } 144 145 @Override 146 public void close() throws IOException { 147 synchronized (buffer) { 148 closed = true; 149 buffer.notifyAll(); 150 } 151 synchronized (other.buffer) { 152 other.buffer.notifyAll(); 153 } 154 } 155 156 @Override 157 public boolean isClosed() { 158 synchronized (buffer) { 159 return closed; 160 } 161 } 162 163 // unsupported socket methods: 164 165 @Override 166 public void bind(SocketAddress bindpoint) throws IOException { 167 throw new AssertionError(); 168 } 169 170 @Override 171 public void connect(SocketAddress endpoint, int timeout) 172 throws IOException { 173 throw new AssertionError(); 174 } 175 176 @Override 177 public void connect(SocketAddress endpoint) throws IOException { 178 throw new AssertionError(); 179 } 180 181 @Override 182 public SocketChannel getChannel() { 183 throw new AssertionError(); 184 } 185 186 @Override 187 public InetAddress getInetAddress() { 188 throw new AssertionError(); 189 } 190 191 @Override 192 public boolean getKeepAlive() throws SocketException { 193 throw new AssertionError(); 194 } 195 196 @Override 197 public InetAddress getLocalAddress() { 198 throw new AssertionError(); 199 } 200 201 @Override 202 public int getLocalPort() { 203 throw new AssertionError(); 204 } 205 206 @Override 207 public SocketAddress getLocalSocketAddress() { 208 throw new AssertionError(); 209 } 210 211 @Override 212 public boolean getOOBInline() throws SocketException { 213 throw new AssertionError(); 214 } 215 216 @Override 217 public int getPort() { 218 throw new AssertionError(); 219 } 220 221 @Override 222 public synchronized int getReceiveBufferSize() throws SocketException { 223 throw new AssertionError(); 224 } 225 226 @Override 227 public SocketAddress getRemoteSocketAddress() { 228 throw new AssertionError(); 229 } 230 231 @Override 232 public boolean getReuseAddress() throws SocketException { 233 throw new AssertionError(); 234 } 235 236 @Override 237 public synchronized int getSendBufferSize() throws SocketException { 238 throw new AssertionError(); 239 } 240 241 @Override 242 public int getSoLinger() throws SocketException { 243 throw new AssertionError(); 244 } 245 246 @Override 247 public synchronized int getSoTimeout() throws SocketException { 248 throw new AssertionError(); 249 } 250 251 @Override 252 public boolean getTcpNoDelay() throws SocketException { 253 throw new AssertionError(); 254 } 255 256 @Override 257 public int getTrafficClass() throws SocketException { 258 throw new AssertionError(); 259 } 260 261 @Override 262 public boolean isBound() { 263 throw new AssertionError(); 264 } 265 266 @Override 267 public boolean isConnected() { 268 throw new AssertionError(); 269 } 270 271 @Override 272 public boolean isInputShutdown() { 273 throw new AssertionError(); 274 } 275 276 @Override 277 public boolean isOutputShutdown() { 278 throw new AssertionError(); 279 } 280 281 @Override 282 public void sendUrgentData(int data) throws IOException { 283 throw new AssertionError(); 284 } 285 286 @Override 287 public void setKeepAlive(boolean on) throws SocketException { 288 throw new AssertionError(); 289 } 290 291 @Override 292 public void setOOBInline(boolean on) throws SocketException { 293 throw new AssertionError(); 294 } 295 296 @Override 297 public void setPerformancePreferences(int connectionTime, int latency, 298 int bandwidth) { 299 throw new AssertionError(); 300 } 301 302 @Override 303 public synchronized void setReceiveBufferSize(int size) 304 throws SocketException { 305 throw new AssertionError(); 306 } 307 308 @Override 309 public void setReuseAddress(boolean on) throws SocketException { 310 throw new AssertionError(); 311 } 312 313 @Override 314 public synchronized void setSendBufferSize(int size) 315 throws SocketException { 316 throw new AssertionError(); 317 } 318 319 @Override 320 public void setSoLinger(boolean on, int linger) throws SocketException { 321 throw new AssertionError(); 322 } 323 324 @Override 325 public synchronized void setSoTimeout(int timeout) 326 throws SocketException { 327 throw new AssertionError(); 328 } 329 330 @Override 331 public void setTcpNoDelay(boolean on) throws SocketException { 332 throw new AssertionError(); 333 } 334 335 @Override 336 public void setTrafficClass(int tc) throws SocketException { 337 throw new AssertionError(); 338 } 339 340 @Override 341 public void shutdownInput() throws IOException { 342 throw new AssertionError(); 343 } 344 345 @Override 346 public void shutdownOutput() throws IOException { 347 throw new AssertionError(); 348 } 349 350 } 351 352 } 353