/***********************************************************************
 * 
 *  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;

/**
 * AuthMechConfig Class.
 * <p>
 * This class obtains and maintains configuration for authentication mechanisms.
 * 
 */
public final class AuthMechConfig
{
   private static final Logger m_log = Logger.getLogger(AuthMechConfig.class);

   // Well known authentication token configuration settings
   public final static String ClassName = "ClassName";
   public final static String RelativeClassPath = "RelativeClassPath";
   public final static String ClassPath = "ClassPath";
   public final static String Krb5ServicePrincipalName = "ServicePrincipalName";

   // Default configuration values
   private final String m_defaultKrb5ServicePrincipalNameValue = "host";

   private final Map<String,String> m_mechSettingsMap;

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

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

   /**
    * Constructor.
    *
    * @param mechSettingsFileName   Name of mechanism's settings file.
    * @throws Exception
    */
   public AuthMechConfig(String mechSettingsFileName) throws Exception
   {
      m_log.debug("Constructor()-");

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

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

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

         InputSource source = new InputSource(inStream);
         xr.parse(source);
      }
      catch (SAXException e)
      {
        m_log.warn("Constructor()- " + mechSettingsFileName + " format error, exception: " + e.toString());
        throw new Exception("Constructor- authtoken.settings format error", e);
      }
      catch (SecurityException e)
      {
         m_log.warn("Constructo()r- SecurityException accessing " + mechSettingsFileName + " Exception=" + e.toString());
         throw new Exception("Constructor- Not able to access file", e);
      }
      catch (FileNotFoundException e)
      {
         m_log.debug("Constructor()- File " + mechSettingsFileName + " not found");
         throw new Exception("Constructor- File not found", e);
      }
      catch (IOException e)
      {
         m_log.warn("Constructor()- IOException accessing " + mechSettingsFileName + " Exception=" + e.toString());
         throw new Exception("Constructor- 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_mechSettingsMap.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.equals(Krb5ServicePrincipalName))
         {
            value = m_defaultKrb5ServicePrincipalNameValue;
            m_log.debug("getSetting()- Assigning default value " + value);

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

      return value;
   }
}