package org.springframework.security.oauth2.provider;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.core.UriBuilder;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Assume;
import org.junit.internal.AssumptionViolatedException;
import org.junit.rules.TestWatchman;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;

import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.WebClient;

/**
 * <p> A rule that prevents integration tests from failing if the server application is not running or not accessible.
 * If the server is not running in the background all the tests here will simply be skipped because of a violated
 * assumption (showing as successful). Usage: </p>
 * 
 * <pre> &#064;Rule public static BrokerRunning brokerIsRunning = BrokerRunning.isRunning();
 * 
 * &#064;Test public void testSendAndReceive() throws Exception { // ... test using RabbitTemplate etc. } </pre> <p> The
 * rule can be declared as static so that it only has to check once for all tests in the enclosing test case, but there
 * isn't a lot of overhead in making it non-static. </p>
 * 
 * @see Assume
 * @see AssumptionViolatedException
 * 
 * @author Dave Syer
 * 
 */
public class ServerRunning extends TestWatchman {

	private static Log logger = LogFactory.getLog(ServerRunning.class);

	// Static so that we only test once on failure: speeds up test suite
	private static Map<Integer, Boolean> serverOnline = new HashMap<Integer, Boolean>();

	// Static so that we only test once on failure
	private static Map<Integer, Boolean> serverOffline = new HashMap<Integer, Boolean>();

	private final boolean assumeOnline;

	private static int DEFAULT_PORT = 8080;

	private static String DEFAULT_HOST = "localhost";

	private int port;

	private String hostName = DEFAULT_HOST;

	/**
	 * @return a new rule that assumes an existing running broker
	 */
	public static ServerRunning isRunning() {
		return new ServerRunning(true);
	}

	/**
	 * @return a new rule that assumes there is no existing broker
	 */
	public static ServerRunning isNotRunning() {
		return new ServerRunning(false);
	}

	private ServerRunning(boolean assumeOnline) {
		this.assumeOnline = assumeOnline;
		setPort(DEFAULT_PORT);
	}

	/**
	 * @param port the port to set
	 */
	public void setPort(int port) {
		this.port = port;
		if (!serverOffline.containsKey(port)) {
			serverOffline.put(port, true);
		}
		if (!serverOnline.containsKey(port)) {
			serverOnline.put(port, true);
		}
	}

	/**
	 * @param hostName the hostName to set
	 */
	public void setHostName(String hostName) {
		this.hostName = hostName;
	}

	@Override
	public Statement apply(Statement base, FrameworkMethod method, Object target) {

		// Check at the beginning, so this can be used as a static field
		if (assumeOnline) {
			Assume.assumeTrue(serverOnline.get(port));
		} else {
			Assume.assumeTrue(serverOffline.get(port));
		}

		WebClient userAgent = new WebClient(BrowserVersion.FIREFOX_3);
		userAgent.setRedirectEnabled(false);
		UriBuilder uriBuilder = UriBuilder.fromUri(getUrl("/sparklr/oauth/user/authorize"));
		boolean online = false;
		try {
			userAgent.getPage(uriBuilder.build().toURL());
			online = true;
		} catch (IOException e) {
			if (assumeOnline) {
				Assume.assumeNoException(e);
			}
			logger.warn("Not executing tests because basic connectivity test failed", e);
		} catch (FailingHttpStatusCodeException e) {
			// That's OK
			online = true;
			logger.info("Basic connectivity test passed with exception");
		} finally {
			if (online) {
				serverOffline.put(port, false);
				if (!assumeOnline) {
					Assume.assumeTrue(serverOffline.get(port));
				}

			} else {
				serverOnline.put(port, false);
			}
		}

		return super.apply(base, method, target);

	}

	public String getBaseUrl() {
		return "http://" + hostName + ":" + port;
	}

	public String getUrl(String path) {
		if (!path.startsWith("/")) {
			path = "/" + path;
		}
		return "http://" + hostName + ":" + port + path;
	}

}

@@ -64,18 +64,25 @@
 ava.
-io.IOExcep
+net.HttpURLConnec
 tion
@@ -136,45 +136,8 @@
 p;%0A%0A
-import javax.ws.rs.core.UriBuilder;%0A%0A
 impo
@@ -428,177 +428,166 @@
 nt;%0A
-%0A
 import 
-com.gargoylesoftware.htmlunit.BrowserVersion;%0Aimport com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;%0Aimport com.gargoylesoftware.htmlunit.WebClient
+org.springframework.web.client.RestClientException;%0Aimport org.springframework.web.client.RestTemplate;%0Aimport org.springframework.web.util.UriTemplate
 ;%0A%0A/
@@ -3073,94 +3073,87 @@
 %0A%0A%09%09
-WebClient userAgent = new WebClient(BrowserVersion.FIREFOX_3);%0A%09%09userAgent.set
+RestTemplate client = new RestTemplate();%0A%09%09HttpURLConnection.setFollow
 Redirect
 Enab
@@ -3152,15 +3152,9 @@
 rect
-Enabled
+s
 (fal
@@ -3164,265 +3164,236 @@
 ;%0A%09%09
-UriBuilder uriBuilder = UriBuilder.fromUri(getUrl(%22/sparklr/oauth/user/authorize%22));%0A%09%09boolean online = false;%0A%09%09try %7B%0A%09%09%09userAgent.getPage(uriBuilder.build().toURL());%0A%09%09%09online = true;%0A%09%09%7D catch (IOException e) %7B%0A%09%09%09if (assumeOnline) %7B%0A%09%09%09%09Assume.assumeNo
+boolean online = false;%0A%09%09try %7B%0A%09%09%09client.getForEntity(new UriTemplate(getUrl(%22/sparklr/oauth/user/authorize%22)).toString(), String.class);%0A%09%09%09online = true;%0A%09%09%09logger.info(%22Basic connectivity test passed%22);%0A%09%09%7D catch (RestClient
 Exce
@@ -3401,17 +3401,13 @@
 tion
-(e);%0A%09%09%09%7D
+ e) %7B
 %0A%09%09%09
@@ -3490,151 +3490,66 @@
 ;%0A%09%09
-%7D catch (FailingHttpStatusCodeException e) %7B%0A%09%09%09// That's OK%0A%09%09%09online = true;%0A%09%09%09logger.info(%22Basic connectivity test passed with exception%22);
+%09if (assumeOnline) %7B%0A%09%09%09%09Assume.assumeNoException(e);%0A%09%09%09%7D
 %0A%09%09%7D

use rest template in server running rule