using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Collections.ObjectModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Web;
using System.ServiceModel.Syndication;
using System.ServiceModel.Description;
using System.Runtime.Serialization;
using System.Xml;
using System.IO;
using System.ServiceModel.Activation;
using System.Security.Permissions;
using dasBlog.Storage.Configuration;
using System.Configuration;
using System.ServiceModel.Configuration;
#if BIZTALKSERVICES
using System.ServiceBus;
#endif
namespace dasBlog.Storage{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public sealed class StorageBus : IStorageBus, IStorageBusLocal, IStorageNode, IStreamStorageNode
{
Dictionary<string, ScopeDescription> storageScopes = new Dictionary<string, ScopeDescription>();
Dictionary<PathSegmentName, List<NodeDescription>> storageNodesByNodeName = new Dictionary<PathSegmentName, List<NodeDescription>>();
private static StorageBus _singletonInstance;
public static StorageBus Current
{
get
{
if (_singletonInstance == null)
{
_singletonInstance = new StorageBus();
}
return _singletonInstance;
}
}
private StorageBus()
{
InitializeFromConfig();
}
private void InitializeFromConfig()
{
UserNameCredentialsSection credentialsSection = ConfigurationManager.GetSection("dasBlog.Storage/userNameCredentials") as UserNameCredentialsSection;
UriLayoutsSection layoutsSection = ConfigurationManager.GetSection("dasBlog.Storage/uriLayouts") as UriLayoutsSection;
NodesSection nodesSection = ConfigurationManager.GetSection("dasBlog.Storage/nodes") as NodesSection;
StorageBusSection storageBusSection = ConfigurationManager.GetSection("dasBlog.Storage/storageBus") as StorageBusSection;
ClientSection wcfClientSection = ConfigurationManager.GetSection("system.serviceModel/clients") as ClientSection;
foreach (ScopeElement scope in storageBusSection.Scopes)
{
if (storageScopes.ContainsKey(scope.Name))
{
throw new ConfigurationErrorsException(
String.Format("Duplicate scope '{0}'",
scope.Name),
scope.ElementInformation.Source,
scope.ElementInformation.LineNumber);
}
else
{
Dictionary<string, NodeDescription> usedNodes = new Dictionary<string, NodeDescription>();
UriLayoutSection layout = layoutsSection.UriLayouts.Get(scope.UriLayout);
if (layout != null)
{
ScopeDescription scopeDescription = new ScopeDescription(scope.Name);
scopeDescription.Paths = BuildPathMappings(credentialsSection,
nodesSection,
wcfClientSection,
usedNodes,
layout.Segments);
storageScopes.Add(scope.Name, scopeDescription);
}
else
{
throw new ConfigurationErrorsException(
String.Format("Cannot find UriLayout '{0}' for scope '{1}'",
scope.UriLayout, scope.Name),
scope.ElementInformation.Source,
scope.ElementInformation.LineNumber);
}
}
}
}
private static PathMappings BuildPathMappings(UserNameCredentialsSection credentialsSection, NodesSection nodesSection, ClientSection wcfClientSection, Dictionary<string, NodeDescription> usedNodes, SegmentElementCollection segments)
{
PathMappings pathMappings = new PathMappings();
foreach (SegmentElement segment in segments)
{
NodeDescription nodeDescription = null;
if (usedNodes.ContainsKey(segment.Node))
{
nodeDescription = usedNodes[segment.Node];
pathMappings.Add(new PathMapping(new PathSegmentName(segment.Role), nodeDescription));
}
else
{
NodeElement node = nodesSection.Nodes.Get(segment.Node);
if (node != null)
{
if (node.Provider != null)
{
Type providerType = Type.GetType(node.Provider);
if (providerType != null)
{
IStorageNode nodeInstance = StorageNodeFactory.CreateStorageNode(providerType, node.InitData);
nodeDescription = new NodeDescription(nodeInstance);
usedNodes.Add(node.Name, nodeDescription);
if (segment.Segments.Count > 0)
{
nodeDescription.Paths =
BuildPathMappings(credentialsSection, nodesSection, wcfClientSection,
usedNodes, segment.Segments);
}
}
else
{
throw new ConfigurationErrorsException(
String.Format("Could not load provider type '{0}' for storage node '{1}'",
node.Provider, node.Name),
node.ElementInformation.Source,
node.ElementInformation.LineNumber);
}
}
else if (node.Client != null)
{
UserNameCredentialElement credential = null;
if (node.ClientCredential != null)
{
credential = credentialsSection.UserNameCredentials.Get(node.ClientCredential);
}
if (wcfClientSection.Endpoints.ContainsKey(node.Client))
{
ChannelEndpointElement endpointElement = wcfClientSection.Endpoints[node.Client];
Type contractType = Type.GetType(endpointElement.Contract);
if (contractType is IStreamStorageNode)
{
ChannelFactory<IStorageNodeChannel> factory = new ChannelFactory<IStorageNodeChannel>(endpointElement.Name);
factory.Endpoint.Behaviors.Add(new SimpleAuthenticationBehavior());
if (credential != null)
{
factory.Credentials.UserName.UserName = credential.Username;
factory.Credentials.UserName.Password = credential.Password;
}
nodeDescription = new NodeDescription(factory.CreateChannel());
usedNodes.Add(node.Name, nodeDescription);
if ( segment.Segments.Count > 0 )
{
nodeDescription.Paths =
BuildPathMappings(credentialsSection,nodesSection, wcfClientSection,
usedNodes, segment.Segments);
}
}
else if (contractType is IStorageNode)
{
ChannelFactory<IStreamStorageNodeChannel> factory = new ChannelFactory<IStreamStorageNodeChannel>(endpointElement.Name);
factory.Endpoint.Behaviors.Add(new SimpleAuthenticationBehavior());
if (credential != null)
{
factory.Credentials.UserName.UserName = credential.Username;
factory.Credentials.UserName.Password = credential.Password;
}
nodeDescription = new NodeDescription(factory.CreateChannel());
usedNodes.Add(node.Name, nodeDescription);
if ( segment.Segments.Count > 0 )
{
nodeDescription.Paths =
BuildPathMappings(credentialsSection,nodesSection, wcfClientSection,
usedNodes, segment.Segments);
}
}
else
{
throw new ConfigurationErrorsException(
String.Format("Invalid contract type '{0}' for client endpoint '{1}' referenced by storage node '{2}'",
endpointElement.Contract, endpointElement.Name, node.Name),
node.ElementInformation.Source,
node.ElementInformation.LineNumber);
}
}
else
{
throw new ConfigurationErrorsException(
String.Format("Cannot find system.serviceModel/clients/endpoint named '{0}' for storage node '{1}'",
node.Client, node.Name),
node.ElementInformation.Source,
node.ElementInformation.LineNumber);
}
}
if (nodeDescription != null)
{
pathMappings.Add(new PathMapping(new PathSegmentName(segment.Role), nodeDescription));
}
else
{
throw new ConfigurationErrorsException(
String.Format("No or invalid client reference or provider reference specified for storage node '{1}'",
node.Name),
node.ElementInformation.Source,
node.ElementInformation.LineNumber);
}
}
else
{
throw new ConfigurationErrorsException(
String.Format("Cannot find node '{0}' for segment '{1}'",
segment.Node, segment.Role),
node.ElementInformation.Source,
node.ElementInformation.LineNumber);
}
}
}
return pathMappings;
}
public IStorageNode FindNode(Moniker moniker)
{
var nodeDesc = ((IStorageBus)this).FindNode(moniker);
if (nodeDesc != null)
{
return nodeDesc.GetStorageNode();
}
return null;
}
NodeDescription IStorageBus.FindNode(Moniker moniker)
{
if (moniker.Segments.Count > 0)
{
if (storageScopes.ContainsKey(moniker.Scope))
{
NodeDescription node = null;
ScopeDescription scope = storageScopes[moniker.Scope];
PathMappings mappings = scope.Paths;
for (int i = 0; i < moniker.Segments.Count; i++)
{
PathMapping mapping = mappings[moniker.Segments[i].Name];
if (mapping == null)
return null;
node = mapping.Node;
mappings = node.Paths;
}
return node;
}
}
return null;
}
public void AddStorageScope(ScopeDescription scopeDesc)
{
if (!storageScopes.ContainsKey(scopeDesc.Name))
{
storageScopes.Add(scopeDesc.Name, scopeDesc);
foreach (PathMapping mapping in scopeDesc.Paths)
{
mapping.Node.BindNode();
}
}
}
public List<ScopeDescription> GetScopes()
{
return new List<ScopeDescription>(storageScopes.Values);
}
public void RemoveStorageScope(string scopeName)
{
if (storageScopes.ContainsKey(scopeName))
{
storageScopes.Remove(scopeName);
}
}
Message IStorageNode.GetItemSchema(string baseUri, string schemaId)
{
throw new NotImplementedException();
}
Message IStorageNode.Select(string baseUri, Moniker moniker, MonikerMatch match, QueryDescription query, SerializationMode serializationMode)
{
IStorageNode node = this.FindNode(moniker);
return node.Select(baseUri, moniker, match, query, serializationMode);
}
Message IStorageNode.Aggregate(string baseUri, Moniker moniker, MonikerMatch match, string propertyName, SerializationMode serializationMode)
{
IStorageNode node = this.FindNode(moniker);
return node.Aggregate(baseUri,moniker,match,propertyName,serializationMode);
}
Message IStorageNode.Get(string baseUri, Moniker itemId, SerializationMode serializationMode)
{
IStorageNode node = this.FindNode(itemId);
return node.Get(baseUri, itemId, serializationMode);
}
void IStorageNode.Delete(Moniker itemId)
{
IStorageNode node = this.FindNode(itemId);
node.Delete(itemId);
}
Moniker IStorageNode.Store(Moniker moniker, XmlElement item, SerializationMode serializationMode)
{
IStorageNode node = this.FindNode(moniker);
return node.Store(moniker, item, serializationMode);
}
StreamStorageGetReply IStreamStorageNode.GetStream(StreamStorageGetRequest getRequest)
{
IStreamStorageNode node = this.FindNode(getRequest.itemId) as IStreamStorageNode;
return node.GetStream(getRequest);
}
StreamStorageSetReply IStreamStorageNode.SetStream(StreamStorageSetRequest addRequest)
{
IStreamStorageNode node = this.FindNode(addRequest.moniker) as IStreamStorageNode;
return node.SetStream(addRequest);
}
}
public class StorageBusFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
if (serviceType == typeof(StorageBus))
{
var host = new ServiceHost(StorageBus.Current, baseAddresses);
host.Opening += delegate(object sender, EventArgs e)
{
foreach (var ep in host.Description.Endpoints)
{
ep.Behaviors.Add(new SimpleAuthenticationBehavior());
}
};
return host;
}
else
{
throw new CommunicationException();
}
}
}
}
|