Преглед на файлове

2006-08-14 Atsushi Enomoto <[email protected]>

	* System.dll.sources : added LocalFileEventLog.cs and NullEventLog.cs.

	* EventLogImpl.cs, EventLogEntryCollection.cs, EventLog.cs :
	  some rework to support actual event log implementations.
	* NullEventLog.cs, LocalFileEventLog.cs :
	  new files. The former (default) implementation does nothing for
	  any event log features. The latter implements local file based
	  event logs.


svn path=/trunk/mcs/; revision=63705
Atsushi Eno преди 19 години
родител
ревизия
00a58245be

+ 5 - 1
mcs/class/System/ChangeLog

@@ -1,4 +1,8 @@
-2006-08-11  Atsushi Enomoto  <[email protected]>
+2006-08-14  Atsushi Enomoto  <[email protected]>
+
+	* System.dll.sources : added LocalFileEventLog.cs and NullEventLog.cs.
+
+2006-08-14  Atsushi Enomoto  <[email protected]>
 
 	* System.dll.sources : reverted all recent changes on EventLogs.
 	  It does not work at all.

+ 9 - 0
mcs/class/System/System.Diagnostics/ChangeLog

@@ -1,3 +1,12 @@
+2006-08-14  Atsushi Enomoto  <[email protected]>
+
+	* EventLogImpl.cs, EventLogEntryCollection.cs, EventLog.cs :
+	  some rework to support actual event log implementations.
+	* NullEventLog.cs, LocalFileEventLog.cs :
+	  new files. The former (default) implementation does nothing for
+	  any event log features. The latter implements local file based
+	  event logs.
+
 2006-08-14  Atsushi Enomoto  <[email protected]>
 
 	* UnixEventLog.cs, EventLogEntry.cs, EventSourceCreationData.cs,

+ 1 - 1
mcs/class/System/System.Diagnostics/EventLog.cs

@@ -72,7 +72,7 @@ namespace System.Diagnostics
 			this.machineName = machineName;
 			this.logName = logName;
 
-			this.Impl = new EventLogImpl (this);
+			this.Impl = EventLogImpl.Create (this);
 			EventLogImpl.EntryWritten += new EntryWrittenEventHandler (EntryWrittenHandler);
 		}
 

+ 3 - 1
mcs/class/System/System.Diagnostics/EventLogEntryCollection.cs

