From f6b43961d0f783727a662cadb24850a6957f12dd Mon Sep 17 00:00:00 2001 From: Nathan Brown Date: Wed, 18 Feb 2015 03:36:24 -0700 Subject: [PATCH 01/10] Use SynchronizedList instead of SynchronizedCollection for better compatibility with future .NET framework changes (all non-desktop frameworks). --- .../RabbitMQ.Client/src/client/impl/ModelBase.cs | 6 +++--- .../RabbitMQ.Client/src/util/SynchronizedList.cs | 10 ++++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/projects/client/RabbitMQ.Client/src/client/impl/ModelBase.cs b/projects/client/RabbitMQ.Client/src/client/impl/ModelBase.cs index 936597b29e..ce174e811d 100644 --- a/projects/client/RabbitMQ.Client/src/client/impl/ModelBase.cs +++ b/projects/client/RabbitMQ.Client/src/client/impl/ModelBase.cs @@ -66,8 +66,8 @@ public abstract class ModelBase : IFullModel, IRecoverable private readonly object m_flowSendLock = new object(); private readonly object m_shutdownLock = new object(); - private readonly SynchronizedCollection m_unconfirmedSet = - new SynchronizedCollection(); + private readonly SynchronizedList m_unconfirmedSet = + new SynchronizedList(); private EventHandler m_basicAck; private EventHandler m_basicNack; @@ -1612,4 +1612,4 @@ public class QueueDeclareRpcContinuation : SimpleBlockingRpcContinuation public QueueDeclareOk m_result; } } -} \ No newline at end of file +} diff --git a/projects/client/RabbitMQ.Client/src/util/SynchronizedList.cs b/projects/client/RabbitMQ.Client/src/util/SynchronizedList.cs index 479e6f28eb..ef4b0d3177 100644 --- a/projects/client/RabbitMQ.Client/src/util/SynchronizedList.cs +++ b/projects/client/RabbitMQ.Client/src/util/SynchronizedList.cs @@ -50,6 +50,11 @@ internal class SynchronizedList : IList private readonly IList list; private readonly object root; + internal SynchronizedList() + : this(new List()) + { + } + internal SynchronizedList(IList list) { this.list = list; @@ -84,6 +89,11 @@ public T this[int index] } } + public object SyncRoot + { + get { return root; } + } + public void Add(T item) { lock (root) From 7c1a7d757dd62c184e8bbfd73288eccf465b4d05 Mon Sep 17 00:00:00 2001 From: Nathan Brown Date: Sun, 19 Apr 2015 11:07:32 -0700 Subject: [PATCH 02/10] Added WinRT (Windows 8) compatible library, sharing code where possible. Includes NUnit driven tests. Also includes Windows Store example application. Addresses GitHub issue #16 --- RabbitMQDotNetClient.sln | 51 +- RabbitMQDotNetClient.sln.DotSettings | 164 ++ .../RabbitMQ.Client.WinRT.csproj | 150 ++ .../src/client/impl/SocketFrameHandler.cs | 242 +++ .../src/tokenized/AssemblyInfo.cs.in | 55 + .../src/util/ICloneable.cs | 49 + .../src/util/MetroEventSource.cs | 79 + .../src/util/SerializableAttribute.cs | 48 + .../src/util/SortedList.cs | 1304 ++++++++++++ .../RabbitMQ.Client.WinRT/src/util/Timer.cs | 132 ++ .../src/client/api/ConnectionFactory.cs | 10 +- .../src/client/api/ConnectionFactoryBase.cs | 20 +- .../src/client/api/IProtocol.cs | 16 +- .../src/client/api/NetworkConnection.cs | 6 +- .../src/client/api/SslHelper.cs | 6 +- .../src/client/api/SslOption.cs | 21 +- .../src/client/content/BytesWireFormatting.cs | 2 +- .../client/content/StreamWireFormatting.cs | 5 +- .../exceptions/ConnectFailureException.cs | 2 +- .../OperationInterruptedException.cs | 2 + .../client/impl/AutorecoveringConnection.cs | 29 +- .../src/client/impl/CommandAssembler.cs | 4 + .../src/client/impl/Connection.cs | 122 +- .../src/client/impl/ConsumerWorkService.cs | 5 + .../RabbitMQ.Client/src/client/impl/Frame.cs | 16 + .../src/client/impl/IFrameHandler.cs | 4 + .../src/client/impl/ModelBase.cs | 4 + .../src/client/impl/ProtocolBase.cs | 15 +- .../src/client/impl/SessionManager.cs | 9 + .../impl/SimpleBlockingRpcContinuation.cs | 7 +- .../src/client/impl/WireFormatting.cs | 3 +- .../client/messagepatterns/Subscription.cs | 34 + .../src/util/BatchingWorkPool.cs | 6 + .../RabbitMQ.Client/src/util/DebugUtil.cs | 15 +- .../RabbitMQ.Client/src/util/SharedQueue.cs | 62 + .../RabbitMQ.Client.Unit.WinRT.csproj | 104 + .../Unit.WinRT/properties/AssemblyInfo.cs | 63 + .../Unit/src/unit/TestContentHeaderCodec.cs | 4 +- .../Unit/src/unit/TestMethodArgumentCodec.cs | 4 +- projects/client/Unit/src/unit/TestSsl.cs | 18 +- .../Unit/src/unit/WireFormattingFixture.cs | 4 +- projects/examples/WinRT/Subscriber/App.xaml | 21 + .../examples/WinRT/Subscriber/App.xaml.cs | 103 + .../examples/WinRT/Subscriber/Assets/Logo.png | Bin 0 -> 1232 bytes .../WinRT/Subscriber/Assets/SmallLogo.png | Bin 0 -> 539 bytes .../WinRT/Subscriber/Assets/SplashScreen.png | Bin 0 -> 32307 bytes .../WinRT/Subscriber/Assets/StoreLogo.png | Bin 0 -> 460 bytes .../WinRT/Subscriber/Assets/WideLogo.png | Bin 0 -> 7943 bytes .../Subscriber/Common/StandardStyles.xaml | 1829 +++++++++++++++++ .../examples/WinRT/Subscriber/MainPage.xaml | 129 ++ .../WinRT/Subscriber/MainPage.xaml.cs | 252 +++ .../WinRT/Subscriber/MainPageViewModel.cs | 209 ++ .../WinRT/Subscriber/Package.appxmanifest | 27 + .../Subscriber/Properties/Annotations.cs | 689 +++++++ .../Subscriber/Properties/AssemblyInfo.cs | 29 + ...MQ.Client.Examples.WinRT.Subscriber.csproj | 160 ++ ...Examples.WinRT.Subscriber_TemporaryKey.pfx | Bin 0 -> 2512 bytes .../Subscriber/StorageFileEventListener.cs | 12 + 58 files changed, 6300 insertions(+), 56 deletions(-) create mode 100644 projects/client/RabbitMQ.Client.WinRT/RabbitMQ.Client.WinRT.csproj create mode 100644 projects/client/RabbitMQ.Client.WinRT/src/client/impl/SocketFrameHandler.cs create mode 100644 projects/client/RabbitMQ.Client.WinRT/src/tokenized/AssemblyInfo.cs.in create mode 100644 projects/client/RabbitMQ.Client.WinRT/src/util/ICloneable.cs create mode 100644 projects/client/RabbitMQ.Client.WinRT/src/util/MetroEventSource.cs create mode 100644 projects/client/RabbitMQ.Client.WinRT/src/util/SerializableAttribute.cs create mode 100644 projects/client/RabbitMQ.Client.WinRT/src/util/SortedList.cs create mode 100644 projects/client/RabbitMQ.Client.WinRT/src/util/Timer.cs create mode 100644 projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj create mode 100644 projects/client/Unit.WinRT/properties/AssemblyInfo.cs create mode 100644 projects/examples/WinRT/Subscriber/App.xaml create mode 100644 projects/examples/WinRT/Subscriber/App.xaml.cs create mode 100644 projects/examples/WinRT/Subscriber/Assets/Logo.png create mode 100644 projects/examples/WinRT/Subscriber/Assets/SmallLogo.png create mode 100644 projects/examples/WinRT/Subscriber/Assets/SplashScreen.png create mode 100644 projects/examples/WinRT/Subscriber/Assets/StoreLogo.png create mode 100644 projects/examples/WinRT/Subscriber/Assets/WideLogo.png create mode 100644 projects/examples/WinRT/Subscriber/Common/StandardStyles.xaml create mode 100644 projects/examples/WinRT/Subscriber/MainPage.xaml create mode 100644 projects/examples/WinRT/Subscriber/MainPage.xaml.cs create mode 100644 projects/examples/WinRT/Subscriber/MainPageViewModel.cs create mode 100644 projects/examples/WinRT/Subscriber/Package.appxmanifest create mode 100644 projects/examples/WinRT/Subscriber/Properties/Annotations.cs create mode 100644 projects/examples/WinRT/Subscriber/Properties/AssemblyInfo.cs create mode 100644 projects/examples/WinRT/Subscriber/RabbitMQ.Client.Examples.WinRT.Subscriber.csproj create mode 100644 projects/examples/WinRT/Subscriber/RabbitMQ.Client.Examples.WinRT.Subscriber_TemporaryKey.pfx create mode 100644 projects/examples/WinRT/Subscriber/StorageFileEventListener.cs diff --git a/RabbitMQDotNetClient.sln b/RabbitMQDotNetClient.sln index b874d77fa1..91b22a470d 100644 --- a/RabbitMQDotNetClient.sln +++ b/RabbitMQDotNetClient.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 -VisualStudioVersion = 12.0.21005.1 +VisualStudioVersion = 12.0.31101.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "projects", "projects", "{068D7DC3-8E6E-4951-B9E3-272C641BF0DE}" EndProject @@ -17,6 +17,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wcf", "wcf", "{EA42A7EF-7CE EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ConfigDemo", "ConfigDemo", "{20E34D9F-EE72-4B55-B6FE-1D0DBE5B74CD}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WinRT", "WinRT", "{5B87326D-1C2C-45A2-AD9E-4BD005A1629D}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RabbitMQ.Client.ApigenBootstrap", "projects\client\ApigenBootstrap\RabbitMQ.Client.ApigenBootstrap.csproj", "{CC8F4572-6730-4C4D-A0BB-15151E2A26AE}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RabbitMQ.Client.Apigen", "projects\client\Apigen\RabbitMQ.Client.Apigen.csproj", "{9E8B8DC5-3837-46E9-90D7-8391CC62AB45}" @@ -64,6 +66,15 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RabbitMQ.Client.Examples.Pe EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RabbitMQ.Client.Examples.Subscriber", "projects\examples\client\Subscriber\RabbitMQ.Client.Examples.Subscriber.csproj", "{F6DF1899-A038-4DBF-86D0-0DE64F2422EC}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RabbitMQ.Client.WinRT", "projects\client\RabbitMQ.Client.WinRT\RabbitMQ.Client.WinRT.csproj", "{61D29F90-5B1C-4748-89FC-9FD2937F09C6}" + ProjectSection(ProjectDependencies) = postProject + {9E8B8DC5-3837-46E9-90D7-8391CC62AB45} = {9E8B8DC5-3837-46E9-90D7-8391CC62AB45} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RabbitMQ.Client.Examples.WinRT.Subscriber", "projects\examples\WinRT\Subscriber\RabbitMQ.Client.Examples.WinRT.Subscriber.csproj", "{6F01C132-7938-4001-8B70-D84EBAA662CC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RabbitMQ.Client.Unit.WinRT", "projects\client\Unit.WinRT\RabbitMQ.Client.Unit.WinRT.csproj", "{897505A9-8373-4F41-8DE8-221BF06D877D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -202,6 +213,26 @@ Global {F6DF1899-A038-4DBF-86D0-0DE64F2422EC}.DebugNoTest|Any CPU.Build.0 = Debug|Any CPU {F6DF1899-A038-4DBF-86D0-0DE64F2422EC}.Release|Any CPU.ActiveCfg = Release|Any CPU {F6DF1899-A038-4DBF-86D0-0DE64F2422EC}.Release|Any CPU.Build.0 = Release|Any CPU + {61D29F90-5B1C-4748-89FC-9FD2937F09C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {61D29F90-5B1C-4748-89FC-9FD2937F09C6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {61D29F90-5B1C-4748-89FC-9FD2937F09C6}.DebugNoTest|Any CPU.ActiveCfg = Debug|Any CPU + {61D29F90-5B1C-4748-89FC-9FD2937F09C6}.DebugNoTest|Any CPU.Build.0 = Debug|Any CPU + {61D29F90-5B1C-4748-89FC-9FD2937F09C6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {61D29F90-5B1C-4748-89FC-9FD2937F09C6}.Release|Any CPU.Build.0 = Release|Any CPU + {6F01C132-7938-4001-8B70-D84EBAA662CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6F01C132-7938-4001-8B70-D84EBAA662CC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6F01C132-7938-4001-8B70-D84EBAA662CC}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {6F01C132-7938-4001-8B70-D84EBAA662CC}.DebugNoTest|Any CPU.ActiveCfg = Debug|Any CPU + {6F01C132-7938-4001-8B70-D84EBAA662CC}.DebugNoTest|Any CPU.Build.0 = Debug|Any CPU + {6F01C132-7938-4001-8B70-D84EBAA662CC}.DebugNoTest|Any CPU.Deploy.0 = Debug|Any CPU + {6F01C132-7938-4001-8B70-D84EBAA662CC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6F01C132-7938-4001-8B70-D84EBAA662CC}.Release|Any CPU.Build.0 = Release|Any CPU + {6F01C132-7938-4001-8B70-D84EBAA662CC}.Release|Any CPU.Deploy.0 = Release|Any CPU + {897505A9-8373-4F41-8DE8-221BF06D877D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {897505A9-8373-4F41-8DE8-221BF06D877D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {897505A9-8373-4F41-8DE8-221BF06D877D}.DebugNoTest|Any CPU.ActiveCfg = Debug|Any CPU + {897505A9-8373-4F41-8DE8-221BF06D877D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {897505A9-8373-4F41-8DE8-221BF06D877D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -210,13 +241,15 @@ Global {ECCBAEE2-24C9-4C95-A88C-03B68E866F0F} = {068D7DC3-8E6E-4951-B9E3-272C641BF0DE} {9093855F-C802-407D-B127-CADD8F92FCD8} = {068D7DC3-8E6E-4951-B9E3-272C641BF0DE} {23B4D18E-E5D3-4BF8-A488-021B96A5DD72} = {068D7DC3-8E6E-4951-B9E3-272C641BF0DE} + {78D13AD2-B1AC-442C-95C8-958D643FC40B} = {23B4D18E-E5D3-4BF8-A488-021B96A5DD72} + {EA42A7EF-7CE6-4EDA-98EA-6675C7EF7F69} = {23B4D18E-E5D3-4BF8-A488-021B96A5DD72} + {20E34D9F-EE72-4B55-B6FE-1D0DBE5B74CD} = {EA42A7EF-7CE6-4EDA-98EA-6675C7EF7F69} + {5B87326D-1C2C-45A2-AD9E-4BD005A1629D} = {23B4D18E-E5D3-4BF8-A488-021B96A5DD72} {CC8F4572-6730-4C4D-A0BB-15151E2A26AE} = {ECCBAEE2-24C9-4C95-A88C-03B68E866F0F} {9E8B8DC5-3837-46E9-90D7-8391CC62AB45} = {ECCBAEE2-24C9-4C95-A88C-03B68E866F0F} {71713FDD-D5EC-40B2-A924-76F80AD57E12} = {ECCBAEE2-24C9-4C95-A88C-03B68E866F0F} {DC9022AA-DC30-4871-AD28-3F166E05DBB5} = {ECCBAEE2-24C9-4C95-A88C-03B68E866F0F} {5117232B-EE07-46F8-8AF5-2B636F1DBF56} = {9093855F-C802-407D-B127-CADD8F92FCD8} - {78D13AD2-B1AC-442C-95C8-958D643FC40B} = {23B4D18E-E5D3-4BF8-A488-021B96A5DD72} - {EA42A7EF-7CE6-4EDA-98EA-6675C7EF7F69} = {23B4D18E-E5D3-4BF8-A488-021B96A5DD72} {F03945AD-08C5-4531-805C-5B0BA110E9CF} = {78D13AD2-B1AC-442C-95C8-958D643FC40B} {95E9B6BE-FCA4-4C59-AFAB-1D974D972981} = {78D13AD2-B1AC-442C-95C8-958D643FC40B} {7B63B8B6-6D7B-4A97-B842-F92106300EF5} = {78D13AD2-B1AC-442C-95C8-958D643FC40B} @@ -226,14 +259,16 @@ Global {A626CC84-04E9-4614-A389-FCE3122BE6BC} = {78D13AD2-B1AC-442C-95C8-958D643FC40B} {23680866-F877-4E06-B999-FDFD0B6A8CF6} = {78D13AD2-B1AC-442C-95C8-958D643FC40B} {6BF8B993-1722-446E-89B3-7BAC6066BECC} = {78D13AD2-B1AC-442C-95C8-958D643FC40B} + {201B37E1-9BFC-4A01-9760-30C5BB19CFE3} = {20E34D9F-EE72-4B55-B6FE-1D0DBE5B74CD} + {8D0DEB29-349C-4617-B61E-B22DE144BD22} = {20E34D9F-EE72-4B55-B6FE-1D0DBE5B74CD} + {034B2E6C-78F4-4205-A73A-5D74E83B5F26} = {20E34D9F-EE72-4B55-B6FE-1D0DBE5B74CD} + {39CA1299-1F9E-452E-AA00-4BF874944B1E} = {EA42A7EF-7CE6-4EDA-98EA-6675C7EF7F69} {44D14FF0-1015-4AAA-ABCA-BF611879816C} = {78D13AD2-B1AC-442C-95C8-958D643FC40B} {8BCE15DB-C92F-4FA4-AE57-9CA73DE91EB2} = {78D13AD2-B1AC-442C-95C8-958D643FC40B} {6ED176D6-B789-4673-8300-CB671962FE00} = {78D13AD2-B1AC-442C-95C8-958D643FC40B} {F6DF1899-A038-4DBF-86D0-0DE64F2422EC} = {78D13AD2-B1AC-442C-95C8-958D643FC40B} - {20E34D9F-EE72-4B55-B6FE-1D0DBE5B74CD} = {EA42A7EF-7CE6-4EDA-98EA-6675C7EF7F69} - {39CA1299-1F9E-452E-AA00-4BF874944B1E} = {EA42A7EF-7CE6-4EDA-98EA-6675C7EF7F69} - {201B37E1-9BFC-4A01-9760-30C5BB19CFE3} = {20E34D9F-EE72-4B55-B6FE-1D0DBE5B74CD} - {8D0DEB29-349C-4617-B61E-B22DE144BD22} = {20E34D9F-EE72-4B55-B6FE-1D0DBE5B74CD} - {034B2E6C-78F4-4205-A73A-5D74E83B5F26} = {20E34D9F-EE72-4B55-B6FE-1D0DBE5B74CD} + {61D29F90-5B1C-4748-89FC-9FD2937F09C6} = {ECCBAEE2-24C9-4C95-A88C-03B68E866F0F} + {6F01C132-7938-4001-8B70-D84EBAA662CC} = {5B87326D-1C2C-45A2-AD9E-4BD005A1629D} + {897505A9-8373-4F41-8DE8-221BF06D877D} = {ECCBAEE2-24C9-4C95-A88C-03B68E866F0F} EndGlobalSection EndGlobal diff --git a/RabbitMQDotNetClient.sln.DotSettings b/RabbitMQDotNetClient.sln.DotSettings index c418d2b7c4..3ca61f6169 100644 --- a/RabbitMQDotNetClient.sln.DotSettings +++ b/RabbitMQDotNetClient.sln.DotSettings @@ -100,6 +100,167 @@ CHOP_ALWAYS True True + <Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns"> + <TypePattern DisplayName="COM interfaces or structs"> + <TypePattern.Match> + <Or> + <And> + <Kind Is="Interface" /> + <Or> + <HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" /> + <HasAttribute Name="System.Runtime.InteropServices.ComImport" /> + </Or> + </And> + <HasAttribute Name="System.Runtime.InteropServices.StructLayoutAttribute" /> + </Or> + </TypePattern.Match> + </TypePattern> + + <TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All"> + <TypePattern.Match> + <And> + <Kind Is="Class" /> + <HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="true" /> + <HasAttribute Name="NUnit.Framework.TestCaseFixtureAttribute" Inherited="true" /> + </And> + </TypePattern.Match> + + <Entry DisplayName="Setup/Teardown Methods"> + <Entry.Match> + <And> + <Kind Is="Method" /> + <Or> + <HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="true" /> + <HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="true" /> + <HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="true" /> + <HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="true" /> + </Or> + </And> + </Entry.Match> + </Entry> + + <Entry DisplayName="All other members" /> + + <Entry DisplayName="Test Methods" Priority="100"> + <Entry.Match> + <And> + <Kind Is="Method" /> + <HasAttribute Name="NUnit.Framework.TestAttribute" Inherited="false" /> + </And> + </Entry.Match> + + <Entry.SortBy> + <Name /> + </Entry.SortBy> + </Entry> + </TypePattern> + + <TypePattern DisplayName="Default Pattern"> + <Entry DisplayName="Public Delegates" Priority="100"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Kind Is="Delegate" /> + </And> + </Entry.Match> + + <Entry.SortBy> + <Name /> + </Entry.SortBy> + </Entry> + + <Entry DisplayName="Public Enums" Priority="100"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Kind Is="Enum" /> + </And> + </Entry.Match> + + <Entry.SortBy> + <Name /> + </Entry.SortBy> + </Entry> + + <Entry DisplayName="Static Fields and Constants"> + <Entry.Match> + <Or> + <Kind Is="Constant" /> + <And> + <Kind Is="Field" /> + <Static /> + </And> + </Or> + </Entry.Match> + + <Entry.SortBy> + <Kind> + <Kind.Order> + <DeclarationKind>Constant</DeclarationKind> + <DeclarationKind>Field</DeclarationKind> + </Kind.Order> + </Kind> + </Entry.SortBy> + </Entry> + + <Entry DisplayName="Fields"> + <Entry.Match> + <And> + <Kind Is="Field" /> + <Not> + <Static /> + </Not> + </And> + </Entry.Match> + + <Entry.SortBy> + <Readonly /> + <Name /> + </Entry.SortBy> + </Entry> + + <Entry DisplayName="Constructors"> + <Entry.Match> + <Kind Is="Constructor" /> + </Entry.Match> + + <Entry.SortBy> + <Static/> + </Entry.SortBy> + </Entry> + + <Entry DisplayName="Properties, Indexers"> + <Entry.Match> + <Or> + <Kind Is="Property" /> + <Kind Is="Indexer" /> + </Or> + </Entry.Match> + </Entry> + + <Entry DisplayName="Interface Implementations" Priority="100"> + <Entry.Match> + <And> + <Kind Is="Member" /> + <ImplementsInterface /> + </And> + </Entry.Match> + + <Entry.SortBy> + <ImplementsInterface Immediate="true" /> + </Entry.SortBy> + </Entry> + + <Entry DisplayName="All other members" /> + + <Entry DisplayName="Nested Types"> + <Entry.Match> + <Kind Is="Type" /> + </Entry.Match> + </Entry> + </TypePattern> +</Patterns> + <?xml version="1.0" encoding="utf-8" ?> <!-- @@ -396,5 +557,8 @@ II.2.12 <HandlesEvent /> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> $object$_On$event$ + True + True True + True True \ No newline at end of file diff --git a/projects/client/RabbitMQ.Client.WinRT/RabbitMQ.Client.WinRT.csproj b/projects/client/RabbitMQ.Client.WinRT/RabbitMQ.Client.WinRT.csproj new file mode 100644 index 0000000000..b60efba008 --- /dev/null +++ b/projects/client/RabbitMQ.Client.WinRT/RabbitMQ.Client.WinRT.csproj @@ -0,0 +1,150 @@ + + + + + + $(MSBuildProjectDirectory)\..\..\..\Local.props + + + + + $(MSBuildProjectDirectory)\..\..\..\lib\MSBuild.Community.Tasks\ + + + + + ..\..\..\gensrc\$(MSBuildProjectName)\ + + + + + + + ..\..\..\docs\specs\ + amqp0-9-1.stripped.xml + amqp0-9.stripped.xml + $(SpecsDir)$(AmqpSpec0_9_1BaseName) + autogenerated-api-0-9-1.cs + $(GensrcDir)$(AutogeneratedApi0_9_1BaseName) + ..\Apigen\build\bin\rabbitmq-dotnet-apigen.exe + + + + specs\$(AmqpSpec0_9_1BaseName) + + + src\gensrc\$(AutogeneratedApi0_9_1BaseName) + + + false + + + + + + + + + + + AssemblyInfo.cs + src\tokenized\$(AssemblyInfoBaseName).in + $(GensrcDir)$(AssemblyInfoBaseName) + + + + + properties\$(AssemblyInfoBaseName) + + + false + + + $(PropAssemblyVersion) + false + + + + + + + + + + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {61D29F90-5B1C-4748-89FC-9FD2937F09C6} + Library + properties + RabbitMQ.Client + RabbitMQ.Client + en-US + 512 + {BC8A1FFA-BEE3-4634-8014-F334798102B3};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + true + full + false + build\bin\ + DEBUG;TRACE;NETFX_CORE + none + 4 + build\bin\RabbitMQ.Client.xml + 1591 + Auto + false + false + true + + + pdbonly + true + build\bin\ + TRACE;NETFX_CORE + none + 4 + build\bin\RabbitMQ.Client.xml + 1591 + true + false + true + $(PropKeyfile) + true + + + + src\client\%(RecursiveDir)%(Filename)%(Extension) + + + src\util\%(RecursiveDir)%(Filename)%(Extension) + + + + + + + + + + + + + 11.0 + + + + <_DisabledWarnings>$(NoWarn) + + + + + + + + diff --git a/projects/client/RabbitMQ.Client.WinRT/src/client/impl/SocketFrameHandler.cs b/projects/client/RabbitMQ.Client.WinRT/src/client/impl/SocketFrameHandler.cs new file mode 100644 index 0000000000..27df47bc71 --- /dev/null +++ b/projects/client/RabbitMQ.Client.WinRT/src/client/impl/SocketFrameHandler.cs @@ -0,0 +1,242 @@ +// This source code is dual-licensed under the Apache License, version +// 2.0, and the Mozilla Public License, version 1.1. +// +// The APL v2.0: +// +//--------------------------------------------------------------------------- +// Copyright (C) 2007-2014 GoPivotal, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//--------------------------------------------------------------------------- +// +// The MPL v1.1: +// +//--------------------------------------------------------------------------- +// The contents of this file are subject to the Mozilla Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License +// at http://www.mozilla.org/MPL/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +// the License for the specific language governing rights and +// limitations under the License. +// +// The Original Code is RabbitMQ. +// +// The Initial Developer of the Original Code is GoPivotal, Inc. +// Copyright (c) 2007-2014 GoPivotal, Inc. All rights reserved. +//--------------------------------------------------------------------------- + +using System; +using System.IO; +using System.Text; + +using System.Threading; + +using Windows.Foundation; +using Windows.Networking; +using Windows.Networking.Sockets; + +using RabbitMQ.Util; +using RabbitMQ.Client.Exceptions; + +namespace RabbitMQ.Client.Impl +{ + /// + /// Implement for WinRT. The significant + /// difference is that TcpClient is not available and the new + /// needs to be used. + /// + public class SocketFrameHandler : IFrameHandler + { + // Timeout in seconds to wait for a clean socket close. + public const int SOCKET_CLOSING_TIMEOUT = 1; + + public StreamSocket m_socket; + private CancellationTokenSource cts; + public NetworkBinaryReader m_reader; + public NetworkBinaryWriter m_writer; + private bool _closed = false; + private readonly object _semaphore = new object(); + + private int? defaultTimeout; + + public SocketFrameHandler(AmqpTcpEndpoint endpoint, + Func socketFactory, + int timeout) + { + Endpoint = endpoint; + + m_socket = socketFactory(); + Connect(m_socket, endpoint, timeout); + + if (endpoint.Ssl.Enabled) + { + IAsyncAction ar = null; + try + { + cts = new CancellationTokenSource(); + if (this.defaultTimeout.HasValue) + cts.CancelAfter(this.defaultTimeout.Value); + + ar = this.m_socket.UpgradeToSslAsync( + SocketProtectionLevel.Ssl, new HostName(endpoint.Ssl.ServerName)); + ar.AsTask(cts.Token).Wait(); + ar.GetResults(); + } + catch (Exception) + { + Close(); + throw; + } + finally + { + if (ar != null) + ar.Close(); + } + } + m_reader = new NetworkBinaryReader(m_socket.InputStream.AsStreamForRead()); + m_writer = new NetworkBinaryWriter(m_socket.OutputStream.AsStreamForWrite()); + } + + public AmqpTcpEndpoint Endpoint { get; set; } + + public int LocalPort + { + get + { + // the port string may be empty, so TryParse will set to 0; + int port; + Int32.TryParse(m_socket.Information.LocalPort, out port); + return port; + } + } + public int RemotePort + { + get + { + // the port string may be empty, so TryParse will set to 0; + int port; + Int32.TryParse(m_socket.Information.RemotePort, out port); + return port; + } + } + + public int Timeout + { + set + { + defaultTimeout = value; + if (cts != null && cts.Token.CanBeCanceled) + { + cts.CancelAfter(value); + } + } + } + + public void Close() + { + lock (_semaphore) + { + if (!_closed) + { + // TODO: Figure out the equivalent for LingerState + //m_socket.LingerState = new LingerOption(true, SOCKET_CLOSING_TIMEOUT); + m_socket.Dispose(); + _closed = true; + } + } + } + + public Frame ReadFrame() + { + lock (m_reader) + { + return Frame.ReadFrom(m_reader); + } + } + + public void SendHeader() + { + lock (m_writer) + { + m_writer.Write(Encoding.UTF8.GetBytes("AMQP")); + if (Endpoint.Protocol.Revision != 0) + { + m_writer.Write((byte)0); + m_writer.Write((byte)Endpoint.Protocol.MajorVersion); + m_writer.Write((byte)Endpoint.Protocol.MinorVersion); + m_writer.Write((byte)Endpoint.Protocol.Revision); + } + else + { + m_writer.Write((byte)1); + m_writer.Write((byte)1); + m_writer.Write((byte)Endpoint.Protocol.MajorVersion); + m_writer.Write((byte)Endpoint.Protocol.MinorVersion); + } + m_writer.Flush(); + } + } + + public void WriteFrame(Frame frame) + { + lock (m_writer) + { + frame.WriteTo(m_writer); + m_writer.Flush(); + } + } + + private void Connect(StreamSocket socket, AmqpTcpEndpoint endpoint, int timeout) + { + IAsyncAction ar = null; + try + { + cts = new CancellationTokenSource(); + if (this.defaultTimeout.HasValue) + cts.CancelAfter(this.defaultTimeout.Value); + + ar = socket.ConnectAsync(new HostName(endpoint.HostName), endpoint.Port.ToString(), SocketProtectionLevel.PlainSocket); + if (!ar.AsTask(cts.Token).Wait(timeout)) + { + socket.Dispose(); + throw new TimeoutException("Connection to " + endpoint + " timed out"); + } + ar.GetResults(); + } + catch (ArgumentException e) + { + throw new ConnectFailureException("Connection failed", e); + } + catch (Exception e) + { + // If this is an unknown status it means that the error is fatal and retry will likely fail. + if (SocketError.GetStatus(e.HResult) == SocketErrorStatus.Unknown) + { + throw; + } + + throw new ConnectFailureException("Connection failed", e); + } + finally + { + if (ar != null) + { + ar.Close(); + } + } + } + } +} diff --git a/projects/client/RabbitMQ.Client.WinRT/src/tokenized/AssemblyInfo.cs.in b/projects/client/RabbitMQ.Client.WinRT/src/tokenized/AssemblyInfo.cs.in new file mode 100644 index 0000000000..49939dd39f --- /dev/null +++ b/projects/client/RabbitMQ.Client.WinRT/src/tokenized/AssemblyInfo.cs.in @@ -0,0 +1,55 @@ +// This source code is dual-licensed under the Apache License, version +// 2.0, and the Mozilla Public License, version 1.1. +// +// The APL v2.0: +// +//--------------------------------------------------------------------------- +// Copyright (C) 2007-2014 GoPivotal, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//--------------------------------------------------------------------------- +// +// The MPL v1.1: +// +//--------------------------------------------------------------------------- +// The contents of this file are subject to the Mozilla Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License +// at http://www.mozilla.org/MPL/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +// the License for the specific language governing rights and +// limitations under the License. +// +// The Original Code is RabbitMQ. +// +// The Initial Developer of the Original Code is GoPivotal, Inc. +// Copyright (c) 2007-2014 GoPivotal, Inc. All rights reserved. +//--------------------------------------------------------------------------- + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("RabbitMQ Client Library for .Net")] +[assembly: AssemblyDescription("Open Source Enterprise Messaging")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("GoPivotal, Inc.")] +[assembly: AssemblyProduct("RabbitMQ")] +[assembly: AssemblyCopyright("Copyright © 2007-2014 GoPivotal, Inc.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: AssemblyVersion("${PropAssemblyVersion}")] + diff --git a/projects/client/RabbitMQ.Client.WinRT/src/util/ICloneable.cs b/projects/client/RabbitMQ.Client.WinRT/src/util/ICloneable.cs new file mode 100644 index 0000000000..d88ff298bb --- /dev/null +++ b/projects/client/RabbitMQ.Client.WinRT/src/util/ICloneable.cs @@ -0,0 +1,49 @@ +// This source code is dual-licensed under the Apache License, version +// 2.0, and the Mozilla Public License, version 1.1. +// +// The APL v2.0: +// +//--------------------------------------------------------------------------- +// Copyright (C) 2007-2014 GoPivotal, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//--------------------------------------------------------------------------- +// +// The MPL v1.1: +// +//--------------------------------------------------------------------------- +// The contents of this file are subject to the Mozilla Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License +// at http://www.mozilla.org/MPL/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +// the License for the specific language governing rights and +// limitations under the License. +// +// The Original Code is RabbitMQ. +// +// The Initial Developer of the Original Code is GoPivotal, Inc. +// Copyright (c) 2013-2014 GoPivotal, Inc. All rights reserved. +//--------------------------------------------------------------------------- + +namespace System +{ +#if (NETFX_CORE) + public interface ICloneable + { + object Clone(); + } +#endif +} \ No newline at end of file diff --git a/projects/client/RabbitMQ.Client.WinRT/src/util/MetroEventSource.cs b/projects/client/RabbitMQ.Client.WinRT/src/util/MetroEventSource.cs new file mode 100644 index 0000000000..803cb16ea3 --- /dev/null +++ b/projects/client/RabbitMQ.Client.WinRT/src/util/MetroEventSource.cs @@ -0,0 +1,79 @@ +// This source code is dual-licensed under the Apache License, version +// 2.0, and the Mozilla Public License, version 1.1. +// +// The APL v2.0: +// +//--------------------------------------------------------------------------- +// Copyright (C) 2007-2014 GoPivotal, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//--------------------------------------------------------------------------- +// +// The MPL v1.1: +// +//--------------------------------------------------------------------------- +// The contents of this file are subject to the Mozilla Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License +// at http://www.mozilla.org/MPL/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +// the License for the specific language governing rights and +// limitations under the License. +// +// The Original Code is RabbitMQ. +// +// The Initial Developer of the Original Code is GoPivotal, Inc. +// Copyright (c) 2013-2014 GoPivotal, Inc. All rights reserved. +//--------------------------------------------------------------------------- + +using System.Diagnostics.Tracing; + +namespace RabbitMQ.Util +{ + public class MetroEventSource : EventSource + { + public static MetroEventSource Log = new MetroEventSource(); + + [Event(1, Level = EventLevel.Verbose)] + public void Debug(string message) + { + this.WriteEvent(1, message); + } + + [Event(2, Level = EventLevel.Informational)] + public void Info(string message) + { + this.WriteEvent(2, message); + } + + [Event(3, Level = EventLevel.Warning)] + public void Warn(string message) + { + this.WriteEvent(3, message); + } + + [Event(4, Level = EventLevel.Error)] + public void Error(string message) + { + this.WriteEvent(4, message); + } + + [Event(5, Level = EventLevel.Critical)] + public void Critical(string message) + { + this.WriteEvent(5, message); + } + } +} \ No newline at end of file diff --git a/projects/client/RabbitMQ.Client.WinRT/src/util/SerializableAttribute.cs b/projects/client/RabbitMQ.Client.WinRT/src/util/SerializableAttribute.cs new file mode 100644 index 0000000000..68bcf22a62 --- /dev/null +++ b/projects/client/RabbitMQ.Client.WinRT/src/util/SerializableAttribute.cs @@ -0,0 +1,48 @@ +// This source code is dual-licensed under the Apache License, version +// 2.0, and the Mozilla Public License, version 1.1. +// +// The APL v2.0: +// +//--------------------------------------------------------------------------- +// Copyright (C) 2007-2014 GoPivotal, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//--------------------------------------------------------------------------- +// +// The MPL v1.1: +// +//--------------------------------------------------------------------------- +// The contents of this file are subject to the Mozilla Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License +// at http://www.mozilla.org/MPL/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +// the License for the specific language governing rights and +// limitations under the License. +// +// The Original Code is RabbitMQ. +// +// The Initial Developer of the Original Code is GoPivotal, Inc. +// Copyright (c) 2013-2014 GoPivotal, Inc. All rights reserved. +//--------------------------------------------------------------------------- + +namespace System +{ +#if (NETFX_CORE) + internal class SerializableAttribute : Attribute + { + } +#endif +} \ No newline at end of file diff --git a/projects/client/RabbitMQ.Client.WinRT/src/util/SortedList.cs b/projects/client/RabbitMQ.Client.WinRT/src/util/SortedList.cs new file mode 100644 index 0000000000..bd969c4cbf --- /dev/null +++ b/projects/client/RabbitMQ.Client.WinRT/src/util/SortedList.cs @@ -0,0 +1,1304 @@ +// +// System.Collections.Generic.SortedList.cs +// +// Author: +// Sergey Chaban (serge@wildwestsoftware.com) +// Duncan Mak (duncan@ximian.com) +// Herve Poussineau (hpoussineau@fr.st +// Zoltan Varga (vargaz@gmail.com) +// + +// +// Copyright (C) 2004 Novell, Inc (http://www.novell.com) +// +// 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.Collections; +using System.Collections.Generic; +using System.Diagnostics; + +namespace RabbitMQ.Util +{ + /// + /// Represents a collection of associated keys and values + /// that are sorted by the keys and are accessible by key + /// and by index. + /// + [DebuggerDisplay("Count={Count}")] + internal class SortedList : IDictionary, + IDictionary, + ICollection, + ICollection>, + IEnumerable>, + IEnumerable + { + + private readonly static int INITIAL_SIZE = 16; + + private enum EnumeratorMode : int { KEY_MODE = 0, VALUE_MODE, ENTRY_MODE } + + private int inUse; + private int modificationCount; + private KeyValuePair[] table; + private IComparer comparer; + private int defaultCapacity; + + // + // Constructors + // + public SortedList() + : this(INITIAL_SIZE, null) + { + } + + public SortedList(int capacity) + : this(capacity, null) + { + } + + public SortedList(int capacity, IComparer comparer) + { + if (capacity < 0) + throw new ArgumentOutOfRangeException("initialCapacity"); + + if (capacity == 0) + defaultCapacity = 0; + else + defaultCapacity = INITIAL_SIZE; + Init(comparer, capacity, true); + } + + public SortedList(IComparer comparer) + : this(INITIAL_SIZE, comparer) + { + } + + public SortedList(IDictionary dictionary) + : this(dictionary, null) + { + } + + public SortedList(IDictionary dictionary, IComparer comparer) + { + if (dictionary == null) + throw new ArgumentNullException("dictionary"); + + Init(comparer, dictionary.Count, true); + + foreach (KeyValuePair kvp in dictionary) + Add(kvp.Key, kvp.Value); + } + + // + // Properties + // + + // ICollection + + public int Count + { + get + { + return inUse; + } + } + + bool ICollection.IsSynchronized + { + get + { + return false; + } + } + + Object ICollection.SyncRoot + { + get + { + return this; + } + } + + // IDictionary + + bool IDictionary.IsFixedSize + { + get + { + return false; + } + } + + bool IDictionary.IsReadOnly + { + get + { + return false; + } + } + + public TValue this[TKey key] + { + get + { + if (key == null) + throw new ArgumentNullException("key"); + + int i = Find(key); + + if (i >= 0) + return table[i].Value; + else + throw new KeyNotFoundException(); + } + set + { + if (key == null) + throw new ArgumentNullException("key"); + + PutImpl(key, value, true); + } + } + + object IDictionary.this[object key] + { + get + { + if (!(key is TKey)) + return null; + else + return this[(TKey)key]; + } + + set + { + this[ToKey(key)] = ToValue(value); + } + } + + public int Capacity + { + get + { + return table.Length; + } + + set + { + int current = this.table.Length; + + if (inUse > value) + { + throw new ArgumentOutOfRangeException("capacity too small"); + } + else if (value == 0) + { + // return to default size + KeyValuePair[] newTable = new KeyValuePair[defaultCapacity]; + Array.Copy(table, newTable, inUse); + this.table = newTable; + } + else if (value > inUse) + { + KeyValuePair[] newTable = new KeyValuePair[value]; + Array.Copy(table, newTable, inUse); + this.table = newTable; + } + else if (value > current) + { + KeyValuePair[] newTable = new KeyValuePair[value]; + Array.Copy(table, newTable, current); + this.table = newTable; + } + } + } + + public IList Keys + { + get + { + return new ListKeys(this); + } + } + + public IList Values + { + get + { + return new ListValues(this); + } + } + + ICollection IDictionary.Keys + { + get + { + return new ListKeys(this); + } + } + + ICollection IDictionary.Values + { + get + { + return new ListValues(this); + } + } + + ICollection IDictionary.Keys + { + get + { + return Keys; + } + } + + ICollection IDictionary.Values + { + get + { + return Values; + } + } + + public IComparer Comparer + { + get + { + return comparer; + } + } + + bool ICollection>.IsReadOnly + { + get + { + return false; + } + } + + // + // Public instance methods. + // + + public void Add(TKey key, TValue value) + { + if (key == null) + throw new ArgumentNullException("key"); + + PutImpl(key, value, false); + } + + public bool ContainsKey(TKey key) + { + if (key == null) + throw new ArgumentNullException("key"); + + return (Find(key) >= 0); + } + + public IEnumerator> GetEnumerator() + { + for (int i = 0; i < inUse; i++) + { + KeyValuePair current = this.table[i]; + + yield return new KeyValuePair(current.Key, current.Value); + } + } + + public bool Remove(TKey key) + { + if (key == null) + throw new ArgumentNullException("key"); + + int i = IndexOfKey(key); + if (i >= 0) + { + RemoveAt(i); + return true; + } + else + return false; + } + + // ICollection> + + void ICollection>.Clear() + { + defaultCapacity = INITIAL_SIZE; + this.table = new KeyValuePair[defaultCapacity]; + inUse = 0; + modificationCount++; + } + + public void Clear() + { + defaultCapacity = INITIAL_SIZE; + this.table = new KeyValuePair[defaultCapacity]; + inUse = 0; + modificationCount++; + } + + void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) + { + if (Count == 0) + return; + + if (null == array) + throw new ArgumentNullException(); + + if (arrayIndex < 0) + throw new ArgumentOutOfRangeException(); + + if (arrayIndex >= array.Length) + throw new ArgumentNullException("arrayIndex is greater than or equal to array.Length"); + if (Count > (array.Length - arrayIndex)) + throw new ArgumentNullException("Not enough space in array from arrayIndex to end of array"); + + int i = arrayIndex; + foreach (KeyValuePair pair in this) + array[i++] = pair; + } + + void ICollection>.Add(KeyValuePair keyValuePair) + { + Add(keyValuePair.Key, keyValuePair.Value); + } + + bool ICollection>.Contains(KeyValuePair keyValuePair) + { + int i = Find(keyValuePair.Key); + + if (i >= 0) + return Comparer>.Default.Compare(table[i], keyValuePair) == 0; + else + return false; + } + + bool ICollection>.Remove(KeyValuePair keyValuePair) + { + int i = Find(keyValuePair.Key); + + if (i >= 0 && (Comparer>.Default.Compare(table[i], keyValuePair) == 0)) + { + RemoveAt(i); + return true; + } + else + return false; + } + + // IEnumerable> + + IEnumerator> IEnumerable>.GetEnumerator() + { + for (int i = 0; i < inUse; i++) + { + KeyValuePair current = this.table[i]; + + yield return new KeyValuePair(current.Key, current.Value); + } + } + + // IEnumerable + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + // IDictionary + + void IDictionary.Add(object key, object value) + { + PutImpl(ToKey(key), ToValue(value), false); + } + + bool IDictionary.Contains(object key) + { + if (null == key) + throw new ArgumentNullException(); + if (!(key is TKey)) + return false; + + return (Find((TKey)key) >= 0); + } + + IDictionaryEnumerator IDictionary.GetEnumerator() + { + return new Enumerator(this, EnumeratorMode.ENTRY_MODE); + } + + void IDictionary.Remove(object key) + { + if (null == key) + throw new ArgumentNullException("key"); + if (!(key is TKey)) + return; + int i = IndexOfKey((TKey)key); + if (i >= 0) RemoveAt(i); + } + + // ICollection + + void ICollection.CopyTo(Array array, int arrayIndex) + { + if (Count == 0) + return; + + if (null == array) + throw new ArgumentNullException(); + + if (arrayIndex < 0) + throw new ArgumentOutOfRangeException(); + + if (array.Rank > 1) + throw new ArgumentException("array is multi-dimensional"); + if (arrayIndex >= array.Length) + throw new ArgumentNullException("arrayIndex is greater than or equal to array.Length"); + if (Count > (array.Length - arrayIndex)) + throw new ArgumentNullException("Not enough space in array from arrayIndex to end of array"); + + IEnumerator> it = GetEnumerator(); + int i = arrayIndex; + + while (it.MoveNext()) + { + array.SetValue(it.Current, i++); + } + } + + // + // SortedList + // + + public void RemoveAt(int index) + { + KeyValuePair[] table = this.table; + int cnt = Count; + if (index >= 0 && index < cnt) + { + if (index != cnt - 1) + { + Array.Copy(table, index + 1, table, index, cnt - 1 - index); + } + else + { + table[index] = default(KeyValuePair); + } + --inUse; + ++modificationCount; + } + else + { + throw new ArgumentOutOfRangeException("index out of range"); + } + } + + public int IndexOfKey(TKey key) + { + if (key == null) + throw new ArgumentNullException("key"); + + int indx = 0; + try + { + indx = Find(key); + } + catch (Exception) + { + throw new InvalidOperationException(); + } + + return (indx | (indx >> 31)); + } + + public int IndexOfValue(TValue value) + { + if (inUse == 0) + return -1; + + for (int i = 0; i < inUse; i++) + { + KeyValuePair current = this.table[i]; + + if (Equals(value, current.Value)) + return i; + } + + return -1; + } + + public bool ContainsValue(TValue value) + { + return IndexOfValue(value) >= 0; + } + + public void TrimExcess() + { + if (inUse < table.Length * 0.9) + Capacity = inUse; + } + + public bool TryGetValue(TKey key, out TValue value) + { + if (key == null) + throw new ArgumentNullException("key"); + + int i = Find(key); + + if (i >= 0) + { + value = table[i].Value; + return true; + } + else + { + value = default(TValue); + return false; + } + } + + // + // Private methods + // + + private void EnsureCapacity(int n, int free) + { + KeyValuePair[] table = this.table; + KeyValuePair[] newTable = null; + int cap = Capacity; + bool gap = (free >= 0 && free < Count); + + if (n > cap) + { + newTable = new KeyValuePair[n << 1]; + } + + if (newTable != null) + { + if (gap) + { + int copyLen = free; + if (copyLen > 0) + { + Array.Copy(table, 0, newTable, 0, copyLen); + } + copyLen = Count - free; + if (copyLen > 0) + { + Array.Copy(table, free, newTable, free + 1, copyLen); + } + } + else + { + // Just a resizing, copy the entire table. + Array.Copy(table, newTable, Count); + } + this.table = newTable; + } + else if (gap) + { + Array.Copy(table, free, table, free + 1, Count - free); + } + } + + private void PutImpl(TKey key, TValue value, bool overwrite) + { + if (key == null) + throw new ArgumentNullException("null key"); + + KeyValuePair[] table = this.table; + + int freeIndx = -1; + + try + { + freeIndx = Find(key); + } + catch (Exception) + { + throw new InvalidOperationException(); + } + + if (freeIndx >= 0) + { + if (!overwrite) + throw new ArgumentException("element already exists"); + + table[freeIndx] = new KeyValuePair(key, value); + ++modificationCount; + return; + } + + freeIndx = ~freeIndx; + + if (freeIndx > Capacity + 1) + throw new Exception("SortedList::internal error (" + key + ", " + value + ") at [" + freeIndx + "]"); + + + EnsureCapacity(Count + 1, freeIndx); + + table = this.table; + table[freeIndx] = new KeyValuePair(key, value); + + ++inUse; + ++modificationCount; + + } + + private void Init(IComparer comparer, int capacity, bool forceSize) + { + if (comparer == null) + comparer = Comparer.Default; + this.comparer = comparer; + if (!forceSize && (capacity < defaultCapacity)) + capacity = defaultCapacity; + this.table = new KeyValuePair[capacity]; + this.inUse = 0; + this.modificationCount = 0; + } + + private void CopyToArray(Array arr, int i, + EnumeratorMode mode) + { + if (arr == null) + throw new ArgumentNullException("arr"); + + if (i < 0 || i + this.Count > arr.Length) + throw new ArgumentOutOfRangeException("i"); + + IEnumerator it = new Enumerator(this, mode); + + while (it.MoveNext()) + { + arr.SetValue(it.Current, i++); + } + } + + private int Find(TKey key) + { + KeyValuePair[] table = this.table; + int len = Count; + + if (len == 0) return ~0; + + int left = 0; + int right = len - 1; + + while (left <= right) + { + int guess = (left + right) >> 1; + + int cmp = comparer.Compare(table[guess].Key, key); + if (cmp == 0) return guess; + + if (cmp < 0) left = guess + 1; + else right = guess - 1; + } + + return ~left; + } + + private TKey ToKey(object key) + { + if (key == null) + throw new ArgumentNullException("key"); + if (!(key is TKey)) + throw new ArgumentException("The value \"" + key + "\" isn't of type \"" + typeof(TKey) + "\" and can't be used in this generic collection.", "key"); + return (TKey)key; + } + + private TValue ToValue(object value) + { + if (!(value is TValue)) + throw new ArgumentException("The value \"" + value + "\" isn't of type \"" + typeof(TValue) + "\" and can't be used in this generic collection.", "value"); + return (TValue)value; + } + + internal TKey KeyAt(int index) + { + if (index >= 0 && index < Count) + return table[index].Key; + else + throw new ArgumentOutOfRangeException("Index out of range"); + } + + internal TValue ValueAt(int index) + { + if (index >= 0 && index < Count) + return table[index].Value; + else + throw new ArgumentOutOfRangeException("Index out of range"); + } + + // + // Inner classes + // + + + private sealed class Enumerator : ICloneable, IDictionaryEnumerator, IEnumerator + { + + private SortedList host; + private int stamp; + private int pos; + private int size; + private EnumeratorMode mode; + + private object currentKey; + private object currentValue; + + bool invalid = false; + + private readonly static string xstr = "SortedList.Enumerator: snapshot out of sync."; + + public Enumerator(SortedList host, EnumeratorMode mode) + { + this.host = host; + stamp = host.modificationCount; + size = host.Count; + this.mode = mode; + Reset(); + } + + public Enumerator(SortedList host) + : this(host, EnumeratorMode.ENTRY_MODE) + { + } + + public void Reset() + { + if (host.modificationCount != stamp || invalid) + throw new InvalidOperationException(xstr); + + pos = -1; + currentKey = null; + currentValue = null; + } + + public bool MoveNext() + { + if (host.modificationCount != stamp || invalid) + throw new InvalidOperationException(xstr); + + KeyValuePair[] table = host.table; + + if (++pos < size) + { + KeyValuePair entry = table[pos]; + + currentKey = entry.Key; + currentValue = entry.Value; + return true; + } + + currentKey = null; + currentValue = null; + return false; + } + + public DictionaryEntry Entry + { + get + { + if (invalid || pos >= size || pos == -1) + throw new InvalidOperationException(xstr); + + return new DictionaryEntry(currentKey, + currentValue); + } + } + + public Object Key + { + get + { + if (invalid || pos >= size || pos == -1) + throw new InvalidOperationException(xstr); + return currentKey; + } + } + + public Object Value + { + get + { + if (invalid || pos >= size || pos == -1) + throw new InvalidOperationException(xstr); + return currentValue; + } + } + + public Object Current + { + get + { + if (invalid || pos >= size || pos == -1) + throw new InvalidOperationException(xstr); + + switch (mode) + { + case EnumeratorMode.KEY_MODE: + return currentKey; + case EnumeratorMode.VALUE_MODE: + return currentValue; + case EnumeratorMode.ENTRY_MODE: + return this.Entry; + + default: + throw new NotSupportedException(mode + " is not a supported mode."); + } + } + } + + // ICloneable + + public object Clone() + { + Enumerator e = new Enumerator(host, mode); + e.stamp = stamp; + e.pos = pos; + e.size = size; + e.currentKey = currentKey; + e.currentValue = currentValue; + e.invalid = invalid; + return e; + } + } + + [Serializable] + struct KeyEnumerator : IEnumerator, IDisposable + { + const int NOT_STARTED = -2; + + // this MUST be -1, because we depend on it in move next. + // we just decr the size, so, 0 - 1 == FINISHED + const int FINISHED = -1; + + SortedList l; + int idx; + int ver; + + internal KeyEnumerator(SortedList l) + { + this.l = l; + idx = NOT_STARTED; + ver = l.modificationCount; + } + + public void Dispose() + { + idx = NOT_STARTED; + } + + public bool MoveNext() + { + if (ver != l.modificationCount) + throw new InvalidOperationException("Collection was modified after the enumerator was instantiated."); + + if (idx == NOT_STARTED) + idx = l.Count; + + return idx != FINISHED && --idx != FINISHED; + } + + public TKey Current + { + get + { + if (idx < 0) + throw new InvalidOperationException(); + + return l.KeyAt(l.Count - 1 - idx); + } + } + + void IEnumerator.Reset() + { + if (ver != l.modificationCount) + throw new InvalidOperationException("Collection was modified after the enumerator was instantiated."); + + idx = NOT_STARTED; + } + + object IEnumerator.Current + { + get { return Current; } + } + } + + [Serializable] + struct ValueEnumerator : IEnumerator, IDisposable + { + const int NOT_STARTED = -2; + + // this MUST be -1, because we depend on it in move next. + // we just decr the size, so, 0 - 1 == FINISHED + const int FINISHED = -1; + + SortedList l; + int idx; + int ver; + + internal ValueEnumerator(SortedList l) + { + this.l = l; + idx = NOT_STARTED; + ver = l.modificationCount; + } + + public void Dispose() + { + idx = NOT_STARTED; + } + + public bool MoveNext() + { + if (ver != l.modificationCount) + throw new InvalidOperationException("Collection was modified after the enumerator was instantiated."); + + if (idx == NOT_STARTED) + idx = l.Count; + + return idx != FINISHED && --idx != FINISHED; + } + + public TValue Current + { + get + { + if (idx < 0) + throw new InvalidOperationException(); + + return l.ValueAt(l.Count - 1 - idx); + } + } + + void IEnumerator.Reset() + { + if (ver != l.modificationCount) + throw new InvalidOperationException("Collection was modified after the enumerator was instantiated."); + + idx = NOT_STARTED; + } + + object IEnumerator.Current + { + get { return Current; } + } + } + + private class ListKeys : IList, ICollection, IEnumerable + { + + private SortedList host; + + public ListKeys(SortedList host) + { + if (host == null) + throw new ArgumentNullException(); + + this.host = host; + } + + // ICollection + + public virtual void Add(TKey item) + { + throw new NotSupportedException(); + } + + public virtual bool Remove(TKey key) + { + throw new NotSupportedException(); + } + + public virtual void Clear() + { + throw new NotSupportedException(); + } + + public virtual void CopyTo(TKey[] array, int arrayIndex) + { + if (host.Count == 0) + return; + if (array == null) + throw new ArgumentNullException("array"); + if (arrayIndex < 0) + throw new ArgumentOutOfRangeException(); + if (arrayIndex >= array.Length) + throw new ArgumentOutOfRangeException("arrayIndex is greater than or equal to array.Length"); + if (Count > (array.Length - arrayIndex)) + throw new ArgumentOutOfRangeException("Not enough space in array from arrayIndex to end of array"); + + int j = arrayIndex; + for (int i = 0; i < Count; ++i) + array[j++] = host.KeyAt(i); + } + + public virtual bool Contains(TKey item) + { + return host.IndexOfKey(item) > -1; + } + + // + // IList + // + public virtual int IndexOf(TKey item) + { + return host.IndexOfKey(item); + } + + public virtual void Insert(int index, TKey item) + { + throw new NotSupportedException(); + } + + public virtual void RemoveAt(int index) + { + throw new NotSupportedException(); + } + + public virtual TKey this[int index] + { + get + { + return host.KeyAt(index); + } + set + { + throw new NotSupportedException("attempt to modify a key"); + } + } + + // + // IEnumerable + // + + public virtual IEnumerator GetEnumerator() + { + /* We couldn't use yield as it does not support Reset () */ + return new KeyEnumerator(host); + } + + // + // ICollection + // + + public virtual int Count + { + get + { + return host.Count; + } + } + + public virtual bool IsSynchronized + { + get + { + return ((ICollection)host).IsSynchronized; + } + } + + public virtual bool IsReadOnly + { + get + { + return true; + } + } + + public virtual Object SyncRoot + { + get + { + return ((ICollection)host).SyncRoot; + } + } + + public virtual void CopyTo(Array array, int arrayIndex) + { + host.CopyToArray(array, arrayIndex, EnumeratorMode.KEY_MODE); + } + + // + // IEnumerable + // + + IEnumerator IEnumerable.GetEnumerator() + { + for (int i = 0; i < host.Count; ++i) + yield return host.KeyAt(i); + } + } + + private class ListValues : IList, ICollection, IEnumerable + { + + private SortedList host; + + public ListValues(SortedList host) + { + if (host == null) + throw new ArgumentNullException(); + + this.host = host; + } + + // ICollection + + public virtual void Add(TValue item) + { + throw new NotSupportedException(); + } + + public virtual bool Remove(TValue value) + { + throw new NotSupportedException(); + } + + public virtual void Clear() + { + throw new NotSupportedException(); + } + + public virtual void CopyTo(TValue[] array, int arrayIndex) + { + if (host.Count == 0) + return; + if (array == null) + throw new ArgumentNullException("array"); + if (arrayIndex < 0) + throw new ArgumentOutOfRangeException(); + if (arrayIndex >= array.Length) + throw new ArgumentOutOfRangeException("arrayIndex is greater than or equal to array.Length"); + if (Count > (array.Length - arrayIndex)) + throw new ArgumentOutOfRangeException("Not enough space in array from arrayIndex to end of array"); + + int j = arrayIndex; + for (int i = 0; i < Count; ++i) + array[j++] = host.ValueAt(i); + } + + public virtual bool Contains(TValue item) + { + return host.IndexOfValue(item) > -1; + } + + // + // IList + // + public virtual int IndexOf(TValue item) + { + return host.IndexOfValue(item); + } + + public virtual void Insert(int index, TValue item) + { + throw new NotSupportedException(); + } + + public virtual void RemoveAt(int index) + { + throw new NotSupportedException(); + } + + public virtual TValue this[int index] + { + get + { + return host.ValueAt(index); + } + set + { + throw new NotSupportedException("attempt to modify a key"); + } + } + + // + // IEnumerable + // + + public virtual IEnumerator GetEnumerator() + { + /* We couldn't use yield as it does not support Reset () */ + return new ValueEnumerator(host); + } + + // + // ICollection + // + + public virtual int Count + { + get + { + return host.Count; + } + } + + public virtual bool IsSynchronized + { + get + { + return ((ICollection)host).IsSynchronized; + } + } + + public virtual bool IsReadOnly + { + get + { + return true; + } + } + + public virtual Object SyncRoot + { + get + { + return ((ICollection)host).SyncRoot; + } + } + + public virtual void CopyTo(Array array, int arrayIndex) + { + host.CopyToArray(array, arrayIndex, EnumeratorMode.VALUE_MODE); + } + + // + // IEnumerable + // + + IEnumerator IEnumerable.GetEnumerator() + { + for (int i = 0; i < host.Count; ++i) + yield return host.ValueAt(i); + } + } + + } // SortedList +} \ No newline at end of file diff --git a/projects/client/RabbitMQ.Client.WinRT/src/util/Timer.cs b/projects/client/RabbitMQ.Client.WinRT/src/util/Timer.cs new file mode 100644 index 0000000000..0b06e26c15 --- /dev/null +++ b/projects/client/RabbitMQ.Client.WinRT/src/util/Timer.cs @@ -0,0 +1,132 @@ +// This source code is dual-licensed under the Apache License, version +// 2.0, and the Mozilla Public License, version 1.1. +// +// The APL v2.0: +// +//--------------------------------------------------------------------------- +// Copyright (C) 2007-2014 GoPivotal, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//--------------------------------------------------------------------------- +// +// The MPL v1.1: +// +//--------------------------------------------------------------------------- +// The contents of this file are subject to the Mozilla Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License +// at http://www.mozilla.org/MPL/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +// the License for the specific language governing rights and +// limitations under the License. +// +// The Original Code is RabbitMQ. +// +// The Initial Developer of the Original Code is GoPivotal, Inc. +// Copyright (c) 2013-2014 GoPivotal, Inc. All rights reserved. +//--------------------------------------------------------------------------- + +using System; +using Windows.System.Threading; + +namespace System.Threading +{ +#if NETFX_CORE + /// + /// Provides a mechanism for executing a method at specified intervals. Adapts to on Windows 8+ platforms. + /// + internal class Timer : IDisposable + { + private readonly Action callback; + private readonly object state; + + private ThreadPoolTimer threadPoolTimer; + + public Timer(Action callback) + { + this.callback = callback; + this.state = null; + } + + public void Dispose() + { + if (threadPoolTimer != null) + { + threadPoolTimer.Cancel(); + threadPoolTimer = null; + } + } + + /// + /// Changes the start time and the interval between method invocations for a timer, using 32-bit signed integers to measure time intervals. + /// + /// + /// The amount of time to delay before the invoking the callback method specified when the Timer was constructed, in milliseconds. Specify Timeout.Infinite to prevent the timer from restarting. Specify zero (0) to restart the timer immediately. + /// + /// + /// The time interval between invocations of the callback method specified when the Timer was constructed, in milliseconds. Specify Timeout.Infinite to disable periodic signaling. + /// + /// true if the timer was successfully updated; otherwise, false. + public bool Change(int dueTime, int period) + { + if (dueTime < -1) + { + throw new ArgumentOutOfRangeException("dueTime", "NeedNonNegOrNegative1"); + } + + if (period < -1) + { + throw new ArgumentOutOfRangeException("period", "NeedNonNegOrNegative1"); + } + + if (threadPoolTimer != null) + { + threadPoolTimer.Cancel(); + threadPoolTimer = null; + } + + if (dueTime == Timeout.Infinite) + { + // If dueTime is Infinite, the callback method is never invoked; the timer is disabled + return true; + } + else if (dueTime == 0) + { + // If dueTime is zero (0), the callback method is invoked immediately + StartTimers(period); + } + else + { + ThreadPoolTimer.CreateTimer(timer => this.StartTimers(period), TimeSpan.FromMilliseconds(dueTime), timer => timer.Cancel()); + } + + return true; + } + + private void StartTimers(int period) + { + if (period == Timeout.Infinite || period == 0) + { + // If period is zero (0) or Infinite, and dueTime is not Infinite, the callback method is invoked once; + threadPoolTimer = ThreadPoolTimer.CreateTimer(timer => callback(state), TimeSpan.FromMilliseconds(0), timer => timer.Cancel()); + } + else + { + threadPoolTimer = ThreadPoolTimer.CreatePeriodicTimer(timer => callback(state), TimeSpan.FromMilliseconds(period)); + } + } + } +#endif +} \ No newline at end of file diff --git a/projects/client/RabbitMQ.Client/src/client/api/ConnectionFactory.cs b/projects/client/RabbitMQ.Client/src/client/api/ConnectionFactory.cs index c40397e514..d3f852d249 100644 --- a/projects/client/RabbitMQ.Client/src/client/api/ConnectionFactory.cs +++ b/projects/client/RabbitMQ.Client/src/client/api/ConnectionFactory.cs @@ -40,8 +40,12 @@ using System; using System.Collections.Generic; -using System.Net.Security; using System.Threading.Tasks; + +#if !NETFX_CORE +using System.Net.Security; +#endif + using RabbitMQ.Client.Exceptions; using RabbitMQ.Client.Framing.Impl; using RabbitMQ.Client.Impl; @@ -339,7 +343,9 @@ private void SetUri(Uri uri) else if (string.Equals("amqps", uri.Scheme, StringComparison.OrdinalIgnoreCase)) { Ssl.Enabled = true; +#if !(NETFX_CORE) Ssl.AcceptablePolicyErrors = SslPolicyErrors.RemoteCertificateNameMismatch; +#endif Port = AmqpTcpEndpoint.DefaultAmqpSslPort; } else @@ -396,4 +402,4 @@ private string UriDecode(string uri) return System.Uri.UnescapeDataString(uri.Replace("+", "%2B")); } } -} \ No newline at end of file +} diff --git a/projects/client/RabbitMQ.Client/src/client/api/ConnectionFactoryBase.cs b/projects/client/RabbitMQ.Client/src/client/api/ConnectionFactoryBase.cs index fce1ce5a39..032ebec2b3 100644 --- a/projects/client/RabbitMQ.Client/src/client/api/ConnectionFactoryBase.cs +++ b/projects/client/RabbitMQ.Client/src/client/api/ConnectionFactoryBase.cs @@ -39,7 +39,12 @@ //--------------------------------------------------------------------------- using System; + +#if NETFX_CORE +using Windows.Networking.Sockets; +#else using System.Net.Sockets; +#endif namespace RabbitMQ.Client { @@ -48,13 +53,25 @@ public class ConnectionFactoryBase /// /// Set custom socket options by providing a SocketFactory. /// +#if NETFX_CORE + public Func SocketFactory = DefaultSocketFactory; +#else public Func SocketFactory = DefaultSocketFactory; +#endif /// /// Creates a new instance of the . /// /// Specifies the addressing scheme. /// New instance of a . +#if NETFX_CORE + public static StreamSocket DefaultSocketFactory() + { + StreamSocket tcpClient = new StreamSocket(); + tcpClient.Control.NoDelay = true; + return tcpClient; + } +#else public static TcpClient DefaultSocketFactory(AddressFamily addressFamily) { var tcpClient = new TcpClient(addressFamily) @@ -63,5 +80,6 @@ public static TcpClient DefaultSocketFactory(AddressFamily addressFamily) }; return tcpClient; } +#endif } -} \ No newline at end of file +} diff --git a/projects/client/RabbitMQ.Client/src/client/api/IProtocol.cs b/projects/client/RabbitMQ.Client/src/client/api/IProtocol.cs index f3db7230da..3f215361c4 100644 --- a/projects/client/RabbitMQ.Client/src/client/api/IProtocol.cs +++ b/projects/client/RabbitMQ.Client/src/client/api/IProtocol.cs @@ -39,7 +39,13 @@ //--------------------------------------------------------------------------- using System; + +#if !NETFX_CORE using System.Net.Sockets; +#else +using Windows.Networking.Sockets; +#endif + using RabbitMQ.Client.Impl; namespace RabbitMQ.Client @@ -95,8 +101,14 @@ public interface IProtocol /// Socket factory method. /// Timeout in milliseconds. /// Represents a TCP-addressable AMQP peer: a host name and port number. - IFrameHandler CreateFrameHandler(AmqpTcpEndpoint endpoint, Func socketFactory, int timeout); - + IFrameHandler CreateFrameHandler( + AmqpTcpEndpoint endpoint, +#if !NETFX_CORE + Func socketFactory, +#else + Func socketFactory, +#endif + int timeout); /// /// Construct a protocol model atop a given session. /// diff --git a/projects/client/RabbitMQ.Client/src/client/api/NetworkConnection.cs b/projects/client/RabbitMQ.Client/src/client/api/NetworkConnection.cs index 27d34e26bb..5e81e159f7 100644 --- a/projects/client/RabbitMQ.Client/src/client/api/NetworkConnection.cs +++ b/projects/client/RabbitMQ.Client/src/client/api/NetworkConnection.cs @@ -47,24 +47,28 @@ namespace RabbitMQ.Client /// public interface NetworkConnection { +#if !NETFX_CORE /// /// Identifies local network address. /// EndPoint LocalEndPoint { get; } +#endif /// /// Local port. /// int LocalPort { get; } +#if !NETFX_CORE /// /// Identifies remote network address. /// EndPoint RemoteEndPoint { get; } +#endif /// /// Remote port. /// int RemotePort { get; } } -} \ No newline at end of file +} diff --git a/projects/client/RabbitMQ.Client/src/client/api/SslHelper.cs b/projects/client/RabbitMQ.Client/src/client/api/SslHelper.cs index 007baa43c4..521b75b3cd 100644 --- a/projects/client/RabbitMQ.Client/src/client/api/SslHelper.cs +++ b/projects/client/RabbitMQ.Client/src/client/api/SslHelper.cs @@ -38,6 +38,8 @@ // Copyright (c) 2007-2014 GoPivotal, Inc. All rights reserved. //--------------------------------------------------------------------------- +#if !NETFX_CORE + using System; using System.IO; using System.Net.Security; @@ -105,4 +107,6 @@ private bool CertificateValidationCallback(object sender, X509Certificate certif return (sslPolicyErrors & ~_sslOption.AcceptablePolicyErrors) == SslPolicyErrors.None; } } -} \ No newline at end of file +} + +#endif diff --git a/projects/client/RabbitMQ.Client/src/client/api/SslOption.cs b/projects/client/RabbitMQ.Client/src/client/api/SslOption.cs index 843a705553..6eb6dd5e49 100644 --- a/projects/client/RabbitMQ.Client/src/client/api/SslOption.cs +++ b/projects/client/RabbitMQ.Client/src/client/api/SslOption.cs @@ -39,9 +39,14 @@ //--------------------------------------------------------------------------- using System; + +#if !NETFX_CORE using System.Net.Security; using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; +#else +using Windows.Networking.Sockets; +#endif namespace RabbitMQ.Client { @@ -50,20 +55,28 @@ namespace RabbitMQ.Client /// public class SslOption { +#if !NETFX_CORE private X509CertificateCollection _certificateCollection; +#endif /// /// Constructs an SslOption specifying both the server cannonical name and the client's certificate path. /// public SslOption(string serverName, string certificatePath = "", bool enabled = false) { +#if !NETFX_CORE Version = SslProtocols.Tls; AcceptablePolicyErrors = SslPolicyErrors.None; +#endif + ServerName = serverName; CertPath = certificatePath; Enabled = enabled; + +#if !NETFX_CORE CertificateValidationCallback = null; CertificateSelectionCallback = null; +#endif } /// @@ -74,10 +87,12 @@ public SslOption() { } +#if !NETFX_CORE /// /// Retrieve or set the set of ssl policy errors that are deemed acceptable. /// public SslPolicyErrors AcceptablePolicyErrors { get; set; } +#endif /// /// Retrieve or set the path to client certificate. @@ -89,6 +104,7 @@ public SslOption() /// public string CertPath { get; set; } +#if !NETFX_CORE /// /// An optional client specified SSL certificate selection callback. If this is not specified, /// the first valid certificate found will be used. @@ -126,6 +142,7 @@ public X509CertificateCollection Certs } set { _certificateCollection = value; } } +#endif /// /// Flag specifying if Ssl should indeed be used. @@ -138,9 +155,11 @@ public X509CertificateCollection Certs /// public string ServerName { get; set; } +#if !NETFX_CORE /// /// Retrieve or set the Ssl protocol version. /// public SslProtocols Version { get; set; } +#endif } -} \ No newline at end of file +} diff --git a/projects/client/RabbitMQ.Client/src/client/content/BytesWireFormatting.cs b/projects/client/RabbitMQ.Client/src/client/content/BytesWireFormatting.cs index b8f565256b..fa1e9fba55 100644 --- a/projects/client/RabbitMQ.Client/src/client/content/BytesWireFormatting.cs +++ b/projects/client/RabbitMQ.Client/src/client/content/BytesWireFormatting.cs @@ -98,7 +98,7 @@ public static string ReadString(NetworkBinaryReader reader) { ushort length = reader.ReadUInt16(); byte[] bytes = reader.ReadBytes(length); - return Encoding.UTF8.GetString(bytes); + return Encoding.UTF8.GetString(bytes, 0, bytes.Length); } public static void Write(NetworkBinaryWriter writer, byte[] source, int offset, int count) diff --git a/projects/client/RabbitMQ.Client/src/client/content/StreamWireFormatting.cs b/projects/client/RabbitMQ.Client/src/client/content/StreamWireFormatting.cs index d5e0b65b1c..4252230a76 100644 --- a/projects/client/RabbitMQ.Client/src/client/content/StreamWireFormatting.cs +++ b/projects/client/RabbitMQ.Client/src/client/content/StreamWireFormatting.cs @@ -299,7 +299,8 @@ public static string ReadUntypedString(NetworkBinaryReader reader) byte b = reader.ReadByte(); if (b == 0) { - return Encoding.UTF8.GetString(NetworkBinaryWriter.TemporaryContents(buffer)); + byte[] temporaryContents = NetworkBinaryWriter.TemporaryContents(buffer); + return Encoding.UTF8.GetString(temporaryContents, 0, temporaryContents.Length); } buffer.Write(b); } @@ -435,4 +436,4 @@ public static void WriteUntypedString(NetworkBinaryWriter writer, string value) writer.Write((byte) 0); } } -} \ No newline at end of file +} diff --git a/projects/client/RabbitMQ.Client/src/client/exceptions/ConnectFailureException.cs b/projects/client/RabbitMQ.Client/src/client/exceptions/ConnectFailureException.cs index 2886eb057e..ddc2363dd9 100644 --- a/projects/client/RabbitMQ.Client/src/client/exceptions/ConnectFailureException.cs +++ b/projects/client/RabbitMQ.Client/src/client/exceptions/ConnectFailureException.cs @@ -43,7 +43,7 @@ namespace RabbitMQ.Client.Exceptions { /// Thrown when a connection to the broker fails - public class ConnectFailureException : SystemException + public class ConnectFailureException : Exception { public ConnectFailureException(String msg, Exception inner) : base(msg, inner) diff --git a/projects/client/RabbitMQ.Client/src/client/exceptions/OperationInterruptedException.cs b/projects/client/RabbitMQ.Client/src/client/exceptions/OperationInterruptedException.cs index f29f3d10ee..4635881c44 100644 --- a/projects/client/RabbitMQ.Client/src/client/exceptions/OperationInterruptedException.cs +++ b/projects/client/RabbitMQ.Client/src/client/exceptions/OperationInterruptedException.cs @@ -88,10 +88,12 @@ protected OperationInterruptedException(string message, Exception inner) { } +#if !(NETFX_CORE) protected OperationInterruptedException(SerializationInfo info, StreamingContext context) : base(info, context) { } +#endif ///Retrieves the explanation for the shutdown. May ///return null if no explanation is available. diff --git a/projects/client/RabbitMQ.Client/src/client/impl/AutorecoveringConnection.cs b/projects/client/RabbitMQ.Client/src/client/impl/AutorecoveringConnection.cs index f3a45b557b..ae3bbeb316 100644 --- a/projects/client/RabbitMQ.Client/src/client/impl/AutorecoveringConnection.cs +++ b/projects/client/RabbitMQ.Client/src/client/impl/AutorecoveringConnection.cs @@ -47,7 +47,6 @@ using System.Net; using System.Threading; using System.Threading.Tasks; -using Timer = System.Timers.Timer; namespace RabbitMQ.Client.Framing.Impl { @@ -277,10 +276,12 @@ public AmqpTcpEndpoint[] KnownHosts set { m_delegate.KnownHosts = value; } } +#if !NETFX_CORE public EndPoint LocalEndPoint { get { return m_delegate.LocalEndPoint; } } +#endif public int LocalPort { @@ -302,10 +303,12 @@ public IDictionary RecordedQueues get { return m_recordedQueues; } } +#if !NETFX_CORE public EndPoint RemoteEndPoint { get { return m_delegate.RemoteEndPoint; } } +#endif public int RemotePort { @@ -340,7 +343,11 @@ public void BeginAutomaticRecovery() { try { +#if NETFX_CORE + System.Threading.Tasks.Task.Delay(m_factory.NetworkRecoveryInterval).Wait(); +#else Thread.Sleep(m_factory.NetworkRecoveryInterval); +#endif self.PerformAutomaticRecovery(); } finally @@ -558,7 +565,12 @@ public void init() catch (Exception e) { // TODO: logging - Console.WriteLine("BeginAutomaticRecovery() failed: {0}", e); +#if NETFX_CORE + System.Diagnostics.Debug.WriteLine( +#else + Console.WriteLine( +#endif + "BeginAutomaticRecovery() failed: {0}", e); } } } @@ -668,7 +680,12 @@ protected void EnsureIsOpen() protected void HandleTopologyRecoveryException(TopologyRecoveryException e) { // TODO - Console.WriteLine("Topology recovery exception: {0}", e); +#if NETFX_CORE + System.Diagnostics.Debug.WriteLine( +#else + Console.WriteLine( +#endif + "Topology recovery exception: {0}", e); } protected void PropagateQueueNameChangeToBindings(string oldName, string newName) @@ -739,7 +756,11 @@ protected void RecoverConnectionDelegate() catch (Exception) { // TODO: exponential back-off +#if NETFX_CORE + System.Threading.Tasks.Task.Delay(m_factory.NetworkRecoveryInterval).Wait(); +#else Thread.Sleep(m_factory.NetworkRecoveryInterval); +#endif // TODO: provide a way to handle these exceptions } } @@ -937,4 +958,4 @@ protected bool ShouldTriggerConnectionRecovery(ShutdownEventArgs args) args.Initiator == ShutdownInitiator.Library); } } -} \ No newline at end of file +} diff --git a/projects/client/RabbitMQ.Client/src/client/impl/CommandAssembler.cs b/projects/client/RabbitMQ.Client/src/client/impl/CommandAssembler.cs index 95534b2927..6a3c74fb47 100644 --- a/projects/client/RabbitMQ.Client/src/client/impl/CommandAssembler.cs +++ b/projects/client/RabbitMQ.Client/src/client/impl/CommandAssembler.cs @@ -117,7 +117,11 @@ public Command HandleFrame(Frame f) } case AssemblyState.Complete: default: +#if NETFX_CORE + Debug.WriteLine("Received frame in invalid state {0}; {1}", m_state, f); +#else Trace.Fail(string.Format("Received frame in invalid state {0}; {1}", m_state, f)); +#endif return null; } } diff --git a/projects/client/RabbitMQ.Client/src/client/impl/Connection.cs b/projects/client/RabbitMQ.Client/src/client/impl/Connection.cs index 72e28a8812..356d684077 100644 --- a/projects/client/RabbitMQ.Client/src/client/impl/Connection.cs +++ b/projects/client/RabbitMQ.Client/src/client/impl/Connection.cs @@ -45,8 +45,16 @@ using System; using System.Collections.Generic; using System.IO; + +#if NETFX_CORE +using System.Threading.Tasks; +using Windows.Networking.Sockets; +using Windows.ApplicationModel; +#else using System.Net; using System.Net.Sockets; +#endif + using System.Reflection; using System.Text; using System.Threading; @@ -111,7 +119,21 @@ public Connection(IConnectionFactory factory, bool insist, IFrameHandler frameHa StartMainLoop(factory.UseBackgroundThreadsForIO); Open(insist); StartHeartbeatTimers(); + +#if NETFX_CORE +#pragma warning disable 0168 + try + { + Windows.UI.Xaml.Application.Current.Suspending += this.HandleApplicationSuspend; + } + catch(Exception ex) + { + // If called from a desktop app (i.e. unit tests), then there is no current application + } +#pragma warning restore 0168 +#else AppDomain.CurrentDomain.DomainUnload += HandleDomainUnload; +#endif } public event EventHandler CallbackException @@ -244,10 +266,12 @@ public bool IsOpen public AmqpTcpEndpoint[] KnownHosts { get; set; } +#if !NETFX_CORE public EndPoint LocalEndPoint { get { return m_frameHandler.LocalEndPoint; } } +#endif public int LocalPort { @@ -261,10 +285,12 @@ public ProtocolBase Protocol get { return (ProtocolBase)Endpoint.Protocol; } } +#if !NETFX_CORE public EndPoint RemoteEndPoint { get { return m_frameHandler.RemoteEndPoint; } } +#endif public int RemotePort { @@ -287,7 +313,12 @@ IProtocol IConnection.Protocol public static IDictionary DefaultClientProperties() { Assembly assembly = - Assembly.GetAssembly(typeof(Connection)); +#if NETFX_CORE + System.Reflection.IntrospectionExtensions.GetTypeInfo(typeof(Connection)).Assembly; +#else + System.Reflection.Assembly.GetAssembly(typeof(Connection)); +#endif + string version = assembly.GetName().Version.ToString(); //TODO: Get the rest of this data from the Assembly Attributes IDictionary table = new Dictionary(); @@ -382,7 +413,14 @@ public void Close(ShutdownEventArgs reason, bool abort, int timeout) TerminateMainloop(); } } - if (!m_appContinuation.WaitOne(BlockingCell.validatedTimeout(timeout), true)) + +#if NETFX_CORE + var receivedSignal = m_appContinuation.WaitOne(BlockingCell.validatedTimeout(timeout)); +#else + var receivedSignal = m_appContinuation.WaitOne(BlockingCell.validatedTimeout(timeout), true); +#endif + + if (!receivedSignal) { m_frameHandler.Close(); } @@ -471,6 +509,15 @@ public void FinishClose() m_model0.FinishClose(); } +#if NETFX_CORE + /// + /// We need to close the socket, otherwise suspending the application will take the maximum time allowed + /// + public void HandleApplicationSuspend(object sender, SuspendingEventArgs suspendingEventArgs) + { + Abort(Constants.InternalError, "Application Suspend"); + } +#else /// /// We need to close the socket, otherwise attempting to unload the domain /// could cause a CannotUnloadAppDomainException @@ -479,6 +526,7 @@ public void HandleDomainUnload(object sender, EventArgs ea) { Abort(Constants.InternalError, "Domain Unload"); } +#endif public void HandleMainLoopException(ShutdownEventArgs reason) { @@ -525,7 +573,7 @@ public void HeartbeatReadTimerCallback(object state) bool shouldTerminate = false; if (!m_closed) { - if (!m_heartbeatRead.WaitOne(0, false)) + if (!m_heartbeatRead.WaitOne(0)) { m_missedHeartbeats++; } @@ -568,7 +616,7 @@ public void HeartbeatWriteTimerCallback(object state) { if (!m_closed) { - if (!m_heartbeatWrite.WaitOne(0, false)) + if (!m_heartbeatWrite.WaitOne(0)) { WriteFrame(m_heartbeatFrame); } @@ -649,6 +697,7 @@ public void MainLoop() { shutdownCleanly = HardProtocolExceptionHandler(hpe); } +#if !NETFX_CORE catch (SocketException se) { // Possibly due to handshake timeout @@ -657,6 +706,7 @@ public void MainLoop() "Socket exception", se)); } +#endif catch (Exception ex) { HandleMainLoopException(new ShutdownEventArgs(ShutdownInitiator.Library, @@ -669,17 +719,33 @@ public void MainLoop() // connection closes. if (shutdownCleanly) { +#pragma warning disable 0168 try { ClosingLoop(); -#pragma warning disable 0168 + } +#if NETFX_CORE + catch (Exception ex) + { + if (SocketError.GetStatus(ex.HResult) != SocketErrorStatus.Unknown) + { + // means that socket was closed when frame handler + // attempted to use it. Since we are shutting down, + // ignore it. + } + else + { + throw; + } } +#else catch (SocketException se) { // means that socket was closed when frame handler // attempted to use it. Since we are shutting down, // ignore it. } +#endif #pragma warning restore 0168 } @@ -869,7 +935,20 @@ public void OnShutdown() } } } +#if NETFX_CORE +#pragma warning disable 0168 + try + { + Windows.UI.Xaml.Application.Current.Suspending -= this.HandleApplicationSuspend; + } + catch (Exception ex) + { + // If called from a desktop app (i.e. unit tests), then there is no current application + } +#pragma warning restore 0168 +#else AppDomain.CurrentDomain.DomainUnload -= HandleDomainUnload; +#endif } public void Open(bool insist) @@ -882,14 +961,29 @@ public void PrettyPrintShutdownReport() { if (ShutdownReport.Count == 0) { - Console.Error.WriteLine("No errors reported when closing connection {0}", this); +#if NETFX_CORE + System.Diagnostics.Debug.WriteLine( +#else + Console.Error.WriteLine( +#endif + "No errors reported when closing connection {0}", this); } else { - Console.Error.WriteLine("Log of errors while closing connection {0}:", this); +#if NETFX_CORE + System.Diagnostics.Debug.WriteLine( +#else + Console.Error.WriteLine( +#endif + "Log of errors while closing connection {0}:", this); foreach (ShutdownReportEntry entry in ShutdownReport) { - Console.Error.WriteLine(entry.ToString()); +#if NETFX_CORE + System.Diagnostics.Debug.WriteLine( +#else + Console.Error.WriteLine( +#endif + entry.ToString()); } } } @@ -982,10 +1076,16 @@ public void StartHeartbeatTimers() public void StartMainLoop(bool useBackgroundThread) { + var taskName = "AMQP Connection " + Endpoint; + +#if NETFX_CORE + Task.Factory.StartNew(this.MainLoop, TaskCreationOptions.LongRunning); +#else var mainLoopThread = new Thread(MainLoop); - mainLoopThread.Name = "AMQP Connection " + Endpoint; + mainLoopThread.Name = taskName; mainLoopThread.IsBackground = useBackgroundThread; mainLoopThread.Start(); +#endif } protected void StopHeartbeatTimers() @@ -1148,7 +1248,7 @@ protected void StartAndTune() bool tuned = false; try { - string mechanismsString = Encoding.UTF8.GetString(connectionStart.m_mechanisms); + string mechanismsString = Encoding.UTF8.GetString(connectionStart.m_mechanisms, 0, connectionStart.m_mechanisms.Length); string[] mechanisms = mechanismsString.Split(' '); AuthMechanismFactory mechanismFactory = m_factory.AuthMechanismFactory(mechanisms); if (mechanismFactory == null) @@ -1220,4 +1320,4 @@ private static uint NegotiatedMaxValue(uint clientValue, uint serverValue) Math.Min(clientValue, serverValue); } } -} \ No newline at end of file +} diff --git a/projects/client/RabbitMQ.Client/src/client/impl/ConsumerWorkService.cs b/projects/client/RabbitMQ.Client/src/client/impl/ConsumerWorkService.cs index a744564a07..5706bad138 100755 --- a/projects/client/RabbitMQ.Client/src/client/impl/ConsumerWorkService.cs +++ b/projects/client/RabbitMQ.Client/src/client/impl/ConsumerWorkService.cs @@ -54,7 +54,12 @@ public void ExecuteThunk() } catch (Exception e) { +#if NETFX_CORE + // To end a task, return + return; +#else Thread.CurrentThread.Interrupt(); +#endif } } diff --git a/projects/client/RabbitMQ.Client/src/client/impl/Frame.cs b/projects/client/RabbitMQ.Client/src/client/impl/Frame.cs index b9f45cd675..2f574fe112 100644 --- a/projects/client/RabbitMQ.Client/src/client/impl/Frame.cs +++ b/projects/client/RabbitMQ.Client/src/client/impl/Frame.cs @@ -40,7 +40,12 @@ using System; using System.IO; + +#if NETFX_CORE +using Windows.Networking.Sockets; +#else using System.Net.Sockets; +#endif using RabbitMQ.Client.Exceptions; using RabbitMQ.Util; using RabbitMQ.Client.Framing; @@ -121,6 +126,15 @@ public static Frame ReadFrom(NetworkBinaryReader reader) } catch (IOException ioe) { +#if NETFX_CORE + if (ioe.InnerException != null + && SocketError.GetStatus(ioe.InnerException.HResult) == SocketErrorStatus.ConnectionTimedOut) + { + throw ioe.InnerException; + } + + throw; +#else // If it's a WSAETIMEDOUT SocketException, unwrap it. // This might happen when the limit of half-open connections is // reached. @@ -131,6 +145,8 @@ public static Frame ReadFrom(NetworkBinaryReader reader) throw ioe; } throw ioe.InnerException; + +#endif } if (type == 'A') diff --git a/projects/client/RabbitMQ.Client/src/client/impl/IFrameHandler.cs b/projects/client/RabbitMQ.Client/src/client/impl/IFrameHandler.cs index 8a46728c8a..529e1efbb3 100644 --- a/projects/client/RabbitMQ.Client/src/client/impl/IFrameHandler.cs +++ b/projects/client/RabbitMQ.Client/src/client/impl/IFrameHandler.cs @@ -47,11 +47,15 @@ public interface IFrameHandler { AmqpTcpEndpoint Endpoint { get; } +#if !NETFX_CORE EndPoint LocalEndPoint { get; } +#endif int LocalPort { get; } +#if !NETFX_CORE EndPoint RemoteEndPoint { get; } +#endif int RemotePort { get; } diff --git a/projects/client/RabbitMQ.Client/src/client/impl/ModelBase.cs b/projects/client/RabbitMQ.Client/src/client/impl/ModelBase.cs index ce174e811d..ce2189506e 100644 --- a/projects/client/RabbitMQ.Client/src/client/impl/ModelBase.cs +++ b/projects/client/RabbitMQ.Client/src/client/impl/ModelBase.cs @@ -49,6 +49,10 @@ using System.IO; using System.Threading; +#if (NETFX_CORE) +using Trace = System.Diagnostics.Debug; +#endif + namespace RabbitMQ.Client.Impl { public abstract class ModelBase : IFullModel, IRecoverable diff --git a/projects/client/RabbitMQ.Client/src/client/impl/ProtocolBase.cs b/projects/client/RabbitMQ.Client/src/client/impl/ProtocolBase.cs index a8d82e5883..3949e4e1f5 100644 --- a/projects/client/RabbitMQ.Client/src/client/impl/ProtocolBase.cs +++ b/projects/client/RabbitMQ.Client/src/client/impl/ProtocolBase.cs @@ -40,7 +40,13 @@ using System; using System.Collections.Generic; + +#if !NETFX_CORE using System.Net.Sockets; +#else +using Windows.Networking.Sockets; +#endif + using RabbitMQ.Client.Impl; using RabbitMQ.Client; using RabbitMQ.Util; @@ -138,8 +144,13 @@ public IConnection CreateConnection(ConnectionFactory factory, return ac; } - public IFrameHandler CreateFrameHandler(AmqpTcpEndpoint endpoint, - Func socketFactory, + public IFrameHandler CreateFrameHandler( + AmqpTcpEndpoint endpoint, +#if !NETFX_CORE + Func socketFactory, +#else + Func socketFactory, +#endif int timeout) { return new SocketFrameHandler(endpoint, socketFactory, timeout); diff --git a/projects/client/RabbitMQ.Client/src/client/impl/SessionManager.cs b/projects/client/RabbitMQ.Client/src/client/impl/SessionManager.cs index 64846fb062..8be9bf657e 100644 --- a/projects/client/RabbitMQ.Client/src/client/impl/SessionManager.cs +++ b/projects/client/RabbitMQ.Client/src/client/impl/SessionManager.cs @@ -41,6 +41,11 @@ using System; using System.Collections.Generic; using System.Threading; + +#if NETFX_CORE +using System.Threading.Tasks; +#endif + using RabbitMQ.Client.Exceptions; using RabbitMQ.Client.Framing.Impl; using RabbitMQ.Util; @@ -111,7 +116,11 @@ public void CheckAutoClose() // deadlock as the connection thread would be // blocking waiting for its own mainloop to // reply to it. +#if NETFX_CORE + Task.Factory.StartNew(AutoCloseConnection, TaskCreationOptions.LongRunning); +#else new Thread(AutoCloseConnection).Start(); +#endif } } } diff --git a/projects/client/RabbitMQ.Client/src/client/impl/SimpleBlockingRpcContinuation.cs b/projects/client/RabbitMQ.Client/src/client/impl/SimpleBlockingRpcContinuation.cs index d3b4c28bb4..ea62cd84f5 100644 --- a/projects/client/RabbitMQ.Client/src/client/impl/SimpleBlockingRpcContinuation.cs +++ b/projects/client/RabbitMQ.Client/src/client/impl/SimpleBlockingRpcContinuation.cs @@ -59,7 +59,12 @@ public virtual Command GetReply() case EitherAlternative.Right: throw new OperationInterruptedException((ShutdownEventArgs)result.Value); default: - Trace.Fail("Illegal EitherAlternative " + result.Alternative); + string error = "Illegal EitherAlternative " + result.Alternative; +#if !(NETFX_CORE) + Trace.Fail(error); +#else + MetroEventSource.Log.Error(error); +#endif return null; } } diff --git a/projects/client/RabbitMQ.Client/src/client/impl/WireFormatting.cs b/projects/client/RabbitMQ.Client/src/client/impl/WireFormatting.cs index 5e4f508b5e..1f48e5c864 100644 --- a/projects/client/RabbitMQ.Client/src/client/impl/WireFormatting.cs +++ b/projects/client/RabbitMQ.Client/src/client/impl/WireFormatting.cs @@ -199,7 +199,8 @@ public static ushort ReadShort(NetworkBinaryReader reader) public static string ReadShortstr(NetworkBinaryReader reader) { int byteCount = reader.ReadByte(); - return Encoding.UTF8.GetString(reader.ReadBytes(byteCount)); + byte[] readBytes = reader.ReadBytes(byteCount); + return Encoding.UTF8.GetString(readBytes, 0, readBytes.Length); } ///Reads an AMQP "table" definition from the reader. diff --git a/projects/client/RabbitMQ.Client/src/client/messagepatterns/Subscription.cs b/projects/client/RabbitMQ.Client/src/client/messagepatterns/Subscription.cs index 68f5b49390..11172ca414 100644 --- a/projects/client/RabbitMQ.Client/src/client/messagepatterns/Subscription.cs +++ b/projects/client/RabbitMQ.Client/src/client/messagepatterns/Subscription.cs @@ -41,6 +41,11 @@ using System; using System.Collections; using System.IO; + +#if NETFX_CORE || NET4 // For Windows 8 Store, but could be .NET 4.0 and greater +using System.Threading.Tasks; +#endif + using RabbitMQ.Client.Events; using RabbitMQ.Client.Exceptions; @@ -315,6 +320,35 @@ public BasicDeliverEventArgs Next() return LatestEvent; } +#if NETFX_CORE || NET4 + public async Task NextAsync() { + try { + // Alias the pointer as otherwise it may change out + // from under us by the operation of Close() from + // another thread. + QueueingBasicConsumer consumer = m_consumer; + if (consumer == null) { + // Closed! + MutateLatestEvent(null); + } + else { + MutateLatestEvent(await consumer.Queue.DequeueAsync()); + } + } + catch (AggregateException ex) { + // since tasks wrap exceptions as AggregateException, + // reach in and check if the EndOfStream exception is what happened + if (ex.InnerException is EndOfStreamException) { + MutateLatestEvent(null); + } + } + catch (EndOfStreamException) { + MutateLatestEvent(null); + } + return LatestEvent; + } +#endif + ///Retrieves the next incoming delivery in our ///subscription queue, or times out after a specified number ///of milliseconds. diff --git a/projects/client/RabbitMQ.Client/src/util/BatchingWorkPool.cs b/projects/client/RabbitMQ.Client/src/util/BatchingWorkPool.cs index 6c7c18cad3..2a86c07dd3 100755 --- a/projects/client/RabbitMQ.Client/src/util/BatchingWorkPool.cs +++ b/projects/client/RabbitMQ.Client/src/util/BatchingWorkPool.cs @@ -69,6 +69,10 @@ public bool AddWorkItem(K key, V item) return false; } } + +#if NETFX_CORE + q.Add(item); +#else try { q.Add(item); @@ -77,6 +81,8 @@ public bool AddWorkItem(K key, V item) { // most likely due to shutdown. ok. } +#endif + lock (lockObject) { if (IsDormant(key)) diff --git a/projects/client/RabbitMQ.Client/src/util/DebugUtil.cs b/projects/client/RabbitMQ.Client/src/util/DebugUtil.cs index 36aed287a0..6e393f6bec 100644 --- a/projects/client/RabbitMQ.Client/src/util/DebugUtil.cs +++ b/projects/client/RabbitMQ.Client/src/util/DebugUtil.cs @@ -49,18 +49,15 @@ namespace RabbitMQ.Util /// ///Not part of the public API. /// - public class DebugUtil + public static class DebugUtil { - ///Private constructor - this class has no instances - private DebugUtil() - { - } - +#if !(NETFX_CORE) ///Print a hex dump of the supplied bytes to stdout. public static void Dump(byte[] bytes) { Dump(bytes, Console.Out); } +#endif ///Print a hex dump of the supplied bytes to the supplied TextWriter. public static void Dump(byte[] bytes, TextWriter writer) @@ -124,7 +121,7 @@ public static void DumpProperties(object value, TextWriter writer, int indent) else if (value is byte[]) { writer.WriteLine("byte[]"); - Dump((byte[])value); + Dump((byte[])value, writer); } else if (value is ValueType) { @@ -153,9 +150,13 @@ public static void DumpProperties(object value, TextWriter writer, int indent) { Type t = value.GetType(); writer.WriteLine(t.FullName); +#if !(NETFX_CORE) foreach (PropertyInfo pi in t.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)) +#else + foreach (PropertyInfo pi in t.GetRuntimeProperties()) +#endif { if (pi.GetIndexParameters().Length == 0) { diff --git a/projects/client/RabbitMQ.Client/src/util/SharedQueue.cs b/projects/client/RabbitMQ.Client/src/util/SharedQueue.cs index 32859a2a5c..762bce66f8 100644 --- a/projects/client/RabbitMQ.Client/src/util/SharedQueue.cs +++ b/projects/client/RabbitMQ.Client/src/util/SharedQueue.cs @@ -44,6 +44,10 @@ using System.IO; using System.Threading; +#if NETFX_CORE || NET4 // For Windows 8 Store, but could be .NET 4.0 and greater +using System.Threading.Tasks; +#endif + namespace RabbitMQ.Util { ///A thread-safe shared queue implementation. @@ -66,6 +70,10 @@ public class SharedQueue : IEnumerable /// protected Queue m_queue = new Queue(); +#if NETFX_CORE || NET4 + protected Queue> m_waiting = new Queue>(); +#endif + ///Close the queue. Causes all further Enqueue() ///operations to throw EndOfStreamException, and all pending ///or subsequent Dequeue() operations to throw an @@ -76,6 +84,23 @@ public void Close() { m_isOpen = false; Monitor.PulseAll(m_queue); +#if NETFX_CORE + // let all waiting tasks know we just closed by passing them an exception + if (m_waiting.Count > 0) + { + try + { + this.EnsureIsOpen(); + } + catch (Exception ex) + { + foreach (var tcs in m_waiting) + { + tcs.TrySetException(ex); + } + } + } +#endif } } @@ -99,6 +124,29 @@ public T Dequeue() } } +#if NETFX_CORE || NET4 + /// + /// Asynchronously retrieves the first item from the queue. + /// + public Task DequeueAsync() + { + lock (m_queue) + { + EnsureIsOpen(); + if (m_queue.Count > 0) + { + return Task.FromResult(this.Dequeue()); + } + else + { + var tcs = new TaskCompletionSource(); + m_waiting.Enqueue(tcs); + return tcs.Task; + } + } + } +#endif + ///Retrieve the first item from the queue, or return ///nothing if no items are available after the given ///timeout @@ -214,6 +262,20 @@ public void Enqueue(T o) lock (m_queue) { EnsureIsOpen(); + +#if NETFX_CORE + while (m_waiting.Count > 0) + { + var tcs = m_waiting.Dequeue(); + if (tcs != null && tcs.TrySetResult(o)) + { + // We successfully set a task return result, so + // no need to Enqueue or Monitor.Pulse + return; + } + } +#endif + m_queue.Enqueue(o); Monitor.Pulse(m_queue); } diff --git a/projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj b/projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj new file mode 100644 index 0000000000..3b3bb74619 --- /dev/null +++ b/projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj @@ -0,0 +1,104 @@ + + + + + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {897505A9-8373-4F41-8DE8-221BF06D877D} + Library + properties + RabbitMQ.Client.Test + unit-tests + v4.5 + 512 + + 8.0 + + + true + full + false + build\bin\ + TRACE;DEBUG;NETFX_CORE + prompt + 4 + false + + + pdbonly + true + build\bin\ + TRACE;NETFX_CORE + prompt + 4 + false + + + + + false + + + true + $(SSL_CERTS_DIR) + + + + + + + + temp=/tmp + + + + + + + + + + + + + + + + + + + False + ..\..\..\lib\nunit\nunit.framework.dll + + + + + + + + + + + + + {61D29F90-5B1C-4748-89FC-9FD2937F09C6} + RabbitMQ.Client + + + + + + + + <_DisabledWarnings>$(NoWarn) + + + + + + diff --git a/projects/client/Unit.WinRT/properties/AssemblyInfo.cs b/projects/client/Unit.WinRT/properties/AssemblyInfo.cs new file mode 100644 index 0000000000..91824f26cc --- /dev/null +++ b/projects/client/Unit.WinRT/properties/AssemblyInfo.cs @@ -0,0 +1,63 @@ +// This source code is dual-licensed under the Apache License, version +// 2.0, and the Mozilla Public License, version 1.1. +// +// The APL v2.0: +// +//--------------------------------------------------------------------------- +// Copyright (C) 2007-2014 GoPivotal, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//--------------------------------------------------------------------------- +// +// The MPL v1.1: +// +//--------------------------------------------------------------------------- +// The contents of this file are subject to the Mozilla Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License +// at http://www.mozilla.org/MPL/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +// the License for the specific language governing rights and +// limitations under the License. +// +// The Original Code is RabbitMQ. +// +// The Initial Developer of the Original Code is GoPivotal, Inc. +// Copyright (c) 2007-2014 GoPivotal, Inc. All rights reserved. +//--------------------------------------------------------------------------- + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("RabbitMQ.Client.WinRT Unit Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("GoPivotal, Inc.")] +[assembly: AssemblyProduct("RabbitMQ.Client.WinRT")] +[assembly: AssemblyCopyright("Copyright © 2007-2014 GoPivotal, Inc.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("42d39d91-847a-44fa-9875-a508ae59bda6")] diff --git a/projects/client/Unit/src/unit/TestContentHeaderCodec.cs b/projects/client/Unit/src/unit/TestContentHeaderCodec.cs index 0e3f18d874..77b477e359 100644 --- a/projects/client/Unit/src/unit/TestContentHeaderCodec.cs +++ b/projects/client/Unit/src/unit/TestContentHeaderCodec.cs @@ -80,9 +80,9 @@ public void Check(ContentHeaderPropertyWriter w, byte[] expected) { Console.WriteLine(); Console.WriteLine("EXPECTED =================================================="); - DebugUtil.Dump(expected); + DebugUtil.Dump(expected, Console.Out); Console.WriteLine("ACTUAL ===================================================="); - DebugUtil.Dump(actual); + DebugUtil.Dump(actual, Console.Out); Console.WriteLine("==========================================================="); throw; } diff --git a/projects/client/Unit/src/unit/TestMethodArgumentCodec.cs b/projects/client/Unit/src/unit/TestMethodArgumentCodec.cs index d359dbd4d0..2f1b7cf24d 100644 --- a/projects/client/Unit/src/unit/TestMethodArgumentCodec.cs +++ b/projects/client/Unit/src/unit/TestMethodArgumentCodec.cs @@ -80,9 +80,9 @@ public void Check(MethodArgumentWriter w, byte[] expected) { Console.WriteLine(); Console.WriteLine("EXPECTED =================================================="); - DebugUtil.Dump(expected); + DebugUtil.Dump(expected, Console.Out); Console.WriteLine("ACTUAL ===================================================="); - DebugUtil.Dump(actual); + DebugUtil.Dump(actual, Console.Out); Console.WriteLine("==========================================================="); throw; } diff --git a/projects/client/Unit/src/unit/TestSsl.cs b/projects/client/Unit/src/unit/TestSsl.cs index 0f65f26afe..4cb398217e 100644 --- a/projects/client/Unit/src/unit/TestSsl.cs +++ b/projects/client/Unit/src/unit/TestSsl.cs @@ -92,7 +92,11 @@ public void TestServerVerifiedIgnoringNameMismatch() ConnectionFactory cf = new ConnectionFactory(); cf.Ssl.ServerName = "*"; + +#if !(NETFX_CORE) cf.Ssl.AcceptablePolicyErrors = SslPolicyErrors.RemoteCertificateNameMismatch; +#endif + cf.Ssl.Enabled = true; SendReceive(cf); } @@ -113,6 +117,7 @@ public void TestServerVerified() SendReceive(cf); } +#if !NETFX_CORE [Test] public void TestVersionVerified() { @@ -133,6 +138,7 @@ public void TestVersionVerified() cf.Ssl.Version = SslProtocols.Default; Assert.DoesNotThrow(() => SendReceive(cf)); } +#endif [Test] public void TestClientAndServerVerified() @@ -169,13 +175,17 @@ public void TestNoClientCertificate() ConnectionFactory cf = new ConnectionFactory(); cf.Ssl = new SslOption() { - Version = SslProtocols.Tls, - AcceptablePolicyErrors = SslPolicyErrors.RemoteCertificateNotAvailable | - SslPolicyErrors.RemoteCertificateNameMismatch, CertPath = null, Enabled = true, }; + +#if !NETFX_CORE + cf.Ssl.Version = SslProtocols.Tls; + cf.Ssl.AcceptablePolicyErrors = SslPolicyErrors.RemoteCertificateNotAvailable | + SslPolicyErrors.RemoteCertificateNameMismatch; +#endif + SendReceive(cf); } } -} \ No newline at end of file +} diff --git a/projects/client/Unit/src/unit/WireFormattingFixture.cs b/projects/client/Unit/src/unit/WireFormattingFixture.cs index 7ec476cad3..8a38dc719d 100644 --- a/projects/client/Unit/src/unit/WireFormattingFixture.cs +++ b/projects/client/Unit/src/unit/WireFormattingFixture.cs @@ -76,9 +76,9 @@ public void Check(NetworkBinaryWriter w, byte[] expected) { Console.WriteLine(); Console.WriteLine("EXPECTED =================================================="); - DebugUtil.Dump(expected); + DebugUtil.Dump(expected, Console.Out); Console.WriteLine("ACTUAL ===================================================="); - DebugUtil.Dump(actual); + DebugUtil.Dump(actual, Console.Out); Console.WriteLine("==========================================================="); throw; } diff --git a/projects/examples/WinRT/Subscriber/App.xaml b/projects/examples/WinRT/Subscriber/App.xaml new file mode 100644 index 0000000000..2166314965 --- /dev/null +++ b/projects/examples/WinRT/Subscriber/App.xaml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + diff --git a/projects/examples/WinRT/Subscriber/App.xaml.cs b/projects/examples/WinRT/Subscriber/App.xaml.cs new file mode 100644 index 0000000000..1aa3f8c159 --- /dev/null +++ b/projects/examples/WinRT/Subscriber/App.xaml.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.Tracing; +using System.IO; +using System.Linq; +using Windows.ApplicationModel; +using Windows.ApplicationModel.Activation; +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Navigation; + +using RabbitMQ.Util; + +// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=234227 + +namespace RabbitMQ.Client.Examples.WinRT.Subscriber +{ + /// + /// Provides application-specific behavior to supplement the default Application class. + /// + sealed partial class App : Application + { + /// + /// Initializes the singleton application object. This is the first line of authored code + /// executed, and as such is the logical equivalent of main() or WinMain(). + /// + public App() + { + this.InitializeComponent(); + this.Suspending += OnSuspending; + } + + /// + /// Invoked when the application is launched normally by the end user. Other entry points + /// will be used when the application is launched to open a specific file, to display + /// search results, and so forth. + /// + /// Details about the launch request and process. + protected override void OnLaunched(LaunchActivatedEventArgs args) + { + Frame rootFrame = Window.Current.Content as Frame; + + // Do not repeat app initialization when the Window already has content, + // just ensure that the window is active + if (rootFrame == null) + { + // Create a Frame to act as the navigation context and navigate to the first page + rootFrame = new Frame(); + + if (args.PreviousExecutionState == ApplicationExecutionState.Terminated) + { + //TODO: Load state from previously suspended application + } + + // Place the frame in the current Window + Window.Current.Content = rootFrame; + } + + if (rootFrame.Content == null) + { + this.ConfigureEventListeners(); + + // When the navigation stack isn't restored navigate to the first page, + // configuring the new page by passing required information as a navigation + // parameter + if (!rootFrame.Navigate(typeof(MainPage), args.Arguments)) + { + throw new Exception("Failed to create initial page"); + } + } + // Ensure the current window is active + Window.Current.Activate(); + } + + private void ConfigureEventListeners() + { + // First time execution, initialize the logger + EventListener verboseListener = new StorageFileEventListener(); + + verboseListener.EnableEvents(MetroEventSource.Log, EventLevel.Verbose); + } + + /// + /// Invoked when application execution is being suspended. Application state is saved + /// without knowing whether the application will be terminated or resumed with the contents + /// of memory still intact. + /// + /// The source of the suspend request. + /// Details about the suspend request. + private void OnSuspending(object sender, SuspendingEventArgs e) + { + var deferral = e.SuspendingOperation.GetDeferral(); + //TODO: Save application state and stop any background activity + deferral.Complete(); + } + } +} diff --git a/projects/examples/WinRT/Subscriber/Assets/Logo.png b/projects/examples/WinRT/Subscriber/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c16d44655b212e18431c05edd6acdaf75932f57b GIT binary patch literal 1232 zcmeAS@N?(olHy`uVBq!ia0vp^(?FPm4M^HB7Cr(}Ea{HEjtmSN`?>!lvI6;>1s;*b z3=DjSK$uZf!>a)(C{^MbQ4*Y=R#Ki=l*$m0n3-3i=jR%tP-d)Ws%L0m@TF)W&?FyE z7srr_xVLu=`(j)rToc!~Ug1t)yvMMc!D)HQ41ptj5sX59g3$_YNt{Q_wyin1Z058# zVdZBzSKa@g*S-Il%}ejR54U1Vn>desn|%0TLGk+e_O>;jUY$O_?$ft+eZOPh!}k1o z_3tlhxqkedp7(V<1wO`WzCN6h7V-M9;n@w>+LNVNjbFe0{ynhPWZ(9tq@Bm^p3e6_ zR&MWRu`JMFGtX*vnadh8BHOMq_hpKl(K-Bz@wf?B+O)*44IquDH&h)k>}{Hv8e#ij zhTFk2Mr-5>d=@99Nrv$c0`33y*9+g;aPA=%m+>EXDhqaGqKER1J<4Ej@no`0FHZsa zq)oB+!KXg3-wl=s#@w3-_HLU=(`jq44-ZdpE2v!jaqo4j{>FRtz5Dn7{FCx$&T)?8 zCLlA+rS4bj9zJ!@kk?u2;M3k?-{VeiC@Sy)Yw}+Be$VFmy1yS&_B5NwTz(-Sx8QUH zXYKR3l41+d7F0W7?Rbx+;DFHa83@1J|d=KsI1&ri-4Kd*No{jAX%R*7q>AV=*oUgK@C z?4n}H_jk+J`)i&5eZPL6!+g`z8^jVKrUN6``Ng>ndLUO_xLeRUd;aJ7=lfo4PUEdt z+tV!q)-SDB_&GU(wS?m?@AMr%4c9PPwY+QdzVk;Sj8WF9{IF_X9nb0pzJPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qQF!XYv0004sNkl6F|v7R_~){6VAM1V(BI;vrT>Ax#$qvz@$j(tbB^Z! zFLh4;zchP8aFfUX&t+!+KVLo5<%Kh5r^Z(CRL;&B3fX$#a|m81-{hTVpT*7{H4}j d@7KCUMgX}i+}N=7w3Gk<002ovPDHLkV1nqL`Q-or literal 0 HcmV?d00001 diff --git a/projects/examples/WinRT/Subscriber/Assets/SplashScreen.png b/projects/examples/WinRT/Subscriber/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..d0e49466e1d0672c01082cb442a39cd95c957f46 GIT binary patch literal 32307 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 A1ONa4 literal 0 HcmV?d00001 diff --git a/projects/examples/WinRT/Subscriber/Assets/StoreLogo.png b/projects/examples/WinRT/Subscriber/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..5904b1e20291e72b2a30d4c148a8d474b96b2ddf GIT binary patch literal 460 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 P3N?-vL?7G)a)|yP{UQZ; literal 0 HcmV?d00001 diff --git a/projects/examples/WinRT/Subscriber/Common/StandardStyles.xaml b/projects/examples/WinRT/Subscriber/Common/StandardStyles.xaml new file mode 100644 index 0000000000..85f4ed640e --- /dev/null +++ b/projects/examples/WinRT/Subscriber/Common/StandardStyles.xaml @@ -0,0 +1,1829 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Mouse + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/examples/WinRT/Subscriber/MainPage.xaml b/projects/examples/WinRT/Subscriber/MainPage.xaml new file mode 100644 index 0000000000..e301feb363 --- /dev/null +++ b/projects/examples/WinRT/Subscriber/MainPage.xaml @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Exchange: + + + + Exchange Type: + + + + + Routing Key: + + + + + + + Uri: + + + + + + + + + + + + + + + Send Count: + + + + + + + + + + + + + + + + + + + + diff --git a/projects/examples/WinRT/Subscriber/MainPage.xaml.cs b/projects/examples/WinRT/Subscriber/MainPage.xaml.cs new file mode 100644 index 0000000000..bd98882745 --- /dev/null +++ b/projects/examples/WinRT/Subscriber/MainPage.xaml.cs @@ -0,0 +1,252 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.UI.Core; +using Windows.UI.Popups; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Navigation; + +using RabbitMQ.Client.Events; +// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 +using RabbitMQ.Client.MessagePatterns; + +namespace RabbitMQ.Client.Examples.WinRT.Subscriber +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class MainPage : Page + { + private MainPageViewModel viewModel; + + private int messageNumber = 0; + private int sentMessageNumber = 0; + + private ConnectionFactory connectionFactory; + private IConnection connection; + private IModel model; + private Subscription sub; + + public MainPage() + { + this.InitializeComponent(); + + this.viewModel = new MainPageViewModel(); + this.DataContext = this.viewModel; + } + + /// + /// Invoked when this page is about to be displayed in a Frame. + /// + /// Event data that describes how this page was reached. The Parameter + /// property is typically used to configure the page. + protected override void OnNavigatedTo(NavigationEventArgs e) + { + } + + private async void ConnectAction_Click(object sender, RoutedEventArgs e) + { + Exception exceptionOccurred = null; + try + { + this.Disconnect(); + + var exchange = this.viewModel.Exchange ?? string.Empty; + var exchangeType = this.viewModel.ExchangeType; + var routingKey = this.viewModel.RoutingKey; + + this.connectionFactory = new ConnectionFactory + { + Uri = this.viewModel.Uri, + }; + + await this.ConnectAsync(routingKey, exchange, exchangeType); + + this.viewModel.ConnectionStatus = "Connected"; + } + catch (Exception ex) + { + exceptionOccurred = ex; + } + + if (exceptionOccurred != null) + { + await this.ErrorOccured(exceptionOccurred); + this.viewModel.ConnectionStatus = "Error Connecting"; + } + } + + private Task ConnectAsync(string routingKey, string exchange, string exchangeType) { + var currentSynchronizationContext = TaskScheduler.FromCurrentSynchronizationContext(); + return Task.Factory.StartNew( + () => + { + this.connection = this.connectionFactory.CreateConnection(); + this.connection.ConnectionShutdown += ConnectionOnConnectionShutdown; + + this.model = this.connection.CreateModel(); + this.model.QueueDeclare(routingKey, false, false, false, null); + + this.sub = new Subscription(this.model, routingKey); + var ignoreTask = this.sub.NextAsync() + .ContinueWith(this.SubscriptionContinuation, currentSynchronizationContext); + + if (exchange != "") { + this.model.ExchangeDeclare(exchange, exchangeType); + this.model.QueueBind(routingKey, exchange, routingKey, null); + } + }); + } + + private void ConnectionOnConnectionShutdown(object sender, ShutdownEventArgs reason) { + connection.ConnectionShutdown -= this.ConnectionOnConnectionShutdown; + + Debug.WriteLine("Connection was shutdown: " + reason.ToString()); + + var ignoreTask = this.Dispatcher.RunAsync( + CoreDispatcherPriority.Normal, + () => this.viewModel.ConnectionStatus = "Shutdown - " + reason.ReplyText); + + // NOTE: Normally, one would tie into the App.Resuming event and re-connect to the AMQP broker + } + + private async void SubscriptionContinuation(Task continuation) + { + Exception exceptionOccurred = null; + try { + // receive and add to the viewmodel + BasicDeliverEventArgs eventArgs = continuation.Result; + + if (eventArgs == null) { + Debug.WriteLine("Received empty BasicDeliverEventArgs."); + return; + } + + this.AddReceivedMessage(eventArgs); + await Task.Factory.StartNew(() => this.sub.Ack(eventArgs)); + + // Receive the next message + var ignoreTask = this.sub.NextAsync() + .ContinueWith(this.SubscriptionContinuation, TaskScheduler.FromCurrentSynchronizationContext()); + } + catch (AggregateException ex) { + if (ex.InnerException is EndOfStreamException) { + Debug.WriteLine("Shutdown"); + } + else { + exceptionOccurred = ex; + } + } + catch (Exception ex) { + exceptionOccurred = ex; + } + + if (exceptionOccurred != null) + { + await this.ErrorOccured(exceptionOccurred); + } + } + + private void AddReceivedMessage(BasicDeliverEventArgs eventArgs) { + this.viewModel.MessagesReceived.Insert( + 0, + new MainPageViewModel.ReceivedMessage(this.messageNumber++, eventArgs.Body)); + } + + private void AddMessage(string message) + { + this.viewModel.MessagesReceived.Insert( + 0, + new MainPageViewModel.ReceivedMessage(this.messageNumber++, message)); + } + + private async void DisconnectAction_Click(object sender, RoutedEventArgs e) + { + Exception exceptionOccurred = null; + try + { + this.Disconnect(); + } + catch (Exception ex) + { + exceptionOccurred = ex; + } + + if (exceptionOccurred != null) + { + this.viewModel.ConnectionStatus = "Error Disconnecting"; + await this.ErrorOccured(exceptionOccurred); + } + } + + private void Disconnect() { + if (this.sub != null) { + this.sub.Close(); + } + this.sub = null; + + if (this.model != null && this.model.IsOpen) { + this.model.Abort(); + } + this.model = null; + + if (this.connection != null && this.connection.IsOpen) { + this.connection.Abort(); + } + this.connection = null; + this.viewModel.ConnectionStatus = "Disconnected"; + } + + private async void SendMessagesAction_Click(object sender, RoutedEventArgs e) + { + Exception exceptionOccurred = null; + var exchange = this.viewModel.Exchange ?? string.Empty; + if (exchange != string.Empty) + { + this.model.ExchangeDeclare(exchange, this.viewModel.ExchangeType); + } + + try + { + for (int i = 0; i < this.viewModel.SendCount; i++) { + var format = string.Format("Welcome to Caerbannog! (sent: {0})", this.sentMessageNumber++); + await this.SendMessageAsync(Encoding.UTF8.GetBytes(format), exchange, "test"); + } + } + catch (Exception ex) + { + exceptionOccurred = ex; + } + + if (exceptionOccurred != null) { + await this.ErrorOccured(exceptionOccurred); + } + } + + private Task SendMessageAsync(byte[] message, string exchange, string routingKey) { + var model = this.model; + if (model == null) throw new NullReferenceException("IModel is not set, probably not connected."); + + return Task.Factory.StartNew( + () => model.BasicPublish(exchange, routingKey, null, message)); + } + + private async Task ErrorOccured(Exception exceptionOccurred) { + Debug.WriteLine(exceptionOccurred); + var dialog = new MessageDialog(exceptionOccurred.ToString()); + await dialog.ShowAsync(); + } + } +} diff --git a/projects/examples/WinRT/Subscriber/MainPageViewModel.cs b/projects/examples/WinRT/Subscriber/MainPageViewModel.cs new file mode 100644 index 0000000000..f621c54a13 --- /dev/null +++ b/projects/examples/WinRT/Subscriber/MainPageViewModel.cs @@ -0,0 +1,209 @@ +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using System.Text; + +using RabbitMQ.Client.Examples.WinRT.Subscriber.Annotations; + +namespace RabbitMQ.Client.Examples.WinRT.Subscriber +{ + public class MainPageViewModel : INotifyPropertyChanged + { + private bool useServerNamedQueue; + private string exchange; + private string uri; + private int sendCount; + private bool blockingReceiveSelected; + private bool enumeratingReceiveSelected; + private readonly ObservableCollection messagesReceived = new ObservableCollection(); + private readonly ObservableCollection exchangeTypes = new ObservableCollection(Client.ExchangeType.All()); + private string exchangeType; + private string routingKey; + private string connectionStatus; + + public event PropertyChangedEventHandler PropertyChanged; + + public bool UseServerNamedQueue + { + get { return this.useServerNamedQueue; } + set + { + if (value.Equals(this.useServerNamedQueue)) + { + return; + } + this.useServerNamedQueue = value; + this.OnPropertyChanged(); + } + } + + public string Exchange + { + get { return this.exchange; } + set + { + if (value == this.exchange) + { + return; + } + this.exchange = value; + this.OnPropertyChanged(); + } + } + + public string ExchangeType + { + get { return this.exchangeType; } + set + { + if (value == this.exchangeType) + { + return; + } + this.exchangeType = value; + this.OnPropertyChanged(); + } + } + + public string RoutingKey + { + get { return this.routingKey; } + set + { + if (value == this.routingKey) + { + return; + } + this.routingKey = value; + this.OnPropertyChanged(); + } + } + + public string ConnectionStatus + { + get { return this.connectionStatus; } + set + { + if (value == this.connectionStatus) + { + return; + } + this.connectionStatus = value; + this.OnPropertyChanged(); + } + } + + public string Uri + { + get { return this.uri; } + set + { + if (value == this.uri) + { + return; + } + this.uri = value; + this.OnPropertyChanged(); + } + } + + public int SendCount + { + get { return this.sendCount; } + set + { + if (value == this.sendCount) + { + return; + } + this.sendCount = value; + this.OnPropertyChanged(); + } + } + + public bool BlockingReceiveSelected + { + get { return this.blockingReceiveSelected; } + set + { + if (value.Equals(this.blockingReceiveSelected)) + { + return; + } + this.blockingReceiveSelected = value; + this.OnPropertyChanged(); + } + } + + public bool EnumeratingReceiveSelected + { + get { return this.enumeratingReceiveSelected; } + set + { + if (value.Equals(this.enumeratingReceiveSelected)) + { + return; + } + this.enumeratingReceiveSelected = value; + this.OnPropertyChanged(); + } + } + + public ObservableCollection MessagesReceived + { + get { return this.messagesReceived; } + } + + public ObservableCollection ExchangeTypes + { + get { return this.exchangeTypes; } + } + + public MainPageViewModel() + { + //this.uri = "amqp://user:pass@host:port/vhost"; + this.uri = "amqp://localhost/"; + this.exchange = string.Empty; + this.routingKey = "test"; + this.sendCount = 10; + this.blockingReceiveSelected = true; + this.useServerNamedQueue = false; + this.connectionStatus = "Disconnected"; + this.exchangeType = Client.ExchangeType.Direct; + } + + [NotifyPropertyChangedInvocator] + protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChangedEventHandler handler = PropertyChanged; + if (handler != null) + { + handler(this, new PropertyChangedEventArgs(propertyName)); + } + } + + public class ReceivedMessage + { + public ReceivedMessage(int i, byte[] body) + :this(i, Encoding.UTF8.GetString(body, 0, body.Length)) + { + } + + public ReceivedMessage(int i, string message) + { + this.DecodedString = string.Format("Message {0}: {1}", i, message); + } + + public string DecodedString { get; set; } + } + } + + public class MainPageViewModelDesign : MainPageViewModel + { + public MainPageViewModelDesign() + { + this.MessagesReceived.Add(new ReceivedMessage(0, "Welcome to Caerbannog!")); + this.MessagesReceived.Add(new ReceivedMessage(1, "Welcome to Caerbannog!")); + } + } +} \ No newline at end of file diff --git a/projects/examples/WinRT/Subscriber/Package.appxmanifest b/projects/examples/WinRT/Subscriber/Package.appxmanifest new file mode 100644 index 0000000000..7fbd94edf7 --- /dev/null +++ b/projects/examples/WinRT/Subscriber/Package.appxmanifest @@ -0,0 +1,27 @@ + + + + + RabbitMQ.Client.Examples.WinRT.Subscriber + RabbitMQ Example + Assets\StoreLogo.png + + + 6.2.1 + 6.2.1 + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/projects/examples/WinRT/Subscriber/Properties/Annotations.cs b/projects/examples/WinRT/Subscriber/Properties/Annotations.cs new file mode 100644 index 0000000000..39fb45f925 --- /dev/null +++ b/projects/examples/WinRT/Subscriber/Properties/Annotations.cs @@ -0,0 +1,689 @@ +/* + * Copyright 2007-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.ComponentModel; + +namespace RabbitMQ.Client.Examples.WinRT.Subscriber.Annotations +{ + /// + /// Indicates that marked element should be localized or not. + /// + /// + /// + /// [LocalizationRequiredAttribute(true)] + /// public class Foo + /// { + /// private string str = "my string"; // Warning: Localizable string + /// } + /// + /// + [AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)] + public sealed class LocalizationRequiredAttribute : Attribute + { + /// + /// Initializes a new instance of the class with + /// set to . + /// + public LocalizationRequiredAttribute() : this(true) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// true if a element should be localized; otherwise, false. + public LocalizationRequiredAttribute(bool required) + { + Required = required; + } + + /// + /// Gets a value indicating whether a element should be localized. + /// true if a element should be localized; otherwise, false. + /// + [UsedImplicitly] public bool Required { get; private set; } + + /// + /// Returns whether the value of the given object is equal to the current . + /// + /// The object to test the value equality of. + /// + /// true if the value of the given object is equal to that of the current; otherwise, false. + /// + public override bool Equals(object obj) + { + var attribute = obj as LocalizationRequiredAttribute; + return attribute != null && attribute.Required == Required; + } + + /// + /// Returns the hash code for this instance. + /// + /// A hash code for the current . + public override int GetHashCode() + { + return base.GetHashCode(); + } + } + + /// + /// Indicates that the marked method builds string by format pattern and (optional) arguments. + /// Parameter, which contains format string, should be given in constructor. + /// The format string should be in -like form + /// + /// + /// + /// [StringFormatMethod("message")] + /// public void ShowError(string message, params object[] args) + /// { + /// //Do something + /// } + /// public void Foo() + /// { + /// ShowError("Failed: {0}"); // Warning: Non-existing argument in format string + /// } + /// + /// + [AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public sealed class StringFormatMethodAttribute : Attribute + { + /// + /// Initializes new instance of StringFormatMethodAttribute + /// + /// Specifies which parameter of an annotated method should be treated as format-string + public StringFormatMethodAttribute(string formatParameterName) + { + FormatParameterName = formatParameterName; + } + + /// + /// Gets format parameter name + /// + [UsedImplicitly] public string FormatParameterName { get; private set; } + } + + /// + /// Indicates that the function argument should be string literal and match one of the parameters + /// of the caller function. + /// For example, ReSharper annotates the parameter of . + /// + /// + /// + /// public void Foo(string param) + /// { + /// if (param == null) + /// throw new ArgumentNullException("par"); // Warning: Cannot resolve symbol + /// } + /// + /// + [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] + public sealed class InvokerParameterNameAttribute : Attribute { } + + /// + /// Indicates that the method is contained in a type that implements + /// interface + /// and this method is used to notify that some property value changed. + /// + /// + /// The method should be non-static and conform to one of the supported signatures: + /// + /// NotifyChanged(string) + /// NotifyChanged(params string[]) + /// NotifyChanged{T}(Expression{Func{T}}) + /// NotifyChanged{T,U}(Expression{Func{T,U}}) + /// SetProperty{T}(ref T, T, string) + /// + /// + /// + /// + /// public class Foo : INotifyPropertyChanged + /// { + /// public event PropertyChangedEventHandler PropertyChanged; + /// + /// [NotifyPropertyChangedInvocator] + /// protected virtual void NotifyChanged(string propertyName) + /// {} + /// + /// private string _name; + /// public string Name + /// { + /// get { return _name; } + /// set + /// { + /// _name = value; + /// NotifyChanged("LastName"); // Warning + /// } + /// } + /// } + /// + /// Examples of generated notifications: + /// + /// NotifyChanged("Property") + /// NotifyChanged(() => Property) + /// NotifyChanged((VM x) => x.Property) + /// SetProperty(ref myField, value, "Property") + /// + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public sealed class NotifyPropertyChangedInvocatorAttribute : Attribute + { + public NotifyPropertyChangedInvocatorAttribute() { } + public NotifyPropertyChangedInvocatorAttribute(string parameterName) + { + ParameterName = parameterName; + } + + [UsedImplicitly] public string ParameterName { get; private set; } + } + + /// + /// Indicates that the value of the marked element could be null sometimes, + /// so the check for null is necessary before its usage. + /// + /// + /// + /// [CanBeNull] + /// public object Test() + /// { + /// return null; + /// } + /// + /// public void UseTest() + /// { + /// var p = Test(); + /// var s = p.ToString(); // Warning: Possible 'System.NullReferenceException' + /// } + /// + /// + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Delegate | AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + public sealed class CanBeNullAttribute : Attribute { } + + /// + /// Indicates that the value of the marked element could never be null + /// + /// + /// + /// [NotNull] + /// public object Foo() + /// { + /// return null; // Warning: Possible 'null' assignment + /// } + /// + /// + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Delegate | AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + public sealed class NotNullAttribute : Attribute { } + + /// + /// Describes dependency between method input and output. + /// + /// + ///

Function Definition Table syntax:

+ /// + /// FDT ::= FDTRow [;FDTRow]* + /// FDTRow ::= Input => Output | Output <= Input + /// Input ::= ParameterName: Value [, Input]* + /// Output ::= [ParameterName: Value]* {halt|stop|void|nothing|Value} + /// Value ::= true | false | null | notnull | canbenull + /// + /// If method has single input parameter, it's name could be omitted.
+ /// Using halt (or void/nothing, which is the same) for method output means that the methos doesn't return normally.
+ /// canbenull annotation is only applicable for output parameters.
+ /// You can use multiple [ContractAnnotation] for each FDT row, or use single attribute with rows separated by semicolon.
+ ///
+ /// + /// + /// + /// [ContractAnnotation("=> halt")] + /// public void TerminationMethod() + /// + /// + /// [ContractAnnotation("halt <= condition: false")] + /// public void Assert(bool condition, string text) // Regular Assertion method + /// + /// + /// [ContractAnnotation("s:null => true")] + /// public bool IsNullOrEmpty(string s) // String.IsNullOrEmpty + /// + /// + /// // A method that returns null if the parameter is null, and not null if the parameter is not null + /// [ContractAnnotation("null => null; notnull => notnull")] + /// public object Transform(object data) + /// + /// + /// [ContractAnnotation("s:null=>false; =>true,result:notnull; =>false, result:null")] + /// public bool TryParse(string s, out Person result) + /// + /// + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)] + public sealed class ContractAnnotationAttribute : Attribute + { + public ContractAnnotationAttribute([NotNull] string fdt) : this (fdt, false) + { + } + + public ContractAnnotationAttribute([NotNull] string fdt, bool forceFullStates) + { + FDT = fdt; + ForceFullStates = forceFullStates; + } + + public string FDT { get; private set; } + public bool ForceFullStates { get; private set; } + } + + /// + /// Indicates that the value of the marked type (or its derivatives) + /// cannot be compared using '==' or '!=' operators and Equals() should be used instead. + /// However, using '==' or '!=' for comparison with null is always permitted. + /// + /// + /// + /// [CannotApplyEqualityOperator] + /// class NoEquality + /// { + /// } + /// + /// class UsesNoEquality + /// { + /// public void Test() + /// { + /// var ca1 = new NoEquality(); + /// var ca2 = new NoEquality(); + /// + /// if (ca1 != null) // OK + /// { + /// bool condition = ca1 == ca2; // Warning + /// } + /// } + /// } + /// + /// + [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = true)] + public sealed class CannotApplyEqualityOperatorAttribute : Attribute { } + + /// + /// When applied to a target attribute, specifies a requirement for any type marked with + /// the target attribute to implement or inherit specific type or types. + /// + /// + /// + /// [BaseTypeRequired(typeof(IComponent)] // Specify requirement + /// public class ComponentAttribute : Attribute + /// {} + /// + /// [Component] // ComponentAttribute requires implementing IComponent interface + /// public class MyComponent : IComponent + /// {} + /// + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] + [BaseTypeRequired(typeof(Attribute))] + public sealed class BaseTypeRequiredAttribute : Attribute + { + /// + /// Initializes new instance of BaseTypeRequiredAttribute + /// + /// Specifies which types are required + public BaseTypeRequiredAttribute(Type baseType) + { + BaseTypes = new[] { baseType }; + } + + /// + /// Gets enumerations of specified base types + /// + public Type[] BaseTypes { get; private set; } + } + + /// + /// Indicates that the marked symbol is used implicitly (e.g. via reflection, in external library), + /// so this symbol will not be marked as unused (as well as by other usage inspections) + /// + [AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)] + public sealed class UsedImplicitlyAttribute : Attribute + { + [UsedImplicitly] public UsedImplicitlyAttribute() + : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { } + + [UsedImplicitly] + public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) + { + UseKindFlags = useKindFlags; + TargetFlags = targetFlags; + } + + [UsedImplicitly] public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags) + : this(useKindFlags, ImplicitUseTargetFlags.Default) { } + + [UsedImplicitly] public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags) + : this(ImplicitUseKindFlags.Default, targetFlags) { } + + [UsedImplicitly] public ImplicitUseKindFlags UseKindFlags { get; private set; } + + /// + /// Gets value indicating what is meant to be used + /// + [UsedImplicitly] public ImplicitUseTargetFlags TargetFlags { get; private set; } + } + + /// + /// Should be used on attributes and causes ReSharper + /// to not mark symbols marked with such attributes as unused (as well as by other usage inspections) + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public sealed class MeansImplicitUseAttribute : Attribute + { + [UsedImplicitly] public MeansImplicitUseAttribute() + : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { } + + [UsedImplicitly] + public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) + { + UseKindFlags = useKindFlags; + TargetFlags = targetFlags; + } + + [UsedImplicitly] public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags) + : this(useKindFlags, ImplicitUseTargetFlags.Default) + { + } + + [UsedImplicitly] public MeansImplicitUseAttribute(ImplicitUseTargetFlags targetFlags) + : this(ImplicitUseKindFlags.Default, targetFlags) { } + + [UsedImplicitly] public ImplicitUseKindFlags UseKindFlags { get; private set; } + + /// + /// Gets value indicating what is meant to be used + /// + [UsedImplicitly] public ImplicitUseTargetFlags TargetFlags { get; private set; } + } + + [Flags] + public enum ImplicitUseKindFlags + { + Default = Access | Assign | InstantiatedWithFixedConstructorSignature, + + /// + /// Only entity marked with attribute considered used + /// + Access = 1, + + /// + /// Indicates implicit assignment to a member + /// + Assign = 2, + + /// + /// Indicates implicit instantiation of a type with fixed constructor signature. + /// That means any unused constructor parameters won't be reported as such. + /// + InstantiatedWithFixedConstructorSignature = 4, + + /// + /// Indicates implicit instantiation of a type + /// + InstantiatedNoFixedConstructorSignature = 8, + } + + /// + /// Specify what is considered used implicitly when marked with or + /// + [Flags] + public enum ImplicitUseTargetFlags + { + Default = Itself, + + Itself = 1, + + /// + /// Members of entity marked with attribute are considered used + /// + Members = 2, + + /// + /// Entity marked with attribute and all its members considered used + /// + WithMembers = Itself | Members + } + + /// + /// This attribute is intended to mark publicly available API which should not be removed and so is treated as used. + /// + [MeansImplicitUse] + public sealed class PublicAPIAttribute : Attribute + { + public PublicAPIAttribute() { } + public PublicAPIAttribute(string comment) { } + } + + /// + /// Tells code analysis engine if the parameter is completely handled when the invoked method is on stack. + /// If the parameter is a delegate, indicates that delegate is executed while the method is executed. + /// If the parameter is an enumerable, indicates that it is enumerated while the method is executed. + /// + [AttributeUsage(AttributeTargets.Parameter, Inherited = true)] + public sealed class InstantHandleAttribute : Attribute { } + + + /// + /// Indicates that a method does not make any observable state changes. + /// The same as + /// + /// + /// + /// [Pure] + /// private int Multiply(int x, int y) + /// { + /// return x*y; + /// } + /// + /// public void Foo() + /// { + /// const int a=2, b=2; + /// Multiply(a, b); // Waring: Return value of pure method is not used + /// } + /// + /// + [AttributeUsage(AttributeTargets.Method, Inherited = true)] + public sealed class PureAttribute : Attribute { } + + /// + /// Indicates that a parameter is a path to a file or a folder within a web project. + /// Path can be relative or absolute, starting from web root (~). + /// + [AttributeUsage(AttributeTargets.Parameter)] + public class PathReferenceAttribute : Attribute + { + public PathReferenceAttribute() { } + + [UsedImplicitly] + public PathReferenceAttribute([PathReference] string basePath) + { + BasePath = basePath; + } + + [UsedImplicitly] public string BasePath { get; private set; } + } + + // ASP.NET MVC attributes + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is an MVC action. + /// If applied to a method, the MVC action name is calculated implicitly from the context. + /// Use this attribute for custom wrappers similar to + /// + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] + public sealed class AspMvcActionAttribute : Attribute + { + [UsedImplicitly] public string AnonymousProperty { get; private set; } + + public AspMvcActionAttribute() { } + + public AspMvcActionAttribute(string anonymousProperty) + { + AnonymousProperty = anonymousProperty; + } + } + + /// + /// ASP.NET MVC attribute. Indicates that a parameter is an MVC araa. + /// Use this attribute for custom wrappers similar to + /// + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class AspMvcAreaAttribute : PathReferenceAttribute + { + [UsedImplicitly] public string AnonymousProperty { get; private set; } + + [UsedImplicitly] public AspMvcAreaAttribute() { } + + public AspMvcAreaAttribute(string anonymousProperty) + { + AnonymousProperty = anonymousProperty; + } + } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is an MVC controller. + /// If applied to a method, the MVC controller name is calculated implicitly from the context. + /// Use this attribute for custom wrappers similar to + /// + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] + public sealed class AspMvcControllerAttribute : Attribute + { + [UsedImplicitly] public string AnonymousProperty { get; private set; } + + public AspMvcControllerAttribute() { } + + public AspMvcControllerAttribute(string anonymousProperty) + { + AnonymousProperty = anonymousProperty; + } + } + + /// + /// ASP.NET MVC attribute. Indicates that a parameter is an MVC Master. + /// Use this attribute for custom wrappers similar to + /// + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class AspMvcMasterAttribute : Attribute { } + + /// + /// ASP.NET MVC attribute. Indicates that a parameter is an MVC model type. + /// Use this attribute for custom wrappers similar to + /// + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class AspMvcModelTypeAttribute : Attribute { } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is an MVC partial view. + /// If applied to a method, the MVC partial view name is calculated implicitly from the context. + /// Use this attribute for custom wrappers similar to + /// + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] + public sealed class AspMvcPartialViewAttribute : PathReferenceAttribute { } + + /// + /// ASP.NET MVC attribute. Allows disabling all inspections for MVC views within a class or a method. + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] + public sealed class AspMvcSupressViewErrorAttribute : Attribute { } + + /// + /// ASP.NET MVC attribute. Indicates that a parameter is an MVC display template. + /// Use this attribute for custom wrappers similar to + /// + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class AspMvcDisplayTemplateAttribute : Attribute { } + + /// + /// ASP.NET MVC attribute. Indicates that a parameter is an MVC editor template. + /// Use this attribute for custom wrappers similar to + /// + /// + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class AspMvcEditorTemplateAttribute : Attribute { } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is an MVC view. + /// If applied to a method, the MVC view name is calculated implicitly from the context. + /// Use this attribute for custom wrappers similar to + /// + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] + public sealed class AspMvcViewAttribute : PathReferenceAttribute { } + + /// + /// ASP.NET MVC attribute. When applied to a parameter of an attribute, + /// indicates that this parameter is an MVC action name. + /// + /// + /// + /// [ActionName("Foo")] + /// public ActionResult Login(string returnUrl) + /// { + /// ViewBag.ReturnUrl = Url.Action("Foo"); // OK + /// return RedirectToAction("Bar"); // Error: Cannot resolve action + /// } + /// + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property)] + public sealed class AspMvcActionSelectorAttribute : Attribute { } + + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field, Inherited = true)] + public sealed class HtmlElementAttributesAttribute : Attribute + { + public HtmlElementAttributesAttribute() { } + + public HtmlElementAttributesAttribute(string name) + { + Name = name; + } + + [UsedImplicitly] public string Name { get; private set; } + } + + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property, Inherited = true)] + public sealed class HtmlAttributeValueAttribute : Attribute + { + public HtmlAttributeValueAttribute([NotNull] string name) + { + Name = name; + } + + [NotNull,UsedImplicitly] public string Name { get; private set; } + } + + // Razor attributes + + /// + /// Razor attribute. Indicates that a parameter or a method is a Razor section. + /// Use this attribute for custom wrappers similar to + /// + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method, Inherited = true)] + public sealed class RazorSectionAttribute : Attribute { } + +} \ No newline at end of file diff --git a/projects/examples/WinRT/Subscriber/Properties/AssemblyInfo.cs b/projects/examples/WinRT/Subscriber/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..f3ed040cef --- /dev/null +++ b/projects/examples/WinRT/Subscriber/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("RabbitMQ.Client.Examples.WinRT.Subscriber")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("RabbitMQ.Client.Examples.WinRT.Subscriber")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: ComVisible(false)] \ No newline at end of file diff --git a/projects/examples/WinRT/Subscriber/RabbitMQ.Client.Examples.WinRT.Subscriber.csproj b/projects/examples/WinRT/Subscriber/RabbitMQ.Client.Examples.WinRT.Subscriber.csproj new file mode 100644 index 0000000000..af8eecb047 --- /dev/null +++ b/projects/examples/WinRT/Subscriber/RabbitMQ.Client.Examples.WinRT.Subscriber.csproj @@ -0,0 +1,160 @@ + + + + + Debug + AnyCPU + {6F01C132-7938-4001-8B70-D84EBAA662CC} + AppContainerExe + Properties + RabbitMQ.Client.Examples.WinRT.Subscriber + RabbitMQ.Client.Examples.WinRT.Subscriber + en-US + 512 + {BC8A1FFA-BEE3-4634-8014-F334798102B3};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + RabbitMQ.Client.Examples.WinRT.Subscriber_TemporaryKey.pfx + A7016A18C09D6BCA14BF3B004B80BAD680FEE679 + + + AnyCPU + true + full + false + build\bin\Debug\ + DEBUG;TRACE;NETFX_CORE + prompt + 4 + + + AnyCPU + pdbonly + true + build\bin\Release\ + TRACE;NETFX_CORE + prompt + 4 + + + true + build\bin\ARM\Debug\ + DEBUG;TRACE;NETFX_CORE + ;2008 + full + ARM + false + prompt + true + + + build\bin\ARM\Release\ + TRACE;NETFX_CORE + true + ;2008 + pdbonly + ARM + false + prompt + true + + + true + build\bin\x64\Debug\ + DEBUG;TRACE;NETFX_CORE + ;2008 + full + x64 + false + prompt + true + + + build\bin\x64\Release\ + TRACE;NETFX_CORE + true + ;2008 + pdbonly + x64 + false + prompt + true + + + true + build\bin\x86\Debug\ + DEBUG;TRACE;NETFX_CORE + ;2008 + full + x86 + false + prompt + true + + + build\bin\x86\Release\ + TRACE;NETFX_CORE + true + ;2008 + pdbonly + x86 + false + prompt + true + + + + + {61d29f90-5b1c-4748-89fc-9fd2937f09c6} + RabbitMQ.Client.WinRT + + + + + App.xaml + + + MainPage.xaml + + + + + + + + + Designer + + + + + + + + + + + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + + 11.0 + + + + \ No newline at end of file diff --git a/projects/examples/WinRT/Subscriber/RabbitMQ.Client.Examples.WinRT.Subscriber_TemporaryKey.pfx b/projects/examples/WinRT/Subscriber/RabbitMQ.Client.Examples.WinRT.Subscriber_TemporaryKey.pfx new file mode 100644 index 0000000000000000000000000000000000000000..39e0ca600d124bfb2248b35d7a21ed43f414e9f4 GIT binary patch literal 2512 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 Date: Sun, 19 Apr 2015 14:34:41 -0700 Subject: [PATCH 03/10] Update nuspec for WinRT. --- RabbitMQ.Client.nuspec | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/RabbitMQ.Client.nuspec b/RabbitMQ.Client.nuspec index a2f8d9e8b8..6f191bb507 100644 --- a/RabbitMQ.Client.nuspec +++ b/RabbitMQ.Client.nuspec @@ -19,7 +19,12 @@ + + + + + From a9953a75b2f57af71bd357e761380e6ce301caf8 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Mon, 20 Apr 2015 09:44:29 +0300 Subject: [PATCH 04/10] Exclude WinRT version from building on Mono --- Local.props.example | 8 +++-- .../RabbitMQ.Client.WinRT.csproj | 35 ++++++++++++------- ...MQ.Client.Examples.WinRT.Subscriber.csproj | 30 +++++++++++----- 3 files changed, 50 insertions(+), 23 deletions(-) diff --git a/Local.props.example b/Local.props.example index b240569cd2..a6849c68c0 100644 --- a/Local.props.example +++ b/Local.props.example @@ -4,14 +4,17 @@ v4.0 0.0.0.0 false - + - + mono --debug + + true + true @@ -19,4 +22,3 @@ - diff --git a/projects/client/RabbitMQ.Client.WinRT/RabbitMQ.Client.WinRT.csproj b/projects/client/RabbitMQ.Client.WinRT/RabbitMQ.Client.WinRT.csproj index b60efba008..7f74976fb0 100644 --- a/projects/client/RabbitMQ.Client.WinRT/RabbitMQ.Client.WinRT.csproj +++ b/projects/client/RabbitMQ.Client.WinRT/RabbitMQ.Client.WinRT.csproj @@ -1,11 +1,6 @@ - + - - - - $(MSBuildProjectDirectory)\..\..\..\Local.props - - + $(MSBuildProjectDirectory)\..\..\..\lib\MSBuild.Community.Tasks\ @@ -134,15 +129,31 @@ - - 11.0 - + + + + + <_DisabledWarnings>$(NoWarn) - - + + + + + + + + + + + + + + 11.0 + + diff --git a/projects/examples/WinRT/Subscriber/RabbitMQ.Client.Examples.WinRT.Subscriber.csproj b/projects/examples/WinRT/Subscriber/RabbitMQ.Client.Examples.WinRT.Subscriber.csproj index af8eecb047..4cf0a043b6 100644 --- a/projects/examples/WinRT/Subscriber/RabbitMQ.Client.Examples.WinRT.Subscriber.csproj +++ b/projects/examples/WinRT/Subscriber/RabbitMQ.Client.Examples.WinRT.Subscriber.csproj @@ -1,6 +1,7 @@ - + + Debug AnyCPU @@ -149,12 +150,25 @@ 11.0 - - + + + + + + + <_DisabledWarnings>$(NoWarn) + + + + + - + + - --> - \ No newline at end of file + + + + From 9c1acac77c93cc65ece92fbca87660c83c5e8432 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Mon, 20 Apr 2015 10:17:31 +0300 Subject: [PATCH 05/10] Rename reference for clarity --- projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj b/projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj index 3b3bb74619..7a079bf0fd 100644 --- a/projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj +++ b/projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj @@ -1,4 +1,4 @@ - + @@ -87,7 +87,7 @@ {61D29F90-5B1C-4748-89FC-9FD2937F09C6} - RabbitMQ.Client + RabbitMQ.Client.WinRT From d66c7c93e4de52fa34c1da845f6ebb490e387de2 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Mon, 20 Apr 2015 10:55:59 +0300 Subject: [PATCH 06/10] Reduce distance between Unit and Unit.WinRT --- .../RabbitMQ.Client.Unit.WinRT.csproj | 23 +++++++++++++++---- .../client/Unit/RabbitMQ.Client.Unit.csproj | 9 ++------ 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj b/projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj index 7a079bf0fd..a13865c884 100644 --- a/projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj +++ b/projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj @@ -14,10 +14,8 @@ properties RabbitMQ.Client.Test unit-tests - v4.5 + $(PropTargetFramework) 512 - - 8.0 true @@ -76,6 +74,7 @@ ..\..\..\lib\nunit\nunit.framework.dll + @@ -87,7 +86,7 @@ {61D29F90-5B1C-4748-89FC-9FD2937F09C6} - RabbitMQ.Client.WinRT + RabbitMQ.Client @@ -101,4 +100,20 @@ + + + + <_DisabledWarnings>$(NoWarn) + + + + + + + + + + + + diff --git a/projects/client/Unit/RabbitMQ.Client.Unit.csproj b/projects/client/Unit/RabbitMQ.Client.Unit.csproj index 5c0a30971e..55b39bc7ef 100644 --- a/projects/client/Unit/RabbitMQ.Client.Unit.csproj +++ b/projects/client/Unit/RabbitMQ.Client.Unit.csproj @@ -1,4 +1,4 @@ - + @@ -16,11 +16,6 @@ unit-tests $(PropTargetFramework) 512 - - - - - 3.5 true @@ -146,4 +141,4 @@ - \ No newline at end of file + From 50ecead4547cf28517bb8d5a30acc4a7e0455a90 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Mon, 20 Apr 2015 11:25:26 +0300 Subject: [PATCH 07/10] Undo Mono workarounds Having stub targets trips up msbuild --- .../RabbitMQ.Client.WinRT.csproj | 17 ----------------- .../RabbitMQ.Client.Unit.WinRT.csproj | 16 ---------------- 2 files changed, 33 deletions(-) diff --git a/projects/client/RabbitMQ.Client.WinRT/RabbitMQ.Client.WinRT.csproj b/projects/client/RabbitMQ.Client.WinRT/RabbitMQ.Client.WinRT.csproj index 7f74976fb0..69badf35ad 100644 --- a/projects/client/RabbitMQ.Client.WinRT/RabbitMQ.Client.WinRT.csproj +++ b/projects/client/RabbitMQ.Client.WinRT/RabbitMQ.Client.WinRT.csproj @@ -132,23 +132,6 @@ - - - - - <_DisabledWarnings>$(NoWarn) - - - - - - - - - - - - 11.0 diff --git a/projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj b/projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj index a13865c884..723c2b4050 100644 --- a/projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj +++ b/projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj @@ -100,20 +100,4 @@ - - - - <_DisabledWarnings>$(NoWarn) - - - - - - - - - - - - From 9822cbdf11563044eb38540a6d03e0fa5db909a5 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Mon, 20 Apr 2015 12:04:39 +0300 Subject: [PATCH 08/10] Fix WinRT C# target, re-add Mono stubs in the correct order --- .../RabbitMQ.Client.WinRT.csproj | 16 ++++++++++++++ .../RabbitMQ.Client.Unit.WinRT.csproj | 22 ++++++++++++++++--- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/projects/client/RabbitMQ.Client.WinRT/RabbitMQ.Client.WinRT.csproj b/projects/client/RabbitMQ.Client.WinRT/RabbitMQ.Client.WinRT.csproj index 69badf35ad..3bb85ef3eb 100644 --- a/projects/client/RabbitMQ.Client.WinRT/RabbitMQ.Client.WinRT.csproj +++ b/projects/client/RabbitMQ.Client.WinRT/RabbitMQ.Client.WinRT.csproj @@ -42,6 +42,7 @@ + 4.5 AssemblyInfo.cs src\tokenized\$(AssemblyInfoBaseName).in $(GensrcDir)$(AssemblyInfoBaseName) @@ -130,6 +131,21 @@ + + + <_DisabledWarnings>$(NoWarn) + + + + + + + + + + + + diff --git a/projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj b/projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj index 723c2b4050..cc6058621f 100644 --- a/projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj +++ b/projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj @@ -14,7 +14,7 @@ properties RabbitMQ.Client.Test unit-tests - $(PropTargetFramework) + 4.5 512 @@ -74,7 +74,6 @@ ..\..\..\lib\nunit\nunit.framework.dll - @@ -96,8 +95,25 @@ <_DisabledWarnings>$(NoWarn) + + + <_DisabledWarnings>$(NoWarn) + + + + + + + + + + + + + + - + From 1fbf5028dfafccab66c0caff83f92c5f4348b5e7 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Mon, 20 Apr 2015 12:25:19 +0300 Subject: [PATCH 09/10] Ignore test results for Unit.WinRT --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 7b68c3a874..a4a96a78d8 100644 --- a/.gitignore +++ b/.gitignore @@ -87,4 +87,4 @@ Backup*/ UpgradeLog*.XML UpgradeLog*.htm -projects/client/Unit/TestResult.xml +projects/client/Unit*/TestResult.xml From 4943bbe3064e29a2047d6b47b96898f2adf25108 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Mon, 20 Apr 2015 12:25:55 +0300 Subject: [PATCH 10/10] Makes Unit.WinRT build and pass with msbuild.exe --- projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj | 3 +-- projects/client/Unit/RabbitMQ.Client.Unit.csproj | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj b/projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj index cc6058621f..3183ab9bd4 100644 --- a/projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj +++ b/projects/client/Unit.WinRT/RabbitMQ.Client.Unit.WinRT.csproj @@ -76,7 +76,6 @@ - @@ -113,7 +112,7 @@ - + diff --git a/projects/client/Unit/RabbitMQ.Client.Unit.csproj b/projects/client/Unit/RabbitMQ.Client.Unit.csproj index 55b39bc7ef..a9c36674d2 100644 --- a/projects/client/Unit/RabbitMQ.Client.Unit.csproj +++ b/projects/client/Unit/RabbitMQ.Client.Unit.csproj @@ -137,8 +137,10 @@ <_DisabledWarnings>$(NoWarn) + +