Skip to content

Commit

Permalink
changes in the infrastructure
Browse files Browse the repository at this point in the history
  • Loading branch information
SHSE committed May 5, 2013
1 parent 94ea223 commit 2a499fc
Show file tree
Hide file tree
Showing 46 changed files with 330 additions and 245 deletions.
2 changes: 1 addition & 1 deletion LogWatch.Tests/FilteredRecordCollectionTests.cs
Expand Up @@ -5,7 +5,7 @@
using System.Threading;
using System.Threading.Tasks;
using LogWatch.Features.Records;
using LogWatch.Sources;
using LogWatch.Features.Sources;
using Microsoft.Reactive.Testing;
using Moq;
using Xunit;
Expand Down
2 changes: 1 addition & 1 deletion LogWatch.Tests/Formats/CsvFormatTests.cs
Expand Up @@ -5,7 +5,7 @@
using System.Reactive.Subjects;
using System.Text;
using System.Threading;
using LogWatch.Formats;
using LogWatch.Features.Formats;
using Xunit;

namespace LogWatch.Tests.Formats {
Expand Down
2 changes: 1 addition & 1 deletion LogWatch.Tests/Formats/LexFormatTests.cs
Expand Up @@ -3,7 +3,7 @@
using System.Reactive.Subjects;
using System.Text;
using System.Threading;
using LogWatch.Formats;
using LogWatch.Features.Formats;
using Xunit;
using System.Reactive.Linq;
using System.Reactive.Threading.Tasks;
Expand Down
2 changes: 1 addition & 1 deletion LogWatch.Tests/Formats/Log4JXmlFormatTests.cs
Expand Up @@ -3,7 +3,7 @@
using System.Linq;
using System.Text;
using System.Threading;
using LogWatch.Formats;
using LogWatch.Features.Formats;
using Microsoft.Reactive.Testing;
using Xunit;

Expand Down
2 changes: 1 addition & 1 deletion LogWatch.Tests/RecordCollectionTests.cs
Expand Up @@ -5,7 +5,7 @@
using System.Threading;
using System.Threading.Tasks;
using LogWatch.Features.Records;
using LogWatch.Sources;
using LogWatch.Features.Sources;
using Microsoft.Reactive.Testing;
using Moq;
using Xunit;
Expand Down
2 changes: 1 addition & 1 deletion LogWatch.Tests/ViewModels/RecordDetailsViewModelTests.cs
@@ -1,6 +1,6 @@
using GalaSoft.MvvmLight.Messaging;
using LogWatch.Features.RecordDetails;
using LogWatch.Features.SelectSource;
using LogWatch.Features.Sources;
using LogWatch.Messages;
using Xunit;

Expand Down
2 changes: 1 addition & 1 deletion LogWatch.Tests/ViewModels/RecordsViewModelTests.cs
Expand Up @@ -5,8 +5,8 @@
using System.Threading;
using GalaSoft.MvvmLight.Messaging;
using LogWatch.Features.Records;
using LogWatch.Features.Sources;
using LogWatch.Messages;
using LogWatch.Sources;
using Microsoft.Reactive.Testing;
using Moq;
using Xunit;
Expand Down
2 changes: 1 addition & 1 deletion LogWatch.Tests/ViewModels/StatsViewModelTests.cs
Expand Up @@ -4,9 +4,9 @@
using System.Reactive.Subjects;
using System.Threading;
using GalaSoft.MvvmLight.Messaging;
using LogWatch.Features.Sources;
using LogWatch.Features.Stats;
using LogWatch.Messages;
using LogWatch.Sources;
using Microsoft.Reactive.Testing;
using Moq;
using Xunit;
Expand Down
74 changes: 29 additions & 45 deletions LogWatch/App.xaml.cs
Expand Up @@ -7,9 +7,8 @@
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
using LogWatch.Features.SelectSource;
using LogWatch.Formats;
using LogWatch.Sources;
using LogWatch.Features.Formats;
using LogWatch.Features.Sources;

namespace LogWatch {
public sealed partial class App {
Expand All @@ -24,60 +23,41 @@ public sealed partial class App {
Current.Dispatcher.Invoke(() => HandleException(exception));
};

private static readonly Func<string, bool> CollectStatsOnDemand =
filePath => new FileInfo(filePath).Length >= 10*1024*1024;

private static CompositionContainer container;

public static readonly Func<Stream, ILogFormat> SelectFormat = stream => {
var formatSelector = new AutoLogFormatSelector();
container.SatisfyImportsOnce(formatSelector);
var logFormats = formatSelector.SelectFormat(stream).ToArray();
public static readonly Func<Stream, ILogFormat> SelectFormat =
stream => {
if (!Current.CheckAccess())
return Current.Dispatcher.InvokeAsync(() => SelectFormat(stream)).Result;
if (logFormats.Length == 0)
return new PlainTextLogFormat();
var formatSelector = new AutoLogFormatSelector();
if (logFormats.Length == 1)
return logFormats[0].Value;
container.SatisfyImportsOnce(formatSelector);
var view = new SelectFormatView();
var viewModel = view.ViewModel;
var logFormats = formatSelector.SelectFormat(stream).ToArray();
foreach (var format in logFormats)
viewModel.Formats.Add(format);
if (logFormats.Length == 0)
return new PlainTextLogFormat();
viewModel.Formats.Add(
new Lazy<ILogFormat, ILogFormatMetadata>(
() => new PlainTextLogFormat(),
new LogFormatAttribute("Plain text")));
if (logFormats.Length == 1)
return logFormats[0].Value.Create();
return view.ShowDialog() != true ? null : viewModel.Format;
};
var view = new SelectFormatView();
var viewModel = view.ViewModel;
public static readonly Func<string, LogSourceInfo> CreateFileLogSource = filePath => {
ILogFormat format;
foreach (var format in logFormats)
viewModel.Formats.Add(format);
using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
format = SelectFormat(stream);
viewModel.Formats.Add(
new Lazy<ILogFormatFactory, ILogFormatMetadata>(
() => new SimpleLogFormatFactory<PlainTextLogFormat>(),
new LogFormatFactoryAttribute("Plain text")));
if (format == null)
return null;
return new LogSourceInfo(
new FileLogSource(filePath, format),
filePath,
false,
CollectStatsOnDemand(filePath));
};
return view.ShowDialog() != true ? null : viewModel.Format;
};

public static LogSourceInfo SourceInfo { get; set; }

public static ILogSource Source {
get { return SourceInfo == null ? null : SourceInfo.Source; }
}

protected override void OnStartup(StartupEventArgs e) {
base.OnStartup(e);

Expand All @@ -97,10 +77,14 @@ public sealed partial class App {
if (string.IsNullOrEmpty(filePath)) {
var view = new SelectSourceView();

container.SatisfyImportsOnce(view.ViewModel);

if (view.ShowDialog() == true)
SourceInfo = view.ViewModel.Source;
} else
SourceInfo = CreateFileLogSource(filePath);
} else {
var factory = new FileLogSourceFactory();
SourceInfo = factory.Create(SelectFormat);
}

if (SourceInfo == null) {
this.Shutdown();
Expand Down
Expand Up @@ -3,12 +3,12 @@
using System.ComponentModel.Composition;
using System.IO;

namespace LogWatch.Formats {
namespace LogWatch.Features.Formats {
public class AutoLogFormatSelector {
[ImportMany(typeof (ILogFormat))]
public IEnumerable<Lazy<ILogFormat, ILogFormatMetadata>> Formats { get; set; }
[ImportMany(typeof (ILogFormatFactory))]
public IEnumerable<Lazy<ILogFormatFactory, ILogFormatMetadata>> Formats { get; set; }

public IEnumerable<Lazy<ILogFormat, ILogFormatMetadata>> SelectFormat(Stream stream) {
public IEnumerable<Lazy<ILogFormatFactory, ILogFormatMetadata>> SelectFormat(Stream stream) {
foreach (var format in this.Formats) {
stream.Position = 0;

Expand Down
Expand Up @@ -6,8 +6,7 @@
using System.Threading;
using System.Threading.Tasks;

namespace LogWatch.Formats {
[LogFormat("CSV")]
namespace LogWatch.Features.Formats {
public class CsvLogFormat : ILogFormat {
private bool isHeader = true;

Expand All @@ -18,6 +17,11 @@ public class CsvLogFormat : ILogFormat {
this.ReadHeader = true;
}

[LogFormatFactory("CSV")]
public static ILogFormatFactory Factory {
get { return new SimpleLogFormatFactory<CsvLogFormat>(CanRead); }
}

public Tuple<int, string>[] AttributeMappings { get; set; }
public Encoding Encoding { get; set; }
public char? Delimeter { get; set; }
Expand All @@ -28,6 +32,7 @@ public class CsvLogFormat : ILogFormat {
public int? MessageFieldIndex { get; set; }
public int? ExceptionFieldIndex { get; set; }
public int? FieldCount { get; set; }
public bool ReadHeader { get; set; }

public Record DeserializeRecord(ArraySegment<byte> segment) {
var text = Encoding.UTF8.GetString(segment.Array, segment.Offset, segment.Count);
Expand Down Expand Up @@ -62,7 +67,7 @@ public class CsvLogFormat : ILogFormat {
using (var reader = new StreamReader(stream, this.Encoding, false, 4096, true)) {
var offset = stream.Position;

if (this.isHeader && ReadHeader) {
if (this.isHeader && this.ReadHeader) {
var header = await reader.ReadLineAsync();

if (header == null)
Expand Down Expand Up @@ -95,7 +100,7 @@ public class CsvLogFormat : ILogFormat {
}
}

public bool CanRead(Stream stream) {
private static bool CanRead(Stream stream) {
using (var reader = new StreamReader(stream, Encoding.UTF8, true, 4096, true)) {
var buffer = new char[4*1024];
var count = reader.Read(buffer, 0, buffer.Length);
Expand Down Expand Up @@ -287,7 +292,5 @@ public class CsvLogFormat : ILogFormat {

return -1;
}

public bool ReadHeader { get; set; }
}
}
Expand Up @@ -3,15 +3,13 @@
using System.Threading;
using System.Threading.Tasks;

namespace LogWatch.Formats {
namespace LogWatch.Features.Formats {
public interface ILogFormat {
Record DeserializeRecord(ArraySegment<byte> segment);

Task<long> ReadSegments(
IObserver<RecordSegment> observer,
Stream stream,
CancellationToken cancellationToken);

bool CanRead(Stream stream);
}
}
8 changes: 8 additions & 0 deletions LogWatch/Features/Formats/ILogFormatFactory.cs
@@ -0,0 +1,8 @@
using System.IO;

namespace LogWatch.Features.Formats {
public interface ILogFormatFactory {
ILogFormat Create();
bool CanRead(Stream stream);
}
}
@@ -1,4 +1,4 @@
namespace LogWatch.Formats {
namespace LogWatch.Features.Formats {
public interface ILogFormatMetadata {
string Name { get; }
}
Expand Down
Expand Up @@ -11,7 +11,7 @@
using Roslyn.Compilers;
using Roslyn.Compilers.CSharp;

namespace LogWatch.Formats {
namespace LogWatch.Features.Formats {
public class LexLogFormat : ILogFormat {
private const string ScannerBase = @"
using System;
Expand Down
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
Expand All @@ -9,8 +8,7 @@
using System.Xml.Linq;
using LogWatch.Util;

namespace LogWatch.Formats {
[LogFormat("Log4J XML")]
namespace LogWatch.Features.Formats {
public class Log4JXmlLogFormat : ILogFormat {
private static readonly byte[] EventStart = Encoding.UTF8.GetBytes("<log4j:event ");
private static readonly byte[] EventEnd = Encoding.UTF8.GetBytes("</log4j:event>");
Expand All @@ -19,6 +17,11 @@ public class Log4JXmlLogFormat : ILogFormat {
this.BufferSize = 16*1024;
}

[LogFormatFactory("Log4J XML")]
public static ILogFormatFactory Factory {
get { return new SimpleLogFormatFactory<Log4JXmlLogFormat>(CanRead); }
}

public int BufferSize { get; set; }

public Record DeserializeRecord(ArraySegment<byte> segment) {
Expand Down Expand Up @@ -107,7 +110,7 @@ public class Log4JXmlLogFormat : ILogFormat {
}
}

public bool CanRead(Stream stream) {
private static bool CanRead(Stream stream) {
using (var reader = new StreamReader(stream, Encoding.UTF8, true, 4096, true)) {
var buffer = new char[4*1024];
var count = reader.Read(buffer, 0, buffer.Length);
Expand Down
18 changes: 18 additions & 0 deletions LogWatch/Features/Formats/LogFormatFactoryAttribute.cs
@@ -0,0 +1,18 @@
using System;
using System.ComponentModel.Composition;

namespace LogWatch.Features.Formats {
[MetadataAttribute]
[AttributeUsage(
AttributeTargets.Class |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = false)]
public sealed class LogFormatFactoryAttribute : ExportAttribute, ILogFormatMetadata {
public LogFormatFactoryAttribute(string name) : base(typeof (ILogFormatFactory)) {
this.Name = name;
}

public string Name { get; private set; }
}
}
Expand Up @@ -4,7 +4,7 @@
using System.Threading;
using System.Threading.Tasks;

namespace LogWatch.Formats {
namespace LogWatch.Features.Formats {
public class PlainTextLogFormat : ILogFormat {
public PlainTextLogFormat() {
this.Encoding = Encoding.UTF8;
Expand Down
@@ -1,19 +1,18 @@
<mui:ModernDialog
x:Class="LogWatch.Features.SelectSource.SelectFormatView"
x:Class="LogWatch.Features.Formats.SelectFormatView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:feature="clr-namespace:LogWatch.Features.Formats"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:mui="http://firstfloorsoftware.com/ModernUI"
xmlns:selectSource="clr-namespace:LogWatch.Features.SelectSource"
xmlns:util="clr-namespace:LogWatch.Util"
x:Name="View"
Title="Log Watch"
Width="300"

Height="300">

<mui:ModernDialog.Resources>
<selectSource:SelectFormatViewModel x:Key="ViewModel" />
<feature:SelectFormatViewModel x:Key="ViewModel" />
</mui:ModernDialog.Resources>

<mui:ModernDialog.DataContext>
Expand Down
@@ -1,4 +1,4 @@
namespace LogWatch.Features.SelectSource {
namespace LogWatch.Features.Formats {
public partial class SelectFormatView {
public SelectFormatView() {
this.InitializeComponent();
Expand Down

0 comments on commit 2a499fc

Please sign in to comment.