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

import info.dragonlady.sso.AssertionManager;
import info.dragonlady.sso.AssertionNotFoundException;
import info.dragonlady.sso.authority.SAMLAuthorityProvider;
import info.dragonlady.sso.message.SSOMessageResource;

import java.util.Iterator;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.opensaml.SAMLAssertion;
import org.opensaml.SAMLBinding;
import org.opensaml.SAMLBindingFactory;
import org.opensaml.SAMLException;
import org.opensaml.SAMLRequest;
import org.opensaml.SAMLResponse;
import org.opensaml.artifact.SAMLArtifactType0001;


/**
 * SAML応答実行クラス
 * 
 * @author Hiroshi.Ebata(INFOCITY)
 * @version $Revision: 1.0 $ $Date: 2006/04/13 22:50:33 $
 */
public class Responder {

	private HttpServletRequest request = null;

	private HttpServletResponse response = null;

	/**
	 * コンストラクタ
	 * 
	 * @param request 要求オブジェクト
	 * @param response 応答オブジェクト
	 */
	public Responder(HttpServletRequest request, HttpServletResponse response) {
		super();
		this.request = request;
		this.response = response;
	}

	/**
	 * SAML要求からアーティファクトを取得し、アーティファクトに対応するアサーションからSAML応答を返す
	 * 
	 * @throws SSOException
	 */
	public void processRequest() throws SSOException {
		try {
			SAMLBinding binding = SAMLBindingFactory.getInstance(SAMLBinding.SOAP);
			SAMLRequest samlRequest = binding.receive(request, 1);
			SAMLResponse samlResponse = new SAMLResponse(samlRequest.getId(), null, null, null);
			SAMLException samlException = null;

			Iterator<SAMLArtifactType0001> itr = samlRequest.getArtifacts();
			if(itr.hasNext()) {
				// SAML要求にアーティファクトが含まれる場合
				while(itr.hasNext()) {
					SAMLArtifactType0001 artifact = itr.next();
					try {
						SAMLAssertion assertionOrg = AssertionManager.getInstance().get(artifact.getAssertionHandle());
						if(assertionOrg == null) {
							// アーティファクトに対応するアサーションがない
							throw new AssertionNotFoundException(SSOMessageResource.getMessage("1003", new Object[]{artifact}));
						}
						// アサーションは使い回すので、クローンを作成
						SAMLAssertion assertion = (SAMLAssertion)assertionOrg.clone();
	
						samlResponse.addAssertion(assertion);
					} catch(Exception e) {
						samlException = new SAMLException(SAMLException.RESPONDER, SSOMessageResource.getMessage("1004"), e);
						samlResponse.setStatus(samlException);
						samlResponse.setAssertions(null);
						break;
					}
				}
				if(samlException == null) {
					samlResponse.setStatus(new SAMLException(SAMLException.SUCCESS));
				}
			} else {
				// SAMLAuthority に問い合わせ
				try {
					samlResponse = SAMLAuthorityProvider.getAuthority(samlRequest).query(samlRequest);
					samlException = samlResponse.getStatus();
				} catch(Exception e) {
					samlException = new SAMLException(SAMLException.RESPONDER, SSOMessageResource.getMessage("1004"), e);
					samlResponse.setStatus(samlException);
				}
			}

			// SAML応答送信
			binding.respond(response, samlResponse, samlException);
			response.setStatus(HttpServletResponse.SC_OK);
			response.getOutputStream().close();
		} catch(Exception e) {
			throw new SSOException(SSOMessageResource.getMessage("1005"), e);
		}
	}

}
