1 /******************************************************************************* 2 * Copyright (c) 2009, 2021 Mountainminds GmbH & Co. KG and Contributors 3 * This program and the accompanying materials are made available under 4 * the terms of the Eclipse Public License 2.0 which is available at 5 * http://www.eclipse.org/legal/epl-2.0 6 * 7 * SPDX-License-Identifier: EPL-2.0 8 * 9 * Contributors: 10 * Marc R. Hoffmann - initial API and implementation 11 * 12 *******************************************************************************/ 13 package org.jacoco.examples; 14 15 import java.io.FileOutputStream; 16 import java.io.IOException; 17 import java.net.InetAddress; 18 import java.net.ServerSocket; 19 import java.net.Socket; 20 21 import org.jacoco.core.data.ExecutionData; 22 import org.jacoco.core.data.ExecutionDataWriter; 23 import org.jacoco.core.data.IExecutionDataVisitor; 24 import org.jacoco.core.data.ISessionInfoVisitor; 25 import org.jacoco.core.data.SessionInfo; 26 import org.jacoco.core.runtime.RemoteControlReader; 27 import org.jacoco.core.runtime.RemoteControlWriter; 28 29 /** 30 * This example starts a socket server to collect coverage from agents that run 31 * in output mode <code>tcpclient</code>. The collected data is dumped to a 32 * local file. 33 */ 34 public final class ExecutionDataServer { 35 36 private static final String DESTFILE = "jacoco-server.exec"; 37 38 private static final String ADDRESS = "localhost"; 39 40 private static final int PORT = 6300; 41 42 /** 43 * Start the server as a standalone program. 44 * 45 * @param args 46 * @throws IOException 47 */ main(final String[] args)48 public static void main(final String[] args) throws IOException { 49 final ExecutionDataWriter fileWriter = new ExecutionDataWriter( 50 new FileOutputStream(DESTFILE)); 51 final ServerSocket server = new ServerSocket(PORT, 0, 52 InetAddress.getByName(ADDRESS)); 53 while (true) { 54 final Handler handler = new Handler(server.accept(), fileWriter); 55 new Thread(handler).start(); 56 } 57 } 58 59 private static class Handler 60 implements Runnable, ISessionInfoVisitor, IExecutionDataVisitor { 61 62 private final Socket socket; 63 64 private final RemoteControlReader reader; 65 66 private final ExecutionDataWriter fileWriter; 67 Handler(final Socket socket, final ExecutionDataWriter fileWriter)68 Handler(final Socket socket, final ExecutionDataWriter fileWriter) 69 throws IOException { 70 this.socket = socket; 71 this.fileWriter = fileWriter; 72 73 // Just send a valid header: 74 new RemoteControlWriter(socket.getOutputStream()); 75 76 reader = new RemoteControlReader(socket.getInputStream()); 77 reader.setSessionInfoVisitor(this); 78 reader.setExecutionDataVisitor(this); 79 } 80 run()81 public void run() { 82 try { 83 while (reader.read()) { 84 } 85 socket.close(); 86 synchronized (fileWriter) { 87 fileWriter.flush(); 88 } 89 } catch (final IOException e) { 90 e.printStackTrace(); 91 } 92 } 93 visitSessionInfo(final SessionInfo info)94 public void visitSessionInfo(final SessionInfo info) { 95 System.out.printf("Retrieving execution Data for session: %s%n", 96 info.getId()); 97 synchronized (fileWriter) { 98 fileWriter.visitSessionInfo(info); 99 } 100 } 101 visitClassExecution(final ExecutionData data)102 public void visitClassExecution(final ExecutionData data) { 103 synchronized (fileWriter) { 104 fileWriter.visitClassExecution(data); 105 } 106 } 107 } 108 ExecutionDataServer()109 private ExecutionDataServer() { 110 } 111 } 112