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

import info.dragonlady.sso.ArtifactReceiver;
import info.dragonlady.sso.AssertionManager;
import info.dragonlady.sso.ReceiverResource;
import info.dragonlady.sso.SSOConfig;
import info.dragonlady.sso.SSOConstants;
import info.dragonlady.sso.SSOContext;
import info.dragonlady.sso.SSOException;
import info.dragonlady.sso.SiteTransfer;
import info.dragonlady.sso.util.AssertionGenerator;
import info.dragonlady.sso.util.ResourceParseException;

import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


import org.apache.cactus.ServletTestCase;
import org.apache.cactus.WebRequest;
import org.apache.cactus.WebResponse;
import org.opensaml.SAMLAssertion;
import org.opensaml.SAMLAuthenticationStatement;
import org.opensaml.SAMLSubject;
import org.opensaml.artifact.Artifact;

/**
 * ArtifactReceiverクラスのテストケース
 * 
 * @author Hiroshi.Ebata(INFOCITY)
 * @version $Revision: 1.3 $ $Date: 2005/11/25 06:53:02 $
 */
public class ArtifactReceiverTest extends ServletTestCase {
	private String userId = "testuser";

	/**
	 * Constructor for ArtifactReceiverTest.
	 * @param arg0
	 */
	public ArtifactReceiverTest(String arg0) {
		super(arg0);
	}

	/*
	 * @see TestCase#setUp()
	 */
	protected void setUp() throws Exception {
		super.setUp();
	}

	/*
	 * @see TestCase#tearDown()
	 */
	protected void tearDown() throws Exception {
		super.tearDown();
	}

	/**
	 * サーバにアサーションを設定しておく為の処理
	 * ※SiteTransferサーブレット呼び出し
	 */
	public final void beginSetAssertion(WebRequest theRequest) {
		// ターゲットサイトを指定
		theRequest.addParameter(SSOConstants.NAME_TARGET, "http://172.16.3.74:8080/sso_test/target.html", WebRequest.GET_METHOD);
	}

	/**
	 * サーバにアサーションを設定しておく為の処理
	 * ※SiteTransferサーブレット呼び出し
	 */
	public final void testSetAssertion() {
		try {
			SAMLAssertion assertion1 = AssertionGenerator.generateAuthenticationAssertion(userId, SAMLSubject.CONF_ARTIFACT, SAMLAuthenticationStatement.AuthenticationMethod_Unspecified);
			Artifact artifact1 = AssertionGenerator.generateArtifact(AssertionManager.getInstance().add(assertion1));
			SAMLAssertion assertion2 = AssertionGenerator.generateAttributeAssertion(userId, getAttributes());
			Artifact artifact2 = AssertionGenerator.generateArtifact(AssertionManager.getInstance().add(assertion2));
			SAMLAssertion assertion3 = AssertionGenerator.generateAuthenticationAssertion(userId, SAMLSubject.CONF_ARTIFACT, SAMLAuthenticationStatement.AuthenticationMethod_Unspecified);
			Artifact artifact3 = AssertionGenerator.generateArtifact(AssertionManager.getInstance().add(assertion3));
			SAMLAssertion assertion4 = AssertionGenerator.generateAttributeAssertion(userId, getAttributes());
			Artifact artifact4 = AssertionGenerator.generateArtifact(AssertionManager.getInstance().add(assertion4));
			SAMLAssertion assertion5 = AssertionGenerator.generateAuthenticationAssertion(userId, SAMLSubject.CONF_ARTIFACT, SAMLAuthenticationStatement.AuthenticationMethod_Unspecified);
			Artifact artifact5 = AssertionGenerator.generateArtifact(AssertionManager.getInstance().add(assertion5));
			SAMLAssertion assertion6 = AssertionGenerator.generateAttributeAssertion(userId, getAttributes());
			Artifact artifact6 = AssertionGenerator.generateArtifact(AssertionManager.getInstance().add(assertion6));

			SiteTransfer st = new SiteTransfer(request, response);
			st.forward(Arrays.asList(new Artifact[]{artifact1, artifact2, artifact3, artifact4, artifact5, artifact6}), null);
		} catch(Exception e) {
			assertTrue(e.toString(), false);
		}
	}

	private final Map<String, List<String>> getAttributes() throws ResourceParseException {
		Map<String, List<String>> attributes = new HashMap<String, List<String>>();
		List keyList = SSOConfig.getSAMLAttributeList();
		for(int i = 0; i < keyList.size(); i++) {
			String key = keyList.get(i).toString();
			List<String> list = new ArrayList<String>();
			list.add("val_" + key);
			attributes.put(key, list);
		}
		return attributes;
	}

