using System.ServiceModel.Syndication;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.IO;
using System.Xml;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System;
using System.ServiceModel.Channels;
using System.Xml.Linq;
using System.Xml.Schema;
using System.ServiceModel.Web;
using System.Web.Caching;
namespace dasBlog.Storage{
[ServiceBehavior(ConfigurationName = "StorageNode", InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
internal sealed class StorageNodeService<T> : IStorageNode where T : class, IEntry<T>, new()
{
private IStorageProvider<T> _provider;
public StorageNodeService(IStorageProvider<T> provider)
{
_provider = provider;
}
public StorageNodeService(Type providerType, string initData)
{
_provider = (IStorageProvider<T>)Activator.CreateInstance(providerType);
if (_provider is IInitStorageProvider)
{
((IInitStorageProvider)_provider).Initialize(initData);
}
}
public Message GetItemSchema(string baseUri, string schemaId)
{
var replyAction = Names.IStorageNodeNamespace+"GetItemSchemaResponse";
XmlSchema schema = SerializationTools<T>.GetSchema(baseUri, schemaId);
if (schema != null)
{
return Message.CreateMessage(
GetReplyMessageVersion(),
replyAction,
new XmlSchemaBodyWriter(schema));
}
else
{
throw new FaultException<StorageNodeInvalidSchemaId>(
new StorageNodeInvalidSchemaId { SchemaId = schemaId });
}
}
public Message Select(string baseUri, Moniker moniker, MonikerMatch contextMatch, QueryDescription query, SerializationMode serializationMode)
{
var replyAction = Names.IStorageNodeNamespace+"SelectResponse";
XmlDictionaryReader cachedReader = null;
string cacheKey = CacheUtil.MakeQueryKey(moniker, query, serializationMode);
if ((cachedReader = Cache.GetReader(cacheKey)) != null)
{
return Message.CreateMessage(
GetReplyMessageVersion(),
replyAction,
cachedReader);
}
else
{
var result = _provider.Select(moniker, contextMatch, query);
if (serializationMode == SerializationMode.Rss || serializationMode == SerializationMode.Atom)
{
List<SyndicationItem> items = new List<SyndicationItem>();
foreach (SyndicationItem item in from T t in result select t.ToSyndicationItem<T>())
{
List<SyndicationLink> links = new List<SyndicationLink>();
foreach (SyndicationLink link in item.Links)
{
if (link.Uri.Scheme == Moniker.Scheme)
{
links.Add(
new SyndicationLink(
new Moniker(link.Uri).ToUri(new Uri(baseUri)),
link.RelationshipType,
link.Title,
link.MediaType,
link.Length));
}
}
item.Links.Clear();
foreach (var link in links)
{
item.Links.Add(link);
}
if (item.Id != null)
{
item.Id = new Moniker(item.Id).ToUri(new Uri(baseUri)).ToString();
}
items.Add(item);
}
var feed = new SyndicationFeed(items);
feed.Generator = "dasBlog Storage";
if (serializationMode == SerializationMode.Rss)
{
cachedReader = Cache.AddFeed(cacheKey, new Rss20FeedFormatter<SyndicationFeed>(feed));
return Message.CreateMessage(
GetReplyMessageVersion(),
replyAction,
cachedReader);
}
else
{
cachedReader = Cache.AddFeed(cacheKey, new Atom10FeedFormatter<SyndicationFeed>(feed));
return Message.CreateMessage(
GetReplyMessageVersion(),
replyAction,
cachedReader);
}
}
else
{
cachedReader = Cache.AddReader(cacheKey,
SerializationTools<T>.SerializeList(result),
moniker.ItemPath,
CacheItemPriority.Normal);
return Message.CreateMessage(
GetReplyMessageVersion(),
replyAction,
cachedReader );
}
}
}
public Message Get(string baseUri, Moniker itemId, SerializationMode serializationMode)
{
var replyAction = Names.IStorageNodeNamespace+"GetResponse";
XmlDictionaryReader cachedReader = null;
string cacheKey = CacheUtil.MakeQueryKey(itemId, null, SerializationMode.Native);
if ((cachedReader = Cache.GetReader(cacheKey)) != null)
{
return Message.CreateMessage(
GetReplyMessageVersion(),
replyAction,
cachedReader);
}
else
{
var item = _provider.Get(itemId);
if (item != null)
{
XmlDictionaryReader messageBody =
Cache.AddReader(cacheKey,
SerializationTools<T>.Serialize(item),
itemId.ItemPath,
CacheItemPriority.Normal);
return Message.CreateMessage(
GetReplyMessageVersion(),
replyAction,
messageBody);
}
else
{
return Message.CreateMessage(
GetReplyMessageVersion(),
replyAction);
}
}
}
public void Delete(Moniker itemId)
{
Cache.RemoveByKeyPrefix(itemId.ItemPath);
_provider.Delete(itemId);
}
public Moniker Store(Moniker moniker, XmlElement xitem, SerializationMode serializationMode)
{
Cache.RemoveByKeyPrefix(moniker.ItemPath);
return _provider.Store(moniker, SerializationTools<T>.Deserialize(new XmlNodeReader(xitem), serializationMode == SerializationMode.Json ? WebMessageFormat.Json : WebMessageFormat.Xml));
}
public Message Aggregate(string baseUri, Moniker moniker, MonikerMatch match, string propertyName, SerializationMode serializationMode)
{
var replyAction = Names.IStorageNodeNamespace+"AggregateResponse";
XmlDictionaryReader cachedReader = null;
string cacheKey = CacheUtil.MakeAggregateKey(moniker, propertyName, serializationMode);
if ((cachedReader = Cache.GetReader(cacheKey)) != null)
{
return Message.CreateMessage(
GetReplyMessageVersion(),
replyAction,
cachedReader);
}
var result = _provider.Aggregate(moniker, match, propertyName);
if (result == null || result.Count() == 0)
{
return Message.CreateMessage(
GetReplyMessageVersion(),
replyAction);
}
else
{
if (serializationMode == SerializationMode.Rss || serializationMode == SerializationMode.Atom)
{
var feed = new SyndicationFeed(from PropertyAggregate prop in result select new SyndicationItem { Title = TextSyndicationContent.CreatePlaintextContent(prop.Value), Content = TextSyndicationContent.CreatePlaintextContent(prop.Count.ToString()) });
if (serializationMode == SerializationMode.Rss)
{
cachedReader = Cache.AddFeed(cacheKey, new Rss20FeedFormatter<SyndicationFeed>(feed));
return Message.CreateMessage(
GetReplyMessageVersion(),
replyAction,
cachedReader);
}
else
{
cachedReader = Cache.AddFeed(cacheKey, new Atom10FeedFormatter<SyndicationFeed>(feed));
return Message.CreateMessage(
GetReplyMessageVersion(),
replyAction,
cachedReader);
}
}
else
{
cachedReader = Cache.AddReader(cacheKey,
SerializationTools<PropertyAggregate>.SerializeList(result),
moniker.ItemPath,
CacheItemPriority.Normal);
return Message.CreateMessage(
GetReplyMessageVersion(),
replyAction,
cachedReader);
}
}
}
private static MessageVersion GetReplyMessageVersion()
{
if (OperationContext.Current != null)
{
return OperationContext.Current.IncomingMessageVersion;
}
else
{
return MessageVersion.Default;
}
}
private static System.Web.Caching.Cache _cache = null;
private System.Web.Caching.Cache Cache
{
get
{
if (System.Web.Hosting.HostingEnvironment.Cache != null)
{
return System.Web.Hosting.HostingEnvironment.Cache;
}
else if ( _cache == null )
{
_cache = new System.Web.Caching.Cache();
}
return _cache;
}
}
}
}
|