Permalink
Browse files

Adds an Windows Azure blob storage repository provider

  • Loading branch information...
lfoust committed May 20, 2012
1 parent 33a88f4 commit 0a7d618a3924dc181fffc177ee7f539c6919226a
Binary file not shown.

Large diffs are not rendered by default.

Oops, something went wrong.
Binary file not shown.

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -62,6 +62,10 @@
<Content Include="HtmlSanitizationLibrary.xml" />
<Content Include="Ionic.Zip.dll" />
<Content Include="MarkdownSharp.dll" />
+ <Content Include="Microsoft.WindowsAzure.ServiceRuntime.dll" />
+ <Content Include="Microsoft.WindowsAzure.ServiceRuntime.xml" />
+ <Content Include="Microsoft.WindowsAzure.StorageClient.dll" />
+ <Content Include="Microsoft.WindowsAzure.StorageClient.xml" />
<Content Include="MongoDB.Bson.dll" />
<Content Include="MongoDB.Bson.xml" />
<Content Include="MongoDB.Driver.dll" />
@@ -0,0 +1,97 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Microsoft.WindowsAzure;
+using Microsoft.WindowsAzure.ServiceRuntime;
+using Microsoft.WindowsAzure.StorageClient;
+using NBlog.Web.Application.Infrastructure;
+using Newtonsoft.Json;
+
+namespace NBlog.Web.Application.Storage.Azure
+{
+ public class AzureBlobRepository : IRepository
+ {
+ private readonly RepositoryKeys _keys;
+ private readonly HttpTenantSelector _tenantSelector;
+ private readonly CloudBlobContainer _container;
+
+ public AzureBlobRepository(RepositoryKeys keys, HttpTenantSelector tenantSelector)
+ {
+ _keys = keys;
+ _tenantSelector = tenantSelector;
+
+ var storage = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue("AzureBlobRepository.ConnectionString"));
+ var blobClient = storage.CreateCloudBlobClient();
+ string name = GetContainerSafeName(tenantSelector);
+ _container = blobClient.GetContainerReference(name);
+ }
+
+ private string GetContainerSafeName(HttpTenantSelector selector)
+ {
+ string name = selector.Name;
+ if (name.Any(c => Char.IsNumber(c)))
+ name = "localhost";
+ return name;
+ }
+
+ private string GetItemPath<TEntity>(string key)
+ {
+ return String.Format("{0}/{1}.json", typeof(TEntity).Name, key);
+ }
+
+ public TEntity Single<TEntity>(object key) where TEntity : class, new()
+ {
+ string relativePath = GetItemPath<TEntity>(key.ToString());
+ CloudBlob blob = _container.GetBlobReference(relativePath);
+ if (!blob.Exists())
+ {
+ throw new FileNotFoundException("The item '" + relativePath + "' could not be found. Container: " + _container.Name + " " + _container.Uri);
+ }
+ string json = blob.DownloadText();
+ var item = JsonConvert.DeserializeObject<TEntity>(json);
+ return item;
+ }
+
+ public IEnumerable<TEntity> All<TEntity>() where TEntity : class, new()
+ {
+ var list = new List<TEntity>();
+ var directory = _container.GetDirectoryReference(typeof(TEntity).Name);
+ var blobs = directory.ListBlobs();
+
+ foreach (var blob in blobs)
+ {
+ CloudBlob b = _container.GetBlobReference(blob.Uri.ToString());
+ string json = b.DownloadText();
+
+ var entity = JsonConvert.DeserializeObject<TEntity>(json);
+ list.Add(entity);
+ }
+
+ return list;
+ }
+
+ public bool Exists<TEntity>(object key) where TEntity : class, new()
+ {
+ string relativePath = GetItemPath<TEntity>(key.ToString());
+ CloudBlob blob = _container.GetBlobReference(relativePath);
+ return blob.Exists();
+ }
+
+ public void Save<TEntity>(TEntity item) where TEntity : class, new()
+ {
+ var json = JsonConvert.SerializeObject(item, Formatting.Indented);
+ var key = _keys.GetKeyValue(item).ToString();
+ string relativePath = GetItemPath<TEntity>(key);
+ CloudBlob blob = _container.GetBlobReference(relativePath);
+ blob.UploadText(json);
+ }
+
+ public void Delete<TEntity>(object key) where TEntity : class, new()
+ {
+ string relativePath = GetItemPath<TEntity>(key.ToString());
+ CloudBlob blob = _container.GetBlobReference(relativePath);
+ blob.Delete();
+ }
+ }
+}
@@ -0,0 +1,47 @@
+namespace NBlog.Web.Application.Storage.Azure
+{
+ using Microsoft.WindowsAzure.StorageClient;
+
+ public static class AzureExtensions
+ {
+ public static bool Exists(this CloudBlob blob)
+ {
+ try
+ {
+ blob.FetchAttributes();
+ return true;
+ }
+ catch (StorageClientException e)
+ {
+ if (e.ErrorCode == StorageErrorCode.ResourceNotFound)
+ {
+ return false;
+ }
+ else
+ {
+ throw;
+ }
+ }
+ }
+
+ public static bool Exists(this CloudBlobContainer container)
+ {
+ try
+ {
+ container.FetchAttributes();
+ return true;
+ }
+ catch (StorageClientException e)
+ {
+ if (e.ErrorCode == StorageErrorCode.ResourceNotFound)
+ {
+ return false;
+ }
+ else
+ {
+ throw;
+ }
+ }
+ }
+ }
+}
View
@@ -18,6 +18,7 @@
using NBlog.Web.Application.Storage.Sql;
using Quartz;
using Quartz.Impl;
+using NBlog.Web.Application.Storage.Azure;
namespace NBlog.Web
{
@@ -87,6 +88,11 @@ protected IContainer RegisterDependencies()
new NamedParameter("databaseName", "nblog")
});
+ builder.RegisterType<AzureBlobRepository>().Named<IRepository>("azure").InstancePerHttpRequest().WithParameters(new[] {
+ new NamedParameter("keys", repositoryKeys),
+ new NamedParameter("tenantSelector", new HttpTenantSelector())
+ });
+
builder.RegisterType<ConfigService>().As<IConfigService>().InstancePerLifetimeScope()
.WithParameter(GetResolvedParameterByName<IRepository>("json"));
View
@@ -112,6 +112,14 @@
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
</Reference>
+ <Reference Include="Microsoft.WindowsAzure.ServiceRuntime, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\NBlog.Lib\Microsoft.WindowsAzure.ServiceRuntime.dll</HintPath>
+ </Reference>
+ <Reference Include="Microsoft.WindowsAzure.StorageClient, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\NBlog.Lib\Microsoft.WindowsAzure.StorageClient.dll</HintPath>
+ </Reference>
<Reference Include="MongoDB.Bson">
<HintPath>..\NBlog.Lib\MongoDB.Bson.dll</HintPath>
</Reference>
@@ -217,6 +225,8 @@
<Compile Include="Application\Service\MessageService.cs" />
<Compile Include="Application\Service\Internal\ThemeService.cs" />
<Compile Include="Application\Service\Entity\Theme.cs" />
+ <Compile Include="Application\Storage\Azure\AzureBlobRepository.cs" />
+ <Compile Include="Application\Storage\Azure\AzureExtensions.cs" />
<Compile Include="Application\Storage\IRepository.cs" />
<Compile Include="Application\Storage\Mongo\MongoRepository.cs" />
<Compile Include="Application\Storage\RepositoryKeys.cs" />

0 comments on commit 0a7d618

Please sign in to comment.