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