using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.IO;
using System.Net.Mime;
using System.Security.AccessControl;
namespace dasBlog.Storage.Ntfs{
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
public class StreamStorageProvider : IStreamStorageProvider, IInitStorageProvider
{
#region IStreamStorageNode Members
string storageDirectory;
DirectoryInfo rootInfo;
bool init = false;
public StreamStorageProvider()
{
}
public void Initialize(string initData)
{
initData = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,initData);
this.storageDirectory = initData;
if (!Directory.Exists(this.storageDirectory))
{
Directory.CreateDirectory(this.storageDirectory);
}
this.rootInfo = new DirectoryInfo(this.storageDirectory);
init = true;
}
void EnsureInit()
{
if (!init)
{
this.Initialize(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), ".\\dasBlog\\binaries"));
}
}
public IEnumerable<StreamStorageInfo> Select(Moniker contextId, MonikerMatch contextMatch, QueryDescription query)
{
EnsureInit();
DirectoryInfo info = new DirectoryInfo(GetDirectoryNameForContext(contextId));
if (info.Exists)
{
return from FileInfo file in info.GetFiles()
where !file.Name.EndsWith(".categories")
select new StreamStorageInfo
{
Id = new Moniker(contextId, file.Name),
Size = file.Length,
Created = file.CreationTimeUtc,
ContentType = MediaTypeNames.Application.Octet,
Categories = GetCategoriesForFile(file.FullName)
};
}
else
{
return null;
}
}
private static List<string> GetCategoriesForFile(string fileName)
{
List<string> categories = new List<string>();
try
{
if (File.Exists(fileName + ".categories"))
{
using (StreamReader categoriesStream = new StreamReader(fileName + ".categories", Encoding.UTF8))
{
while (!categoriesStream.EndOfStream)
{
categories.Add(categoriesStream.ReadLine());
}
}
}
return categories;
}
catch (FileNotFoundException)
{
return categories;
}
catch
{
throw;
}
}
public StreamStorageSetReply SetStream(StreamStorageSetRequest addRequest)
{
EnsureInit();
Moniker contextUri = addRequest.moniker;
DirectoryInfo info = new DirectoryInfo(GetDirectoryNameForContext(contextUri));
if (!info.Exists)
{
info.Create();
}
string fileName = Path.Combine(info.FullName, addRequest.name);
using (FileStream fileStream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
{
int bytesRead;
byte[] buffer = new byte[64 * 1024];
fileStream.SetLength(0);
while ((bytesRead = addRequest.Stream.Read(buffer, 0, buffer.Length)) > 0)
{
fileStream.Write(buffer, 0, bytesRead);
}
}
WriteCategoriesForFile(fileName, addRequest.categories);
return new StreamStorageSetReply
{
StreamInfo = Get(new Moniker(contextUri, addRequest.name))
};
}
public StreamStorageGetReply GetStream(StreamStorageGetRequest getRequest)
{
EnsureInit();
Moniker itemId = getRequest.itemId;
DirectoryInfo info = new DirectoryInfo(GetDirectoryNameForContext(itemId));
var fileInfo = info.GetFiles(itemId.ItemId);
if (fileInfo.Length > 0)
{
return new StreamStorageGetReply
{
StreamInfo = new StreamStorageInfo
{
ContentType = MediaTypeNames.Application.Octet,
Id = itemId,
Size = fileInfo[0].Length,
Created = fileInfo[0].CreationTimeUtc,
Categories = GetCategoriesForFile(fileInfo[0].FullName)
},
Stream = fileInfo[0].Open(FileMode.Open, FileAccess.Read, FileShare.Read)
};
}
else
{
return null;
}
}
private static void WriteCategoriesForFile(string fileName, IEnumerable<string> categories)
{
using (TextWriter categoriesStream = new StreamWriter(fileName + ".categories", false, Encoding.UTF8))
{
if (categories != null)
{
foreach (string s in categories)
{
categoriesStream.WriteLine(s);
}
}
}
}
public void Delete(Moniker itemId)
{
EnsureInit();
DirectoryInfo info = new DirectoryInfo(GetDirectoryNameForContext(itemId));
if (info.Exists)
{
File.Delete(Path.Combine(info.FullName, itemId.ItemId));
}
}
private string GetDirectoryNameForContext(Moniker contextId)
{
string path = Path.Combine(rootInfo.FullName, contextId.Scope);
foreach (var segment in contextId.Segments)
{
if (segment.Id != null && !segment.IsLast)
{
path = Path.Combine(Path.Combine(path, segment.Name.Value), segment.Id);
}
else
{
path = Path.Combine(path, segment.Name.Value);
}
}
return path;
}
#endregion
#region IStorageProvider<StreamStorageInfo> Members
public StreamStorageInfo Get(Moniker itemId)
{
DirectoryInfo info = new DirectoryInfo(GetDirectoryNameForContext(itemId));
var fileInfo = info.GetFiles(itemId.ItemId);
if (fileInfo.Length > 0)
{
return new StreamStorageInfo
{
ContentType = MediaTypeNames.Application.Octet,
Id = itemId,
Size = fileInfo[0].Length,
Created = fileInfo[0].CreationTimeUtc,
Categories = GetCategoriesForFile(fileInfo[0].FullName)
};
}
else
{
return null;
}
}
public Moniker Store(Moniker contextId, StreamStorageInfo item)
{
throw new NotSupportedException();
}
public void Update(StreamStorageInfo item)
{
throw new NotSupportedException();
}
#endregion
public IEnumerable<PropertyAggregate> Aggregate(Moniker contextId, MonikerMatch contextMatch, string propertyName)
{
EnsureInit();
DirectoryInfo info = new DirectoryInfo(GetDirectoryNameForContext(contextId));
if (info.Exists)
{
return from file in info.GetFiles()
from tag in GetCategoriesForFile(file.FullName)
group tag by tag into tags
select new PropertyAggregate { Value = tags.Key, Count = tags.Count() };
}
else
{
return null;
}
}
}
}
|