package ch.tkuhn.nanopub.monitor;

import java.io.InputStream;
import java.util.Random;

import net.trustyuri.TrustyUriUtils;

import org.apache.commons.lang.time.StopWatch;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.wicket.util.thread.ICode;
import org.apache.wicket.util.thread.Task;
import org.apache.wicket.util.time.Duration;
import org.nanopub.Nanopub;
import org.nanopub.NanopubImpl;
import org.nanopub.extra.server.NanopubServerUtils;
import org.nanopub.extra.server.ServerInfo;
import org.nanopub.trusty.TrustyNanopubUtils;
import org.openrdf.rio.RDFFormat;
import org.slf4j.Logger;

public class ServerScanner implements ICode {

	private static ServerScanner singleton;
	private static Random random = new Random();
	private Logger logger;

	public static void initDaemon() {
		if (singleton != null) return;
		Task scanTask = new Task("server-scanner");
		scanTask.setDaemon(true);
		singleton = new ServerScanner();
		scanTask.run(Duration.seconds(MonitorConf.get().getScanFreq()), singleton);
	}

	private ServerScanner() {
	}

	@Override
	public void run(Logger logger) {
		this.logger = logger;
		logger.info("Scan servers...");
		ServerList.get().refresh();
		testServers();
	}

	private void testServers() {
		for (ServerData d : ServerList.get().getServerData()) {
			logger.info("Testing server " + d.getServerInfo().getPublicUrl() + "...");
			ServerInfo i = d.getServerInfo();
			if (i.getNextNanopubNo() == 0) continue;
			try {
				long npNo = (long) (random.nextDouble() * (i.getNextNanopubNo()));
				logger.info("Trying to retrieve nanopub number " + npNo);
				int pageNo = (int) (npNo / i.getPageSize()) + 1;
				int rowNo = (int) (npNo % i.getPageSize());
				int r = 0;
				for (String nanopubUri : NanopubServerUtils.loadNanopubUriList(i, pageNo)) {
					if (rowNo < r) {
						r++;
						continue;
					}
					String ac = TrustyUriUtils.getArtifactCode(nanopubUri);
					HttpGet get = new HttpGet(i.getPublicUrl() + ac);
					get.setHeader("Accept", "application/trig");
					StopWatch watch = new StopWatch();
					watch.start();
					HttpResponse resp = HttpClientBuilder.create().build().execute(get);
					watch.stop();
					if (!wasSuccessful(resp)) {
						logger.info("Test failed. HTTP code " + resp.getStatusLine().getStatusCode());
						d.reportTestFailure("INACCESSIBLE");
					} else {
						InputStream in = resp.getEntity().getContent();
						Nanopub np = new NanopubImpl(in, RDFFormat.TRIG);
						if (TrustyNanopubUtils.isValidTrustyNanopub(np)) {
							d.reportTestSuccess(watch.getTime());
						} else {
							logger.info("Test failed. Not a trusty nanopub: " + np.getUri());
							d.reportTestFailure("BROKEN");
						}
					}
					break;
				}
			} catch (Exception ex) {
				ex.printStackTrace();
				d.reportTestFailure("INACCESSIBLE");
			}
		}
	}

	private boolean wasSuccessful(HttpResponse resp) {
		int c = resp.getStatusLine().getStatusCode();
		return c >= 200 && c < 300;
	}

}

@@ -204,16 +204,110 @@
 sponse;%0A
+import org.apache.http.client.HttpClient;%0Aimport org.apache.http.client.config.RequestConfig;%0A
 import o
@@ -345,16 +345,16 @@
 ttpGet;%0A
-
 import o
@@ -1426,16 +1426,201 @@
 ers() %7B%0A
+%09%09RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(10 * 1000).build();%0A%09%09HttpClient c = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).build();%0A
 %09%09for (S
@@ -2478,42 +2478,9 @@
 p = 
-HttpClientBuilder.create().build()
+c
 .exe

Apply 10s timeout for server test requests