Line data Source code
1 : #region Copyright
2 : // // -----------------------------------------------------------------------
3 : // // <copyright company="Chinchilla Software Limited">
4 : // // Copyright Chinchilla Software Limited. All rights reserved.
5 : // // </copyright>
6 : // // -----------------------------------------------------------------------
7 : #endregion
8 :
9 : using System;
10 : using System.Collections.Generic;
11 : using System.Linq;
12 : using Cqrs.Configuration;
13 : using cdmdotnet.Logging;
14 : using Cqrs.DataStores;
15 : using Cqrs.Entities;
16 :
17 : namespace Cqrs.Azure.BlobStorage.DataStores
18 : {
19 : /// <summary>
20 : /// A factory for getting connection strings and container names for <see cref="IDataStore{TData}"/> access.
21 : /// This factory supports reading and writing from separate storage accounts. Specifically you can have as many different storage accounts as you want to configure when writing.
22 : /// This allows for manual mirroring of data while reading from the fastest/closest location possible.
23 : /// </summary>
24 : public class BlobStorageDataStoreConnectionStringFactory : IBlobStorageDataStoreConnectionStringFactory
25 1 : {
26 : /// <summary>
27 : /// The name of the app setting in <see cref="IConfigurationManager"/> that will have the connection string of the readable storage account if using a separate storage account for reads and writes.
28 : /// </summary>
29 : public static string BlobStorageReadableDataStoreConnectionStringKey = "Cqrs.Azure.BlobStorage.DataStore.Read.ConnectionStringName";
30 :
31 : /// <summary>
32 : /// The name of the app setting in <see cref="IConfigurationManager"/> that will have the connection string of the writeable storage account if using a separate storage account for reads and writes.
33 : /// This value gets appended with a ".1", ".2" etc allowing you to write to as many different locations as possible.
34 : /// </summary>
35 : public static string BlobStorageWritableDataStoreConnectionStringKey = "Cqrs.Azure.BlobStorage.DataStore.Write.ConnectionStringName";
36 :
37 : /// <summary>
38 : /// The name of the app setting in <see cref="IConfigurationManager"/> that will have the connection string if using a single storage account for both reads and writes.
39 : /// </summary>
40 : public static string BlobStorageDataStoreConnectionStringKey = "Cqrs.Azure.BlobStorage.DataStore.ConnectionStringName";
41 :
42 : /// <summary>
43 : /// The name of the app setting in <see cref="IConfigurationManager"/> that will have the base name of the container used.
44 : /// </summary>
45 : public static string BlobStorageBaseContainerNameKey = "Cqrs.Azure.BlobStorage.DataStore.BaseContainerName";
46 :
47 : /// <summary>
48 : /// The name of the app setting in <see cref="IConfigurationManager"/> that will indicate if the container is public or not.
49 : /// </summary>
50 : public static string BlobStorageIsContainerPublicKey = "Cqrs.Azure.BlobStorage.DataStore.{0}.IsPublic";
51 :
52 : /// <summary>
53 : /// Gets or sets the <see cref="IConfigurationManager"/>.
54 : /// </summary>
55 : protected IConfigurationManager ConfigurationManager { get; private set; }
56 :
57 : /// <summary>
58 : /// Gets or sets the <see cref="ILogger"/>.
59 : /// </summary>
60 : protected ILogger Logger { get; private set; }
61 :
62 : /// <summary>
63 : /// Instantiates a new instance of <see cref="BlobStorageDataStoreConnectionStringFactory"/>.
64 : /// </summary>
65 1 : public BlobStorageDataStoreConnectionStringFactory(IConfigurationManager configurationManager, ILogger logger)
66 : {
67 : ConfigurationManager = configurationManager;
68 : Logger = logger;
69 : }
70 :
71 : /// <summary>
72 : /// Gets all writeable connection strings. If using a single storage account, then <see cref="BlobStorageDataStoreConnectionStringKey"/> will most likely be returned.
73 : /// If a value for <see cref="BlobStorageWritableDataStoreConnectionStringKey"/> is found, it will append ".1", ".2" etc returning any additionally found connection string values in <see cref="ConfigurationManager"/>.
74 : /// </summary>
75 1 : public virtual IEnumerable<string> GetWritableConnectionStrings()
76 : {
77 : Logger.LogDebug("Getting blob storage writeable connection strings", "BlobStorageDataStoreConnectionStringFactory\\GetWritableConnectionStrings");
78 : try
79 : {
80 : var collection = new List<string> ();
81 :
82 : string blobStorageWritableDataStoreConnectionString = ConfigurationManager.GetSetting(BlobStorageWritableDataStoreConnectionStringKey);
83 : if (blobStorageWritableDataStoreConnectionString == null)
84 : {
85 : Logger.LogDebug(string.Format("No application settings named '{0}' was found in the configuration file with the cloud storage connection string.", BlobStorageWritableDataStoreConnectionStringKey), "BlobStorageDataStoreConnectionStringFactory\\GetWritableConnectionStrings");
86 : blobStorageWritableDataStoreConnectionString = ConfigurationManager.GetSetting(BlobStorageDataStoreConnectionStringKey);
87 : }
88 :
89 : int writeIndex = 1;
90 : while (!string.IsNullOrWhiteSpace(blobStorageWritableDataStoreConnectionString))
91 : {
92 : collection.Add(blobStorageWritableDataStoreConnectionString);
93 :
94 : blobStorageWritableDataStoreConnectionString = ConfigurationManager.GetSetting(string.Format("{0}.{1}", BlobStorageWritableDataStoreConnectionStringKey, writeIndex));
95 : writeIndex++;
96 : }
97 :
98 : if (!collection.Any())
99 : throw new NullReferenceException();
100 :
101 : return collection;
102 : }
103 : catch (NullReferenceException exception)
104 : {
105 : throw new NullReferenceException(string.Format("No application settings named '{0}' was found in the configuration file with the cloud storage connection string.", BlobStorageDataStoreConnectionStringKey), exception);
106 : }
107 : finally
108 : {
109 : Logger.LogDebug("Getting blob storage writeable connection string... Done", "BlobStorageDataStoreConnectionStringFactory\\GetWritableConnectionStrings");
110 : }
111 : }
112 :
113 : /// <summary>
114 : /// Gets the readable connection string. If using a single storage account, then <see cref="BlobStorageDataStoreConnectionStringKey"/> will most likely be returned.
115 : /// If a value for <see cref="BlobStorageReadableDataStoreConnectionStringKey"/> is found, that will be returned instead.
116 : /// </summary>
117 1 : public virtual string GetReadableConnectionString()
118 : {
119 : Logger.LogDebug("Getting blob storage readable connection strings", "BlobStorageDataStoreConnectionStringFactory\\GetReadableConnectionStrings");
120 : try
121 : {
122 : string blobStorageWritableDataStoreConnectionString = ConfigurationManager.GetSetting(BlobStorageReadableDataStoreConnectionStringKey);
123 : if (blobStorageWritableDataStoreConnectionString == null)
124 : {
125 : Logger.LogDebug(string.Format("No application settings named '{0}' was found in the configuration file with the cloud storage connection string.", BlobStorageReadableDataStoreConnectionStringKey), "BlobStorageDataStoreConnectionStringFactory\\GetReadableConnectionStrings");
126 : blobStorageWritableDataStoreConnectionString = ConfigurationManager.GetSetting(BlobStorageDataStoreConnectionStringKey);
127 : }
128 :
129 : if (string.IsNullOrWhiteSpace(blobStorageWritableDataStoreConnectionString))
130 : throw new NullReferenceException();
131 :
132 : return blobStorageWritableDataStoreConnectionString;
133 : }
134 : catch (NullReferenceException exception)
135 : {
136 : throw new NullReferenceException(string.Format("No application settings named '{0}' was found in the configuration file with the cloud storage connection string.", BlobStorageDataStoreConnectionStringKey), exception);
137 : }
138 : finally
139 : {
140 : Logger.LogDebug("Getting blob storage readable connection string... Done", "BlobStorageDataStoreConnectionStringFactory\\GetReadableConnectionStrings");
141 : }
142 : }
143 :
144 : /// <summary>
145 : /// Returns the name of the base contain to be used.
146 : /// This will be the value from <see cref="ConfigurationManager"/> keyed <see cref="BlobStorageBaseContainerNameKey"/>.
147 : /// </summary>
148 1 : public virtual string GetBaseContainerName()
149 : {
150 : Logger.LogDebug("Getting blob storage base container name", "BlobStorageDataStoreConnectionStringFactory\\GetBaseContainerName");
151 : try
152 : {
153 : string result = ConfigurationManager.GetSetting(BlobStorageBaseContainerNameKey);
154 :
155 : if (string.IsNullOrWhiteSpace(result))
156 : throw new NullReferenceException();
157 :
158 : return result;
159 : }
160 : catch (NullReferenceException exception)
161 : {
162 : throw new NullReferenceException(string.Format("No application setting named '{0}' in the configuration file.", BlobStorageBaseContainerNameKey), exception);
163 : }
164 : finally
165 : {
166 : Logger.LogDebug("Getting blob storage base container name... Done", "BlobStorageDataStoreConnectionStringFactory\\GetBaseContainerName");
167 : }
168 : }
169 :
170 : /// <summary>
171 : /// Returns <see cref="GetBaseContainerName"/> and <see cref="GetEntityName{TData}"/>.
172 : /// </summary>
173 : /// <returns><see cref="GetBaseContainerName"/> and <see cref="GetEntityName{TData}"/></returns>
174 1 : public virtual string GetContainerName<TData>()
175 : where TData : Entity
176 : {
177 : Logger.LogDebug("Getting blob storage container name", "BlobStorageDataStoreConnectionStringFactory\\GetContainerName");
178 :
179 : string name = string.Format("{0}\\{1}", GetBaseContainerName(), GetEntityName<TData>());
180 :
181 : Logger.LogDebug("Getting blob storage container name... Done", "BlobStorageDataStoreConnectionStringFactory\\GetContainerName");
182 :
183 : return name;
184 : }
185 :
186 : /// <summary>
187 : /// Get if the container is public or not.
188 : /// </summary>
189 1 : public virtual bool IsContainerPublic<TData>()
190 : where TData : Entity
191 : {
192 : bool result;
193 : // We default to false to protect the data
194 : if (!ConfigurationManager.TryGetSetting(string.Format(BlobStorageIsContainerPublicKey, GetEntityName<TData>()), out result))
195 : result = false;
196 :
197 : return result;
198 : }
199 :
200 : /// <summary>
201 : /// Gets the name of the entity that is safe for container use.
202 : /// </summary>
203 1 : public virtual string GetEntityName<TData>()
204 : where TData : Entity
205 : {
206 : Type type = typeof (TData);
207 : string name = type.AssemblyQualifiedName ?? string.Empty;
208 : int index1 = name.IndexOf(",", StringComparison.InvariantCultureIgnoreCase);
209 : int index2 = -1;
210 : if (index1 > -1)
211 : index2 = name.IndexOf(",", index1 + 1, StringComparison.InvariantCultureIgnoreCase);
212 : if (index2 > -1)
213 : return name.Substring(0, index2);
214 : if (index1 > -1)
215 : return name.Substring(0, index1);
216 : return name;
217 : }
218 : }
219 : }
|