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

/**
 *
 * Class for the creation and editing of svc.settings files.
 *
 */
public final class SvcSettingsEditor implements IVerifySetting
{
   private static final String usage =
      "usage: SvcSettingsEditor -op [settingName [settingValue]] -file settingsFilePath\n\n" +
      "   where:\n" +
      "      -op - Corresponds to one of the following operations:\n" +
      "         -create - Create new svc settings file\n" +
      "         -list   - List settings\n" +
      "         -get    - Get settings, must be followed by settingName parameter\n" +
      "         -set    - Set settings, must be followed by settingName and settingValue parameters\n" +
      "         -remove - Remove settings\n" +
      "      -file - Path the the svc settings file\n" +
      "      settingName - Name of the setting being retrieved or set\n" +
      "      settingValue - Value of the setting being set\n\n" +
      "   The following settings are valid:\n" +
      "      SessionTokenLifetime\n" +
      "      LifetimeShorter\n" +
      "      IAConfigFile\n" +
      "      ReconfigureInterval\n" +
      "      SigningKeyAliasName\n" +
      "      SigningKeyPassword\n";

   private static final String settings =
      "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
      "<settings>\n" +
      "  <IAConfigFile>/etc/CASA/authtoken/svc/iaRealms.xml</IAConfigFile>\n" +
      "</settings>\n";


   /**
    * Checks if the specified setting is valid.
    *
    * @param setting The name of the setting being checked.
    * @return        True if the specified setting is valid.
    */
   public final boolean validSetting(String setting)
   {
      boolean result = false;

      if (setting.equalsIgnoreCase(SvcConfig.SessionTokenLifetime))
         result = true;
      else if (setting.equalsIgnoreCase(SvcConfig.LifetimeShorter))
         result = true;
      else if (setting.equalsIgnoreCase(SvcConfig.IdentityAbstractionConfigFile))
         result = true;
      else if (setting.equalsIgnoreCase(SvcConfig.ReconfigureInterval))
         result = true;
      else if (setting.equalsIgnoreCase(SvcConfig.SigningKeyAliasName))
         result = true;
      else if (setting.equalsIgnoreCase(SvcConfig.SigningKeyPassword))
         result = true;
      else
         System.err.println("Invalid setting specified");

      return result;
   }

   /**
    * Checks if the specified setting is valid in conjunction
    * with the specified value.
    *
    * @param setting The name of the setting being checked.
    * @param value   The value of the specified setting.
    * @return        The formal name of the setting if found to be valid.
    */
   public final String validSettingNameAndValue(String setting,
                                                String value)
   {
      String validSetting = null;

      if (setting.equalsIgnoreCase(SvcConfig.SessionTokenLifetime))
      {
         // Verify that we are dealing with a numeric value
         try
         {
            Integer.valueOf(value);

            // Good
            validSetting = SvcConfig.SessionTokenLifetime;
         }
         catch (NumberFormatException e)
         {
            System.err.println("Invalid setting value specified");
         }
      }
      else if (setting.equalsIgnoreCase(SvcConfig.LifetimeShorter))
      {
         // Verify that we are dealing with a numeric value
         try
         {
            Integer.valueOf(value);

            // Good
            validSetting = SvcConfig.LifetimeShorter;
         }
         catch (NumberFormatException e)
         {
            System.err.println("Invalid setting value specified");
         }
      }
      else if (setting.equalsIgnoreCase(SvcConfig.IdentityAbstractionConfigFile))
      {
         // Output a warning if the specified file does not exist
         try
         {
            File f = new File(value);
            if (f.exists() == false)
            {
               System.err.println("Warning: File " + value + " does not exist");
            }
         }
         catch (SecurityException e)
         {
            System.err.println("Warning: Not able to access file " + value);
         }

         // Always succeed
         validSetting = SvcConfig.IdentityAbstractionConfigFile;
      }
      else if (setting.equalsIgnoreCase(SvcConfig.ReconfigureInterval))
      {
         // Verify that we are dealing with a numeric value
         try
         {
            Integer.valueOf(value);

            // Good
            validSetting = SvcConfig.ReconfigureInterval;
         }
         catch (NumberFormatException e)
         {
            System.err.println("Invalid setting value specified");
         }
      }
      else if (setting.equalsIgnoreCase(SvcConfig.SigningKeyAliasName))
      {
         validSetting = SvcConfig.SigningKeyAliasName;
      }
      else if (setting.equalsIgnoreCase(SvcConfig.SigningKeyPassword))
      {
         validSetting = SvcConfig.SigningKeyPassword;
      }
      else
         System.err.println("Invalid setting specified");

      return validSetting;
   }

