/***********************************************************************
 * 
 *  Copyright (C) 2006 Novell, Inc. All Rights Reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; version 2.1
 *  of the License.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, Novell, Inc.
 * 
 *  To contact Novell about this file by physical or electronic mail, 
 *  you may find current contact information at www.novell.com.
 * 
 *  Author: Juan Carlos Luciani <jluciani@novell.com>
 *  
 ***********************************************************************/

package com.novell.casa.authtoksvc;

import org.apache.log4j.Logger;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;

/**
 * GetAuthToken Class.
 * <p>
 * This class processes requests for tokens to authenticate an entity
 * to a particular service.
 * 
 */
public final class GetAuthToken implements RpcMethod
{
   private static final Logger m_log = Logger.getLogger(GetAuthToken.class);
   private Logger m_trace = null;

   private SvcConfig          m_svcConfig;
   private EnabledSvcsConfig  m_enabledSvcsConfig;

   /**
    * Constructor.
    */
   public GetAuthToken()
   {
      // Nothing to do at this time
   }     

   /**
    * Initialize the Rpc method.
    *
    * @param svcConfig           Service configuration object.
    * @param enabledSvcsConfig   Enabled services configuration object.
    * @param traceLogger         Logger for tracing requests.
    * @throws Exception
    */
   public final void init(SvcConfig svcConfig,
                          EnabledSvcsConfig enabledSvcsConfig,
                          Logger traceLogger) throws Exception
   {
      m_svcConfig = svcConfig;
      m_enabledSvcsConfig = enabledSvcsConfig;
      m_trace = traceLogger;
   }

   /**
    * Process Rpc.
    *
    * @param inStream   Input stream with request.
    * @param out        Ouput print writer for reply.
    * @throws IOException
    */
   public final void invoke(InputStream inStream, PrintWriter out) throws IOException
   {
      try
      {
         m_log.debug("invoke()");

         // Parse the GetAuthTokReqMsg sent from the client
         GetAuthTokReqMsg getAuthTokReqMsg = new GetAuthTokReqMsg(inStream);

         // Verify that the service is enabled
         if (m_enabledSvcsConfig.svcEnabled(getAuthTokReqMsg.getHostName(),
                                            getAuthTokReqMsg.getServiceName()))
         {
            try
            {
               // Now create a session token (This validates the session token provided).
               SessionToken sessionToken = new SessionToken(getAuthTokReqMsg.getSessionToken());

               // Create the Authentication Token
               AuthToken authToken = new AuthToken(sessionToken.getIdentId(),
                                                   sessionToken.getRealm(),
                                                   m_svcConfig.m_realmsInfo.getUrl(sessionToken.getRealm()),
                                                   getAuthTokReqMsg.getServiceName(),
                                                   getAuthTokReqMsg.getHostName(),
                                                   m_svcConfig,
                                                   m_enabledSvcsConfig);

               // Write out the response
               GetAuthTokRespMsg getAuthTokRespMsg = new GetAuthTokRespMsg(ProtoDefs.httpOkStatusMsg,
                                                                           ProtoDefs.httpOkStatusCode,
                                                                           authToken.serialize(),
                                                                           authToken.getLifetime());
               out.println(getAuthTokRespMsg.toString());
               m_trace.info("GetAuthToken Rpc, Host=" + getAuthTokReqMsg.getHostName()
                            + ", Svc=" + getAuthTokReqMsg.getServiceName()
                            + ", Status=SUCCESS");
            }
            catch (Exception e)
            {
               m_log.info("invoke()- Exception: " + e.toString());
               m_trace.info("GetAuthToken Rpc, Host=" + getAuthTokReqMsg.getHostName()
                            + ", Svc=" + getAuthTokReqMsg.getServiceName()
                            + ", Status=UNAUTHORIZED");

               // Write out the response
               try
               {
                  GetAuthTokRespMsg getAuthTokRespMsg = new GetAuthTokRespMsg(ProtoDefs.httpUnauthorizedStatusMsg,
                                                                              ProtoDefs.httpUnauthorizedStatusCode);
                  out.println(getAuthTokRespMsg.toString());
               }
               catch (Exception e2)
               {
                  m_log.error("invoke()- Exception trying to construct response msg: " + e2.toString());
               }
            }
         }
         else
         {
            // The service has not been enabled to utilize our authentication tokens
            GetAuthTokRespMsg getAuthTokRespMsg = new GetAuthTokRespMsg(ProtoDefs.httpNotFoundStatusMsg,
                                                                        ProtoDefs.httpNotFoundStatusCode);
            out.println(getAuthTokRespMsg.toString());

            m_trace.info("GetAuthToken Rpc, Host=" + getAuthTokReqMsg.getHostName()
                         + ", Svc=" + getAuthTokReqMsg.getServiceName()
                         + ", Status=SERVICE_NOT_CONFIGURED");
         }
      }
      catch (Exception e)
      {
         m_log.error("invoke()- Exception: " + e.toString());
         m_trace.info("GetAuthToken Rpc, Status=INTERNAL_ERROR");

         // Write out the response
         try
         {
            GetAuthTokRespMsg getAuthTokRespMsg = new GetAuthTokRespMsg(ProtoDefs.httpServerErrorStatusMsg,
                                                                        ProtoDefs.httpServerErrorStatusCode);
            out.println(getAuthTokRespMsg.toString());
         }
         catch (Exception e2)
         {
            m_log.error("invoke()- Exception trying to construct response msg: " + e2.toString());
         }
      }
   }

   /**
    * Return the method id.
    *
    * @return Method id.
    */
   public final String getId()
   {
      return "GetAuthToken";
   }
}