00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 using System;
00013 using System.IO;
00014 using System.Text;
00015 using System.Web.Services.Protocols;
00016 using Mcs.Epm.MicrosoftProject.mpFx.Interfaces;
00017 using Mcs.Epm.MicrosoftProject.mpFx.Properties;
00018 using Microsoft.VisualBasic;
00019
00020 namespace Mcs.Epm.MicrosoftProject.mpFx
00021 {
00022
00023
00024
00025 public class Log : ILog, IDisposable
00026 {
00027 #region Private Static Methods
00028
00029 private static bool IsValidDirectory(string directory)
00030 {
00031 if (string.IsNullOrEmpty(directory) || !Directory.Exists(directory))
00032 {
00033 return false;
00034 }
00035
00036 char[] invalidChars = Path.GetInvalidPathChars();
00037
00038 if (directory.IndexOfAny(invalidChars) != -1)
00039 {
00040 return false;
00041 }
00042
00043 return true;
00044 }
00045
00046 private static bool IsValidFileName(string fileName)
00047 {
00048 if (string.IsNullOrEmpty(fileName))
00049 {
00050 return false;
00051 }
00052
00053 char[] invalidChars = Path.GetInvalidFileNameChars();
00054
00055 if (fileName.IndexOfAny(invalidChars) != -1)
00056 {
00057 return false;
00058 }
00059
00060 return true;
00061 }
00062
00063 #endregion
00064
00065 #region Instance Data
00066
00067 private bool _Disposed;
00068
00069 private TextWriter _LogStream;
00070 private readonly LogPeriod _Period;
00071 private readonly string _Description;
00072 private string _CurrentLog;
00073
00074 #endregion
00075
00076 #region Public Properties
00077
00078 public string LogDirectory { get; set; }
00079 public bool Verbose { get; set; }
00080
00081 #endregion
00082
00083 #region Constructors
00084
00085 public Log(string directory, LogPeriod period, string description, bool verbose)
00086 {
00087 if (!IsValidDirectory(directory))
00088 {
00089 throw new ArgumentException(Resources.InvalidLogPath);
00090 }
00091
00092 if (!IsValidFileName(description))
00093 {
00094 throw new ArgumentException(Resources.InvalidLogDescription);
00095 }
00096
00097 LogDirectory = directory;
00098
00099 _Period = period;
00100 _Description = description;
00101
00102 Verbose = verbose;
00103 }
00104
00105 #endregion
00106
00107 #region Public Methods
00108
00109 public void WriteEntry(LogArea area, LogEntryType type, string message)
00110 {
00111 OpenLog();
00112
00113 StringBuilder builder = BuildEntry(area, type, message, null);
00114
00115 _LogStream.WriteLine(builder);
00116 _LogStream.Flush();
00117 }
00118
00119 public void WriteEntry(LogArea area, LogEntryType type, string message, string stackTrace)
00120 {
00121 OpenLog();
00122
00123 StringBuilder builder = BuildEntry(area, type, message, stackTrace);
00124
00125 _LogStream.WriteLine(builder);
00126 }
00127
00128 public void WriteEntry(LogArea area, LogEntryType type, SoapException exception)
00129 {
00130 OpenLog();
00131
00132 StringBuilder builder = BuildEntry(area, type, Errors.ProcessMSProjectErrors(exception), exception.StackTrace);
00133
00134 _LogStream.WriteLine(builder);
00135 }
00136
00137 public void Clear()
00138 {
00139 CloseLog();
00140
00141 string logPath = GetLogPath(DateTime.Now);
00142
00143 if (File.Exists(logPath))
00144 {
00145 File.Delete(logPath);
00146
00147 using (StreamWriter logFile = File.CreateText(logPath))
00148 {
00149 logFile.WriteLine(Resources.LogHeader);
00150 logFile.Close();
00151 }
00152 }
00153
00154 OpenLog();
00155 }
00156
00157 private void CloseLog()
00158 {
00159 if (_LogStream != null)
00160 {
00161 _LogStream.Close();
00162 _LogStream.Dispose();
00163 _LogStream = null;
00164 }
00165 }
00166
00167 #endregion
00168
00169 #region Private Methods
00170
00171 private void OpenLog()
00172 {
00173 bool createNew = false;
00174 DateTime now = DateTime.Now;
00175
00176 string logPath = GetLogPath(now);
00177
00178 if (IsLogOld(now, logPath))
00179 {
00180 logPath = CreateLogFileName(now);
00181 createNew = true;
00182 CloseLog();
00183 }
00184
00185 if (_LogStream == null)
00186 {
00187 _LogStream = new StreamWriter(logPath, true);
00188 }
00189
00190 if (createNew)
00191 {
00192 _LogStream.WriteLine(Resources.LogHeader);
00193 _LogStream.Flush();
00194 }
00195
00196 _CurrentLog = logPath;
00197 }
00198
00199 private string GetLogPath(DateTime now)
00200 {
00201 if (!string.IsNullOrEmpty(_CurrentLog))
00202 {
00203 return _CurrentLog;
00204 }
00205
00206 string[] logFiles = Directory.GetFiles(LogDirectory);
00207
00208 if (logFiles.Length == 0)
00209 {
00210 return CreateLogFileName(now);
00211 }
00212
00213 string newestLog = null;
00214
00215 DateTime testDate = DateTime.Now.AddDays(-1);
00216
00217 foreach (string logFile in logFiles)
00218 {
00219 using (TextReader reader = File.OpenText(logFile))
00220 {
00221 string firstLine = reader.ReadLine();
00222
00223 if (firstLine != null && firstLine.Equals(Resources.LogHeader))
00224 {
00225 DateTime createDate = File.GetCreationTime(logFile);
00226
00227 if (createDate > testDate)
00228 {
00229 newestLog = logFile;
00230 testDate = createDate;
00231 }
00232 }
00233 reader.Close();
00234 }
00235 }
00236
00237 return newestLog;
00238
00239 }
00240
00241 private bool IsLogOld(DateTime now, string logPath)
00242 {
00243 if (string.IsNullOrEmpty(logPath) || !File.Exists(logPath))
00244 {
00245 return true;
00246 }
00247
00248 DateTime createdDate = File.GetCreationTime(logPath);
00249
00250 switch (_Period)
00251 {
00252 case LogPeriod.Hourly:
00253 return DateAndTime.DateDiff(DateInterval.Hour, createdDate, now, FirstDayOfWeek.System,
00254 FirstWeekOfYear.System) >= 1;
00255 case LogPeriod.Daily:
00256 return DateAndTime.DateDiff(DateInterval.Day, createdDate, now, FirstDayOfWeek.System,
00257 FirstWeekOfYear.System) >= 1;
00258 case LogPeriod.Weekly:
00259 return DateAndTime.DateDiff(DateInterval.Weekday, createdDate, now, FirstDayOfWeek.System,
00260 FirstWeekOfYear.System) >= 1;
00261
00262 case LogPeriod.Monthly:
00263 return DateAndTime.DateDiff(DateInterval.Month, createdDate, now, FirstDayOfWeek.System,
00264 FirstWeekOfYear.System) >= 1;
00265
00266 default:
00267 throw new ArgumentOutOfRangeException();
00268 }
00269 }
00270
00271 private string CreateLogFileName(DateTime now)
00272 {
00273 string appendText = now.ToString();
00274
00275 appendText = appendText.Replace("/", "");
00276 appendText = appendText.Replace(":", "");
00277 appendText = appendText.Replace(" ", "");
00278
00279 return Path.Combine(LogDirectory, string.Format("{0}-{1}.txt", _Description, appendText));
00280 }
00281
00282 #endregion
00283
00284 #region Private Static Methods
00285
00286 private static StringBuilder BuildEntry(LogArea area, LogEntryType type, string message, string stackTrace)
00287 {
00288 StringBuilder builder = new StringBuilder();
00289
00290 builder.AppendFormat("Date: {0}\r\n", DateTime.Now);
00291 builder.AppendFormat("User: {0}\\{1}\r\n", Environment.UserDomainName, Environment.UserName);
00292 builder.AppendFormat("Machine: {0}\r\n", Environment.MachineName);
00293 builder.AppendFormat("Area: {0}\r\n", area);
00294 builder.AppendFormat("Type: {0}\r\n", type);
00295 builder.AppendFormat("Message: \r\n\r\n{0}\r\n\r\n", message);
00296
00297 if (!string.IsNullOrEmpty(stackTrace))
00298 {
00299 builder.AppendFormat("Stack Trace: \r\n\r\n{0}\r\n", stackTrace);
00300 }
00301
00302 return builder;
00303 }
00304
00305 #endregion
00306
00307 #region IDisposable Members
00308
00309 ~Log()
00310 {
00311 Dispose(false);
00312 }
00313
00314 private void Dispose(bool disposing)
00315 {
00316 if (!_Disposed)
00317 {
00318 if (disposing)
00319 {
00320
00321 if (_LogStream != null)
00322 {
00323 _LogStream.Flush();
00324 _LogStream.Close();
00325 _LogStream.Dispose();
00326 }
00327 }
00328
00329
00330
00331 _Disposed = true;
00332 }
00333 }
00334
00335 public void Dispose()
00336 {
00337 Dispose(true);
00338 GC.SuppressFinalize(this);
00339 }
00340
00341 #endregion
00342
00343 }
00344 }