/***********************************************************************
 * 
 *  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 java.io.*;
import java.util.*;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
import org.apache.log4j.Logger;

/**
 * IdenTokenConfig Class.
 * <p>
 * This class obtains and maintains identity token configuration.
 * 
 */
public final class IdenTokenConfig
{
   private static final Logger m_log = Logger.getLogger(IdenTokenConfig.class);

   // Well known identity token configuration settings
   public final static String EncryptAttributes = "EncryptAttributes";
   public final static String Attributes = "Attributes";

   // Default configuration values
   private final String m_defaultEncryptAttributesValue = "false";
   private final String m_defaultAttributesValue = "sn";

   private final Map<String,String>       m_tokenSettingsMap;
   private String[]  m_identityAttributes;

   /**
    * Constructor which sets default configuration values.
    */
   public IdenTokenConfig()
   {
      m_log.debug("Constructor()- Default");

      // Create a map to keep track of the token settings
      m_tokenSettingsMap = new HashMap<String, String>();

      // Set the default settings in our map
      m_tokenSettingsMap.put(Attributes, m_defaultAttributesValue);
   }

   /**
    * Constructor.
    *
    * @param idenTokenSettingsFileName   Name of identity token settings file.
    * @throws Exception
    */
   public IdenTokenConfig(String idenTokenSettingsFileName) throws Exception
   {
      m_log.debug("Constructor()-");

      // Create a map to keep track of the token settings
      m_tokenSettingsMap = new HashMap<String, String>();

      FileInputStream inStream = null;
      try
      {
         // Get an input stream to read from the token settings file
         File f = new File(idenTokenSettingsFileName);
         inStream = new FileInputStream(f);

         // Parse the file
         XMLReader xr = XMLReaderFactory.createXMLReader();
         SettingsFileSAXHandler handler = new SettingsFileSAXHandler(m_tokenSettingsMap);
         xr.setContentHandler(handler);
         xr.setErrorHandler(handler);

         InputSource source = new InputSource(inStream);
         xr.parse(source);

         // Process the specified attributes
         if (m_tokenSettingsMap.containsKey(Attributes) == false)
         {
            m_log.debug("Constructor()- Attributes not configured, defaulting them.");
            m_tokenSettingsMap.put(Attributes, m_defaultAttributesValue);
         }
         String attributes = m_tokenSettingsMap.get(Attributes);
         m_identityAttributes = attributes.split(",");
      }
      catch (SAXException e)
      {
        m_log.warn("Constructor()- " + idenTokenSettingsFileName + " format error, exception: " + e.toString());
        throw new Exception("IdenTokenConfig()- authtoken.settings format error", e);
      }
      catch (SecurityException e)
      {
         m_log.warn("Constructor()- SecurityException accessing " + idenTokenSettingsFileName + " Exception=" + e.toString());
         throw new Exception("IdenTokenConfig()- Not able to access file", e);
      }
      catch (FileNotFoundException e)
      {
         m_log.debug("Constructor()- File " + idenTokenSettingsFileName + " not found");
         throw new Exception("IdenTokenConfig()- File not found", e);
      }
      catch (IOException e)
      {
         m_log.warn("Constructor()- IOException accessing " + idenTokenSettingsFileName + " Exception=" + e.toString());
         throw new Exception("IdenTokenConfig()- Read error", e);
      }
      finally
      {
         if (inStream != null)
         {
            try
            {
               inStream.close();
            }
            catch (IOException e)
            {
               // Do nothing
            }
         }
      }
   }

   /**
    * Returns the value associated with the specified setting.
    *
    * @param settingName   Name of the setting.
    * @return              Value of the specified setting.
    */
   public final String getSetting(String settingName)
   {
      // Try to find the setting in our map
      String value = m_tokenSettingsMap.get(settingName);
      if (value == null)
      {
         m_log.debug("getSetting()- Did not find setting " + settingName);

         // The setting is not in our map, check if it is one to
         // which we have defaults.
         if (settingName.equalsIgnoreCase(EncryptAttributes))
         {
            value = m_defaultEncryptAttributesValue;
            m_log.debug("getSetting()- Assigning default value " + value);

            // Add the key to the map so that it can be found quicker next time
            m_tokenSettingsMap.put(EncryptAttributes, m_defaultEncryptAttributesValue);
         }
      }
      else
      {
         m_log.debug("getSetting()- Found setting " + settingName);
         m_log.debug("getSetting()- Setting value = " + value);
      }

      return value;
   }

   /**
    * Returns the identity attributes that must be included in the token.
    *
    * @return Identity Attributes.
    */
   public final String[] getAttributes()
   {
      return m_identityAttributes;
   }
}