PageRenderTime 35ms CodeModel.GetById 10ms app.highlight 17ms RepoModel.GetById 1ms app.codeStats 1ms

/src/NUnit/util/AssemblyWatcher.cs

#
C# | 163 lines | 124 code | 26 blank | 13 comment | 15 complexity | 4d64b93020299e123371b2394319f948 MD5 | raw file
  1// ****************************************************************
  2// This is free software licensed under the NUnit license. You
  3// may obtain a copy of the license as well as information regarding
  4// copyright ownership at http://nunit.org.
  5// ****************************************************************
  6
  7using System;
  8using System.IO;
  9using System.Timers;
 10using NUnit.Core;
 11
 12namespace NUnit.Util
 13{
 14	/// <summary>
 15	/// AssemblyWatcher keeps track of one or more assemblies to 
 16	/// see if they have changed. It incorporates a delayed notification
 17	/// and uses a standard event to notify any interested parties
 18	/// about the change. The path to the assembly is provided as
 19	/// an argument to the event handler so that one routine can
 20	/// be used to handle events from multiple watchers.
 21	/// </summary>
 22	public class AssemblyWatcher : IAssemblyWatcher
 23	{
 24        static Logger log = InternalTrace.GetLogger(typeof(AssemblyWatcher));
 25
 26        private FileSystemWatcher[] fileWatchers;
 27		private FileInfo[] files;
 28		private bool isWatching;
 29
 30		protected System.Timers.Timer timer;
 31		protected string changedAssemblyPath;
 32
 33		protected FileInfo GetFileInfo(int index)
 34		{
 35			return files[index];
 36		}
 37
 38		public void Setup(int delay, string assemblyFileName)
 39		{
 40			Setup(delay, new string[] {assemblyFileName});
 41		}
 42
 43#if NET_2_0 || NET_4_0
 44		public void Setup(int delay, System.Collections.Generic.IList<string> assemblies)
 45#else
 46        public void Setup(int delay, System.Collections.IList assemblies)
 47#endif
 48		{
 49            log.Info("Setting up watcher");
 50
 51			files = new FileInfo[assemblies.Count];
 52			fileWatchers = new FileSystemWatcher[assemblies.Count];
 53
 54			for (int i = 0; i < assemblies.Count; i++)
 55			{
 56                log.Debug("Setting up FileSystemWatcher for {0}", assemblies[i]);
 57                
 58				files[i] = new FileInfo((string)assemblies[i]);
 59
 60				fileWatchers[i] = new FileSystemWatcher();
 61				fileWatchers[i].Path = files[i].DirectoryName;
 62				fileWatchers[i].Filter = files[i].Name;
 63				fileWatchers[i].NotifyFilter = NotifyFilters.Size | NotifyFilters.LastWrite;
 64				fileWatchers[i].Changed += new FileSystemEventHandler(OnChanged);
 65				fileWatchers[i].EnableRaisingEvents = false;
 66			}
 67
 68			timer = new System.Timers.Timer(delay);
 69			timer.AutoReset = false;
 70			timer.Enabled = false;
 71			timer.Elapsed += new ElapsedEventHandler(OnTimer);
 72		}
 73
 74		public void Start()
 75		{
 76			EnableWatchers( true );
 77		}
 78
 79		public void Stop()
 80		{
 81			EnableWatchers( false );
 82		}
 83
 84		private void EnableWatchers( bool enable )
 85		{
 86            if (fileWatchers != null)
 87    			foreach( FileSystemWatcher watcher in fileWatchers )
 88	    			watcher.EnableRaisingEvents = enable;
 89
 90			isWatching = enable;
 91		}
 92
 93		public void FreeResources()
 94		{
 95            log.Info("FreeResources");
 96
 97            Stop();
 98
 99			if (fileWatchers != null)
100			{
101				foreach (FileSystemWatcher watcher in fileWatchers)
102				{
103                    if (watcher != null)
104                    {
105                        watcher.Changed -= new FileSystemEventHandler(OnChanged);
106                        watcher.Dispose();
107                    }
108				}
109			}
110
111			if (timer != null)
112			{
113				timer.Stop();
114				timer.Close();
115			}
116
117			fileWatchers = null;
118			timer = null;
119		}
120
121		public event AssemblyChangedHandler AssemblyChanged;
122
123		protected void OnTimer(Object source, ElapsedEventArgs e)
124		{
125			lock(this)
126			{
127                log.Info("Timer expired");
128				PublishEvent();
129				timer.Enabled=false;
130			}
131		}
132		
133		protected void OnChanged(object source, FileSystemEventArgs e)
134		{
135            log.Info("File {0} changed", e.Name);
136
137			changedAssemblyPath = e.FullPath;
138			if ( timer != null )
139			{
140				lock(this)
141				{
142					if(!timer.Enabled)
143						timer.Enabled=true;
144                    log.Info("Setting timer");
145					timer.Start();
146				}
147			}
148			else
149			{
150				PublishEvent();
151			}
152		}
153	
154		protected void PublishEvent()
155		{
156            if (AssemblyChanged != null)
157            {
158                log.Debug("Publishing Event to {0} listeners", AssemblyChanged.GetInvocationList().Length);
159                AssemblyChanged(changedAssemblyPath);
160            }
161		}
162	}
163}