PageRenderTime 65ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/BlogEngine/DotNetSlave.BusinessLogic/Providers/FileSystemProviders/DbFileSystemProvider.cs

#
C# | 509 lines | 327 code | 42 blank | 140 comment | 68 complexity | 9b2ae3a5243ead33fc33fba19535d5cb MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0, BSD-3-Clause
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web.Configuration;
  5. using System.Collections.Specialized;
  6. using System.Configuration.Provider;
  7. namespace BlogEngine.Core.Providers
  8. {
  9. /// <summary>
  10. /// DbBlogProvider Parial class for manageing all FileSystem methods
  11. /// </summary>
  12. public partial class DbFileSystemProvider : BlogFileSystemProvider
  13. {
  14. /// <summary>
  15. /// The conn string name.
  16. /// </summary>
  17. private string connStringName;
  18. /// <summary>
  19. /// The parm prefix.
  20. /// </summary>
  21. private string parmPrefix;
  22. /// <summary>
  23. /// The table prefix.
  24. /// </summary>
  25. private string tablePrefix;
  26. /// <summary>
  27. /// init
  28. /// </summary>
  29. /// <param name="name"></param>
  30. /// <param name="config"></param>
  31. public override void Initialize(string name, NameValueCollection config)
  32. {
  33. if (config == null)
  34. {
  35. throw new ArgumentNullException("config");
  36. }
  37. if (String.IsNullOrEmpty(name))
  38. {
  39. name = "DbBlogProvider";
  40. }
  41. if (String.IsNullOrEmpty(config["description"]))
  42. {
  43. config.Remove("description");
  44. config.Add("description", "Generic Database Blog Provider");
  45. }
  46. base.Initialize(name, config);
  47. if (config["storageVariable"] == null)
  48. {
  49. // default to BlogEngine
  50. config["storageVariable"] = "BlogEngine";
  51. }
  52. this.connStringName = config["storageVariable"];
  53. config.Remove("storageVariable");
  54. if (config["tablePrefix"] == null)
  55. {
  56. // default
  57. config["tablePrefix"] = "be_";
  58. }
  59. this.tablePrefix = config["tablePrefix"];
  60. config.Remove("tablePrefix");
  61. if (config["parmPrefix"] == null)
  62. {
  63. // default
  64. config["parmPrefix"] = "@";
  65. }
  66. this.parmPrefix = config["parmPrefix"];
  67. config.Remove("parmPrefix");
  68. // Throw an exception if unrecognized attributes remain
  69. if (config.Count > 0)
  70. {
  71. var attr = config.GetKey(0);
  72. if (!String.IsNullOrEmpty(attr))
  73. {
  74. throw new ProviderException(string.Format("Unrecognized attribute: {0}", attr));
  75. }
  76. }
  77. }
  78. #region Contansts & Fields
  79. /// <summary>
  80. /// active web.config connection string, defined by the blogProvider sections
  81. /// </summary>
  82. private string connectionString { get { return WebConfigurationManager.ConnectionStrings[this.connStringName].ConnectionString; } }
  83. #endregion
  84. #region Methods
  85. /// <summary>
  86. /// Clears a file system. This will delete all files and folders recursivly.
  87. /// </summary>
  88. /// <remarks>
  89. /// Handle with care... Possibly an internal method?
  90. /// </remarks>
  91. public override void ClearFileSystem()
  92. {
  93. var root = Blog.CurrentInstance.RootFileStore;
  94. foreach (var directory in root.Directories)
  95. directory.Delete();
  96. foreach (var file in root.Files)
  97. file.Delete();
  98. root.Delete();
  99. }
  100. /// <summary>
  101. /// Creates a directory at a specific path
  102. /// </summary>
  103. /// <param name="VirtualPath">The virtual path to be created</param>
  104. /// <returns>the new Directory object created</returns>
  105. /// <remarks>
  106. /// Virtual path is the path starting from the /files/ containers
  107. /// The entity is created against the current blog id
  108. /// </remarks>
  109. internal override FileSystem.Directory CreateDirectory(string VirtualPath)
  110. {
  111. VirtualPath = VirtualPath.VirtualPathToDbPath();
  112. if (DirectoryExists(VirtualPath))
  113. return GetDirectory(VirtualPath);
  114. var directoryName = "root";
  115. if (!string.IsNullOrWhiteSpace(VirtualPath))
  116. directoryName = string.Format("/{0}", VirtualPath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries).Last());
  117. FileSystem.FileStoreDb db = new FileSystem.FileStoreDb(this.connectionString);
  118. FileSystem.FileStoreDirectory dir = new FileSystem.FileStoreDirectory
  119. {
  120. BlogID = Blog.CurrentInstance.Id,
  121. CreateDate = DateTime.Now,
  122. FullPath = VirtualPath,
  123. Id = Guid.NewGuid(),
  124. LastAccess = DateTime.Now,
  125. Name = directoryName,
  126. LastModify = DateTime.Now
  127. };
  128. if (!string.IsNullOrWhiteSpace(VirtualPath))
  129. {
  130. var parentPath = VirtualPath.Contains("/") ? VirtualPath.Substring(0, VirtualPath.LastIndexOf("/")) : string.Empty;
  131. dir.ParentID = this.GetDirectory(parentPath).Id;
  132. }
  133. db.FileStoreDirectories.InsertOnSubmit(dir);
  134. db.SubmitChanges();
  135. db.Dispose();
  136. return GetDirectory(VirtualPath);
  137. }
  138. /// <summary>
  139. /// Deletes a spefic directory from a virtual path
  140. /// </summary>
  141. /// <param name="VirtualPath">The path to delete</param>
  142. /// <remarks>
  143. /// Virtual path is the path starting from the /files/ containers
  144. /// The entity is queried against to current blog id
  145. /// </remarks>
  146. public override void DeleteDirectory(string VirtualPath)
  147. {
  148. if (!DirectoryExists(VirtualPath.VirtualPathToDbPath()))
  149. return;
  150. FileSystem.FileStoreDb db = new FileSystem.FileStoreDb(this.connectionString);
  151. var query = db.FileStoreDirectories.Where(x => x.FullPath.ToLower() == VirtualPath.VirtualPathToDbPath().ToLower() && x.BlogID == Blog.CurrentInstance.Id);
  152. foreach (var item in query)
  153. {
  154. var subDirectories = db.FileStoreDirectories.Where(x => x.ParentID == item.Id);
  155. foreach (var sb in subDirectories)
  156. DeleteDirectory(sb.FullPath);
  157. }
  158. db.FileStoreDirectories.DeleteAllOnSubmit(query);
  159. db.SubmitChanges();
  160. db.Dispose();
  161. }
  162. /// <summary>
  163. /// Returns wether or not the specific directory by virtual path exists
  164. /// </summary>
  165. /// <param name="VirtualPath">The virtual path to query</param>
  166. /// <returns>boolean</returns>
  167. public override bool DirectoryExists(string VirtualPath)
  168. {
  169. VirtualPath = VirtualPath.VirtualPathToDbPath();
  170. return new FileSystem.FileStoreDb(this.connectionString).FileStoreDirectories.Where(x => x.FullPath.ToLower() == VirtualPath.ToLower() && x.BlogID == Blog.CurrentInstance.Id).Count() > 0;
  171. }
  172. /// <summary>
  173. /// gets a directory by the virtual path, creates the directory path if it does not exist
  174. /// </summary>
  175. /// <param name="VirtualPath">the virtual path</param>
  176. /// <returns>the directory object</returns>
  177. public override FileSystem.Directory GetDirectory(string VirtualPath)
  178. {
  179. return GetDirectory(VirtualPath, true);
  180. }
  181. /// <summary>
  182. /// gets a directory by the virtual path, with a flag to create if not found
  183. /// </summary>
  184. /// <param name="VirtualPath">The virtual path</param>
  185. /// <param name="CreateNew">bool yes \ no to create the director.</param>
  186. /// <returns>the directory object, or null if the create flag is set to false</returns>
  187. public override FileSystem.Directory GetDirectory(string VirtualPath, bool CreateNew)
  188. {
  189. VirtualPath = VirtualPath.VirtualPathToDbPath();
  190. FileSystem.FileStoreDb db = new FileSystem.FileStoreDb(this.connectionString);
  191. if (string.IsNullOrWhiteSpace(VirtualPath))
  192. {
  193. var directory = db.FileStoreDirectories.FirstOrDefault(x => x.BlogID == Blog.CurrentInstance.Id && x.ParentID == null);
  194. if (directory == null)
  195. {
  196. db.Dispose();
  197. return this.CreateDirectory(VirtualPath);
  198. }
  199. var obj = directory.CopyToDirectory();
  200. db.Dispose();
  201. return obj;
  202. }
  203. else
  204. {
  205. var dir = db.FileStoreDirectories.FirstOrDefault(x => x.FullPath.ToLower() == VirtualPath.ToLower() && x.BlogID == Blog.CurrentInstance.Id);
  206. if (dir == null)
  207. {
  208. var newDirectoryPieces = VirtualPath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
  209. var cPath = string.Empty;
  210. foreach (var pieces in newDirectoryPieces)
  211. {
  212. cPath = string.Format("{0}/{1}", cPath, pieces);
  213. if (!DirectoryExists(cPath))
  214. CreateDirectory(cPath);
  215. }
  216. var nObj = GetDirectory(VirtualPath);
  217. db.Dispose();
  218. return nObj;
  219. }
  220. var obj = dir.CopyToDirectory();
  221. db.Dispose();
  222. return obj;
  223. }
  224. }
  225. /// <summary>
  226. /// gets a directory by a basedirectory and a string array of sub path tree
  227. /// </summary>
  228. /// <param name="BaseDirectory">the base directory object</param>
  229. /// <param name="SubPath">the params of sub path</param>
  230. /// <returns>the directory found, or null for no directory found</returns>
  231. public override FileSystem.Directory GetDirectory(FileSystem.Directory BaseDirectory, params string[] SubPath)
  232. {
  233. return GetDirectory(string.Concat(BaseDirectory.FullPath, string.Join("/", SubPath)));
  234. }
  235. public override FileSystem.Directory GetDirectory(FileSystem.Directory BaseDirectory, bool CreateNew, params string[] SubPath)
  236. {
  237. return GetDirectory(string.Concat(BaseDirectory.FullPath, string.Join("/", SubPath)), CreateNew);
  238. }
  239. /// <summary>
  240. /// gets all the directories underneath a base directory. Only searches one level.
  241. /// </summary>
  242. /// <param name="BaseDirectory">the base directory</param>
  243. /// <returns>collection of Directory objects</returns>
  244. public override IEnumerable<FileSystem.Directory> GetDirectories(FileSystem.Directory BaseDirectory)
  245. {
  246. FileSystem.FileStoreDb db = new FileSystem.FileStoreDb(this.connectionString);
  247. var dirs = db.FileStoreDirectories.Where(x => x.ParentID == BaseDirectory.Id && x.BlogID == Blog.CurrentInstance.Id);
  248. List<FileSystem.Directory> directories = new List<FileSystem.Directory>();
  249. foreach (var d in dirs)
  250. directories.Add(d.CopyToDirectory());
  251. db.Dispose();
  252. return directories;
  253. }
  254. /// <summary>
  255. /// gets all the files in a directory, only searches one level
  256. /// </summary>
  257. /// <param name="BaseDirectory">the base directory</param>
  258. /// <returns>collection of File objects</returns>
  259. public override IEnumerable<FileSystem.File> GetFiles(FileSystem.Directory BaseDirectory)
  260. {
  261. var db = new FileSystem.FileStoreDb(this.connectionString);
  262. var fileDir = db.FileStoreDirectories.FirstOrDefault(x=>x.Id == BaseDirectory.Id);
  263. if (fileDir == null)
  264. return new List<FileSystem.File>();
  265. var arr = fileDir.FileStoreFiles.Select(x => x.CopyToFile()).ToList();
  266. db.Dispose();
  267. return arr;
  268. }
  269. /// <summary>
  270. /// gets a specific file by virtual path
  271. /// </summary>
  272. /// <param name="VirtualPath">the virtual path of the file</param>
  273. /// <returns></returns>
  274. public override FileSystem.File GetFile(string VirtualPath)
  275. {
  276. var db = new FileSystem.FileStoreDb(this.connectionString);
  277. var file = db.FileStoreFiles.FirstOrDefault(x => x.FullPath == VirtualPath.VirtualPathToDbPath() && x.FileStoreDirectory.BlogID == Blog.CurrentInstance.Id).CopyToFile();
  278. db.Dispose();
  279. return file;
  280. }
  281. /// <summary>
  282. /// boolean wether a file exists by its virtual path
  283. /// </summary>
  284. /// <param name="VirtualPath">the virtual path</param>
  285. /// <returns>boolean</returns>
  286. public override bool FileExists(string VirtualPath)
  287. {
  288. var db = new FileSystem.FileStoreDb(this.connectionString);
  289. var file = db.FileStoreFiles.FirstOrDefault(x => x.FullPath.ToLower() == VirtualPath.VirtualPathToDbPath() && x.FileStoreDirectory.BlogID == Blog.CurrentInstance.Id) == null;
  290. db.Dispose();
  291. return file;
  292. }
  293. /// <summary>
  294. /// deletes a file by virtual path
  295. /// </summary>
  296. /// <param name="VirtualPath">virtual path</param>
  297. public override void DeleteFile(string VirtualPath)
  298. {
  299. var db = new FileSystem.FileStoreDb(this.connectionString);
  300. var file = db.FileStoreFiles.Where(x => x.FullPath == VirtualPath.VirtualPathToDbPath() && x.FileStoreDirectory.BlogID == Blog.CurrentInstance.Id);
  301. db.FileStoreFiles.DeleteAllOnSubmit(file);
  302. db.SubmitChanges();
  303. db.Dispose();
  304. }
  305. /// <summary>
  306. /// uploads a file to the provider container
  307. /// </summary>
  308. /// <param name="FileBinary">file contents as byte array</param>
  309. /// <param name="FileName">the file name</param>
  310. /// <param name="BaseDirectory">directory object that is the owner</param>
  311. /// <returns>the new file object</returns>
  312. public override FileSystem.File UploadFile(byte[] FileBinary, string FileName, FileSystem.Directory BaseDirectory)
  313. {
  314. return UploadFile(FileBinary, FileName, BaseDirectory, false);
  315. }
  316. /// <summary>
  317. /// uploads a file to the provider container
  318. /// </summary>
  319. /// <param name="FileBinary">the contents of the file as a byte array</param>
  320. /// <param name="FileName">the file name</param>
  321. /// <param name="BaseDirectory">the directory object that is the owner</param>
  322. /// <param name="Overwrite">boolean wether to overwrite the file if it exists.</param>
  323. /// <returns>the new file object</returns>
  324. public override FileSystem.File UploadFile(byte[] FileBinary, string FileName, FileSystem.Directory BaseDirectory, bool Overwrite)
  325. {
  326. var virtualPath = BaseDirectory.FullPath + "/" + FileName;
  327. var db = new FileSystem.FileStoreDb(this.connectionString);
  328. var files = db.FileStoreFiles.Where(x => x.FileStoreDirectory.Id == BaseDirectory.Id && x.FullPath.ToLower() == virtualPath);
  329. if (files.Count() > 0)
  330. {
  331. if (!Overwrite)
  332. {
  333. db.Dispose();
  334. throw new Exception("File " + FileName + " already exists in this path.");
  335. }
  336. db.FileStoreFiles.DeleteAllOnSubmit(files);
  337. db.SubmitChanges();
  338. }
  339. var file = new FileSystem.FileStoreFile()
  340. {
  341. Contents = FileBinary,
  342. CreateDate = DateTime.Now,
  343. FileID = Guid.NewGuid(),
  344. FullPath = virtualPath,
  345. LastAccess = DateTime.Now,
  346. LastModify = DateTime.Now,
  347. Name = FileName,
  348. ParentDirectoryID = BaseDirectory.Id,
  349. Size = FileBinary.Length
  350. };
  351. db.FileStoreFiles.InsertOnSubmit(file);
  352. db.SubmitChanges();
  353. db.Dispose();
  354. return file.CopyToFile();
  355. }
  356. /// <summary>
  357. /// gets the file contents via Lazy load, however in the DbProvider the Contents are loaded when the initial object is created to cut down on DbReads
  358. /// </summary>
  359. /// <param name="BaseFile">the baseFile object to fill</param>
  360. /// <returns>the original file object</returns>
  361. internal override FileSystem.File GetFileContents(FileSystem.File BaseFile)
  362. {
  363. var db = new FileSystem.FileStoreDb(this.connectionString);
  364. var file = db.FileStoreFiles.FirstOrDefault(x => x.FileID == Guid.Parse(BaseFile.Id));
  365. if (file == null)
  366. throw new ArgumentException("File not found in dataset");
  367. BaseFile.FileContents = file.Contents.ToArray();
  368. db.Dispose();
  369. return BaseFile;
  370. }
  371. /// <summary>
  372. /// Returns a thumbnail image at a maximum size. Only one size is provided as the thumbnail will be scaled down. If the thumbnail does not exist the thumbnail is created
  373. /// </summary>
  374. /// <param name="VirtualPath">The virtual path of the image</param>
  375. /// <param name="MaximumSize">The maximum size for the image</param>
  376. /// <returns>The image with the thumbnail contents</returns>
  377. /// <remarks>
  378. /// this is a virtual file and all actual file methods will not be available.
  379. /// </remarks>
  380. public override FileSystem.Image ImageThumbnail(string VirtualPath, int MaximumSize)
  381. {
  382. var file = GetFile(VirtualPath);
  383. if (!file.IsImage)
  384. return null;
  385. var db = new FileSystem.FileStoreDb(this.connectionString);
  386. var image = file.AsImage;
  387. var thumbnail = db.FileStoreFileThumbs.FirstOrDefault(x => x.FileId == Guid.Parse(image.Id));
  388. if (thumbnail == null)
  389. {
  390. FileSystem.FileStoreFileThumb thumb = new FileSystem.FileStoreFileThumb()
  391. {
  392. contents = FileSystem.Image.ResizeImageThumbnail(MaximumSize, image.FileContents),
  393. FileId = Guid.Parse(image.Id),
  394. size = MaximumSize,
  395. thumbnailId = Guid.NewGuid()
  396. };
  397. db.FileStoreFileThumbs.InsertOnSubmit(thumb);
  398. db.SubmitChanges();
  399. image.FileContents = thumb.contents.ToArray();
  400. }
  401. else
  402. image.FileContents = thumbnail.contents.ToArray();
  403. db.Dispose();
  404. return image;
  405. }
  406. #endregion
  407. }
  408. #region Extension Methods
  409. /// <summary>
  410. /// static classes for the DbFileSystem
  411. /// </summary>
  412. public static class DbFileSystemExtensions
  413. {
  414. /// <summary>
  415. /// copy's the database directory object to a Directory object
  416. /// </summary>
  417. /// <param name="inObj">the database directory to copy</param>
  418. /// <returns>a new Directory object</returns>
  419. public static FileSystem.Directory CopyToDirectory(this FileSystem.FileStoreDirectory inObj)
  420. {
  421. if (inObj == null)
  422. return null;
  423. return new FileSystem.Directory()
  424. {
  425. DateCreated = inObj.CreateDate,
  426. DateModified = inObj.LastModify,
  427. FullPath = inObj.FullPath,
  428. Id = inObj.Id,
  429. LastAccessTime = inObj.LastAccess,
  430. Name = inObj.Name,
  431. IsRoot = inObj.ParentID == null,
  432. };
  433. }
  434. /// <summary>
  435. /// copys a database File object to a File object
  436. /// </summary>
  437. /// <param name="inObj">the database file object to copy</param>
  438. /// <returns>a new File object</returns>
  439. public static FileSystem.File CopyToFile(this FileSystem.FileStoreFile inObj)
  440. {
  441. if (inObj == null)
  442. return null;
  443. return new FileSystem.File()
  444. {
  445. DateCreated = inObj.CreateDate,
  446. DateModified = inObj.LastModify,
  447. FilePath = inObj.FullPath,
  448. FileSize = inObj.Size,
  449. Id = inObj.FileID.ToString(),
  450. LastAccessTime = inObj.LastAccess,
  451. Name = inObj.Name,
  452. FileContents = inObj.Contents.ToArray(),
  453. FullPath = inObj.FullPath
  454. };
  455. }
  456. /// <summary>
  457. /// removes the virtual path of BlogStorageLocation + files from the virtual path.
  458. /// </summary>
  459. /// <param name="VirtualPath">the virtual path to replace against</param>
  460. /// <returns>the repleaced string</returns>
  461. public static string VirtualPathToDbPath(this string VirtualPath)
  462. {
  463. return VirtualPath.Replace(Blog.CurrentInstance.StorageLocation + "files", "");
  464. }
  465. }
  466. #endregion
  467. }