@@ -39,8 +39,10 @@ namespace System.Diagnostics {
 
 		private ArrayList eventLogs = new ArrayList ();
 
-		internal EventLogEntryCollection()
+		internal EventLogEntryCollection(IEnumerable entries)
 		{
+			foreach (object entry in entries)
+				eventLogs.Add (entry);
 		}
 
 		public int Count {

+ 80 - 36
mcs/class/System/System.Diagnostics/EventLogImpl.cs

@@ -3,8 +3,10 @@
 //
 // Authors:
 //   Andreas Nahr ([email protected])
+//   Atsushi Enomoto  <[email protected]>
 //
 // (C) 2003 Andreas Nahr
+// (C) 2006 Novell, Inc.
 //
 
 //
@@ -32,89 +34,131 @@ using System;
 using System.Diagnostics;
 using System.ComponentModel;
 using System.ComponentModel.Design;
+using System.Collections;
+using System.Globalization;
+using System.IO;
+using System.Net;
 
 namespace System.Diagnostics
 {
+	internal abstract class EventLogImpl
+	{
+		static EventLogFactory factory;
 
-// FIXME set a symbol for every implementation and include the implementation
-#if (EVENTLOG_WIN32)
+		static EventLogImpl ()
+		{
+			factory = GetFactory ();
+		}
 
-	// TODO implement the EventLog for Win32 platforms
+		static EventLogFactory GetFactory ()
+		{
+			if (LocalFileEventLogUtil.IsEnabled)
+				return new LocalFileEventLogFactory ();
 
-#elif (EVENTLOG_GENERIC)
+			//throw new NotSupportedException (String.Format ("No EventLog implementation is supported. Consider setting MONO_LOCAL_EVENTLOG_PATH environment variable."));
+			return new NullEventLogFactory ();
+		}
 
-	// TODO implement a generic (XML - based?) Eventlog for non - Win32 platforms
+		EventLog log;
 
-#else
-	// Empty implementation that does not need any specific platform
-	// but should be enough to get applications to run that WRITE to eventlog
-	internal class EventLogImpl
-	{
-		public EventLogImpl (EventLog coreEventLog)
+		protected EventLogImpl (EventLog coreEventLog)
 		{
+			this.log = coreEventLog;
+		}
+
+		public static EventLogImpl Create (EventLog source)
+		{
+			return factory.Create (source);
 		}
 
 		public static event EntryWrittenEventHandler EntryWritten;
 
-		public EventLogEntryCollection Entries {
-			get {return new EventLogEntryCollection ();}
-		}
+		public abstract EventLogEntryCollection Entries { get; }
 
-		public string LogDisplayName {
-			get {return "";}
-		}
+		public abstract string LogDisplayName { get; }
 
-		public void BeginInit () {}
+		public abstract void BeginInit ();
 
-		public void Clear () {}
+		public abstract void Clear ();
 
-		public void Close () {}
+		public abstract void Close ();
 
-		public static void CreateEventSource (string source, string logName, string machineName) {}
+		public static void CreateEventSource (string source, string logName, string machineName)
+		{
+			factory.CreateEventSource (source, logName, machineName);
+		}
 
-		public static void Delete (string logName, string machineName) {}
+		public static void Delete (string logName, string machineName)
+		{
+			factory.Delete (logName, machineName);
+		}
 
-		public static void DeleteEventSource (string source, string machineName) {}
+		public static void DeleteEventSource (string source, string machineName)
+		{
+			factory.DeleteEventSource (source, machineName);
+		}
 
-		public void Dispose (bool disposing) {}
+		public abstract void Dispose (bool disposing);
 
-		public void EndInit () {}
+		public abstract void EndInit ();
 
 		public static bool Exists (string logName, string machineName)
 		{
-			return false;
+			return factory.Exists (logName, machineName);
 		}
 
 		public static EventLog[] GetEventLogs (string machineName)
 		{
-			return new EventLog[0];
+			return factory.GetEventLogs (machineName);
 		}
 
 		public static string LogNameFromSourceName (string source, string machineName)
 		{
-			return String.Empty;
+			return factory.LogNameFromSourceName (source, machineName);
 		}
 
 		public static bool SourceExists (string source, string machineName)
 		{
-			return false;
+			return factory.SourceExists (source, machineName);
 		}
 
 		public void WriteEntry (string message, EventLogEntryType type, int eventID, short category, byte[] rawData)
 		{
-			WriteEntry ("", message, type, eventID, category, rawData);
+			WriteEntry (log.Source, message, type, eventID, category, rawData);
 		}
 
 		public static void WriteEntry (string source, string message, EventLogEntryType type, int eventID, short category, byte[] rawData)
 		{
-			EventLogEntry Entry;
-			Entry = new EventLogEntry ("", category, 0, eventID, message, source, 
-				"", "", type, DateTime.Now, DateTime.Now, rawData, null);
-			if (EntryWritten != null)
-				EntryWritten (null, new EntryWrittenEventArgs (Entry));
+			factory.WriteEntry (source, message, type, eventID, category, rawData);
+			if (EntryWritten != null) {
+				// FIXME: some arguments are improper.
+				EventLogEntry e = new EventLogEntry ("",
+					category, 0, eventID, message, source,
+					"", ".", type, DateTime.Now, DateTime.Now,
+					rawData, null);
+				EntryWritten (null, new EntryWrittenEventArgs (e));
+			}
 		}
 	}
 
-#endif
+	internal abstract class EventLogFactory
+	{
+		public abstract EventLogImpl Create (EventLog source);
+
+		public abstract void CreateEventSource (string source, string logName, string machineName);
+
+		public abstract void Delete (string logName, string machineName);
 
+		public abstract void DeleteEventSource (string source, string machineName);
+
+		public abstract bool Exists (string logName, string machineName);
+
+		public abstract EventLog[] GetEventLogs (string machineName);
+
+		public abstract string LogNameFromSourceName (string source, string machineName);
+
+		public abstract bool SourceExists (string source, string machineName);
+
+		public abstract void WriteEntry (string source, string message, EventLogEntryType type, int eventID, short category, byte[] rawData);
+	}
 }

+ 274 - 0
mcs/class/System/System.Diagnostics/LocalFileEventLog.cs

@@ -0,0 +1,274 @@
+//
+// LocalFileEventLog.cs
+//
+// Author:
+//   Atsushi Enomoto  <[email protected]>
+//
+// (C) 2006 Novell, Inc.
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Diagnostics;
+using System.ComponentModel;
+using System.ComponentModel.Design;
+using System.Collections;
+using System.Globalization;
+using System.IO;
+using System.Net;
+
+namespace System.Diagnostics
+{
+	class LocalFileEventLogUtil
+	{
+		public const string DateFormat = "yyyyMMddHHmmssfff";
+
+		static readonly string path;
+
+		static LocalFileEventLogUtil ()
+		{
+			string env = Environment.GetEnvironmentVariable ("MONO_LOCAL_EVENTLOG_PATH");
+			if (env != null)
+				path = Path.GetFullPath (env);
+		}
+
+		public static bool IsEnabled {
+			get { return path != null && Directory.Exists (path); }
+		}
+
+		public static string GetSourceDir (string source)
+		{
+			foreach (string log in GetLogDirectories ()) {
+				string sd = Path.Combine (log, source);
+				if (Directory.Exists (sd))
+					return sd;
+			}
+			return null;
+		}
+
+		public static string GetLogDir (string logName)
+		{
+			return Path.Combine (Path.Combine (path, "logs"), logName);
+		}
+
+		public static string [] GetLogDirectories ()
+		{
+			return Directory.GetDirectories (Path.Combine (path, "logs"));
+		}
+	}
+
+	class LocalFileEventLog : EventLogImpl
+	{
+		static readonly string [] empty_strings = new string [0];
+
+		EventLog log;
+		string source_path;
+
+		public LocalFileEventLog (EventLog log)
+			: base (log)
+		{
+			this.log = log;
+			source_path = LocalFileEventLogUtil.GetSourceDir (log.Source);
+			if (!Directory.Exists (source_path))
+				throw new SystemException (String.Format ("INTERNAL ERROR: directory for {0} does not exist.", log.Source));
+		}
+
+		public override EventLogEntryCollection Entries {
+			get {
+				ArrayList list = new ArrayList ();
+				int index = 0;
+				foreach (string file in Directory.GetFiles (source_path, "*.log"))
+					list.Add (LoadLogEntry (file, index++));
+				return new EventLogEntryCollection ((EventLogEntry []) list.ToArray (typeof (EventLogEntry)));
+			}
+		}
+
+		public override string LogDisplayName {
+			get { return log.Log; }
+		}
+
+		EventLogEntry LoadLogEntry (string file, int index)
+		{
+			using (TextReader tr = File.OpenText (file)) {
+				int id = int.Parse (tr.ReadLine ().Substring (9));
+				EventLogEntryType type = (EventLogEntryType)
+					Enum.Parse (typeof (EventLogEntryType), tr.ReadLine ().Substring (11));
+				string category = tr.ReadLine ().Substring (10);
+				int size = int.Parse (tr.ReadLine ().Substring (15));
+				char [] buf = new char [size];
+				tr.Read (buf, 0, size);
+				string filename = Path.GetFileName (file).Substring (0, LocalFileEventLogUtil.DateFormat.Length);
+				DateTime date = DateTime.ParseExact (filename, LocalFileEventLogUtil.DateFormat, CultureInfo.InvariantCulture);
+				byte [] bin = Convert.FromBase64String (tr.ReadToEnd ());
+				// FIXME: categoryNumber, index, userName, two dates
+				return new EventLogEntry (category, 0, index,
+					id, new string (buf), log.Source, "", log.MachineName,
+					type, date, date, bin, empty_strings);
+			}
+		}
+
+		public override void BeginInit ()
+		{
+		}
+
+		public override void Clear ()
+		{
+			foreach (string file in Directory.GetFiles (source_path, "*.log"))
+				File.Delete (file);
+		}
+
+		public override void Close ()
+		{
+		}
+
+		public override void Dispose (bool disposing)
+		{
+			Close ();
+		}
+
+		public override void EndInit ()
+		{
+		}
+	}
+
+	// Creates a log repository at MONO_LOCAL_EVENTLOG_DIR, which consists of
+	// 	- 
+	internal class LocalFileEventLogFactory : EventLogFactory
+	{
+		static readonly IPAddress local_ip = IPAddress.Parse ("127.0.0.1");
+
+		public LocalFileEventLogFactory ()
+		{
+		}
+
+		public override EventLogImpl Create (EventLog log)
+		{
+			if (!SourceExists (log.Source, log.MachineName))
+				CreateEventSource (log.Source, log.Log, log.MachineName);
+			return new LocalFileEventLog (log);
+		}
+
+		void VerifyMachine (string machineName)
+		{
+			if (machineName != ".") {
+				IPHostEntry entry =
+#if NET_2_0
+					Dns.GetHostEntry (machineName);
+#else
+					Dns.Resolve (machineName);
+#endif
+				if (Array.IndexOf (entry.AddressList, local_ip) < 0)
+					throw new NotSupportedException (String.Format ("LocalFileEventLog does not support remote machine: {0}", machineName));
+			}
+		}
+
+		public override void CreateEventSource (string source, string logName, string machineName)
+		{
+			VerifyMachine (machineName);
+
+			string sourceDir = LocalFileEventLogUtil.GetSourceDir (source);
+			if (sourceDir != null)
+				throw new ArgumentException (String.Format ("Source '{0}' already exists on the local machine.", source));
+
+			string logDir = LocalFileEventLogUtil.GetLogDir (logName);
+			if (!Directory.Exists (logDir))
+				Directory.CreateDirectory (logDir);
+			Directory.CreateDirectory (Path.Combine (logDir, source));
+		}
+
+		public override void Delete (string logName, string machineName)
+		{
+			VerifyMachine (machineName);
+
+			string logDir = LocalFileEventLogUtil.GetLogDir (logName);
+			if (Directory.Exists (logDir))
+				Directory.Delete (logDir);
+		}
+
+		public override void DeleteEventSource (string source, string machineName)
+		{
+			VerifyMachine (machineName);
+
+			string sourceDir = LocalFileEventLogUtil.GetSourceDir (source);
+			if (Directory.Exists (sourceDir))
+				Directory.Delete (sourceDir);
+			else
+				throw new ArgumentException (String.Format ("Event source '{0}' does not exist on the local machine."), source);
+		}
+
+		public override bool Exists (string logName, string machineName)
+		{
+			VerifyMachine (machineName);
+
+			return Directory.Exists (LocalFileEventLogUtil.GetLogDir (logName));
+		}
+
+		public override EventLog[] GetEventLogs (string machineName)
+		{
+			VerifyMachine (machineName);
+
+			ArrayList al = new ArrayList ();
+			foreach (string log in LocalFileEventLogUtil.GetLogDirectories ())
+				al.Add (new EventLog (log));
+			return (EventLog []) al.ToArray (typeof (EventLog));
+		}
+
+		public override string LogNameFromSourceName (string source, string machineName)
+		{
+			VerifyMachine (machineName);
+
+			string sourceDir = LocalFileEventLogUtil.GetSourceDir (source);
+			if (sourceDir == null)
+				throw new ArgumentException (String.Format ("Event source '{0}' does not exist on the local machine."), source);
+			return Directory.GetParent (sourceDir).Name;
+		}
+
+		public override bool SourceExists (string source, string machineName)
+		{
+			VerifyMachine (machineName);
+
+			return LocalFileEventLogUtil.GetSourceDir (source) != null;
+		}
+
+		public override void WriteEntry (string source, string message, EventLogEntryType type, int eventID, short category, byte[] rawData)
+		{
+			if (!SourceExists (source, "."))
+				throw new ArgumentException (String.Format ("Event source '{0}' does not exist on the local machine."), source);
+			string sourceDir = LocalFileEventLogUtil.GetSourceDir (source);
+			string path = Path.Combine (sourceDir, DateTime.Now.ToString (LocalFileEventLogUtil.DateFormat) + ".log");
+			try {
+				using (TextWriter w = File.CreateText (path)) {
+					w.WriteLine ("EventID: {0}", eventID);
+					w.WriteLine ("EntryType: {0}", type);
+					w.WriteLine ("Category: {0}", category);
+					w.WriteLine ("MessageLength: {0}", message.Length);
+					w.Write (message);
+					if (rawData != null)
+						w.Write (Convert.ToBase64String (rawData));
+				}
+			} catch (IOException) {
+				File.Delete (path);
+			}
+		}
+	}
+}

+ 126 - 0
mcs/class/System/System.Diagnostics/NullEventLog.cs

@@ -0,0 +1,126 @@
+//
+// NullEventLog.cs
+//
+// Author:
+//   Atsushi Enomoto  <[email protected]>
+//
+// (C) 2006 Novell, Inc.
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Diagnostics;
+using System.ComponentModel;
+using System.ComponentModel.Design;
+using System.Collections;
+using System.Globalization;
+using System.IO;
+using System.Net;
+
+namespace System.Diagnostics
+{
+	internal class NullEventLog : EventLogImpl
+	{
+		EventLogEntryCollection empty_entries =
+			new EventLogEntryCollection (new EventLogEntry [0]);
+
+		public NullEventLog (EventLog coreEventLog)
+			: base (coreEventLog)
+		{
+		}
+
+		public override EventLogEntryCollection Entries {
+			get { return empty_entries; }
+		}
+
+		public override string LogDisplayName {
+			get { return String.Empty; }
+		}
+
+		public override void BeginInit ()
+		{
+		}
+
+		public override void Clear ()
+		{
+		}
+
+		public override void Close ()
+		{
+		}
+
+		public override void Dispose (bool disposing)
+		{
+		}
+
+		public override void EndInit ()
+		{
+		}
+	}
+
+	internal class NullEventLogFactory : EventLogFactory
+	{
+		EventLog [] empty_logs = new EventLog [0];
+
+		public override EventLogImpl Create (EventLog source)
+		{
+			return new NullEventLog (source);
+		}
+
+		public override void CreateEventSource (string source, string logName, string machineName)
+		{
+		}
+
+		public override void Delete (string logName, string machineName)
+		{
+		}
+
+		public override void DeleteEventSource (string source, string machineName)
+		{
+		}
+
+		public override bool Exists (string logName, string machineName)
+		{
+			return false;
+		}
+
+		public override EventLog [] GetEventLogs (string machineName)
+		{
+			return empty_logs;
+		}
+
+		public override string LogNameFromSourceName (string source, string machineName)
+		{
+			return String.Empty;
+		}
+
+		public override bool SourceExists (string source, string machineName)
+		{
+			return false;
+		}
+
+		public override void WriteEntry (string source, string message, EventLogEntryType type, int eventID, short category, byte[] rawData)
+		{
+		}
+	}
+}

+ 2 - 0
mcs/class/System/System.dll.sources

@@ -450,7 +450,9 @@ System.Diagnostics/ICollectData.cs
 System.Diagnostics/InstanceDataCollectionCollection.cs
 System.Diagnostics/InstanceDataCollection.cs
 System.Diagnostics/InstanceData.cs
+System.Diagnostics/LocalFileEventLog.cs
 System.Diagnostics/MonitoringDescriptionAttribute.cs
+System.Diagnostics/NullEventLog.cs
 System.Diagnostics/OverflowAction.cs
 System.Diagnostics/PerformanceCounterCategory.cs
 System.Diagnostics/PerformanceCounter.cs