using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Web.Script.Serialization; namespace FileInterface.Scheduler { public sealed class WatcherJobRepository { private readonly object _sync = new object(); private readonly string _fileName; private readonly JavaScriptSerializer _serializer = new JavaScriptSerializer(); private List _jobs; public WatcherJobRepository(string fileName) { _fileName = Path.GetFullPath(fileName); _serializer.MaxJsonLength = Int32.MaxValue; _jobs = LoadInternal(); } public IList GetAll() { lock (_sync) return Clone(_jobs); } public WatcherJobConfig GetById(string id) { lock (_sync) { WatcherJobConfig job = _jobs.FirstOrDefault(j => String.Equals(j.Id, id, StringComparison.OrdinalIgnoreCase)); return job == null ? null : Clone(job); } } public WatcherJobConfig Save(WatcherJobConfig job) { if (job == null) throw new ArgumentNullException("job"); Validate(job); lock (_sync) { if (String.IsNullOrWhiteSpace(job.Id)) job.Id = Guid.NewGuid().ToString("N"); int index = _jobs.FindIndex(j => String.Equals(j.Id, job.Id, StringComparison.OrdinalIgnoreCase)); if (index >= 0) _jobs[index] = Clone(job); else _jobs.Add(Clone(job)); SaveInternal(); return Clone(job); } } public bool Delete(string id) { lock (_sync) { int count = _jobs.RemoveAll(j => String.Equals(j.Id, id, StringComparison.OrdinalIgnoreCase)); if (count > 0) SaveInternal(); return count > 0; } } private List LoadInternal() { if (!File.Exists(_fileName)) return new List(); string json = File.ReadAllText(_fileName, Encoding.UTF8); if (String.IsNullOrWhiteSpace(json)) return new List(); return _serializer.Deserialize>(json) ?? new List(); } private void SaveInternal() { string dir = Path.GetDirectoryName(_fileName); if (!String.IsNullOrWhiteSpace(dir)) Directory.CreateDirectory(dir); string json = _serializer.Serialize(_jobs); string tmp = _fileName + ".tmp"; File.WriteAllText(tmp, json, new UTF8Encoding(false)); if (File.Exists(_fileName)) { string backup = _fileName + ".bak"; try { File.Replace(tmp, _fileName, backup, true); } catch { File.Delete(_fileName); File.Move(tmp, _fileName); } } else File.Move(tmp, _fileName); } private static void Validate(WatcherJobConfig job) { if (String.IsNullOrWhiteSpace(job.Name)) throw new InvalidOperationException("Name is required."); if (String.IsNullOrWhiteSpace(job.SourceDirectory)) throw new InvalidOperationException("SourceDirectory is required."); if (String.IsNullOrWhiteSpace(job.CustomFunction)) throw new InvalidOperationException("CustomFunction is required."); if (!job.WatchCreated && !job.WatchChanged && !job.WatchRenamed) throw new InvalidOperationException("At least one watcher event (Created, Changed, Renamed) must be enabled."); if (job.MoveFileAfterSuccess && String.IsNullOrWhiteSpace(job.MoveTargetDirectory)) throw new InvalidOperationException("MoveTargetDirectory is required when MoveFileAfterSuccess=true."); if (job.InArgs == null) job.InArgs = new List(); if (String.IsNullOrWhiteSpace(job.SearchPattern)) job.SearchPattern = "*.*"; if (job.JoinSeparator == null) job.JoinSeparator = ";"; if (job.DebounceMilliseconds < 0) job.DebounceMilliseconds = 0; if (job.FileReadyRetries < 1) job.FileReadyRetries = 1; if (job.FileReadyRetries > 1000) job.FileReadyRetries = 1000; if (job.FileReadyDelayMilliseconds < 10) job.FileReadyDelayMilliseconds = 10; } private T Clone(T value) { return _serializer.Deserialize(_serializer.Serialize(value)); } } }