1d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann/******************************************************************************* 2b9d1b54e300318b470d9fedccc69d75187016444Evgeny Mandrikov * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors 3d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * All rights reserved. This program and the accompanying materials 4d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * are made available under the terms of the Eclipse Public License v1.0 5d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * which accompanies this distribution, and is available at 6d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * http://www.eclipse.org/legal/epl-v10.html 7d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * 8d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * Contributors: 9d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * Marc R. Hoffmann - initial API and implementation 10d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * 11d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann *******************************************************************************/ 12d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmannpackage org.jacoco.core.tools; 13d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann 14d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmannimport java.io.IOException; 15d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmannimport java.io.InterruptedIOException; 16d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmannimport java.net.InetAddress; 17d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmannimport java.net.Socket; 18d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann 19d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmannimport org.jacoco.core.runtime.RemoteControlReader; 20d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmannimport org.jacoco.core.runtime.RemoteControlWriter; 21d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann 22d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann/** 23d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * A client for remote execution data dumps. 24d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann */ 25d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmannpublic class ExecDumpClient { 26d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann 27d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann private boolean dump; 28d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann private boolean reset; 29d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann private int retryCount; 30d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann private long retryDelay; 31d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann 32d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann /** 33d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * New instance with the defaults <code>dump==true</code>, 34d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * <code>reset==false</code>, <code>retryCount==0</code> and 35d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * <code>retryDelay=1000</code>. 36d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann */ 37d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann public ExecDumpClient() { 38d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann this.dump = true; 39d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann this.reset = false; 40d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann this.retryCount = 0; 41d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann this.setRetryDelay(1000); 42d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann } 43d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann 44d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann /** 45d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * Specifies whether a dump should be requested 46d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * 47d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * @param dump 48d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * <code>true</code> if a dump should be requested 49d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann */ 50d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann public void setDump(final boolean dump) { 51d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann this.dump = dump; 52d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann } 53d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann 54d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann /** 55d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * Specifies whether execution data should be reset. 56d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * 57d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * @param reset 58d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * <code>true</code> if execution data should be reset 59d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann */ 60d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann public void setReset(final boolean reset) { 61d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann this.reset = reset; 62d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann } 63d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann 64d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann /** 65d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * Sets the number of retry attempts to connect to the target socket. This 66d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * allows to wait for a certain time until the target agent has initialized. 67d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * 68d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * @param retryCount 69d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * number of retries 70d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann */ 71d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann public void setRetryCount(final int retryCount) { 72d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann this.retryCount = retryCount; 73d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann } 74d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann 75d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann /** 76d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * Sets the delay time before between connection attempts. 77d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * 78d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * @param retryDelay 79d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * delay in milliseconds 80d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann */ 81d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann public void setRetryDelay(final long retryDelay) { 82d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann this.retryDelay = retryDelay; 83d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann } 84d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann 85d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann /** 86d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * Requests a dump from the given end-point. 87d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * 88d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * @param address 89d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * IP-Address to connect to 90d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * @param port 91d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * port to connect to 92d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * @return container for the dumped data 93d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * @throws IOException 94d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * in case the dump can not be requested 95d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann */ 96d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann public ExecFileLoader dump(final String address, final int port) 97d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann throws IOException { 98d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann return dump(InetAddress.getByName(address), port); 99d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann } 100d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann 101d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann /** 102d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * Requests a dump from the given end-point. 103d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * 104d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * @param address 105d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * host name or IP-Address to connect to 106d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * @param port 107d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * port to connect to 108d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * @return container for the dumped data 109d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * @throws IOException 110d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * in case the dump can not be requested 111d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann */ 112d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann public ExecFileLoader dump(final InetAddress address, final int port) 113d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann throws IOException { 114d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann final ExecFileLoader loader = new ExecFileLoader(); 115d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann final Socket socket = tryConnect(address, port); 116d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann try { 117d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann final RemoteControlWriter remoteWriter = new RemoteControlWriter( 118d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann socket.getOutputStream()); 119d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann final RemoteControlReader remoteReader = new RemoteControlReader( 120d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann socket.getInputStream()); 121d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann remoteReader.setSessionInfoVisitor(loader.getSessionInfoStore()); 122d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann remoteReader 123d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann .setExecutionDataVisitor(loader.getExecutionDataStore()); 124d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann 125d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann remoteWriter.visitDumpCommand(dump, reset); 12610f3ff0dd010d647625ef5937f301126250267d0Marc R. Hoffmann 12710f3ff0dd010d647625ef5937f301126250267d0Marc R. Hoffmann if (!remoteReader.read()) { 12810f3ff0dd010d647625ef5937f301126250267d0Marc R. Hoffmann throw new IOException("Socket closed unexpectedly."); 12910f3ff0dd010d647625ef5937f301126250267d0Marc R. Hoffmann } 130d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann 131d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann } finally { 132d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann socket.close(); 133d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann } 134d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann return loader; 135d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann } 136d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann 137d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann private Socket tryConnect(final InetAddress address, final int port) 138d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann throws IOException { 139d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann int count = 0; 140d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann while (true) { 141d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann try { 142d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann onConnecting(address, port); 143d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann return new Socket(address, port); 144d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann } catch (final IOException e) { 145d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann if (++count > retryCount) { 146d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann throw e; 147d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann } 148d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann onConnectionFailure(e); 149d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann sleep(); 150d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann } 151d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann } 152d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann } 153d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann 154d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann private void sleep() throws InterruptedIOException { 155d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann try { 156d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann Thread.sleep(retryDelay); 157d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann } catch (final InterruptedException e) { 158d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann throw new InterruptedIOException(); 159d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann } 160d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann } 161d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann 162d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann /** 163d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * This method can be overwritten to get an event just before a connection 164d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * is made. 165d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * 166d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * @param address 167d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * target address 168d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * @param port 169d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * target port 170d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann */ 171d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann protected void onConnecting( 172d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann @SuppressWarnings("unused") final InetAddress address, 173d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann @SuppressWarnings("unused") final int port) { 174d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann } 175d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann 176d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann /** 177d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * This method can be overwritten to get an event for connection failures 178d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * when another retry will be attempted. 179d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * 180d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * @param exception 181d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann * connection error 182d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann */ 183d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann protected void onConnectionFailure( 184d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann @SuppressWarnings("unused") final IOException exception) { 185d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann } 186d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann 187d3982ef1fff1bf2168f63a6d41102def386fd180Marc R. Hoffmann} 188