using Amazon.DynamoDBv2.DocumentModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using ThirdParty.Json.LitJson;
namespace Amazon.DynamoDBv2.DataModel
{
///
/// S3Link is an object that provides a connection to an S3 resource
/// that can be stored in a DynamoDB field through DynamoDBContext
///
public partial class S3Link
{
#region Statics
internal static Dictionary Caches = new Dictionary();
private static Object cacheLock = new Object();
/////
///// Allows the use of a specific config in the creation of the client for a context
/////
///// The context the client should be used in
///// The config object for the client
//public static void UseConfigForClient(DynamoDBContext context, AmazonS3Config config)
//{
// var castedClient = ((AmazonDynamoDBClient)context.Client);
// var client = new AmazonS3Client(castedClient.GetCredentials(), config);
// S3ClientCache cache;
// if (!S3Link.Caches.TryGetValue(context, out cache))
// {
// cache = new S3ClientCache(castedClient.GetCredentials(),castedClient.CloneConfig());
// S3Link.Caches.Add(context, cache);
// }
// cache.UseClient(client, config.RegionEndpoint);
//}
///
/// Creates an S3Link that can be used to managed an S3 connection
///
/// The context that is handling the S3Link
/// The bucket the S3Link should manage
/// The key that S3Link should store and download from
/// The region of the S3 resource
/// A new S3Link object that can upload and download to the target bucket
public static S3Link Create(DynamoDBContext context, string bucket, string key, Amazon.RegionEndpoint region)
{
S3ClientCache cacheFromKey;
if (S3Link.Caches.TryGetValue(context, out cacheFromKey))
{
return new S3Link(cacheFromKey, bucket, key, region.SystemName);
}
S3ClientCache cache = CreatClientCacheFromContext(context);
return new S3Link(cache, bucket, key, region.SystemName);
}
#endregion
#region Properties
private S3ClientCache s3ClientCache;
private LinkInfo linker;
///
/// The Key that S3Link stores and downloads a resource to and from
///
public string Key
{
get
{
return this.linker.s3.key;
}
set
{
this.linker.s3.key = value;
}
}
///
/// The name of the target Bucket for the managed resource
///
public string BucketName
{
get
{
return this.linker.s3.bucket;
}
set
{
this.linker.s3.bucket = value;
}
}
///
/// The region the S3 resource is in
///
public string Region
{
get
{
if (String.IsNullOrEmpty(this.linker.s3.region))
{
return "us-east-1";
}
return this.linker.s3.region;
}
set
{
if (String.IsNullOrEmpty(value))
{
this.linker.s3.region = "us-east-1";
}
this.linker.s3.region = value;
}
}
///
/// Looks up RegionEndpoint based on region as a string
///
public RegionEndpoint RegionAsEndpoint
{
get
{
if (linker.s3.region == null)
{
return RegionEndpoint.GetBySystemName("us-east-1");
}
return RegionEndpoint.GetBySystemName(linker.s3.region);
}
}
#endregion
#region Constuctors
internal S3Link(S3ClientCache clientCache, string bucketName, string key)
: this(clientCache, new LinkInfo(bucketName, key)) { }
internal S3Link(S3ClientCache clientCache, string bucketName, string key, string region)
: this(clientCache, new LinkInfo(bucketName, key, region)) { }
private S3Link(S3ClientCache clientCache, LinkInfo linker)
{
if (linker == null) throw new ArgumentNullException("linker");
if (clientCache == null) throw new ArgumentNullException("clientCache");
this.s3ClientCache = clientCache;
this.linker = linker;
}
internal S3Link(S3ClientCache clientCache, string json)
{
if (clientCache == null) throw new ArgumentNullException("clientCache");
if (json == null) throw new ArgumentNullException("json");
this.s3ClientCache = clientCache;
linker = JsonMapper.ToObject(json);
}
internal static RegionEndpoint GetRegionFromJSON(string json)
{
var linker = JsonMapper.ToObject(json);
if (linker.s3.region == null)
{
return RegionEndpoint.GetBySystemName("us-east-1");
}
return RegionEndpoint.GetBySystemName(linker.s3.region);
}
#endregion
#region Methods
#region Small getters
internal static S3ClientCache CreatClientCacheFromContext(DynamoDBContext context)
{
var client = ((AmazonDynamoDBClient)context.Client);
var cache = new S3ClientCache(client);
lock (S3Link.cacheLock)
{
S3Link.Caches[context] = cache;
}
return cache;
}
#endregion
#region Misc
///
/// Provides a URL for accessing the S3 object managed by S3Link
///
/// The time the link should become invalid
/// A URL directing to the S3 object
public string GetPreSignedURL(DateTime expiration)
{
return this.s3ClientCache.GetClient(this.RegionAsEndpoint).GeneratePreSignedURL(this.linker.s3.bucket, this.linker.s3.key, expiration, null);
}
internal string ToJson()
{
return JsonMapper.ToJson(linker);
}
#endregion
#endregion
#region Helper Classes
internal class S3LinkConverter : IPropertyConverter
{
private DynamoDBContext context;
public S3LinkConverter(DynamoDBContext context)
{
this.context = context;
}
public DocumentModel.DynamoDBEntry ToEntry(object value)
{
Primitive S3string = ((S3Link)value).ToJson();
return S3string;
}
public object FromEntry(DocumentModel.DynamoDBEntry entry)
{
S3ClientCache cache;
if (!S3Link.Caches.TryGetValue(context, out cache))
{
cache = S3Link.CreatClientCacheFromContext(context);
}
return new S3Link(cache, entry.AsString());
}
}
private class LinkInfo
{
public S3 s3 { get; set; }
// For JSON mapper
public LinkInfo() { }
public LinkInfo(string bucketName, string key)
: this(bucketName, key, null) { }
public LinkInfo(string bucketName, string key, string region)
{
if (bucketName == null) throw new ArgumentNullException("bucketName");
if (key == null) throw new ArgumentNullException("key");
if (String.IsNullOrEmpty(region))
{
region = null;
}
s3 = new S3(bucketName, key, region);
}
}
private class S3
{
public string bucket { get; set; }
public string key { get; set; }
public string region { get; set; }
// For JSON mapper
public S3() { }
public S3(string bucketName, string key, string region)
{
this.bucket = bucketName;
this.key = key;
if (String.IsNullOrEmpty(region))
{
region = null;
}
this.region = region;
}
}
#endregion
}
}