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