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