/************************************************************************
*
* Copyright (c) 2003-2004, C&C Research Laboratories, NEC Europe Ltd.
*
* Copyright in this library belongs to C&C Research Laboratories,
* Rathausallee 10, 53757 Sankt Augustin, Germany.
*
* This software may not be used, sold, licensed, transferred, copied
* or reproduced in whole or in part in any manner or form or in or
* on any media by any person other than in accordance with the terms
* of the Licence Agreement supplied with the software, or otherwise
* without the prior written consent of the copyright owners.
*
* This software is distributed WITHOUT ANY WARRANTY, without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE, except where stated in the Licence Agreement supplied with
* the software.
*
*  Created By :           Federico Crazzolara
*  Created for Project :  GEMSS (IST-2001-37153)
*
************************************************************************/


package de.nece.ccrl.tokenmanager.manager;

import org.xmlsoap.schemas.ws._2002._12.secext.*;
import de.nece.ccrl.schemas.sessid.SessionIdType;
import de.nece.ccrl.schemas.sessid.holders.SessionIdTypeHolder;
import de.nece.ccrl.tokenmanager.*;
import eu.gemss.components.security.token.types.pki.X509CertificateToken;
import javax.xml.namespace.*;
import java.util.Random;

public class X509ExchTokenManager implements TokenManager {

    TokenManagerDriver driver;
    TokenManagerCoDec codec;
    Object[] support;

    public void setDriver(TokenManagerDriver driver) {
	this.driver = driver;
    }

    public void setCoDec(TokenManagerCoDec codec) {
	this.codec = codec;
    }

    public void setSupportTokens(Object[] support) {
	this.support = support;
    }


    public Object execute(String initiator, String responder) throws TokenManagerException {

	if (driver == null) throw new TokenManagerException("No driver ist set");
	if (codec == null) throw new TokenManagerException("No codec is set");

	if ((support == null) || (!(support[0] instanceof X509CertificateToken)))
	    throw new TokenManagerException("X509Certificate support token needed");

	X509CertificateToken cert = (X509CertificateToken) support[0];
	RequestSecurityTokenType request;
	RequestSecurityTokenResponseType response;
	RequestedSecurityTokenType[] token;

	// setup the sessionID

	Random generator = new Random();
       
	SessionIdType sid = new SessionIdType();

	sid.setInitiator(initiator);
	sid.setResponder(responder);
	SessionIdTypeHolder sidh = new SessionIdTypeHolder(sid);


	// send the the certificate

	request = new RequestSecurityTokenType();

	QName requesttype = new QName("wsse:ReqExchange");
	RequestTypeEnum requesttypeen = RequestTypeEnum.fromValue(requesttype);
        request.setRequestType(requesttypeen);

	QName tokentype = new QName("wsse:X509v3");
	TokenTypeEnum tokentypeen = TokenTypeEnum.fromValue(tokentype);
        request.setTokenType(tokentypeen);

	BinarySecurityTokenType t = null;
	try {
	    t = (BinarySecurityTokenType) codec.encode(cert);
	} catch (TokenManagerException e) {}
	RequestedSecurityTokenType[] art = new RequestedSecurityTokenType[1];
	RequestedSecurityTokenType rt = new RequestedSecurityTokenType();
	rt.setBinarySecurityToken(t);
	art[0] = rt;
	request.setRequestedSecurityToken(art);

	// first rpc call. Throws an exception if invocation encounters problems
	// on the server side.
	


	response = driver.invoke(sidh, request, null, null);

	if (response==null) throw new TokenManagerException("No Context token could be estabilshed");
       
	// Extract Security context token to be returned
		
	token = response.getRequestedSecurityToken();
	QName ttype = (response.getTokenType()).getValue();
	if (!(ttype.equals(tokentype))) throw new TokenManagerException("X509 certificate exptected");
  
	// returns the requested certificate 
	if (token != null) {	 
	    RequestedSecurityTokenType rst = token[0];
	    return codec.decode(rst.getBinarySecurityToken());
	}
	else return null;

    }


}
