package eu.stratuslab.marketplace.server.utils;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyStore;
import java.security.cert.CertificateFactory;
import java.security.cert.X509CRL;
import javax.security.auth.x500.X500Principal;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.logging.Logger;

import org.junit.Test;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.w3c.dom.Document;

import eu.stratuslab.marketplace.server.util.ResourceTestBase;

public class EndorserWhitelistTest extends ResourceTestBase {
	
	private String password = "XYZXYZ";
	
	private String classPrefix = "/eu/stratuslab/marketplace/server/resources/";
	
	private static final Logger LOGGER = Logger.getLogger("org.restlet");
	
	@Test
	public void testCertVerificationWithUnverifiedCert() throws Exception {
		Document metadata = extractXmlDocument(this.getClass()
				.getResourceAsStream(classPrefix + "valid-indate-signature.xml"));
				
		EndorserWhitelist whitelist = getWhitelistInstance("test-ca.jks",
				"test-crl-empty.pem", "test-whitelist");
						
		boolean verified = whitelist.isCertVerified(metadata);
		
		assertFalse(verified);
	}
	
	@Test
	public void testCertVerificationWithVerifiedCert() throws Exception {
		Document metadata = extractXmlDocument(this.getClass()
				.getResourceAsStream(classPrefix + "valid-ca-signed.xml"));
				
		EndorserWhitelist whitelist = getWhitelistInstance("test-ca.jks",
				"test-crl-empty.pem", "test-whitelist");
						
		boolean verified = whitelist.isCertVerified(metadata);
		
		assertTrue(verified);
	}
	
	@Test
	public void testCertVerificationWithRevokedCert() {
		try {
		
		Document metadata = extractXmlDocument(this.getClass()
				.getResourceAsStream(classPrefix + "valid-ca-signed.xml"));
				
		EndorserWhitelist whitelist = getWhitelistInstance("test-ca.jks",
				"test-crl-revoked.pem", "test-whitelist");
						
		boolean verified = whitelist.isCertVerified(metadata);
		
		assertFalse(verified);
		} catch(Exception e){
			LOGGER.info("Caught exception: " + e.getMessage());
		}
		
	}
	
	@Test
	public void testWhitelistWithValidUnlistedCert() throws Exception {
		Document metadata = extractXmlDocument(this.getClass()
				.getResourceAsStream(classPrefix + "valid-ca-signed.xml"));
				
		EndorserWhitelist whitelist = getWhitelistInstance("test-ca.jks",
				"test-crl-empty.pem", "test-whitelist");
						
		boolean listed = whitelist.isEndorserWhitelisted(metadata);
		
		assertFalse(listed);
	}
	
	@Test
	public void testWhitelistWithValidListedCert() throws Exception {
		Document metadata = extractXmlDocument(this.getClass()
				.getResourceAsStream(classPrefix + "valid-ca-signed.xml"));
				
		EndorserWhitelist whitelist = getWhitelistInstance("test-ca.jks",
				"test-crl-empty.pem", "test-whitelist-entry");
						
		boolean listed = whitelist.isEndorserWhitelisted(metadata);
		
		assertTrue(listed);
	}
	
	@Test
	public void testWhitelistWithInvalidListedCert() throws Exception {
		Document metadata = extractXmlDocument(this.getClass()
				.getResourceAsStream(classPrefix + "valid-ca-signed.xml"));
				
		EndorserWhitelist whitelist = getWhitelistInstance("test-ca.jks",
				"test-crl-revoked.pem", "test-whitelist-entry");
						
		boolean listed = whitelist.isEndorserWhitelisted(metadata);
		
		assertFalse(listed);
	}
			
	private EndorserWhitelist getWhitelistInstance(String truststore, 
			String crl, String whitelistFile) throws Exception {
		
		KeyStore anchors = createKeyStore(truststore, password);
		Collection<X509CRL> crls = loadCrls(crl);
		List<X500Principal> list = loadWhitelist(whitelistFile);
		
		EndorserWhitelist whitelist = new EndorserWhitelist(anchors, crls, list);
		
		return whitelist;
	}
	
	private KeyStore createKeyStore(String filename, String password) throws Exception {
		InputStream is = EndorserWhitelistTest.class
		.getResourceAsStream(classPrefix + filename);
		
		KeyStore anchors = KeyStore.getInstance(KeyStore.getDefaultType());
		try {
			anchors.load(is, password.toCharArray());
		} finally {
			if (is != null) {
				is.close();
			}
		}

		return anchors;
	}
	
	private Collection<X509CRL> loadCrls(String filename) throws Exception {
		LOGGER.info("Loading CRL");
		InputStream is = EndorserWhitelistTest.class
		.getResourceAsStream(classPrefix + filename);
		CertificateFactory cf = CertificateFactory.getInstance("X.509");

		X509CRL crl = null;

		try {
			crl = (X509CRL)cf.generateCRL(is);
		} finally {
			closeReliably(is);
		}
		Collection<X509CRL> crls = new ArrayList<X509CRL>();
		crls.add(crl);

		LOGGER.info("CRL loaded");
		
		return crls;
	}
	
	private List<X500Principal> loadWhitelist(String filename) throws Exception {
		List<X500Principal> lines = new ArrayList<X500Principal>();

		InputStream is = EndorserWhitelistTest.class
		.getResourceAsStream(classPrefix + filename);
		
		InputStreamReader fileReader = new InputStreamReader(is);
		BufferedReader bufferedReader = new BufferedReader(fileReader);

		String line = null;
		while ((line = bufferedReader.readLine()) != null) {
			lines.add(new X500Principal(line));
		}

		closeReliably(bufferedReader);
		closeReliably(fileReader);
		closeReliably(is);
		
		return lines;
	}
	
}

@@ -378,41 +378,8 @@
 ist;
-%0Aimport java.util.logging.Logger;
 %0A%0Aim
@@ -769,81 +769,8 @@
 ;%0A%09%0A
-%09private static final Logger LOGGER = Logger.getLogger(%22org.restlet%22);%0A%09%0A
 %09@Te
@@ -1663,20 +1663,26 @@
 t() 
-%7B%0A%09%09try %7B%0A%09%09
+throws Exception %7B
 %0A%09%09D
@@ -2015,94 +2015,8 @@
 d);%0A
-%09%09%7D catch(Exception e)%7B%0A%09%09%09LOGGER.info(%22Caught exception: %22 + e.getMessage());%0A%09%09%7D%0A%09%09%0A
 %09%7D%0A%09
@@ -4139,38 +4139,8 @@
 n %7B%0A
-%09%09LOGGER.info(%22Loading CRL%22);%0A
 %09%09In
@@ -4484,40 +4484,8 @@
 );%0A%0A
-%09%09LOGGER.info(%22CRL loaded%22);%0A%09%09%0A
 %09%09re

Fix for crl test