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.InetAddress;
     16 import java.net.ServerSocket;
     17 import java.net.UnknownHostException;
     18 
     19 import org.jacoco.agent.rt.internal.IExceptionLogger;
     20 import org.jacoco.core.runtime.AgentOptions;
     21 import org.jacoco.core.runtime.RuntimeData;
     22 
     23 /**
     24  * Output that opens TCP server socket. This controller uses the following agent
     25  * options:
     26  * <ul>
     27  * <li>address</li>
     28  * <li>port</li>
     29  * </ul>
     30  */
     31 public class TcpServerOutput implements IAgentOutput {
     32 
     33 	private TcpConnection connection;
     34 
     35 	private final IExceptionLogger logger;
     36 
     37 	private ServerSocket serverSocket;
     38 
     39 	private Thread worker;
     40 
     41 	/**
     42 	 * New controller instance.
     43 	 *
     44 	 * @param logger
     45 	 *            logger to use in case of exceptions is spawned threads
     46 	 */
     47 	public TcpServerOutput(final IExceptionLogger logger) {
     48 		this.logger = logger;
     49 	}
     50 
     51 	public void startup(final AgentOptions options, final RuntimeData data)
     52 			throws IOException {
     53 		serverSocket = createServerSocket(options);
     54 		worker = new Thread(new Runnable() {
     55 			public void run() {
     56 				while (!serverSocket.isClosed()) {
     57 					try {
     58 						synchronized (serverSocket) {
     59 							connection = new TcpConnection(
     60 									serverSocket.accept(), data);
     61 						}
     62 						connection.init();
     63 						connection.run();
     64 					} catch (final IOException e) {
     65 						// If the serverSocket is closed while accepting
     66 						// connections a SocketException is expected.
     67 						if (!serverSocket.isClosed()) {
     68 							logger.logExeption(e);
     69 						}
     70 					}
     71 				}
     72 			}
     73 		});
     74 		worker.setName(getClass().getName());
     75 		worker.setDaemon(true);
     76 		worker.start();
     77 	}
     78 
     79 	public void shutdown() throws Exception {
     80 		serverSocket.close();
     81 		synchronized (serverSocket) {
     82 			if (connection != null) {
     83 				connection.close();
     84 			}
     85 		}
     86 		worker.join();
     87 	}
     88 
     89 	public void writeExecutionData(final boolean reset) throws IOException {
     90 		if (connection != null) {
     91 			connection.writeExecutionData(reset);
     92 		}
     93 	}
     94 
     95 	/**
     96 	 * Open a server socket based on the given configuration.
     97 	 *
     98 	 * @param options
     99 	 *            address and port configuration
    100 	 * @return opened server socket
    101 	 * @throws IOException
    102 	 */
    103 	protected ServerSocket createServerSocket(final AgentOptions options)
    104 			throws IOException {
    105 		final InetAddress inetAddr = getInetAddress(options.getAddress());
    106 		return new ServerSocket(options.getPort(), 1, inetAddr);
    107 	}
    108 
    109 	/**
    110 	 * Returns the {@link InetAddress} object to open the server socket on.
    111 	 *
    112 	 * @param address
    113 	 *            address specified as a string
    114 	 * @return address to open the server socket
    115 	 * @throws UnknownHostException
    116 	 */
    117 	protected InetAddress getInetAddress(final String address)
    118 			throws UnknownHostException {
    119 		if ("*".equals(address)) {
    120 			return null;
    121 		} else {
    122 			return InetAddress.getByName(address);
    123 		}
    124 	}
    125 
    126 }
    127