/*
 * PartnerSSOEnabler.java	1.00 22-Feb-2001
 *
 * Copyright 2000-2001 by Oracle Corporation
 * 500 Oracle Parkway, Redwood Shores, California, 94065, U.S.A.
 * All rights reserved.
 */

package oracle.portal.sample.v1.devguide.partnerApp;

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

import java.net.URL;
import java.net.InetAddress;

import java.sql.DriverManager;
import java.sql.Connection;

import oracle.security.sso.enabler.SSOEnabler;
import oracle.security.sso.enabler.SSOUserInfo;
import oracle.security.sso.enabler.SSOEnablerUtil;
import oracle.security.sso.enabler.SSOEnablerException;

public class PartnerSSOEnabler
{
  private  String mListenerToken          = null;
  private  String mRequestedUrl           = null;
  private  String mOnCancelUrl            = null;

  private  String mPartnerAppCookieName   = null;
  private  String mPartnerAppCookieDomain = null;
  private  String mPartnerAppCookieScope  = null;
  private  String mPartnerAppCookieDesc   = null;

  private  String mDbCred                 = null;
  private  String mDbHost                 = null;
  private  String mDbPort                 = null;
  private  String mDbSid                  = null;

 /**
  *  Default constructor
  */
  public PartnerSSOEnabler()
  {
  }

 /**
  * Constructor - sets member variables
  */
  public PartnerSSOEnabler(String pListenerToken,String pRequestedUrl,String pOnCancelUrl,
    String pPappCookieName, String pPappCookieDomain, String pPappCookieScope,
    String pPappCookieDesc, String pSchema, String pPassword, String pDbhost,
    String pDbport, String pDbsid)
  {
    setListenerToken(pListenerToken);
    setUrls(pRequestedUrl,pOnCancelUrl);
    setAppCookieInfo(pPappCookieName,pPappCookieDomain,pPappCookieScope,pPappCookieDesc);
    setDbConnectionInfo(pSchema,pPassword,pDbhost,pDbport,pDbsid);
  }

 /**
  *  Set listener token
  */
  public void setListenerToken(String listenerToken)
  {

    mListenerToken = listenerToken;

  }

 /**
  *  Set requested and cancel url
  */
  public void setUrls(String requestedUrl, String cancelUrl)
  {

    mRequestedUrl = requestedUrl;
    mOnCancelUrl  = cancelUrl;

  }

 /**
  * Set application cookie information
  */
  public void setAppCookieInfo(String name, String domain, String path,String desc)
  {

    mPartnerAppCookieName        = name;
    mPartnerAppCookieDomain      = domain;
    mPartnerAppCookieScope       = path;
    mPartnerAppCookieDesc        = desc;

  }

 /**
  * Set database connection information
  */
  public void setDbConnectionInfo(String schema , String password,
    String hostname, String port, String sid)
  {

    mDbCred   = schema + "/"+ password;
    mDbHost   = hostname;
    mDbPort   = port;
    mDbSid    = sid;

  }

 /**
  * Get partner application cookie name
  */
  public String getAppCookieName()
  {

    return mPartnerAppCookieName;

  }

 /**
  * Get partner application cookie domain
  */
  public String getAppCookieDomain()
  {

    return mPartnerAppCookieDomain;

  }

 /**
  * Get partner application cookie scope
  */
  public String getAppCookieScope()
  {

    return mPartnerAppCookieScope;

  }

 /**
  * Get partner application cookie description
  */
  public String getAppCookieDesc()
  {

    return mPartnerAppCookieDesc;

  }

 /**
  *  getSSOUserInfo(HttpServletRequest, HttpServletResponse) returns
  *  the user name. If the user is not authenticated against SSO server
  *  then it will redirect user to the SSO Server for authentication
  */
  public String getSSOUserInfo(HttpServletRequest request, HttpServletResponse response)
    throws SSOEnablerException
  {

    String userName = null;

    //validation
    if(response == null || response == null)
    {
      throw new SSOEnablerException("Http objects are null");
    }
    if(mListenerToken == null)
    {
      throw new SSOEnablerException("Listener token is null");
    }
    if(mRequestedUrl == null || mOnCancelUrl == null)
    {
      throw new SSOEnablerException("Requested url and cancel url must be set");
    }

    //get user name
    try
    {
      // Get database connection
      Connection dbCon = getDbConnection();

      // Try to get user information from JSP application cookie
      userName = getBakedUserInfo(request);

      //if there is no JSP partner application cookie redirect to login server
      if(userName == null)
      {
        // create SSOEnabler object
        SSOEnabler ssoEnabler = new SSOEnabler(dbCon);

        // create redirect url to the SSO server for user authentication
        String redirectUrl =
          ssoEnabler.generateRedirect(mListenerToken, mRequestedUrl, mOnCancelUrl);

        // close database connection
        closeDbConnection(dbCon);

        // Since the redirect url is usually large, send the redirect url input
        // parameters using HTTP post method instead of usual GET method of
        // response.sendRedirect(redirectUrl);
        String htmlPostForm = SSOEnablerUtil.genHtmlPostForm(redirectUrl);
          response.getWriter().println(htmlPostForm);

        return null;
      }
      else// we got this user information from JSP application cookie
      {
        //unbake cookie and return it
        SSOEnablerUtil ssoAppUtil = new SSOEnablerUtil(dbCon);
        return ssoAppUtil.unbakeAppCookie(mListenerToken, userName);
      }
    }
    catch(Exception e)
    {
      throw new SSOEnablerException(e.toString());
    }
  }//getSSOUserInfo

