Adjusting FileSystemStorageProvider path semantics

All path information coming in and out is within a tenant-specific location
The location is now an implementation detail of the component

--HG--
branch : dev
This commit is contained in:
Louis DeJardin 2010-04-30 10:02:16 -07:00
parent 312d6d812c
commit f60608368c
4 changed files with 212 additions and 53 deletions

View File

@ -3,43 +3,170 @@ using System.IO;
using System.Linq;
using NUnit.Framework;
using System;
using Orchard.Environment.Configuration;
using Orchard.Storage;
namespace Orchard.Tests.Storage {
[TestFixture]
public class FileSystemStorageProviderTests {
#region Setup/Teardown
[TestFixtureSetUp]
public void InitFixture() {
_folderPath = Directory.CreateDirectory(Path.GetTempPath() + "filesystemstorageprovidertests").FullName;
[SetUp]
public void Init() {
_folderPath = Path.Combine(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Media"), "Default");
_filePath = _folderPath + "\\testfile.txt";
FileStream fileStream = File.Create(_filePath);
fileStream.Close();
_fileSystemStorageProvider = new FileSystemStorageProvider();
Directory.CreateDirectory(_folderPath);
File.WriteAllText(_filePath, "testfile contents");
var subfolder1 = Path.Combine(_folderPath, "Subfolder1");
Directory.CreateDirectory(subfolder1);
File.WriteAllText(Path.Combine(subfolder1, "one.txt"), "one contents");
File.WriteAllText(Path.Combine(subfolder1, "two.txt"), "two contents");
var subsubfolder1 = Path.Combine(subfolder1, "SubSubfolder1");
Directory.CreateDirectory(subsubfolder1);
_storageProvider = new FileSystemStorageProvider(new ShellSettings { Name = "Default" });
}
[TestFixtureTearDown]
public void TermFixture() {
[TearDown]
public void Term() {
Directory.Delete(_folderPath, true);
}
#endregion
private string _filePath;
private string _folderPath;
private FileSystemStorageProvider _fileSystemStorageProvider;
private IStorageProvider _storageProvider;
[Test]
[ExpectedException(typeof(ArgumentException))]
public void GetFileThatDoesNotExistShouldThrow() {
_fileSystemStorageProvider.GetFile("notexisting");
_storageProvider.GetFile("notexisting");
}
[Test]
public void ListFilesShouldReturnFilesFromFilesystem() {
IEnumerable<IStorageFile> files = _fileSystemStorageProvider.ListFiles(_folderPath);
IEnumerable<IStorageFile> files = _storageProvider.ListFiles(_folderPath);
Assert.That(files.Count(), Is.EqualTo(1));
}
[Test]
public void ExistingFileIsReturnedWithShortPath() {
var file = _storageProvider.GetFile("testfile.txt");
Assert.That(file, Is.Not.Null);
Assert.That(file.GetPath(), Is.EqualTo("testfile.txt"));
Assert.That(file.GetName(), Is.EqualTo("testfile.txt"));
}
[Test]
public void ListFilesReturnsItemsWithShortPathAndEnvironmentSlashes() {
var files = _storageProvider.ListFiles("Subfolder1");
Assert.That(files, Is.Not.Null);
Assert.That(files.Count(), Is.EqualTo(2));
var one = files.Single(x => x.GetName() == "one.txt");
var two = files.Single(x => x.GetName() == "two.txt");
Assert.That(one.GetPath(), Is.EqualTo("Subfolder1" + Path.DirectorySeparatorChar + "one.txt"));
Assert.That(two.GetPath(), Is.EqualTo("Subfolder1" + Path.DirectorySeparatorChar + "two.txt"));
}
[Test]
public void AnySlashInGetFileBecomesEnvironmentAppropriate() {
var file1 = _storageProvider.GetFile(@"Subfolder1/one.txt");
var file2 = _storageProvider.GetFile(@"Subfolder1\one.txt");
Assert.That(file1.GetPath(), Is.EqualTo("Subfolder1" + Path.DirectorySeparatorChar + "one.txt"));
Assert.That(file2.GetPath(), Is.EqualTo("Subfolder1" + Path.DirectorySeparatorChar + "one.txt"));
}
[Test]
public void ListFoldersReturnsItemsWithShortPathAndEnvironmentSlashes() {
var folders = _storageProvider.ListFolders(@"Subfolder1");
Assert.That(folders, Is.Not.Null);
Assert.That(folders.Count(), Is.EqualTo(1));
Assert.That(folders.Single().GetName(), Is.EqualTo("SubSubfolder1"));
Assert.That(folders.Single().GetPath(), Is.EqualTo(Path.Combine("Subfolder1", "SubSubfolder1")));
}
[Test]
public void ParentFolderPathIsStillShort() {
var subsubfolder = _storageProvider.ListFolders(@"Subfolder1").Single();
var subfolder = subsubfolder.GetParent();
Assert.That(subsubfolder.GetName(), Is.EqualTo("SubSubfolder1"));
Assert.That(subsubfolder.GetPath(), Is.EqualTo(Path.Combine("Subfolder1", "SubSubfolder1")));
Assert.That(subfolder.GetName(), Is.EqualTo("Subfolder1"));
Assert.That(subfolder.GetPath(), Is.EqualTo("Subfolder1"));
}
[Test]
public void CreateFolderAndDeleteFolderTakesAnySlash() {
Assert.That(_storageProvider.ListFolders(@"Subfolder1").Count(), Is.EqualTo(1));
_storageProvider.CreateFolder(@"SubFolder1/SubSubFolder2");
_storageProvider.CreateFolder(@"SubFolder1\SubSubFolder3");
Assert.That(_storageProvider.ListFolders(@"Subfolder1").Count(), Is.EqualTo(3));
_storageProvider.DeleteFolder(@"SubFolder1/SubSubFolder2");
_storageProvider.DeleteFolder(@"SubFolder1\SubSubFolder3");
Assert.That(_storageProvider.ListFolders(@"Subfolder1").Count(), Is.EqualTo(1));
}
private IStorageFolder GetFolder(string path) {
return _storageProvider.ListFolders(Path.GetDirectoryName(path))
.SingleOrDefault(x => string.Equals(x.GetName(), Path.GetFileName(path), StringComparison.OrdinalIgnoreCase));
}
private IStorageFile GetFile(string path) {
try {
return _storageProvider.GetFile(path);
}
catch (ArgumentException) {
return null;
}
}
[Test]
public void RenameFolderTakesShortPathWithAnyKindOfSlash() {
Assert.That(GetFolder(@"SubFolder1/SubSubFolder1"), Is.Not.Null);
_storageProvider.RenameFolder(@"SubFolder1\SubSubFolder1", @"SubFolder1/SubSubFolder2");
_storageProvider.RenameFolder(@"SubFolder1\SubSubFolder2", @"SubFolder1\SubSubFolder3");
_storageProvider.RenameFolder(@"SubFolder1/SubSubFolder3", @"SubFolder1\SubSubFolder4");
_storageProvider.RenameFolder(@"SubFolder1/SubSubFolder4", @"SubFolder1/SubSubFolder5");
Assert.That(GetFolder(Path.Combine("SubFolder1", "SubSubFolder1")), Is.Null);
Assert.That(GetFolder(Path.Combine("SubFolder1", "SubSubFolder2")), Is.Null);
Assert.That(GetFolder(Path.Combine("SubFolder1", "SubSubFolder3")), Is.Null);
Assert.That(GetFolder(Path.Combine("SubFolder1", "SubSubFolder4")), Is.Null);
Assert.That(GetFolder(Path.Combine("SubFolder1", "SubSubFolder5")), Is.Not.Null);
}
[Test]
public void CreateFileAndDeleteFileTakesAnySlash() {
Assert.That(_storageProvider.ListFiles(@"Subfolder1").Count(), Is.EqualTo(2));
var alpha = _storageProvider.CreateFile(@"SubFolder1/alpha.txt");
var beta = _storageProvider.CreateFile(@"SubFolder1\beta.txt");
Assert.That(_storageProvider.ListFiles(@"Subfolder1").Count(), Is.EqualTo(4));
Assert.That(alpha.GetPath(), Is.EqualTo(Path.Combine("SubFolder1", "alpha.txt")));
Assert.That(beta.GetPath(), Is.EqualTo(Path.Combine("SubFolder1", "beta.txt")));
_storageProvider.DeleteFile(@"SubFolder1\alpha.txt");
_storageProvider.DeleteFile(@"SubFolder1/beta.txt");
Assert.That(_storageProvider.ListFiles(@"Subfolder1").Count(), Is.EqualTo(2));
}
[Test]
public void RenameFileTakesShortPathWithAnyKindOfSlash() {
Assert.That(GetFile(@"Subfolder1/one.txt"), Is.Not.Null);
_storageProvider.RenameFile(@"SubFolder1\one.txt", @"SubFolder1/testfile2.txt");
_storageProvider.RenameFile(@"SubFolder1\testfile2.txt", @"SubFolder1\testfile3.txt");
_storageProvider.RenameFile(@"SubFolder1/testfile3.txt", @"SubFolder1\testfile4.txt");
_storageProvider.RenameFile(@"SubFolder1/testfile4.txt", @"SubFolder1/testfile5.txt");
Assert.That(GetFile(Path.Combine("SubFolder1", "one.txt")), Is.Null);
Assert.That(GetFile(Path.Combine("SubFolder1", "testfile2.txt")), Is.Null);
Assert.That(GetFile(Path.Combine("SubFolder1", "testfile3.txt")), Is.Null);
Assert.That(GetFile(Path.Combine("SubFolder1", "testfile4.txt")), Is.Null);
Assert.That(GetFile(Path.Combine("SubFolder1", "testfile5.txt")), Is.Not.Null);
}
}
}

View File

@ -102,6 +102,10 @@
<Project>{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}</Project>
<Name>Orchard.Framework</Name>
</ProjectReference>
<ProjectReference Include="..\Tools\Orchard\Orchard.csproj">
<Project>{33B1BC8D-E292-4972-A363-22056B207156}</Project>
<Name>Orchard</Name>
</ProjectReference>
<ProjectReference Include="Core\Orchard.Core.csproj">
<Project>{9916839C-39FC-4CEB-A5AF-89CA7E87119F}</Project>
<Name>Orchard.Core</Name>

View File

@ -2,44 +2,68 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web.Hosting;
using Orchard.Environment.Configuration;
namespace Orchard.Storage {
public class FileSystemStorageProvider : IStorageProvider {
private readonly ShellSettings _settings;
private string _storagePath;
public FileSystemStorageProvider(ShellSettings settings) {
_settings = settings;
var mediaPath = HostingEnvironment.IsHosted
? HostingEnvironment.MapPath("~/Media/")
: Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Media");
_storagePath = Path.Combine(mediaPath, settings.Name);
}
string Map(string path) {
return Path.Combine(_storagePath, path);
}
static string Fix(string path) {
return Path.DirectorySeparatorChar != '/'
? path.Replace('/', Path.DirectorySeparatorChar)
: path;
}
#region Implementation of IStorageProvider
public IStorageFile GetFile(string path) {
if (!File.Exists(path)) {
if (!File.Exists(Map(path))) {
throw new ArgumentException("File " + path + " does not exist");
}
return new FileSystemStorageFile(new FileInfo(path));
return new FileSystemStorageFile(Fix(path), new FileInfo(Map(path)));
}
public IEnumerable<IStorageFile> ListFiles(string path) {
if (!Directory.Exists(path)) {
if (!Directory.Exists(Map(path))) {
throw new ArgumentException("Directory " + path + " does not exist");
}
return new DirectoryInfo(path)
return new DirectoryInfo(Map(path))
.GetFiles()
.Where(fi => !IsHidden(fi))
.Select<FileInfo, IStorageFile>(fi => new FileSystemStorageFile(fi))
.Select<FileInfo, IStorageFile>(fi => new FileSystemStorageFile(Path.Combine(Fix(path), fi.Name), fi))
.ToList();
}
public IEnumerable<IStorageFolder> ListFolders(string path) {
if (!Directory.Exists(path)) {
if (!Directory.Exists(Map(path))) {
try {
Directory.CreateDirectory(path);
}
Directory.CreateDirectory(Map(path));
}
catch (Exception ex) {
throw new ArgumentException(string.Format("The folder could not be created at path: {0}. {1}",path,ex));
throw new ArgumentException(string.Format("The folder could not be created at path: {0}. {1}", path, ex));
}
}
return new DirectoryInfo(path)
return new DirectoryInfo(Map(path))
.GetDirectories()
.Where(di => !IsHidden(di))
.Select<DirectoryInfo, IStorageFolder>(di => new FileSystemStorageFolder(di))
.Select<DirectoryInfo, IStorageFolder>(di => new FileSystemStorageFolder(Path.Combine(Fix(path), di.Name), di))
.ToList();
}
@ -48,81 +72,80 @@ namespace Orchard.Storage {
}
public void CreateFolder(string path) {
if (Directory.Exists(path)) {
if (Directory.Exists(Map(path))) {
throw new ArgumentException("Directory " + path + " already exists");
}
Directory.CreateDirectory(path);
Directory.CreateDirectory(Map(path));
}
public void DeleteFolder(string path) {
if (!Directory.Exists(path)) {
if (!Directory.Exists(Map(path))) {
throw new ArgumentException("Directory " + path + " does not exist");
}
Directory.Delete(path, true);
Directory.Delete(Map(path), true);
}
public void RenameFolder(string path, string newPath) {
if (!Directory.Exists(path)) {
if (!Directory.Exists(Map(path))) {
throw new ArgumentException("Directory " + path + "does not exist");
}
if (Directory.Exists(newPath)) {
if (Directory.Exists(Map(newPath))) {
throw new ArgumentException("Directory " + newPath + " already exists");
}
Directory.Move(path, newPath);
Directory.Move(Map(path), Map(newPath));
}
public IStorageFile CreateFile(string path) {
if (File.Exists(path)) {
if (File.Exists(Map(path))) {
throw new ArgumentException("File " + path + " already exists");
}
var fileInfo = new FileInfo(path);
fileInfo.Create();
return new FileSystemStorageFile(fileInfo);
var fileInfo = new FileInfo(Map(path));
using (var stream = fileInfo.Create()) {
}
return new FileSystemStorageFile(Fix(path), fileInfo);
}
public void DeleteFile(string path) {
if (!File.Exists(path)) {
if (!File.Exists(Map(path))) {
throw new ArgumentException("File " + path + " does not exist");
}
File.Delete(path);
File.Delete(Map(path));
}
public void RenameFile(string path, string newPath) {
if (!File.Exists(path)) {
if (!File.Exists(Map(path))) {
throw new ArgumentException("File " + path + " does not exist");
}
if (File.Exists(newPath)) {
if (File.Exists(Map(newPath))) {
throw new ArgumentException("File " + newPath + " already exists");
}
File.Move(path, newPath);
}
public string Combine(string path1, string path2)
{
return Path.Combine(path1, path2);
File.Move(Map(path), Map(newPath));
}
#endregion
private class FileSystemStorageFile : IStorageFile {
private readonly string _path;
private readonly FileInfo _fileInfo;
public FileSystemStorageFile(FileInfo fileInfo) {
public FileSystemStorageFile(string path, FileInfo fileInfo) {
_path = path;
_fileInfo = fileInfo;
}
#region Implementation of IStorageFile
public string GetPath() {
return _fileInfo.FullName;
return _path;
}
public string GetName() {
@ -141,13 +164,11 @@ namespace Orchard.Storage {
return _fileInfo.Extension;
}
public Stream OpenRead()
{
public Stream OpenRead() {
return new FileStream(_fileInfo.FullName, FileMode.Open, FileAccess.Read);
}
public Stream OpenWrite()
{
public Stream OpenWrite() {
return new FileStream(_fileInfo.FullName, FileMode.Open, FileAccess.ReadWrite);
}
@ -155,14 +176,20 @@ namespace Orchard.Storage {
}
private class FileSystemStorageFolder : IStorageFolder {
private readonly string _path;
private readonly DirectoryInfo _directoryInfo;
public FileSystemStorageFolder(DirectoryInfo directoryInfo) {
public FileSystemStorageFolder(string path, DirectoryInfo directoryInfo) {
_path = path;
_directoryInfo = directoryInfo;
}
#region Implementation of IStorageFolder
public string GetPath() {
return _path;
}
public string GetName() {
return _directoryInfo.Name;
}
@ -177,7 +204,7 @@ namespace Orchard.Storage {
public IStorageFolder GetParent() {
if (_directoryInfo.Parent != null) {
return new FileSystemStorageFolder(_directoryInfo.Parent);
return new FileSystemStorageFolder(Path.GetDirectoryName(_path), _directoryInfo.Parent);
}
throw new ArgumentException("Directory " + _directoryInfo.Name + " does not have a parent directory");
}

View File

@ -2,6 +2,7 @@
namespace Orchard.Storage {
public interface IStorageFolder {
string GetPath();
string GetName();
long GetSize();
DateTime GetLastUpdated();