/*
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 * (the "License"); you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
 * 
 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
 * language governing rights and limitations under the License.
 * 
 * The Original Code is the Venice Web Communities System.
 * 
 * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
 * for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 * Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios.  All Rights Reserved.
 * 
 * Contributor(s): 
 */
package com.silverwrist.venice.sourceid;

import java.util.*;
import javax.servlet.ServletContext;
import org.apache.log4j.Logger;
import org.sourceid.sso.handlers.AccountHandler;
import org.sourceid.sso.util.NameIdentifierPair;
import org.sourceid.sso.xml.saml.NameIdentifierType;
import com.silverwrist.util.*;
import com.silverwrist.dynamo.WebConstants;
import com.silverwrist.dynamo.app.ApplicationContainer;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.servlet.ServletBase;
import com.silverwrist.dynamo.util.*;

public class VeniceAccountHandler implements AccountHandler
{
  /*--------------------------------------------------------------------------------
   * Static data members
   *--------------------------------------------------------------------------------
   */

  private static Logger logger = Logger.getLogger(VeniceAccountHandler.class);

  /*--------------------------------------------------------------------------------
   * Attributes
   *--------------------------------------------------------------------------------
   */

  private ServletContext m_ctxt = null;
  private ApplicationContainer m_container = null;
  private FederationManager m_fm = null;

  /*--------------------------------------------------------------------------------
   * Constructor
   *--------------------------------------------------------------------------------
   */

  public VeniceAccountHandler()
  { // do nothing
  } // end constructor

  /*--------------------------------------------------------------------------------
   * Internal operations
   *--------------------------------------------------------------------------------
   */

  private static final Map getInitParams(ServletContext ctxt)
  {
    String pstr = ctxt.getInitParameter("SSO.config.attrs");
    if (pstr==null)
      return Collections.EMPTY_MAP;  // no parameters
    String[] parms = StringUtils.split(pstr.trim(),",");
    HashMap rc = new HashMap();
    for (int i=0; i<parms.length; i++)
    { // split each value pair at the = sign and add it to the return map
      String[] pair = StringUtils.split(parms[i].trim(),"=");
      rc.put(pair[0].trim(),pair[1].trim());

    } // end for

    if (rc.isEmpty())
      return Collections.EMPTY_MAP;
    else
      return Collections.unmodifiableMap(rc);

  } // end getInitParams

  private static final String serializeNameID(NameIdentifierType nid)
  {
    StringBuffer buf = new StringBuffer();
    if (nid.getContent()!=null)
      buf.append(nid.getContent());
    buf.append(':');
    if (nid.getNameQualifier()!=null)
      buf.append(nid.getNameQualifier());
    buf.append(':');
    if (nid.getFormat()!=null)
      buf.append(nid.getFormat());
    return buf.toString();

  } // end serializeNameID

  private static final NameIdentifierType deserializeNameID(String data)
  {
    String[] elts = StringUtils.split1(data,':');
    for (int i=0; i<elts.length; i++)
      if ((elts[i]!=null) && (elts[i].length()==0))
	elts[i] = null;
    NameIdentifierType rc = new NameIdentifierType();
    rc.setContent(elts[0]);
    rc.setNameQualifier(elts[1]);
    rc.setFormat(elts[2]);
    return rc;

  } // end deserializeNameID

  /*--------------------------------------------------------------------------------
   * Implementations from interface AccountHandler
   *--------------------------------------------------------------------------------
   */

  public void init(ServletContext servletContext) throws Exception
  {
    if (logger.isDebugEnabled())
      logger.debug("Initializing VeniceAccountHandler");

    // Get the servlet context, then the application container, and add a reference to it.
    m_ctxt = servletContext;
    m_container = ServletBase.getApplicationContainer(servletContext);
    if (m_container==null)
      throw new ConfigException(VeniceAccountHandler.class,"SourceIDMessages","noinit");
    m_container.addRef();

    // Get the initialization parameters and service provider.
    Map params = getInitParams(servletContext);
    ServiceProvider services = m_container.getInitServices();

    // Get the Dynamo object to which we delegate most of this stuff.
    String objname = (String)(params.get("object"));
    if (objname==null)
      throw new ConfigException(VeniceAccountHandler.class,"SourceIDMessages","noobject");
    if (logger.isDebugEnabled())
      logger.debug("Looking for FederationManager with object name \"" + objname + "\"");
    m_fm = (FederationManager)(GetObjectUtils.getDynamoComponent(services,FederationManager.class,objname));

  } // end init
	
  public void destroy() throws Exception
  {
    if (logger.isDebugEnabled())
      logger.debug("Destroying VeniceAccountHandler");
    m_fm = null;
    if ((m_container!=null) && m_container.release())
      m_ctxt.removeAttribute(WebConstants.APPLICATION_ATTRIBUTE);
    m_container = null;
    m_ctxt = null;

  } // end destroy
	
  public void federate(Object userID, String providerID, NameIdentifierPair namePair) throws Exception
  {
    m_fm.addFederation((DynamoUser)userID,providerID,serializeNameID(namePair.getLocalProvided()),
                       serializeNameID(namePair.getRemoteProvided()));

  } // end federate

  public void defederate(Object userID, String providerID) throws Exception
  {
    m_fm.removeFederation((DynamoUser)userID,providerID);

  } // end defederate
	
  public Object getUserID(String providerID, NameIdentifierType nameIdentifier, boolean isLocalProvidedNameIdentifier)
      throws Exception
  {
    return m_fm.lookupFederatedUser(providerID,serializeNameID(nameIdentifier),isLocalProvidedNameIdentifier);

  } // end getUserID
	
  public NameIdentifierPair getNamePair(Object userID, String providerID) throws Exception
  {
    String[] names = m_fm.getFederatedNames((DynamoUser)userID,providerID);
    if (names==null)
      return null;
    NameIdentifierPair rc = new NameIdentifierPair();
    rc.setLocalProvided(deserializeNameID(names[0]));
    rc.setRemoteProvided(deserializeNameID(names[1]));
    return rc;

  } // end getNamePair
	
} // end class VeniceAccountHandler