 /**
  *  getSSOUserInfo(HttpServletRequest) returns the user name.
  *  If the user is not authenticated against the SSO server then the method
  *  will return null.
  *  Usage: This method is used in portlets to check if a user is authenticated.
  */
  public String getSSOUserInfo(HttpServletRequest request)
    throws SSOEnablerException
  {

    String userName = null;

    //validation
    if(request == null )
    {
      throw new SSOEnablerException("Http object is null");
    }
    if(mListenerToken == null)
    {
      throw new SSOEnablerException("Listener token is null");
    }
    if(mRequestedUrl == null || mOnCancelUrl == null)
    {
      throw new SSOEnablerException("Requested url and cancel url must be set");
    }

    //get user name
    try
    {
      // Get database connection
      Connection dbCon = getDbConnection();

      // Try to get user information from JSP application cookie
      userName = getBakedUserInfo(request);

      //if there is no JSP partner application cookie return null
      if(userName == null)
      {
        return null;
      }
      else// we got this user information from JSP application cookie
      {
        // We got this user information from JSP application cookie
        SSOEnablerUtil ssoAppUtil = new SSOEnablerUtil(dbCon);
        return ssoAppUtil.unbakeAppCookie(mListenerToken, userName);
      }
    }
    catch(Exception e)
    {
      throw new SSOEnablerException(e.toString());
    }
  }//getSSOUserInfo

 /**
  *  Get  user information from JSP application cookie
  *  Note: The method returns user information that is encrypted.
  */
  public String getBakedUserInfo(HttpServletRequest request)
    throws SSOEnablerException
  {

    boolean gotPartnerAppCookie = false;
    String  userInfo      = null;

    //validation
    if(mPartnerAppCookieName == null)
      throw new SSOEnablerException("Cookie name is null");

    // get cookie information
    try
    {
      Cookie[] cookies = request.getCookies();
      for(int i=0; i < cookies.length; i++)
      {
        Cookie partnerAppCookie = cookies[i];

        if (partnerAppCookie.getName().equals(mPartnerAppCookieName))
        {
          gotPartnerAppCookie = true;
          userInfo      = partnerAppCookie.getValue();
          break;
        }
      }
    }
    catch(Exception e)
    {
      return null;
    }

    if( (userInfo != null) && (userInfo.length() > 0) )
    {
      return userInfo;
    }
    else
    {
      return null;
    }
  }//getBakedUserInfo

