From 4b52a0aee15afac30be224cf3640c62073a97019 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Mon, 26 Apr 2010 14:58:29 -0700 Subject: [PATCH] Implemented AzureShellSettingsManager Refactored common used methods into AzureHelper Added unit tests from DefaultSettingsManagerTests class --HG-- branch : dev --- .../AzureVirtualEnvironmentTest.cs | 62 ++++++ .../AzureShellSettingsManagerTests.cs | 76 +++++++ .../Orchard.Azure.Tests.csproj | 2 + .../Storage/AzureBlobStorageProviderTests.cs | 70 +------ src/Orchard.Azure/AzureHelper.cs | 82 ++++++++ .../AzureShellSettingsManager.cs | 110 ++++++++++ src/Orchard.Azure/Orchard.Azure.csproj | 6 + .../Storage/AzureBlobStorageProvider.cs | 191 +++++------------- 8 files changed, 399 insertions(+), 200 deletions(-) create mode 100644 src/Orchard.Azure.Tests/AzureVirtualEnvironmentTest.cs create mode 100644 src/Orchard.Azure.Tests/Environment/Configuration/AzureShellSettingsManagerTests.cs create mode 100644 src/Orchard.Azure/AzureHelper.cs create mode 100644 src/Orchard.Azure/Environment/Configuration/AzureShellSettingsManager.cs diff --git a/src/Orchard.Azure.Tests/AzureVirtualEnvironmentTest.cs b/src/Orchard.Azure.Tests/AzureVirtualEnvironmentTest.cs new file mode 100644 index 000000000..6a19547b8 --- /dev/null +++ b/src/Orchard.Azure.Tests/AzureVirtualEnvironmentTest.cs @@ -0,0 +1,62 @@ +using System.Configuration; +using System.Diagnostics; +using System.IO; +using Microsoft.WindowsAzure.StorageClient; +using NUnit.Framework; + +namespace Orchard.Azure.Tests { + public abstract class AzureVirtualEnvironmentTest { + private Process _dsService; + + protected abstract void OnInit(); + + [TestFixtureSetUp] + public void FixtureSetup() { + var count = Process.GetProcessesByName("DSService").Length; + if ( count == 0 ) { + var start = new ProcessStartInfo { + Arguments = "/devstore:start", + FileName = + Path.Combine(ConfigurationManager.AppSettings["AzureSDK"], @"bin\csrun.exe") + }; + + _dsService = new Process { StartInfo = start }; + _dsService.Start(); + _dsService.WaitForExit(); + } + + OnInit(); + } + + [TestFixtureTearDown] + public void FixtureTearDown() { + + if ( _dsService != null ) + _dsService.Close(); + } + + protected void DeleteAllBlobs(CloudBlobContainer container) { + foreach ( var blob in container.ListBlobs() ) { + if ( blob is CloudBlob ) { + ( (CloudBlob)blob ).DeleteIfExists(); + } + + if ( blob is CloudBlobDirectory ) { + DeleteAllBlobs((CloudBlobDirectory)blob); + } + } + } + + private static void DeleteAllBlobs(CloudBlobDirectory cloudBlobDirectory) { + foreach ( var blob in cloudBlobDirectory.ListBlobs() ) { + if ( blob is CloudBlob ) { + ( (CloudBlob)blob ).DeleteIfExists(); + } + + if ( blob is CloudBlobDirectory ) { + DeleteAllBlobs((CloudBlobDirectory)blob); + } + } + } + } +} diff --git a/src/Orchard.Azure.Tests/Environment/Configuration/AzureShellSettingsManagerTests.cs b/src/Orchard.Azure.Tests/Environment/Configuration/AzureShellSettingsManagerTests.cs new file mode 100644 index 000000000..405569136 --- /dev/null +++ b/src/Orchard.Azure.Tests/Environment/Configuration/AzureShellSettingsManagerTests.cs @@ -0,0 +1,76 @@ +using System.IO; +using System.Linq; +using Microsoft.WindowsAzure; +using NUnit.Framework; +using Orchard.Azure.Environment.Configuration; +using Orchard.Environment.Configuration; + +namespace Orchard.Azure.Tests.Environment.Configuration { + [TestFixture] + public class AzureShellSettingsManagerTests : AzureVirtualEnvironmentTest { + + protected IShellSettingsManager Loader; + + protected override void OnInit() { + CloudStorageAccount devAccount; + CloudStorageAccount.TryParse("UseDevelopmentStorage=true", out devAccount); + + Loader = new AzureShellSettingsManager(devAccount); + } + + [SetUp] + public void Setup() { + // ensure default container is empty before running any test + DeleteAllBlobs( ((AzureShellSettingsManager)Loader).Container); + } + + [Test] + public void SingleSettingsFileShouldComeBackAsExpected() { + + Loader.SaveSettings(new ShellSettings { Name = "Default", DataProvider = "SQLite", DataConnectionString = "something else" }); + + var settings = Loader.LoadSettings().Single(); + Assert.That(settings, Is.Not.Null); + Assert.That(settings.Name, Is.EqualTo("Default")); + Assert.That(settings.DataProvider, Is.EqualTo("SQLite")); + Assert.That(settings.DataConnectionString, Is.EqualTo("something else")); + } + + + [Test] + public void MultipleFilesCanBeDetected() { + + Loader.SaveSettings(new ShellSettings { Name = "Default", DataProvider = "SQLite", DataConnectionString = "something else" }); + Loader.SaveSettings(new ShellSettings { Name = "Another", DataProvider = "SQLite2", DataConnectionString = "something else2" }); + + var settings = Loader.LoadSettings(); + Assert.That(settings.Count(), Is.EqualTo(2)); + + var def = settings.Single(x => x.Name == "Default"); + Assert.That(def.Name, Is.EqualTo("Default")); + Assert.That(def.DataProvider, Is.EqualTo("SQLite")); + Assert.That(def.DataConnectionString, Is.EqualTo("something else")); + + var alt = settings.Single(x => x.Name == "Another"); + Assert.That(alt.Name, Is.EqualTo("Another")); + Assert.That(alt.DataProvider, Is.EqualTo("SQLite2")); + Assert.That(alt.DataConnectionString, Is.EqualTo("something else2")); + } + + [Test] + public void NewSettingsCanBeStored() { + Loader.SaveSettings(new ShellSettings { Name = "Default", DataProvider = "SQLite", DataConnectionString = "something else" }); + + var foo = new ShellSettings { Name = "Foo", DataProvider = "Bar", DataConnectionString = "Quux" }; + + Assert.That(Loader.LoadSettings().Count(), Is.EqualTo(1)); + Loader.SaveSettings(foo); + Assert.That(Loader.LoadSettings().Count(), Is.EqualTo(2)); + + var text = ( (AzureShellSettingsManager)Loader ).Container.GetBlockBlobReference("Foo/Settings.txt").DownloadText(); + Assert.That(text, Is.StringContaining("Foo")); + Assert.That(text, Is.StringContaining("Bar")); + Assert.That(text, Is.StringContaining("Quux")); + } + } +} diff --git a/src/Orchard.Azure.Tests/Orchard.Azure.Tests.csproj b/src/Orchard.Azure.Tests/Orchard.Azure.Tests.csproj index 231b57883..393e8b820 100644 --- a/src/Orchard.Azure.Tests/Orchard.Azure.Tests.csproj +++ b/src/Orchard.Azure.Tests/Orchard.Azure.Tests.csproj @@ -53,6 +53,8 @@ + + diff --git a/src/Orchard.Azure.Tests/Storage/AzureBlobStorageProviderTests.cs b/src/Orchard.Azure.Tests/Storage/AzureBlobStorageProviderTests.cs index c9979df6b..5be4b3e8b 100644 --- a/src/Orchard.Azure.Tests/Storage/AzureBlobStorageProviderTests.cs +++ b/src/Orchard.Azure.Tests/Storage/AzureBlobStorageProviderTests.cs @@ -11,74 +11,21 @@ using System.Text; namespace Orchard.Azure.Tests.Storage { [TestFixture] - public class AzureBlobStorageProviderTests { + public class AzureBlobStorageProviderTests : AzureVirtualEnvironmentTest { - #region Azure Environment initialization - - private Process _dsService; - - [TestFixtureSetUp] - public void FixtureSetup() { - var count = Process.GetProcessesByName("DSService").Length; - if (count == 0) - { - var start = new ProcessStartInfo - { - Arguments = "/devstore:start", - FileName = - Path.Combine(ConfigurationManager.AppSettings["AzureSDK"], @"bin\csrun.exe") - }; - - _dsService = new Process { StartInfo = start }; - _dsService.Start(); - _dsService.WaitForExit(); - } + private AzureBlobStorageProvider _azureBlobStorageProvider; + protected override void OnInit() { CloudStorageAccount devAccount; CloudStorageAccount.TryParse("UseDevelopmentStorage=true", out devAccount); _azureBlobStorageProvider = new AzureBlobStorageProvider("default", devAccount); } - [TestFixtureTearDown] - public void FixtureTearDown() { - - if(_dsService != null) - _dsService.Close(); - } - [SetUp] public void Setup() { // ensure default container is empty before running any test - DeleteAllBlobs(); - } - - #endregion - - private AzureBlobStorageProvider _azureBlobStorageProvider; - - private void DeleteAllBlobs() { - foreach(var blob in _azureBlobStorageProvider.Container.ListBlobs()) { - if(blob is CloudBlob) { - ((CloudBlob) blob).DeleteIfExists(); - } - - if (blob is CloudBlobDirectory) { - DeleteAllBlobs((CloudBlobDirectory)blob); - } - } - } - - private static void DeleteAllBlobs(CloudBlobDirectory cloudBlobDirectory) { - foreach (var blob in cloudBlobDirectory.ListBlobs()) { - if (blob is CloudBlob) { - ((CloudBlob)blob).DeleteIfExists(); - } - - if (blob is CloudBlobDirectory) { - DeleteAllBlobs((CloudBlobDirectory)blob); - } - } + DeleteAllBlobs(_azureBlobStorageProvider.Container); } [Test] @@ -131,8 +78,7 @@ namespace Orchard.Azure.Tests.Storage { } [Test] - public void CreateFileShouldBeFolderAgnostic() - { + public void CreateFileShouldBeFolderAgnostic() { _azureBlobStorageProvider.CreateFile("foo.txt"); _azureBlobStorageProvider.CreateFile("folder/foo.txt"); _azureBlobStorageProvider.CreateFile("folder/folder/foo.txt"); @@ -193,9 +139,9 @@ namespace Orchard.Azure.Tests.Storage { var foo = _azureBlobStorageProvider.CreateFile("folder1/foo.txt"); - using(var stream = foo.OpenWrite()) - using (var writer = new StreamWriter(stream)) - writer.Write(teststring); + using ( var stream = foo.OpenWrite() ) + using ( var writer = new StreamWriter(stream) ) + writer.Write(teststring); Assert.AreEqual(22, foo.GetSize()); diff --git a/src/Orchard.Azure/AzureHelper.cs b/src/Orchard.Azure/AzureHelper.cs new file mode 100644 index 000000000..06aaa0c5a --- /dev/null +++ b/src/Orchard.Azure/AzureHelper.cs @@ -0,0 +1,82 @@ +using System; +using System.ComponentModel; +using System.Linq; +using Microsoft.WindowsAzure.StorageClient; + +namespace Orchard.Azure { + public class AzureHelper { + + public static bool BlobExists(CloudBlobContainer container, string path) { + if ( String.IsNullOrEmpty(path) || path.Trim() == String.Empty ) + throw new ArgumentException("Path can't be empty"); + + try { + var blob = container.GetBlockBlobReference(path); + blob.FetchAttributes(); + return true; + } + catch ( StorageClientException e ) { + if ( e.ErrorCode == StorageErrorCode.ResourceNotFound ) { + return false; + } + + throw; + } + } + + public static void EnsurePathIsRelative(string path) { + if ( path.StartsWith("/") ) + throw new ArgumentException("Path must be relative"); + } + + public static void EnsureBlobExists(CloudBlobContainer container, string path) { + if ( !BlobExists(container, path) ) { + throw new ArgumentException("File " + path + " does not exist"); + } + } + + public static void EnsureBlobDoesNotExist(CloudBlobContainer container, string path) { + if ( BlobExists(container, path) ) { + throw new ArgumentException("File " + path + " already exists"); + } + } + + public static bool DirectoryExists(CloudBlobContainer container, string path) { + if ( String.IsNullOrEmpty(path) || path.Trim() == String.Empty ) + throw new ArgumentException("Path can't be empty"); + + return container.GetDirectoryReference(path).ListBlobs().Count() > 0; + } + + public static void EnsureDirectoryExists(CloudBlobContainer container, string path) { + if ( !DirectoryExists(container, path) ) { + throw new ArgumentException("Directory " + path + " does not exist"); + } + } + + public static void EnsureDirectoryDoesNotExist(CloudBlobContainer container, string path) { + if ( DirectoryExists(container, path) ) { + throw new ArgumentException("Directory " + path + " already exists"); + } + } + + public static string Combine(string path1, string path2) { + EnsurePathIsRelative(path1); + EnsurePathIsRelative(path2); + + if ( path1 == null || path2 == null ) + throw new ArgumentException("One or more path is null"); + + if ( path1.Trim() == String.Empty ) + return path2; + + if ( path2.Trim() == String.Empty ) + return path1; + + var uri1 = new Uri(path1); + var uri2 = new Uri(path2); + + return uri2.IsAbsoluteUri ? uri2.ToString() : new Uri(uri1, uri2).ToString(); + } + } +} diff --git a/src/Orchard.Azure/Environment/Configuration/AzureShellSettingsManager.cs b/src/Orchard.Azure/Environment/Configuration/AzureShellSettingsManager.cs new file mode 100644 index 000000000..9f98c658e --- /dev/null +++ b/src/Orchard.Azure/Environment/Configuration/AzureShellSettingsManager.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Yaml.Serialization; +using JetBrains.Annotations; +using Microsoft.WindowsAzure.StorageClient; +using Orchard.Localization; +using Orchard.Environment.Configuration; +using Microsoft.WindowsAzure; + +namespace Orchard.Azure.Environment.Configuration { + + public class AzureShellSettingsManager : IShellSettingsManager { + public const string ContainerName = "sites"; // container names must be lower cased + + private readonly CloudStorageAccount _storageAccount; + public CloudBlobClient BlobClient { get; private set; } + public CloudBlobContainer Container { get; private set; } + + Localizer T { get; [UsedImplicitly] + set; } + + public AzureShellSettingsManager() : this(CloudStorageAccount.FromConfigurationSetting("DataConnectionString")) + { + } + + public AzureShellSettingsManager(CloudStorageAccount storageAccount) + { + // Setup the connection to custom storage accountm, e.g. Development Storage + _storageAccount = storageAccount; + + BlobClient = _storageAccount.CreateCloudBlobClient(); + + // Get and create the container if it does not exist + // The container is named with DNS naming restrictions (i.e. all lower case) + Container = new CloudBlobContainer(ContainerName, BlobClient); + Container.CreateIfNotExist(); + + // Tenant settings are protected by default + Container.SetPermissions(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Off }); + } + + IEnumerable IShellSettingsManager.LoadSettings() { + return LoadSettings().ToArray(); + } + + void IShellSettingsManager.SaveSettings(ShellSettings settings) { + if ( settings == null ) + throw new ArgumentException(T("There are no settings to save.").ToString()); + if ( string.IsNullOrEmpty(settings.Name) ) + throw new ArgumentException(T("Settings \"Name\" is not set.").ToString()); + + var filePath =String.Concat(settings.Name, "/", "Settings.txt"); + var blob = Container.GetBlockBlobReference(filePath); + blob.UploadText(ComposeSettings(settings)); + } + + IEnumerable LoadSettings() { + var settingsBlobs = + BlobClient.ListBlobsWithPrefix(Container.Name + "/" ).OfType() + .SelectMany(directory => directory.ListBlobs()).OfType() + .Where(blob => string.Equals(Path.GetFileName(blob.Uri.ToString()), "Settings.txt", StringComparison.OrdinalIgnoreCase)); + + foreach ( var settingsBlob in settingsBlobs ) { + yield return ParseSettings(settingsBlob.DownloadText()); + } + } + + class Content { + public string Name { get; set; } + public string DataProvider { get; set; } + public string DataConnectionString { get; set; } + public string DataPrefix { get; set; } + public string RequestUrlHost { get; set; } + public string RequestUrlPrefix { get; set; } + public string State { get; set; } + } + + static ShellSettings ParseSettings(string text) { + var ser = new YamlSerializer(); + var content = ser.Deserialize(text, typeof(Content)).Cast().Single(); + return new ShellSettings { + Name = content.Name, + DataProvider = content.DataProvider, + DataConnectionString = content.DataConnectionString, + DataTablePrefix = content.DataPrefix, + RequestUrlHost = content.RequestUrlHost, + RequestUrlPrefix = content.RequestUrlPrefix, + State = new TenantState(content.State) + }; + } + + static string ComposeSettings(ShellSettings settings) { + if ( settings == null ) + return ""; + + var ser = new YamlSerializer(); + return ser.Serialize(new Content { + Name = settings.Name, + DataProvider = settings.DataProvider, + DataConnectionString = settings.DataConnectionString, + DataPrefix = settings.DataTablePrefix, + RequestUrlHost = settings.RequestUrlHost, + RequestUrlPrefix = settings.RequestUrlPrefix, + State = settings.State != null ? settings.State.ToString() : String.Empty + }); + } + } +} diff --git a/src/Orchard.Azure/Orchard.Azure.csproj b/src/Orchard.Azure/Orchard.Azure.csproj index 69c7f0ec3..eac004767 100644 --- a/src/Orchard.Azure/Orchard.Azure.csproj +++ b/src/Orchard.Azure/Orchard.Azure.csproj @@ -44,8 +44,14 @@ + + False + ..\..\lib\yaml\YamlSerializer.dll + + + diff --git a/src/Orchard.Azure/Storage/AzureBlobStorageProvider.cs b/src/Orchard.Azure/Storage/AzureBlobStorageProvider.cs index b79fecd88..b8b7efee4 100644 --- a/src/Orchard.Azure/Storage/AzureBlobStorageProvider.cs +++ b/src/Orchard.Azure/Storage/AzureBlobStorageProvider.cs @@ -6,22 +6,19 @@ using Microsoft.WindowsAzure.StorageClient; using System.IO; using Orchard.Storage; -namespace Orchard.Azure.Storage -{ - public interface IDependency {} +namespace Orchard.Azure.Storage { + public interface IDependency { } - public class AzureBlobStorageProvider : IStorageProvider - { + public class AzureBlobStorageProvider : IStorageProvider { private readonly CloudStorageAccount _storageAccount; public CloudBlobClient BlobClient { get; private set; } public CloudBlobContainer Container { get; private set; } - public AzureBlobStorageProvider(string containerName) : this(containerName, CloudStorageAccount.FromConfigurationSetting("DataConnectionString")) - { + public AzureBlobStorageProvider(string containerName) + : this(containerName, CloudStorageAccount.FromConfigurationSetting("DataConnectionString")) { } - public AzureBlobStorageProvider(string containerName, CloudStorageAccount storageAccount) - { + public AzureBlobStorageProvider(string containerName, CloudStorageAccount storageAccount) { // Setup the connection to custom storage accountm, e.g. Development Storage _storageAccount = storageAccount; @@ -29,102 +26,36 @@ namespace Orchard.Azure.Storage // Get and create the container if it does not exist // The container is named with DNS naming restrictions (i.e. all lower case) Container = BlobClient.GetContainerReference(containerName); + Container.CreateIfNotExist(); Container.SetPermissions(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Container }); } - private static void EnsurePathIsRelative(string path) { - if(path.StartsWith("/")) - throw new ArgumentException("Path must be relative"); - } - - private string GetPrefix(string path) { - var prefix = String.Concat(Container.Name, "/", path); - if (prefix.EndsWith("/")) - return prefix; - - return String.Concat(prefix, "/"); - } - - private bool BlobExists(string path) { - if(String.IsNullOrEmpty(path) || path.Trim() == String.Empty) - throw new ArgumentException("Path can't be empty"); - - try { - var blob = Container.GetBlockBlobReference(path); - blob.FetchAttributes(); - return true; - } - catch (StorageClientException e) { - if (e.ErrorCode == StorageErrorCode.ResourceNotFound) { - return false; - } - - throw; - } - } - - private void EnsureBlobExists(string path) - { - if (!BlobExists(path)) { - throw new ArgumentException("File " + path + " does not exist"); - } - } - - private void EnsureBlobDoesNotExist(string path) - { - if (BlobExists(path)) { - throw new ArgumentException("File " + path + " already exists"); - } - } - - private bool DirectoryExists(string path) - { - if (String.IsNullOrEmpty(path) || path.Trim() == String.Empty) - throw new ArgumentException("Path can't be empty"); - - return Container.GetDirectoryReference(path).ListBlobs().Count() > 0; - } - - private void EnsureDirectoryExists(string path) - { - if (!DirectoryExists(path)) { - throw new ArgumentException("Directory " + path + " does not exist"); - } - } - - private void EnsureDirectoryDoesNotExist(string path) - { - if (DirectoryExists(path)) { - throw new ArgumentException("Directory " + path + " already exists"); - } - } - - #region IStorageProvider Members - public IStorageFile GetFile(string path) { - EnsurePathIsRelative(path); - EnsureBlobExists(path); + AzureHelper.EnsurePathIsRelative(path); + AzureHelper.EnsureBlobExists(Container, path); return new AzureBlobFileStorage(Container.GetBlockBlobReference(path)); } - public IEnumerable ListFiles(string path) - { - EnsurePathIsRelative(path); - foreach (var blobItem in BlobClient.ListBlobsWithPrefix(GetPrefix(path)).OfType()) { + public IEnumerable ListFiles(string path) { + AzureHelper.EnsurePathIsRelative(path); + + string prefix = String.Concat(Container.Name, "/", path); + if ( !prefix.EndsWith("/") ) + prefix += "/"; + + foreach ( var blobItem in BlobClient.ListBlobsWithPrefix(prefix).OfType() ) { yield return new AzureBlobFileStorage(blobItem); } } - public IEnumerable ListFolders(string path) - { - EnsurePathIsRelative(path); - if (!DirectoryExists(path)) - { + public IEnumerable ListFolders(string path) { + AzureHelper.EnsurePathIsRelative(path); + if ( !AzureHelper.DirectoryExists(Container, path) ) { try { CreateFolder(path); } - catch (Exception ex) { + catch ( Exception ex ) { throw new ArgumentException(string.Format("The folder could not be created at path: {0}. {1}", path, ex)); } } @@ -134,28 +65,28 @@ namespace Orchard.Azure.Storage .OfType() .Select(d => new AzureBlobFolderStorage(d)) .ToList(); - } + } public void CreateFolder(string path) { - EnsurePathIsRelative(path); - EnsureDirectoryDoesNotExist(path); + AzureHelper.EnsurePathIsRelative(path); + AzureHelper.EnsureDirectoryDoesNotExist(Container, path); Container.GetDirectoryReference(path); } public void DeleteFolder(string path) { - EnsureDirectoryExists(path); - foreach (var blob in Container.GetDirectoryReference(path).ListBlobs()) { - if (blob is CloudBlob) - ((CloudBlob)blob).Delete(); + AzureHelper.EnsureDirectoryExists(Container, path); + foreach ( var blob in Container.GetDirectoryReference(path).ListBlobs() ) { + if ( blob is CloudBlob ) + ( (CloudBlob)blob ).Delete(); - if (blob is CloudBlobDirectory) + if ( blob is CloudBlobDirectory ) DeleteFolder(blob.Uri.ToString()); } } public void RenameFolder(string path, string newPath) { - EnsurePathIsRelative(path); - EnsurePathIsRelative(newPath); + AzureHelper.EnsurePathIsRelative(path); + AzureHelper.EnsurePathIsRelative(newPath); if ( !path.EndsWith("/") ) path += "/"; @@ -182,17 +113,17 @@ namespace Orchard.Azure.Storage } public void DeleteFile(string path) { - EnsurePathIsRelative(path); - EnsureBlobExists(path); + AzureHelper.EnsurePathIsRelative(path); + AzureHelper.EnsureBlobExists(Container, path); var blob = Container.GetBlockBlobReference(path); blob.Delete(); } public void RenameFile(string path, string newPath) { - EnsurePathIsRelative(path); - EnsurePathIsRelative(newPath); - EnsureBlobExists(path); - EnsureBlobDoesNotExist(newPath); + AzureHelper.EnsurePathIsRelative(path); + AzureHelper.EnsurePathIsRelative(newPath); + AzureHelper.EnsureBlobExists(Container, path); + AzureHelper.EnsureBlobDoesNotExist(Container, newPath); var blob = Container.GetBlockBlobReference(path); var newBlob = Container.GetBlockBlobReference(newPath); @@ -201,8 +132,8 @@ namespace Orchard.Azure.Storage } public IStorageFile CreateFile(string path) { - EnsurePathIsRelative(path); - if (BlobExists(path)) { + AzureHelper.EnsurePathIsRelative(path); + if ( AzureHelper.BlobExists(Container, path) ) { throw new ArgumentException("File " + path + " already exists"); } @@ -211,27 +142,6 @@ namespace Orchard.Azure.Storage return new AzureBlobFileStorage(blob); } - public string Combine(string path1, string path2) { - EnsurePathIsRelative(path1); - EnsurePathIsRelative(path2); - - if (path1 == null || path2 == null) - throw new ArgumentException("One or more path is null"); - - if (path1.Trim() == String.Empty) - return path2; - - if (path2.Trim() == String.Empty) - return path1; - - var uri1 = new Uri(path1); - var uri2 = new Uri(path2); - - return uri2.IsAbsoluteUri ? uri2.ToString() : new Uri(uri1, uri2).ToString(); - } - - #endregion - private class AzureBlobFileStorage : IStorageFile { private readonly CloudBlockBlob _blob; @@ -276,8 +186,6 @@ namespace Orchard.Azure.Storage _blob = blob; } - #region IStorageFolder Members - public string GetName() { return _blob.Uri.ToString(); } @@ -291,7 +199,7 @@ namespace Orchard.Azure.Storage } public IStorageFolder GetParent() { - if (_blob.Parent != null) { + if ( _blob.Parent != null ) { return new AzureBlobFolderStorage(_blob.Parent); } throw new ArgumentException("Directory " + _blob.Uri + " does not have a parent directory"); @@ -300,18 +208,25 @@ namespace Orchard.Azure.Storage private static long GetDirectorySize(CloudBlobDirectory directoryBlob) { long size = 0; - foreach (var blobItem in directoryBlob.ListBlobs()) { - if (blobItem is CloudBlob) - size += ((CloudBlob)blobItem).Properties.Length; + foreach ( var blobItem in directoryBlob.ListBlobs() ) { + if ( blobItem is CloudBlob ) + size += ( (CloudBlob)blobItem ).Properties.Length; - if (blobItem is CloudBlobDirectory) + if ( blobItem is CloudBlobDirectory ) size += GetDirectorySize((CloudBlobDirectory)blobItem); } return size; } - - #endregion } + + #region IStorageProvider Members + + + public string Combine(string path1, string path2) { + return AzureHelper.Combine(path1, path2); + } + + #endregion } }