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.net.Socket; 16 import java.net.SocketException; 17 18 import org.jacoco.core.runtime.IRemoteCommandVisitor; 19 import org.jacoco.core.runtime.RemoteControlReader; 20 import org.jacoco.core.runtime.RemoteControlWriter; 21 import org.jacoco.core.runtime.RuntimeData; 22 23 /** 24 * Handler for a single socket based remote connection. 25 */ 26 class TcpConnection implements IRemoteCommandVisitor { 27 28 private final RuntimeData data; 29 30 private final Socket socket; 31 32 private RemoteControlWriter writer; 33 34 private RemoteControlReader reader; 35 36 private boolean initialized; 37 38 public TcpConnection(final Socket socket, final RuntimeData data) { 39 this.socket = socket; 40 this.data = data; 41 this.initialized = false; 42 } 43 44 public void init() throws IOException { 45 this.writer = new RemoteControlWriter(socket.getOutputStream()); 46 this.reader = new RemoteControlReader(socket.getInputStream()); 47 this.reader.setRemoteCommandVisitor(this); 48 this.initialized = true; 49 } 50 51 /** 52 * Processes all requests for this session until the socket is closed. 53 * 54 * @throws IOException 55 * in case of problems whith the connection 56 */ 57 public void run() throws IOException { 58 try { 59 while (reader.read()) { 60 } 61 } catch (final SocketException e) { 62 // If the local socket is closed while polling for commands the 63 // SocketException is expected. 64 if (!socket.isClosed()) { 65 throw e; 66 } 67 } finally { 68 close(); 69 } 70 } 71 72 /** 73 * Dumps the current execution data if the connection is already initialized 74 * and the underlying socket is still open. 75 * 76 * @param reset 77 * if <code>true</code> execution data is cleared afterwards 78 * @throws IOException 79 */ 80 public void writeExecutionData(final boolean reset) throws IOException { 81 if (initialized && !socket.isClosed()) { 82 visitDumpCommand(true, reset); 83 } 84 } 85 86 /** 87 * Closes the underlying socket if not closed yet. 88 * 89 * @throws IOException 90 */ 91 public void close() throws IOException { 92 if (!socket.isClosed()) { 93 socket.close(); 94 } 95 } 96 97 // === IRemoteCommandVisitor === 98 99 public void visitDumpCommand(final boolean dump, final boolean reset) 100 throws IOException { 101 if (dump) { 102 data.collect(writer, writer, reset); 103 } else { 104 if (reset) { 105 data.reset(); 106 } 107 } 108 writer.sendCmdOk(); 109 } 110 111 } 112