	/**
	 * サーバにアサーションを設定しておく為の処理
	 * ※SiteTransferサーブレット呼び出し
	 */
	public final void endSetAssertion(WebResponse theResponse) {
		try {
			// URL確認
			String expectedReceiver = ReceiverResource.getReceiver("172.16.3.74", "sso_test");
			String receiver = theResponse.getConnection().getHeaderField("Location");
			String[] str = receiver.split("\\?");
			assertTrue(expectedReceiver.equals(str[0]));
			String[] query = str[1].split("&");
			// TARGET,SAMLartの２パラメータ
			assertTrue(query.length == 7);
			List<String> artifacts = new ArrayList<String>();
			for(int i = 0; i < query.length; i++) {
				String[] s = query[i].split("=");
				if(s[0].equals(SSOConstants.NAME_SAMLART)) {
					// artifact文字列存在設定
					artifacts.add(URLDecoder.decode(s[1], "MS932"));
				}
			}
			ArtifactManager.getInstance().setArtifact((String[])artifacts.toArray(new String[artifacts.size()]));
		} catch(Exception e) {
			assertTrue(e.toString(), false);
		}
	}

	public final void beginReceive(WebRequest theRequest) {
		try {
			// ターゲットサイトを指定
			theRequest.addParameter(SSOConstants.NAME_TARGET, "http://172.16.3.74:8080/sso_test/target.html", WebRequest.GET_METHOD);
			// アーティファクトを指定
			String[] artifact = ArtifactManager.getInstance().getArtifact();
			for(int i = 0; i < 2; i++) {
				theRequest.addParameter(SSOConstants.NAME_SAMLART, artifact[i], WebRequest.GET_METHOD);
			}
		} catch(Exception e) {
			assertTrue(e.toString(), false);
		}
	}

	/**
	 * SAML認証成功
	 * 
	 * Test method for 'info.dragonlady.sso.ArtifactReceiver.receive()'
	 */
	public final void testReceive() {
		try {
			SSOContext.getInstance().setCurrentRequest(request);
			ArtifactReceiver receiver = new ArtifactReceiver(request, response);
//			receiver.receive(ArtifactManager.getInstance().getArtifact());
			receiver.receive();

			// プロパティ確認
			assertTrue(receiver.getAuthId().equals(userId));
			assertTrue(receiver.getAttributes().equals(getAttributes()));
			assertTrue(receiver.getExpirationTime() > 0);
			assertTrue(receiver.getTargetUrl().equals("http://172.16.3.74:8080/sso_test/target.html"));
		} catch(Exception e) {
			assertTrue(e.toString(), false);
		}
	}

	public final void beginRedirectToTarget(WebRequest theRequest) {
		try {
			// ターゲットサイトを指定
			theRequest.addParameter(SSOConstants.NAME_TARGET, "http://172.16.3.74:8080/sso_test/target.html", WebRequest.GET_METHOD);
			// アーティファクトを指定
			String[] artifact = ArtifactManager.getInstance().getArtifact();
			for(int i = 2; i < 4; i++) {
				theRequest.addParameter(SSOConstants.NAME_SAMLART, artifact[i], WebRequest.GET_METHOD);
			}
		} catch(Exception e) {
			assertTrue(e.toString(), false);
		}
	}

	/**
	 * 
	 * Test method for 'info.dragonlady.sso.ArtifactReceiver.redirectToTarget()'
	 */
	public final void testRedirectToTarget() {
		try {
			SSOContext.getInstance().setCurrentRequest(request);
			ArtifactReceiver receiver = new ArtifactReceiver(request, response);
			receiver.receive();
			receiver.redirectToTarget();
		} catch(Exception e) {
			assertTrue(e.toString(), false);
		}
	}

	public final void endRedirectToTarget(WebResponse theResponse) {
		try {
			// URL確認
			String expected = "http://172.16.3.74:8080/sso_test/target.html";
			String result = theResponse.getConnection().getHeaderField("Location");
			assertTrue(expected.equals(result));
		} catch(Exception e) {
			assertTrue(e.toString(), false);
		}
	}

	public final void beginReceive2(WebRequest theRequest) {
		try {
			// ターゲットサイトを指定
			theRequest.addParameter(SSOConstants.NAME_TARGET, "http://172.16.3.74:8080/sso_test/target.html", WebRequest.GET_METHOD);
			// アーティファクトを指定
			String[] artifact = ArtifactManager.getInstance().getArtifact();
			for(int i = 4; i < 6; i++) {
				theRequest.addParameter(SSOConstants.NAME_SAMLART, artifact[i], WebRequest.GET_METHOD);
			}
		} catch(Exception e) {
			assertTrue(e.toString(), false);
		}
	}

	/**
	 * SAML認証失敗（アーティファクトに対応するアサーションがない）
	 * 
	 * Test method for 'info.dragonlady.sso.ArtifactReceiver.receive()'
	 */
	public final void testReceive2() {
		try {
			SSOContext.getInstance().setCurrentRequest(request);
			// アサーションを削除しておく
			AssertionManager.getInstance().getAssertionMap().clear();
			AssertionManager.getInstance().getHandleMap().clear();

			ArtifactReceiver receiver = new ArtifactReceiver(request, response);
			try {
//				receiver.receive(ArtifactManager.getInstance().getArtifact());
				receiver.receive();
			} catch(Exception e) {
				assertTrue(e instanceof SSOException);
			}

			// プロパティ確認
			assertNull(receiver.getAuthId());
			assertNull(receiver.getAttributes());
			assertTrue(receiver.getExpirationTime() == 0);
			assertTrue(receiver.getTargetUrl().equals("http://172.16.3.74:8080/sso_test/target.html"));
		} catch(Exception e) {
			assertTrue(e.toString(), false);
		}
	}

}