   /**
   *  Applications Entry Point
   *
   * @param args  Argument.
   */
   public static void main(String[] args)
   {
      String op = null;
      boolean opPerformed = false;
      boolean argumentsError = false;
      String filePath = null;
      String setting = null;
      String value = null;
      SvcSettingsEditor editor = new SvcSettingsEditor();

      // Process the command line arguments
      for (int i = 0; i < args.length; i++)
      {
         // Proceed based on the command
         if (args[i].equalsIgnoreCase("-file"))
         {
            // The next argument should contain the filepath
            if (args.length > (i + 1))
            {
               filePath = args[i + 1];
               i++;
            }
            else
            {
               argumentsError = true;
               break;
            }
         }
         else if (args[i].equalsIgnoreCase("-list"))
         {
            // List operation requested
            if (op == null)
            {
               op = "list";
            }
            else
            {
               argumentsError = true;
               break;
            }
         }
         else if (args[i].equalsIgnoreCase("-create"))
         {
            // List operation requested
            if (op == null)
            {
               op = "create";
            }
            else
            {
               argumentsError = true;
               break;
            }
         }
         else if (args[i].equalsIgnoreCase("-get"))
         {
            // Get setting operation requested
            if (op == null)
            {
               op = "get";

               // The next argument should contain the setting name
               if (args.length > (i + 1))
               {
                  setting = args[i + 1];
                  i++;
               }
               else
               {
                  argumentsError = true;
                  break;
               }
            }
            else
            {
               argumentsError = true;
               break;
            }
         }
         else if (args[i].equalsIgnoreCase("-set"))
         {
            // Set setting operation requested
            if (op == null)
            {
               op = "set";

               // The next two arguments should contain the setting name
               // and the setting value.
               if (args.length > (i + 2))
               {
                  setting = args[i + 1];
                  value = args[i + 2];
                  i += 2;
               }
               else
               {
                  argumentsError = true;
                  break;
               }
            }
            else
            {
               argumentsError = true;
               break;
            }
         }
         else if (args[i].equalsIgnoreCase("-remove"))
         {
            // Remove setting operation requested
            if (op == null)
            {
               op = "remove";

               // The next argument should contain the setting name
               if (args.length > (i + 1))
               {
                  setting = args[i + 1];
                  i++;
               }
               else
               {
                  argumentsError = true;
                  break;
               }
            }
            else
            {
               argumentsError = true;
               break;
            }
         }
         else
         {
            argumentsError = true;
         }
      }

      // Proceed based on the specified parameters
      if (argumentsError == false)
      {
         if (filePath != null && op != null)
         {
            System.err.println("Dealing with settings file: " + filePath);

            // Proceed based on the operation requested
            if (op.compareTo("list") == 0)
            {
               opPerformed = SettingsFileUtil.performListOperation(filePath);
            }
            else if (op.compareTo("create") == 0)
            {
               opPerformed = SettingsFileUtil.performCreateOperation(filePath, settings);
            }
            else if (op.compareTo("get") == 0)
            {
               opPerformed = SettingsFileUtil.performGetOperation(filePath, setting, editor);
            }
            else if (op.compareTo("set") == 0)
            {
               opPerformed = SettingsFileUtil.performSetOperation(filePath, setting, value, editor);
            }
            else if (op.compareTo("remove") == 0)
            {
               opPerformed = SettingsFileUtil.performRemoveOperation(filePath, setting, editor);
            }
            else
            {
               System.err.println("Tool error");
            }
         }
         else
         {
            argumentsError = true;
         }
      }

      // Display the usage string if we encountered an error with the
      // command line arguments.
      if (argumentsError)
         System.out.print(usage);

      // Set the exit code appropriatedly
      if (opPerformed)
         System.exit(0);
      else
         System.exit(1);
   }
}
