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