/////////////////////////////////////////////////////////////////////////
//
// © University of Southampton IT Innovation Centre, 2004
//
// Copyright in this library belongs to the IT Innovation Centre of
// 2 Venture Road, Chilworth Science Park, Southampton, SO16 7NP, UK.
//
// 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:             Darren Marvin
//      Created date:           2003/09/19
//      Created for project:    GEMSS
//
/////////////////////////////////////////////////////////////////////////
//
//      Dependencies: None
//
/////////////////////////////////////////////////////////////////////////
//
//      Last commit info:       $Author: $
//                              $Date: $
//                              $Revision: $
//
/////////////////////////////////////////////////////////////////////////

package uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.context;


import eu.gemss.components.security.token.*;
import eu.gemss.components.security.token.types.*;
import eu.gemss.components.security.SecurityContextException;
import eu.gemss.components.security.InvalidCredentialException;
import eu.gemss.components.security.InvalidPasswordException;
import java.util.logging.*;
import uk.ac.soton.itinnovation.gemss.security.context.*;
import uk.ac.soton.itinnovation.gemss.security.context.configuration.*;
import uk.ac.soton.itinnovation.gemss.transportmessaging.configuration.*;
import uk.ac.soton.itinnovation.gemss.utils.configuration.*;

public class DefaultSecurityContext implements SecurityContext {

    private static Logger mLogger = Logger.getLogger("uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.context.DefaultSecurityContext");
    private uk.ac.soton.itinnovation.gemss.security.context.SecurityContext secCtx = null;

    /**
     * Set the configuration
     * @param config
     */
    public void initialise(TransportMessagingConfiguration config) throws MessageContextException {
        try{
          secCtx = new uk.ac.soton.itinnovation.gemss.security.context.SecurityContext(new SecurityContextConfiguration(config.getConfigurationFileDir()));
        }
        catch(ConfigurationException ex) {
          mLogger.log(Level.SEVERE, "Unable to obtain configuration information for transport and messaging, logs will hold further information",ex);
          throw new MessageSecurityContextException("Unable to obtain configuration information for transport and messaging, logs will hold further information",ex);
        }
        catch(SecurityContextException ex) {
          mLogger.log(Level.SEVERE, "Unable to obtain security context for transport and messaging, logs will hold further information",ex);
          throw new MessageSecurityContextException("Unable to obtain security context for transport and messaging, reason '" + ex.getUserMessage() + "'","Unable to obtain security context for transport and messaging, reason '" + ex.getSystemMessage() + "'",ex);
        }
    }

    /**
     * Retrieve a security token instance matching the provided type
     * @param type token type required
     * @return security token instance
     * @throws MessageContextException
     */
    public SecurityToken generateSecurityToken(TokenDescriptor type) throws MessageContextException {
        try{
            return secCtx.generateSecurityToken(type);
        }
        catch(UnsupportedTokenException ex) {
            mLogger.log(Level.SEVERE,"Unsupported security token described as '" + type.getDescription() + "' from security context component",ex);
            throw new MessageSecurityContextException("Unsupported security token described as '" + type.getDescription() + "' from security context component",ex);
        }
        catch(SecurityContextException ex) {
            //from different component so log it
            mLogger.log(Level.SEVERE,"Unable to obtain a security token described as '" + type.getDescription() + "' from security context component",ex);
            throw new MessageSecurityContextException("Unable to obtain a security token described as '" + type.getDescription() + "' from security context component",ex);
        }
    }

    /**
     * Test to see if the passed security token is trusted in the prevailing security context
     * @param token
     * @return
     * @throws MessageContextException
     */
    public boolean isTrusted(SecurityToken token) throws MessageContextException {

        try{
            secCtx.isTrusted(token);
            return secCtx.isTrusted(token);
        }
        catch(SecurityContextException ex) {
            //from difference component so log it
            try{
                mLogger.log(Level.SEVERE,"Unable to establish trust for a security token described as '" + token.getTokenDescriptor().getDescription() + "' from security context component",ex);
                throw new MessageSecurityContextException("Unable to establish trust for a security token described as '" + token.getTokenDescriptor().getDescription() + "' from security context component",ex);
            }
            catch(SecurityTokenException ex2) {
                mLogger.log(Level.SEVERE,"Unable to establish trust for a security token from security context component",ex);
                throw new MessageSecurityContextException("Unable to establish trust for a security token from security context component",ex);
            }
        }
    }

    /**
     * Add a security token instance to the prevailing security context
     * @param secToken security token to add
     * @throws MessageContextException
     */
    public void addSecurityTokenToContext(SecurityToken token) throws MessageContextException {
      try{
          secCtx.addSecurityTokenToContext(token);
      }
      catch(SecurityContextException ex) {
          //from difference component so log it
          try{
              mLogger.log(Level.SEVERE,"Unable to add security token described as '" + token.getTokenDescriptor().getDescription() + "' from security context component",ex);
              throw new MessageSecurityContextException("Unable to add security token described as '" + token.getTokenDescriptor().getDescription() + "' from security context component",ex);
          }
          catch(SecurityTokenException ex2) {
              mLogger.log(Level.SEVERE,"Unable to add security token to security context component",ex);
              throw new MessageSecurityContextException("Unable to add security token to security context component",ex);
          }
        }
    }

    /**
     * Remove from the prevailing security context the security token identified by the supplied token descriptor
     * @param secToken token to remove
     * @throws MessageContextException
     */
    public void removeSecurityTokenFromContext(SecurityToken token) throws MessageContextException {
      try{
          secCtx.removeSecurityTokenFromContext(token);
      }
      catch(SecurityContextException ex) {
          //from difference component so log it
          try{
              mLogger.log(Level.SEVERE,"Unable to remove security token described as '" + token.getTokenDescriptor().getDescription() + "' from security context component",ex);
              throw new MessageSecurityContextException("Unable to remove security token described as '" + token.getTokenDescriptor().getDescription() + "' from security context component",ex);
          }
          catch(SecurityTokenException ex2) {
              mLogger.log(Level.SEVERE,"Unable to remove security token to security context component",ex);
              throw new MessageSecurityContextException("Unable to remove security token to security context component",ex);
          }
        }
    }

    /**
     * Retrieve from the prevailing security context a previously stored security token matching the passed token descriptor
     * @param tokenDesc token identifier
     * @return security token required
     * @throws MessageContextException
     */
    public SecurityToken getSecurityTokenFromContext(TokenDescriptor tokenDesc) throws MessageContextException {
      try{
         return secCtx.getSecurityTokenFromContext(tokenDesc);
     }
     catch(SecurityContextException ex) {
         mLogger.log(Level.SEVERE,"Unable to get security token described as '" + tokenDesc.getDescription() + "' from security context component",ex);
         throw new MessageSecurityContextException("Unable to get security token described as '" + tokenDesc.getDescription() + "' from security context component",ex);

        }
    }
}