/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
using Amazon.Runtime;
using Amazon.Runtime.Internal.Settings;
using Amazon.Runtime.Internal.Util;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
namespace Amazon.Util.Internal
{
///
/// Manager to access a settings store file. Objects are primarily accessed by DisplayName rather than unique key.
/// Settings store files are located under the current user's AppData\Local\AWSToolkit folder.
/// Select keys in these files are encrypted on a per user, per machine basis using the Windows Data Protection API;
/// the encrypted values cannot be used by any other user or on any other machine.
///
/// This class is not threadsafe.
///
public class NamedSettingsManager
{
///
/// True if the encrypted store is availble, false otherwise.
///
public static bool IsAvailable
{
get { return UserCrypto.IsUserCryptAvailable; }
}
private SettingsManager settingsManager;
///
/// Construct an NamedSettingsManager.
///
/// The base filename to read/write.
public NamedSettingsManager(string settingsType)
{
settingsManager = new SettingsManager(settingsType);
}
///
/// Register an object. Let the uniqueKey be assigned automatically.
///
/// The display name for the object.
/// The property names and values for the object.
/// The unique key that was assigned to the object.
public string RegisterObject(string displayName, Dictionary properties)
{
if (string.IsNullOrEmpty(displayName))
throw new ArgumentException("displayName cannot be null or empty.");
var propertiesPlusName = new Dictionary(properties);
propertiesPlusName[SettingsConstants.DisplayNameField] = displayName;
string uniqueKey;
if (settingsManager.TryGetObjectByProperty(SettingsConstants.DisplayNameField, displayName, out uniqueKey, out properties))
return settingsManager.RegisterObject(uniqueKey, propertiesPlusName);
else
return settingsManager.RegisterObject(propertiesPlusName);
}
///
/// Try to get an object form the store.
///
/// The display name for the object.
/// The property names and values for the object.
/// True if the object was found, false otherwise.
public bool TryGetObject(string displayName, out Dictionary properties)
{
string uniqueKey;
return TryGetObject(displayName, out uniqueKey, out properties);
}
///
/// Try to get an object form the store.
///
/// The display name for the object.
/// The uniqueKey of the object in the store
/// The property names and values for the object.
/// True if the object was found, false otherwise.
public bool TryGetObject(string displayName, out string uniqueKey, out Dictionary properties)
{
return settingsManager.TryGetObjectByProperty(SettingsConstants.DisplayNameField, displayName, out uniqueKey, out properties);
}
///
/// Unregister an object from the store.
///
/// The display name for the object.
public void UnregisterObject(string displayName)
{
string uniqueKey;
Dictionary properties;
if (settingsManager.TryGetObjectByProperty(SettingsConstants.DisplayNameField, displayName, out uniqueKey, out properties))
{
settingsManager.UnregisterObject(uniqueKey);
}
}
///
/// Rename an object in the store.
///
///
///
/// if true and destination object already exists overwrite it
public void RenameObject(string oldDisplayName, string newDisplayName, bool force)
{
Dictionary fromObject;
string fromUniqueKey;
Dictionary toObject;
string toUniqueKey;
if (TryGetObject(oldDisplayName, out fromUniqueKey, out fromObject))
{
if (TryGetObject(newDisplayName, out toUniqueKey, out toObject))
{
// if oldDisplayName == newDisplayName it's a no op
if (!string.Equals(oldDisplayName, newDisplayName, StringComparison.Ordinal))
{
if (force)
{
settingsManager.UnregisterObject(toUniqueKey);
// recursive call with force == false now that the destination object is gone
RenameObject(oldDisplayName, newDisplayName, false);
}
else
throw new ArgumentException("Cannot rename object. The destination object '" + newDisplayName + "' already exists.");
}
}
else
{
fromObject[SettingsConstants.DisplayNameField] = newDisplayName;
settingsManager.RegisterObject(fromUniqueKey, fromObject);
}
}
else
throw new ArgumentException("Cannot rename object. The source object '" + oldDisplayName + "' does not exist.");
}
///
/// Copy an object in the store.
/// The new object will be a copy of the original, except it will be assigned a new unique key.
///
///
///
/// if true and destination object already exists overwrite it
public void CopyObject(string fromDisplayName, string toDisplayName, bool force)
{
Dictionary fromObject;
Dictionary toObject;
string toUniqueKey;
if (TryGetObject(fromDisplayName, out fromObject))
{
if (TryGetObject(toDisplayName, out toUniqueKey, out toObject))
{
// if fromDisplayName == toDisplayName it's a no op
if (!string.Equals(fromDisplayName, toDisplayName, StringComparison.Ordinal))
{
if (force)
{
settingsManager.UnregisterObject(toUniqueKey);
// recursive call with force == false now that the destination object is gone
CopyObject(fromDisplayName, toDisplayName, force);
}
else
throw new ArgumentException("Cannot copy object. The destination object '" + toDisplayName + "' already exists.");
}
}
else
{
// Register the copy. A new unique key will be automatically assigned.
RegisterObject(toDisplayName, fromObject);
}
}
else
throw new ArgumentException("Cannot copy object. The source object '" + fromDisplayName + "' does not exist.");
}
///
/// Get a list of the display names for the objects in the store.
///
/// A list of display names.
public List ListObjectNames()
{
return settingsManager.SelectProperty(SettingsConstants.DisplayNameField);
}
}
}