package org.arquillian.cube.docker.impl.await;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import org.arquillian.cube.docker.impl.client.config.Await;
import org.arquillian.cube.docker.impl.docker.DockerClientExecutor;
import org.arquillian.cube.docker.impl.util.Ping;
import org.arquillian.cube.docker.impl.util.PingCommand;
import org.arquillian.cube.impl.util.IOUtil;
import org.arquillian.cube.spi.Cube;
public class HttpAwaitStrategy extends SleepingAwaitStrategyBase {
public static final String TAG = "http";
private static final String REGEXP_PREFIX = "regexp:";
public static final String DOCKER_HOST = "dockerHost";
private static final int DEFAULT_POLL_ITERATIONS = 10;
private int pollIterations = DEFAULT_POLL_ITERATIONS;
private URL url = null;
private int responseCode = 200;
private Map<String, Object> headers;
private String matcher;
private Cube<?> cube;
private DockerClientExecutor dockerClientExecutor;
private HttpURLConnection urlConnection;
public HttpAwaitStrategy(Cube<?> cube, DockerClientExecutor dockerClientExecutor, Await params) {
super(params.getSleepPollingTime());
this.cube = cube;
this.dockerClientExecutor = dockerClientExecutor;
if (params.getIterations() != null) {
this.pollIterations = params.getIterations();
}
if (params.getUrl() != null) {
String url = params.getUrl();
if (url.contains(DOCKER_HOST)) {
url = url.replaceAll(DOCKER_HOST, dockerClientExecutor.getDockerServerIp());
}
try {
this.url = new URL(url);
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
} else {
throw new IllegalArgumentException("Http Await Strategy requires url field");
}
if (params.getResponseCode() != null) {
this.responseCode = params.getResponseCode();
}
if (params.getHeaders() != null) {
this.headers = params.getHeaders();
}
if (params.getMatch() != null) {
this.matcher = params.getMatch();
}
}
@Override
public boolean await() {
return Ping.ping(pollIterations, getSleepTime(), getTimeUnit(), new PingCommand() {
@Override
public boolean call() {
try {
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.connect();
int connectionResponseCode = urlConnection.getResponseCode();
if (responseCode != connectionResponseCode) {
return false;
}
if (matcher != null) {
String content = IOUtil.asString(urlConnection.getInputStream());
if (matcher.startsWith(REGEXP_PREFIX)) {
String pattern = matcher.substring(REGEXP_PREFIX.length());
final boolean matches = Pattern.compile(pattern, Pattern.DOTALL).matcher(content).matches();
if (!matches) return false;
} else {
final boolean matches = content.startsWith(matcher);
if (!matches) return false;
}
}
if (headers != null) {
final Set<String> keys = headers.keySet();
for (String key : keys) {
if (urlConnection.getHeaderField(key) != null) {
String connectionHeaderValue = urlConnection.getHeaderField(key);
if (!connectionHeaderValue.equals(headers.get(key))) {
return false;
}
} else {
// header has not set the required field yet
return false;
}
}
}
} catch (IOException e) {
return false;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
return true;
}
});
}
public String getUrl() {
if (url == null) {
return "";
}
return url.toString();
}
public int getResponseCode() {
return responseCode;
}
public String getMatcher() {
return matcher;
}
public Map<String, Object> getHeaders() {
return headers;
}
public int getPollIterations() {
return pollIterations;
}
}