// -*- C++ -*-

#include "Security_PolicyFactory.h"

ACE_RCSID (Security,
           Security_PolicyFactory,
           "Security_PolicyFactory.cpp,v 1.8 2004/07/31 13:06:27 ossama Exp")

#include "SL2_QOPPolicy.h"
#include "SL2_EstablishTrustPolicy.h"

#include "SL3_ContextEstablishmentPolicy.h"
#include "SL3_ObjectCredentialsPolicy.h"

#include "orbsvcs/orbsvcs/SecurityLevel2C.h"
#include "orbsvcs/orbsvcs/SecurityLevel3C.h"


#include "tao/ORB_Constants.h"

CORBA::Policy_ptr
TAO::Security::PolicyFactory::create_policy (
    CORBA::PolicyType type,
    const CORBA::Any &value
    ACE_ENV_ARG_DECL)
  ACE_THROW_SPEC ((CORBA::SystemException,
                   CORBA::PolicyError))
{
  // Not all security policies can be created using the
  // ORB::create_policy() mechanism.  Only those that can be created
  // using that mechanism are supported by this factory.

  if (type == ::Security::SecQOPPolicy)
    {
      ::Security::QOP qop;

      // Extract the desired Quality-of-Protection value from the
      // given Any.
      if (!(value >>= qop))
        ACE_THROW_RETURN (CORBA::BAD_PARAM (
                            CORBA::SystemException::_tao_minor_code (
                              TAO_DEFAULT_MINOR_CODE,
                              EINVAL),
                            CORBA::COMPLETED_NO),
                          CORBA::Policy::_nil ());

      TAO::Security::QOPPolicy * qop_policy = 0;
      ACE_NEW_THROW_EX (qop_policy,
                        TAO::Security::QOPPolicy (qop),
                        CORBA::NO_MEMORY (
                          CORBA::SystemException::_tao_minor_code (
                            TAO_DEFAULT_MINOR_CODE,
                            ENOMEM),
                          CORBA::COMPLETED_NO));
      ACE_CHECK_RETURN (CORBA::Policy::_nil ());

      return qop_policy;
    }

  else if (type == ::Security::SecEstablishTrustPolicy)
    {
      ::Security::EstablishTrust *trust = 0;

      // Extract the desired establishing of trust value from the
      // given Any.
      if (!(value >>= trust))
        ACE_THROW_RETURN (CORBA::BAD_PARAM (
                            CORBA::SystemException::_tao_minor_code (
                              TAO_DEFAULT_MINOR_CODE,
                              EINVAL),
                            CORBA::COMPLETED_NO),
                          CORBA::Policy::_nil ());

      TAO::Security::EstablishTrustPolicy * trust_policy = 0;
      ACE_NEW_THROW_EX (trust_policy,
                        TAO::Security::EstablishTrustPolicy (*trust),
                        CORBA::NO_MEMORY (
                          CORBA::SystemException::_tao_minor_code (
                            TAO_DEFAULT_MINOR_CODE,
                            ENOMEM),
                          CORBA::COMPLETED_NO));
      ACE_CHECK_RETURN (CORBA::Policy::_nil ());

      return trust_policy;
    }

  else if (type == SecurityLevel3::ContextEstablishmentPolicyType)
    {
      SecurityLevel3::ContextEstablishmentPolicyArgument * args = 0;

      // Extract the desired establishing of trust value from the
      // given Any.
      if (!(value >>= args))
        ACE_THROW_RETURN (CORBA::BAD_PARAM (
                            CORBA::SystemException::_tao_minor_code (
                              TAO_DEFAULT_MINOR_CODE,
                              EINVAL),
                            CORBA::COMPLETED_NO),
                          CORBA::Policy::_nil ());

      TAO::SL3::ContextEstablishmentPolicy * policy = 0;
      ACE_NEW_THROW_EX (policy,
                        TAO::SL3::ContextEstablishmentPolicy (
                          args->creds_directive,
                          args->creds_list,
                          args->use_client_auth,
                          args->use_target_auth,
                          args->use_confidentiality,
                          args->use_integrity),
                        CORBA::NO_MEMORY (
                          CORBA::SystemException::_tao_minor_code (
                            TAO_DEFAULT_MINOR_CODE,
                            ENOMEM),
                          CORBA::COMPLETED_NO));
      ACE_CHECK_RETURN (CORBA::Policy::_nil ());

      return policy;
    }

  else if (type == SecurityLevel3::ObjectCredentialsPolicyType)
    {
      SecurityLevel3::OwnCredentialsList * creds = 0;

      // Extract the desired establishing of trust value from the
      // given Any.
      if (!(value >>= creds))
        ACE_THROW_RETURN (CORBA::BAD_PARAM (
                            CORBA::SystemException::_tao_minor_code (
                              TAO_DEFAULT_MINOR_CODE,
                              EINVAL),
                            CORBA::COMPLETED_NO),
                          CORBA::Policy::_nil ());

      TAO::SL3::ObjectCredentialsPolicy * policy = 0;
      ACE_NEW_THROW_EX (policy,
                        TAO::SL3::ObjectCredentialsPolicy (*creds),
                        CORBA::NO_MEMORY (
                          CORBA::SystemException::_tao_minor_code (
                            TAO_DEFAULT_MINOR_CODE,
                            ENOMEM),
                          CORBA::COMPLETED_NO));
      ACE_CHECK_RETURN (CORBA::Policy::_nil ());

      return policy;
    }

  else if (type == ::Security::SecInvocationCredentialsPolicy
           || type == ::Security::SecMechanismsPolicy
           || type == ::Security::SecFeaturePolicy             // Deprecated.
           || type == ::Security::SecDelegationDirectivePolicy)
    ACE_THROW_RETURN (CORBA::PolicyError (CORBA::UNSUPPORTED_POLICY),
                      CORBA::Policy::_nil ());
  else
    ACE_THROW_RETURN (CORBA::PolicyError (CORBA::BAD_POLICY_TYPE),
                      CORBA::Policy::_nil ());
}
