Home | History | Annotate | Download | only in output
      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