 /**
  *  setPartnerAppCookie will set application cookie from SSO server token and
  *  then redirect user to the JSP application. If the cookie is created and
  *  the user is redirected then the method will return true. If the SSO
  *  server token was not passed then the method returns false.
  *  The SSO server token is passed by the SSO server when the sso server
  *  is redirecting back to the JSP application after sucessful user
  *  authentication.
  */
  public boolean setPartnerAppCookie(HttpServletRequest request,
    HttpServletResponse response)
    throws SSOEnablerException
  {

    SSOUserInfo ssoUserInfo = null;
    String urlParam = null;

    //validation
    if(request == null || response == null)
    {
      throw new SSOEnablerException("Http objects are null");
    }
    if(mListenerToken == null)
    {
      throw new SSOEnablerException("Listener token is null");
    }
    if( mPartnerAppCookieName    == null
      || mPartnerAppCookieDomain == null
      || mPartnerAppCookieScope  == null
      || mPartnerAppCookieDesc   == null)
    {
      throw new SSOEnablerException("Application cookie information is not available");
    }

    //set cookie
    try
    {
      //get SSO server token
      try
      {
        urlParam = request.getParameterValues("urlc")[0];
      }
      catch(java.lang.NullPointerException e) //if no urlc then this happens
      {
        urlParam = null;
      }

      //if the SSO server token exists, set the cookie
      if(urlParam != null)
      {
        // Get database connection
        Connection dbCon = getDbConnection();

        // Create SSOEnabler object
        SSOEnabler ssoEnabler  = new SSOEnabler(dbCon);

        // Get IP address of the client
        InetAddress clientIp = InetAddress.getByName(request.getRemoteAddr());
        ssoUserInfo = ssoEnabler.getSSOUserInfo(mListenerToken, urlParam, clientIp);

        // Set JSP application cookie
        SSOEnablerUtil ssoAppUtil = new SSOEnablerUtil(dbCon);
        String bakedAppCookie =
          ssoAppUtil.bakeAppCookie(mListenerToken,ssoUserInfo.getSSOUserName());

        // Close database connection
        closeDbConnection(dbCon);

        // Create JSP application cookie and set it
        Cookie jspAppCookie = new Cookie(mPartnerAppCookieName,
          bakedAppCookie);
        jspAppCookie.setDomain(mPartnerAppCookieDomain);
        // In-memory cookie for better security
        jspAppCookie.setMaxAge(-1);
        jspAppCookie.setPath(mPartnerAppCookieScope);
        jspAppCookie.setComment(mPartnerAppCookieDesc);
        response.addCookie(jspAppCookie);

        String reqRedirHtmlStr = SSOEnablerUtil.genRedirect(
          ssoUserInfo.getUrlRequested());
        response.getWriter().println(reqRedirHtmlStr);

        return true;
      }
      else//SSO server token does not exists
      {
        return false;
      }
    }
    catch(Exception e)
    {
      throw new SSOEnablerException(e.toString());
    }

  }//setPartnerAppCookie


 /**
  *  bakeAppCookie encrypts a cookie.
  */
  public String bakeAppCookie(String unbakedAppCookie)
    throws SSOEnablerException
  {

    try
    {
      //Open connection
      Connection dbCon = getDbConnection();

      // Set JSP application cookie
      SSOEnablerUtil ssoAppUtil = new SSOEnablerUtil(dbCon);

      String bakedAppCookie =
        ssoAppUtil.bakeAppCookie(mListenerToken, unbakedAppCookie);

      // Close database connection
      closeDbConnection(dbCon);

      return bakedAppCookie;
    }
    catch(Exception e)
    {
      throw new SSOEnablerException(e.toString());
    }

  }//bakeAppCookie


 /**
  * removeJspAppCookie removes the partner application cookie. This ends the
  * user application session
  */
  public void removeJspAppCookie(HttpServletResponse response)
    throws SSOEnablerException
  {

    //validation
    if(response == null)
    {
      throw new SSOEnablerException("HttpServletResponse is null");
    }
    if( mPartnerAppCookieName  == null
      || mPartnerAppCookieDomain == null
      || mPartnerAppCookieScope  == null
      || mPartnerAppCookieDesc   == null)
    {
      throw new SSOEnablerException("Application cookie information is not available");
    }

    //remove the cookie
    Cookie JspAppCookie = new Cookie(mPartnerAppCookieName, "End application sesion");
    JspAppCookie.setDomain(mPartnerAppCookieDomain);
    JspAppCookie.setMaxAge(0);
    JspAppCookie.setPath(mPartnerAppCookieScope);
    JspAppCookie.setComment(mPartnerAppCookieDesc);
    response.addCookie(JspAppCookie);

  }//removeJspAppCookie


 /**
  * getDbConnection gets a database connection to the schema where the partner
  * application packages are installed and configured.
  */
  private Connection getDbConnection()
    throws SSOEnablerException
  {

    // set the database connection string
    String connectString =
      "jdbc:oracle:thin:" + mDbCred + "@"
      + "(description="
      + "(address_list="
      + "(address=(protocol=tcp)(host=" + mDbHost + ")(port=" + mDbPort + ")))"
      + "(source_route=yes)(connect_data=(sid=" + mDbSid + ")))";

    try
    {
      // Get a database connection
      Class.forName ("oracle.jdbc.driver.OracleDriver");
      Connection dbCon = DriverManager.getConnection(connectString);
      return dbCon;
    }
    catch(Exception e)
    {
      throw new SSOEnablerException(e.toString());
    }

  }//getDbConnection

 /**
  * closeDbConnection releases the database connection to the schema where
  * the partner application packages are installed and configured.
  */
  private void closeDbConnection(Connection dbCon)
    throws SSOEnablerException
  {

    //close the database connection
    try
    {
      dbCon.close();
    }
    catch(Exception e)
    {
      throw new SSOEnablerException(e.toString());
    }

  }//closeDbConnection

}

