/*
 * @(#)AssertionConsumerTest.java
 *
 * Copyright (C) 2007 Infocity Inc. All Rights Reserved.
 */
package test.info.dragonlady.sso;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.Arrays;

import org.apache.cactus.ServletTestCase;
import org.apache.cactus.WebRequest;
import org.apache.xml.security.signature.XMLSignature;
import org.opensaml.SAMLAssertion;
import org.opensaml.SAMLAuthenticationStatement;
import org.opensaml.SAMLException;
import org.opensaml.SAMLResponse;
import org.opensaml.SAMLSubject;

import info.dragonlady.sso.AssertionConsumer;
import info.dragonlady.sso.ConsumerResource;
import info.dragonlady.sso.SSOConstants;
import info.dragonlady.sso.util.AssertionGenerator;
import info.dragonlady.sso.util.ResourceParseException;

/**
 * AssertionConsumerクラステストケース。
 * 
 * @author Hiroshi.Ebata(INFOCITY)
 * @version $Revision: 1.0 $ $Date: 2007/06/07 13:20:00 $
 */
public class AssertionConsumerTest extends ServletTestCase {

	private String consumerHost = "localhost";

	private String consumerContext = "sso_test";

	private String resource = "resource";

	/**
	 * @param arg0
	 */
	public AssertionConsumerTest(String arg0) {
		super(arg0);
	}

	/* (non-Javadoc)
	 * @see junit.framework.TestCase#setUp()
	 */
	protected void setUp() throws Exception {
		super.setUp();
	}

	/* (non-Javadoc)
	 * @see junit.framework.TestCase#tearDown()
	 */
	protected void tearDown() throws Exception {
		super.tearDown();
	}

	/**
	 * {@link info.dragonlady.sso.AssertionConsumer#AssertionConsumer(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)} のためのテスト・メソッド。
	 */
	public final void testAssertionConsumer() {
		try {
			new AssertionConsumer(request, response);
		} catch(Exception e) {
			assertTrue(e.toString(), false);
		}
	}

	private final SAMLResponse createResponse(String authId) throws ResourceParseException, SAMLException, CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException {
		String confirmationMethod = SAMLSubject.CONF_BEARER;
		String authMethod = SAMLAuthenticationStatement.AuthenticationMethod_Unspecified;
		SAMLAssertion assertion = AssertionGenerator.generateAuthenticationAssertion(authId, confirmationMethod, authMethod);
		SAMLResponse samlResponse = new SAMLResponse(
				"responseId",
				ConsumerResource.getConsumer(consumerHost, consumerContext),
				Arrays.asList(new SAMLAssertion[]{assertion}),
				new SAMLException(SAMLException.SUCCESS));
		String certPath = "./sec/SSORoot.cer";
		FileInputStream fis = new FileInputStream(certPath);
		BufferedInputStream bis = new BufferedInputStream(fis);

		CertificateFactory cf = CertificateFactory.getInstance("X.509");

		Certificate cert = null;
		while(bis.available() > 0) {
			cert = cf.generateCertificate(bis);
		}
		fis.close();
		bis.close();

		String storePath = "./sec/.keystore";
		fis = new FileInputStream(storePath);
		bis = new BufferedInputStream(fis);
		String password = "infocity";
		String alias = "SSORoot";

		KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
		while(bis.available() > 0) {
			ks.load(bis, password.toCharArray());
		}
		Key key = ks.getKey(alias, password.toCharArray());
		fis.close();
		bis.close();

		assertion.sign(XMLSignature.ALGO_ID_SIGNATURE_DSA, key, Arrays.asList(new Certificate[]{cert}));
		samlResponse.sign(XMLSignature.ALGO_ID_SIGNATURE_DSA, key, Arrays.asList(new Certificate[]{cert}));
		return samlResponse;
	}

	public final void beginIsEnforceable(WebRequest theRequest) {
		try {
			String authId = "authId";
			theRequest.addParameter(SSOConstants.NAME_SAMLRESPONSE, new String(createResponse(authId).toBase64()), WebRequest.POST_METHOD);
			theRequest.addParameter(SSOConstants.NAME_TARGET, resource, WebRequest.POST_METHOD);
		} catch(Exception e) {
			assertTrue(e.toString(), false);
		}
	}

	/**
	 * {@link info.dragonlady.sso.AssertionConsumer#isEnforceable()} のためのテスト・メソッド。
	 */
	public final void testIsEnforceable() {
		// 成功の場合
		try {
			AssertionConsumer consumer = new AssertionConsumer(request, response);
			assertTrue(consumer.isEnforceable());
		} catch(Exception e) {
			assertTrue(e.toString(), false);
		}
	}

	public final void beginIsEnforceable2(WebRequest theRequest) {
		try {
			String authId = "authId2";
			theRequest.addParameter(SSOConstants.NAME_SAMLRESPONSE, new String(createResponse(authId).toBase64()), WebRequest.POST_METHOD);
			theRequest.addParameter(SSOConstants.NAME_TARGET, resource, WebRequest.POST_METHOD);
		} catch(Exception e) {
			assertTrue(e.toString(), false);
		}
	}

	/**
	 * {@link info.dragonlady.sso.AssertionConsumer#isEnforceable()} のためのテスト・メソッド。
	 */
	public final void testIsEnforceable2() {
		// 失敗の場合
		try {
			AssertionConsumer consumer = new AssertionConsumer(request, response);
			assertFalse(consumer.isEnforceable());
		} catch(Exception e) {
			assertTrue(e.toString(), false);
		}
	}

	public final void beginEnforce(WebRequest theRequest) {
		try {
			String authId = "authId";
			theRequest.addParameter(SSOConstants.NAME_SAMLRESPONSE, new String(createResponse(authId).toBase64()), WebRequest.POST_METHOD);
			theRequest.addParameter(SSOConstants.NAME_TARGET, resource, WebRequest.POST_METHOD);
		} catch(Exception e) {
			assertTrue(e.toString(), false);
		}
	}

	/**
	 * {@link info.dragonlady.sso.AssertionConsumer#enforce()} のためのテスト・メソッド。
	 */
	public final void testEnforce() {
		try {
			// 成功の場合
			AssertionConsumer consumer = new AssertionConsumer(request, response);
			consumer.enforce();
			assertTrue(response.isCommitted());
		} catch(Exception e) {
			assertTrue(e.toString(), false);
		}
	}

	public final void beginEnforce2(WebRequest theRequest) {
		try {
			String authId = "authId2";
			theRequest.addParameter(SSOConstants.NAME_SAMLRESPONSE, new String(createResponse(authId).toBase64()), WebRequest.POST_METHOD);
			theRequest.addParameter(SSOConstants.NAME_TARGET, resource, WebRequest.POST_METHOD);
		} catch(Exception e) {
			assertTrue(e.toString(), false);
		}
	}

	/**
	 * {@link info.dragonlady.sso.AssertionConsumer#enforce()} のためのテスト・メソッド。
	 */
	public final void testEnforce2() {
		try {
			// 失敗の場合
			AssertionConsumer consumer = new AssertionConsumer(request, response);
			consumer.enforce();
			assertTrue(!response.isCommitted());
		} catch(Exception e) {
			assertTrue(e.toString(), false);
		}
	}

}
