From a933b8e838cdfba913d54de76c6729970c7a3aa0 Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Sun, 4 Aug 2013 13:29:32 +0100 Subject: [PATCH] Add SharpDevelop user agent in NuGet feed requests. --- .../Project/PackageManagement.csproj | 4 + .../Src/IPackageRepositoryFactoryEvents.cs | 12 +++ .../Project/Src/PackageManagementServices.cs | 2 + .../Project/Src/PackageRepositoryCache.cs | 14 ++- .../Src/PackageRepositoryFactoryEventArgs.cs | 18 ++++ .../Project/Src/SharpDevelopHttpUserAgent.cs | 37 ++++++++ ...UserAgentGeneratorForRepositoryRequests.cs | 35 ++++++++ .../Test/PackageManagement.Tests.csproj | 1 + .../Test/Src/PackageRepositoryCacheTests.cs | 25 ++++++ ...gentGeneratorForRepositoryRequestsTests.cs | 90 +++++++++++++++++++ 10 files changed, 237 insertions(+), 1 deletion(-) create mode 100644 src/AddIns/Misc/PackageManagement/Project/Src/IPackageRepositoryFactoryEvents.cs create mode 100644 src/AddIns/Misc/PackageManagement/Project/Src/PackageRepositoryFactoryEventArgs.cs create mode 100644 src/AddIns/Misc/PackageManagement/Project/Src/SharpDevelopHttpUserAgent.cs create mode 100644 src/AddIns/Misc/PackageManagement/Project/Src/UserAgentGeneratorForRepositoryRequests.cs create mode 100644 src/AddIns/Misc/PackageManagement/Test/Src/UserAgentGeneratorForRepositoryRequestsTests.cs diff --git a/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj b/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj index 4bb8f7c783..c0e534e813 100644 --- a/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj +++ b/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj @@ -158,6 +158,7 @@ + @@ -236,6 +237,7 @@ + @@ -252,9 +254,11 @@ + + diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/IPackageRepositoryFactoryEvents.cs b/src/AddIns/Misc/PackageManagement/Project/Src/IPackageRepositoryFactoryEvents.cs new file mode 100644 index 0000000000..e882a6f151 --- /dev/null +++ b/src/AddIns/Misc/PackageManagement/Project/Src/IPackageRepositoryFactoryEvents.cs @@ -0,0 +1,12 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.PackageManagement +{ + public interface IPackageRepositoryFactoryEvents + { + event EventHandler RepositoryCreated; + } +} diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementServices.cs b/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementServices.cs index 106bfc0b4e..5e9051d65e 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementServices.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementServices.cs @@ -24,11 +24,13 @@ namespace ICSharpCode.PackageManagement static readonly IPackageRepositoryCache projectTemplatePackageRepositoryCache; static readonly RegisteredProjectTemplatePackageSources projectTemplatePackageSources; static readonly PackageRepositoryCache packageRepositoryCache; + static readonly UserAgentGeneratorForRepositoryRequests userAgentGenerator; static PackageManagementServices() { options = new PackageManagementOptions(); packageRepositoryCache = new PackageRepositoryCache(options.PackageSources, options.RecentPackages); + userAgentGenerator = new UserAgentGeneratorForRepositoryRequests(packageRepositoryCache); registeredPackageRepositories = new RegisteredPackageRepositories(packageRepositoryCache, options); projectTemplatePackageSources = new RegisteredProjectTemplatePackageSources(); projectTemplatePackageRepositoryCache = new ProjectTemplatePackageRepositoryCache(packageRepositoryCache, projectTemplatePackageSources); diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/PackageRepositoryCache.cs b/src/AddIns/Misc/PackageManagement/Project/Src/PackageRepositoryCache.cs index aa05822a7e..c9d75ebc40 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/PackageRepositoryCache.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/PackageRepositoryCache.cs @@ -8,7 +8,7 @@ using NuGet; namespace ICSharpCode.PackageManagement { - public class PackageRepositoryCache : IPackageRepositoryCache + public class PackageRepositoryCache : IPackageRepositoryCache, IPackageRepositoryFactoryEvents { ISharpDevelopPackageRepositoryFactory factory; RegisteredPackageSources registeredPackageSources; @@ -37,6 +37,8 @@ namespace ICSharpCode.PackageManagement { } + public event EventHandler RepositoryCreated; + public IPackageRepository CreateRepository(string packageSource) { IPackageRepository repository = GetExistingRepository(packageSource); @@ -59,9 +61,19 @@ namespace ICSharpCode.PackageManagement { IPackageRepository repository = factory.CreateRepository(packageSource); repositories.TryAdd(packageSource, repository); + + OnPackageRepositoryCreated(repository); + return repository; } + void OnPackageRepositoryCreated(IPackageRepository repository) + { + if (RepositoryCreated != null) { + RepositoryCreated(this, new PackageRepositoryFactoryEventArgs(repository)); + } + } + public ISharedPackageRepository CreateSharedRepository(IPackagePathResolver pathResolver, IFileSystem fileSystem, IFileSystem configSettingsFileSystem) { return factory.CreateSharedRepository(pathResolver, fileSystem, configSettingsFileSystem); diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/PackageRepositoryFactoryEventArgs.cs b/src/AddIns/Misc/PackageManagement/Project/Src/PackageRepositoryFactoryEventArgs.cs new file mode 100644 index 0000000000..851c4b8d45 --- /dev/null +++ b/src/AddIns/Misc/PackageManagement/Project/Src/PackageRepositoryFactoryEventArgs.cs @@ -0,0 +1,18 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using NuGet; + +namespace ICSharpCode.PackageManagement +{ + public class PackageRepositoryFactoryEventArgs : EventArgs + { + public PackageRepositoryFactoryEventArgs(IPackageRepository repository) + { + this.Repository = repository; + } + + public IPackageRepository Repository { get; private set; } + } +} diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/SharpDevelopHttpUserAgent.cs b/src/AddIns/Misc/PackageManagement/Project/Src/SharpDevelopHttpUserAgent.cs new file mode 100644 index 0000000000..885b9393fb --- /dev/null +++ b/src/AddIns/Misc/PackageManagement/Project/Src/SharpDevelopHttpUserAgent.cs @@ -0,0 +1,37 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using NuGet; + +namespace ICSharpCode.PackageManagement +{ + public class SharpDevelopHttpUserAgent + { + public SharpDevelopHttpUserAgent() + { + CreateUserAgent(); + } + + public string Client { get; private set; } + public string Host { get; private set; } + public string UserAgent { get; private set; } + + void CreateUserAgent() + { + Client = "SharpDevelop"; + Host = GetHost(); + UserAgent = HttpUtility.CreateUserAgentString(Client, Host); + } + + string GetHost() + { + return String.Format("SharpDevelop/{0}", RevisionClass.FullVersion); + } + + public override string ToString() + { + return UserAgent; + } + } +} \ No newline at end of file diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/UserAgentGeneratorForRepositoryRequests.cs b/src/AddIns/Misc/PackageManagement/Project/Src/UserAgentGeneratorForRepositoryRequests.cs new file mode 100644 index 0000000000..72ce47e58c --- /dev/null +++ b/src/AddIns/Misc/PackageManagement/Project/Src/UserAgentGeneratorForRepositoryRequests.cs @@ -0,0 +1,35 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using NuGet; + +namespace ICSharpCode.PackageManagement +{ + public class UserAgentGeneratorForRepositoryRequests + { + SharpDevelopHttpUserAgent userAgent = new SharpDevelopHttpUserAgent(); + + public UserAgentGeneratorForRepositoryRequests(IPackageRepositoryFactoryEvents repositoryFactoryEvents) + { + repositoryFactoryEvents.RepositoryCreated += RepositoryCreated; + } + + void RepositoryCreated(object sender, PackageRepositoryFactoryEventArgs e) + { + RegisterHttpClient(e.Repository as IHttpClientEvents); + } + + void RegisterHttpClient(IHttpClientEvents clientEvents) + { + if (clientEvents != null) { + clientEvents.SendingRequest += SendingRequest; + } + } + + void SendingRequest(object sender, WebRequestEventArgs e) + { + HttpUtility.SetUserAgent(e.Request, userAgent.ToString()); + } + } +} diff --git a/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj b/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj index c4690abff0..66e56f446d 100644 --- a/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj +++ b/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj @@ -208,6 +208,7 @@ + diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/PackageRepositoryCacheTests.cs b/src/AddIns/Misc/PackageManagement/Test/Src/PackageRepositoryCacheTests.cs index 5bdbabacab..1c4ee897fb 100644 --- a/src/AddIns/Misc/PackageManagement/Test/Src/PackageRepositoryCacheTests.cs +++ b/src/AddIns/Misc/PackageManagement/Test/Src/PackageRepositoryCacheTests.cs @@ -355,5 +355,30 @@ namespace PackageManagement.Tests Assert.IsNull(fakePackageRepositoryFactory.AggregateRepositoryPassedToCreateRecentPackageRepository); } + + [Test] + public void CreateRepository_NewRepositoryCreated_RepositoryCreatedEventFired() + { + CreateCache(); + PackageRepositoryFactoryEventArgs eventArgs = null; + cache.RepositoryCreated += (sender, e) => eventArgs = e; + + IPackageRepository repository = cache.CreateRepository(nuGetPackageSource.Source); + + Assert.AreEqual(fakePackageRepositoryFactory.FakePackageRepository, eventArgs.Repository); + } + + [Test] + public void CreateRepository_RepositoryCreatedTwice_RepositoryCreatedEventIsNotFiredOnSecondCallToCreateRepository() + { + CreateCache(); + cache.CreateRepository(nuGetPackageSource.Source); + PackageRepositoryFactoryEventArgs eventArgs = null; + cache.RepositoryCreated += (sender, e) => eventArgs = e; + + cache.CreateRepository(nuGetPackageSource.Source); + + Assert.IsNull(eventArgs); + } } } diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/UserAgentGeneratorForRepositoryRequestsTests.cs b/src/AddIns/Misc/PackageManagement/Test/Src/UserAgentGeneratorForRepositoryRequestsTests.cs new file mode 100644 index 0000000000..1feb8c196a --- /dev/null +++ b/src/AddIns/Misc/PackageManagement/Test/Src/UserAgentGeneratorForRepositoryRequestsTests.cs @@ -0,0 +1,90 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Net; +using ICSharpCode.PackageManagement; +using NuGet; +using NUnit.Framework; +using Rhino.Mocks; + +namespace PackageManagement.Tests +{ + [TestFixture] + public class UserAgentGeneratorForRepositoryRequestsTests + { + UserAgentGeneratorForRepositoryRequests generator; + IPackageRepositoryFactoryEvents repositoryFactoryEvents; + + void CreateGenerator() + { + repositoryFactoryEvents = MockRepository.GenerateStub(); + generator = new UserAgentGeneratorForRepositoryRequests(repositoryFactoryEvents); + } + + IPackageRepository CreatePackageRepository() + { + return MockRepository.GenerateStub(); + } + + IHttpClientEvents CreatePackageRepositoryThatImplementsIHttpClientEvents() + { + return MockRepository.GenerateMock(); + } + + void FireRepositoryCreatedEvent(IHttpClientEvents clientEvents) + { + FireRepositoryCreatedEvent(clientEvents as IPackageRepository); + } + + void FireRepositoryCreatedEvent(IPackageRepository repository) + { + var eventArgs = new PackageRepositoryFactoryEventArgs(repository); + repositoryFactoryEvents.Raise( + events => events.RepositoryCreated += null, + repositoryFactoryEvents, + eventArgs); + } + + WebRequest FireSendingRequestEvent(IHttpClientEvents clientEvents) + { + WebRequest request = CreateWebRequest(); + request.Headers = new WebHeaderCollection(); + + var eventArgs = new WebRequestEventArgs(request); + clientEvents.Raise( + events => events.SendingRequest += null, + clientEvents, + eventArgs); + + return request; + } + + WebRequest CreateWebRequest() + { + return MockRepository.GenerateStub(); + } + + [Test] + public void SendingRequest_UserAgentGeneration_UserAgentSetOnRequest() + { + CreateGenerator(); + IHttpClientEvents clientEvents = CreatePackageRepositoryThatImplementsIHttpClientEvents(); + FireRepositoryCreatedEvent(clientEvents); + + WebRequest request = FireSendingRequestEvent(clientEvents); + + string userAgent = request.Headers[HttpRequestHeader.UserAgent]; + Assert.IsTrue(userAgent.StartsWith("SharpDevelop"), userAgent); + } + + [Test] + public void RepositoryCreated_RepositoryDoesNotImplementIHttpClientEvents_NullReferenceExceptionNotThrown() + { + CreateGenerator(); + IPackageRepository repository = CreatePackageRepository(); + + FireRepositoryCreatedEvent(repository); + } + } +}