diff --git a/src/Lithnet.GoogleApps.MA.Setup/Product.wxs b/src/Lithnet.GoogleApps.MA.Setup/Product.wxs index b5c0a92..58ed7ac 100644 --- a/src/Lithnet.GoogleApps.MA.Setup/Product.wxs +++ b/src/Lithnet.GoogleApps.MA.Setup/Product.wxs @@ -3,7 +3,7 @@ diff --git a/src/Lithnet.GoogleApps.MA.UnitTests/AdvancedUserTests.cs b/src/Lithnet.GoogleApps.MA.UnitTests/AdvancedUserTests.cs index fe366b5..5942fed 100644 --- a/src/Lithnet.GoogleApps.MA.UnitTests/AdvancedUserTests.cs +++ b/src/Lithnet.GoogleApps.MA.UnitTests/AdvancedUserTests.cs @@ -262,6 +262,7 @@ public void Update() Department = "test", Symbol = "test", Location = "test", + Type = "work" }); e.Phones = new List(); diff --git a/src/Lithnet.GoogleApps.MA.UnitTests/GroupTests.cs b/src/Lithnet.GoogleApps.MA.UnitTests/GroupTests.cs index c9d5a62..e15f31f 100644 --- a/src/Lithnet.GoogleApps.MA.UnitTests/GroupTests.cs +++ b/src/Lithnet.GoogleApps.MA.UnitTests/GroupTests.cs @@ -1,25 +1,16 @@ using System; -using System.Text; using System.Collections.Generic; using Microsoft.VisualStudio.TestTools.UnitTesting; -using Lithnet.GoogleApps; -using Lithnet.GoogleApps.MA; +using Microsoft.MetadirectoryServices; +using System.Linq; +using System.Net; +using Google; +using Google.Apis.Admin.Directory.directory_v1.Data; +using Lithnet.GoogleApps.ManagedObjects; +using Lithnet.MetadirectoryServices; namespace Lithnet.GoogleApps.MA.UnitTests { - using System.Linq; - using System.Net; - using System.Net.Security; - using System.Security.Cryptography.X509Certificates; - using Google; - using Google.Apis.Admin.Directory.directory_v1.Data; - using Google.GData.Contacts; - using Google.GData.Extensions; - using Lithnet.GoogleApps.MA; - using ManagedObjects; - using MetadirectoryServices; - using Microsoft.MetadirectoryServices; - [TestClass] public class GroupTests { @@ -39,9 +30,11 @@ public void Add() cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("allowWebPosting", true)); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("archiveOnly", false)); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("customReplyTo", "test@test.com")); + cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("customFooterText", "custom footer")); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("defaultMessageDenyNotificationText", "occupation")); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("includeInGlobalAddressList", true)); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("isArchived", false)); + cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("includeCustomFooter", true)); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("maxMessageBytes", 5000000)); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("membersCanPostAsTheGroup", true)); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("messageDisplayFont", "DEFAULT_FONT")); @@ -50,6 +43,7 @@ public void Add() cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("sendMessageDenyNotification", true)); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("showInGroupDirectory", true)); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("spamModerationLevel", "SILENTLY_MODERATE")); + cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("whoCanAdd", "ALL_MANAGERS_CAN_ADD")); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("whoCanContactOwner", "ANYONE_CAN_CONTACT")); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("whoCanInvite", "NONE_CAN_INVITE")); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("whoCanJoin", "CAN_REQUEST_TO_JOIN")); @@ -91,8 +85,10 @@ public void Add() Assert.AreEqual(true, s.AllowWebPosting); Assert.AreEqual(false, s.ArchiveOnly); Assert.AreEqual("test@test.com", s.CustomReplyTo); + Assert.AreEqual("custom footer", s.CustomFooterText); Assert.AreEqual("occupation", s.DefaultMessageDenyNotificationText); Assert.AreEqual(true, s.IncludeInGlobalAddressList); + Assert.AreEqual(true, s.IncludeCustomFooter); Assert.AreEqual(false, s.IsArchived); Assert.AreEqual(5000000, s.MaxMessageBytes); Assert.AreEqual(true, s.MembersCanPostAsTheGroup); @@ -103,6 +99,7 @@ public void Add() Assert.AreEqual(true, s.ShowInGroupDirectory); Assert.AreEqual("SILENTLY_MODERATE", s.SpamModerationLevel); Assert.AreEqual(true, s.ShowInGroupDirectory); + Assert.AreEqual("ALL_MANAGERS_CAN_ADD", s.WhoCanAdd); Assert.AreEqual("ANYONE_CAN_CONTACT", s.WhoCanContactOwner); Assert.AreEqual("NONE_CAN_INVITE", s.WhoCanInvite); Assert.AreEqual("CAN_REQUEST_TO_JOIN", s.WhoCanJoin); @@ -151,9 +148,11 @@ public void Update() cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("allowWebPosting", true)); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("archiveOnly", false)); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("customReplyTo", "test@test.com")); + cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("customFooterText", "custom footer")); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("defaultMessageDenyNotificationText", "occupation")); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("includeInGlobalAddressList", true)); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("isArchived", false)); + cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("includeCustomFooter", true)); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("maxMessageBytes", 5000000)); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("membersCanPostAsTheGroup", true)); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("messageDisplayFont", "DEFAULT_FONT")); @@ -162,6 +161,7 @@ public void Update() cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("sendMessageDenyNotification", true)); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("showInGroupDirectory", true)); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("spamModerationLevel", "SILENTLY_MODERATE")); + cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("whoCanAdd", "ALL_MANAGERS_CAN_ADD")); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("whoCanContactOwner", "ANYONE_CAN_CONTACT")); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("whoCanInvite", "NONE_CAN_INVITE")); cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("whoCanJoin", "CAN_REQUEST_TO_JOIN")); @@ -199,8 +199,10 @@ public void Update() Assert.AreEqual(true, s.AllowWebPosting); Assert.AreEqual(false, s.ArchiveOnly); Assert.AreEqual("test@test.com", s.CustomReplyTo); + Assert.AreEqual("custom footer", s.CustomFooterText); Assert.AreEqual("occupation", s.DefaultMessageDenyNotificationText); Assert.AreEqual(true, s.IncludeInGlobalAddressList); + Assert.AreEqual(true, s.IncludeCustomFooter); Assert.AreEqual(false, s.IsArchived); Assert.AreEqual(5000000, s.MaxMessageBytes); Assert.AreEqual(true, s.MembersCanPostAsTheGroup); @@ -211,6 +213,7 @@ public void Update() Assert.AreEqual(true, s.ShowInGroupDirectory); Assert.AreEqual("SILENTLY_MODERATE", s.SpamModerationLevel); Assert.AreEqual(true, s.ShowInGroupDirectory); + Assert.AreEqual("ALL_MANAGERS_CAN_ADD", s.WhoCanAdd); Assert.AreEqual("ANYONE_CAN_CONTACT", s.WhoCanContactOwner); Assert.AreEqual("NONE_CAN_INVITE", s.WhoCanInvite); Assert.AreEqual("CAN_REQUEST_TO_JOIN", s.WhoCanJoin); @@ -449,29 +452,6 @@ public void RemoveAliases() } - [TestMethod] - public void test() - { - string id = null; - string dn = $"{Guid.NewGuid()}-d1@{UnitTestControl.TestParameters.Domain}"; - Group e = new Group - { - Email = dn, - Name = Guid.NewGuid().ToString() - }; - - e = GroupRequestFactory.Add(e); - id = e.Id; - - string alias1 = $"{Guid.NewGuid()}@{UnitTestControl.TestParameters.Domain}"; - string alias2 = $"{Guid.NewGuid()}@{UnitTestControl.TestParameters.Domain}"; - string alias3 = $"{Guid.NewGuid()}@{UnitTestControl.TestParameters.Domain}"; - - GroupRequestFactory.AddAlias(id, alias1); - GroupRequestFactory.AddAlias(id, alias2); - - } - [TestMethod] public void AddAlias() { diff --git a/src/Lithnet.GoogleApps.MA.UnitTests/Lithnet.GoogleApps.MA.UnitTests.csproj b/src/Lithnet.GoogleApps.MA.UnitTests/Lithnet.GoogleApps.MA.UnitTests.csproj index 15dff33..e7b32ee 100644 --- a/src/Lithnet.GoogleApps.MA.UnitTests/Lithnet.GoogleApps.MA.UnitTests.csproj +++ b/src/Lithnet.GoogleApps.MA.UnitTests/Lithnet.GoogleApps.MA.UnitTests.csproj @@ -37,36 +37,36 @@ 4 - - ..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll + + ..\packages\BouncyCastle.1.8.1\lib\BouncyCastle.Crypto.dll True - - ..\packages\Google.Apis.1.11.1\lib\net45\Google.Apis.dll + + ..\packages\Google.Apis.1.16.0\lib\net45\Google.Apis.dll True - - ..\packages\Google.Apis.Admin.Directory.directory_v1.1.12.0.447\lib\portable-net45+netcore45+wpa81+wp8\Google.Apis.Admin.Directory.directory_v1.dll + + ..\packages\Google.Apis.Admin.Directory.directory_v1.1.16.0.601\lib\portable-net45+netcore45+wpa81+wp8\Google.Apis.Admin.Directory.directory_v1.dll True - - ..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.dll + + ..\packages\Google.Apis.Auth.1.16.0\lib\net45\Google.Apis.Auth.dll True - - ..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.PlatformServices.dll + + ..\packages\Google.Apis.Auth.1.16.0\lib\net45\Google.Apis.Auth.PlatformServices.dll True - - ..\packages\Google.Apis.Core.1.11.1\lib\net45\Google.Apis.Core.dll + + ..\packages\Google.Apis.Core.1.16.0\lib\net45\Google.Apis.Core.dll True - - ..\packages\Google.Apis.Groupssettings.v1.1.12.0.447\lib\portable-net45+netcore45+wpa81+wp8\Google.Apis.Groupssettings.v1.dll + + ..\packages\Google.Apis.Groupssettings.v1.1.16.0.510\lib\portable-net45+netcore45+wpa81+wp8\Google.Apis.Groupssettings.v1.dll True - - ..\packages\Google.Apis.1.11.1\lib\net45\Google.Apis.PlatformServices.dll + + ..\packages\Google.Apis.1.16.0\lib\net45\Google.Apis.PlatformServices.dll True @@ -85,16 +85,16 @@ ..\packages\Google.GData.Extensions.2.2.0.0\lib\Google.GData.Extensions.dll True - - ..\packages\Lithnet.GoogleApps.1.0.6027.26510\lib\net452\Lithnet.GoogleApps.dll + + ..\packages\Lithnet.GoogleApps.1.0.6086.35275\lib\net452\Lithnet.GoogleApps.dll True ..\packages\Lithnet.Logging.1.0.5774.20685\lib\net40\Lithnet.Logging.dll True - - ..\packages\Lithnet.MetadirectoryServices.1.0.6006.11723\lib\net40\Lithnet.MetadirectoryServices.dll + + ..\packages\Lithnet.MetadirectoryServices.1.0.6017.24789\lib\net40\Lithnet.MetadirectoryServices.dll True @@ -102,8 +102,8 @@ True - - ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll + + ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll True diff --git a/src/Lithnet.GoogleApps.MA.UnitTests/UserTests.cs b/src/Lithnet.GoogleApps.MA.UnitTests/UserTests.cs index 03aa424..d32e917 100644 --- a/src/Lithnet.GoogleApps.MA.UnitTests/UserTests.cs +++ b/src/Lithnet.GoogleApps.MA.UnitTests/UserTests.cs @@ -261,6 +261,7 @@ public void Update() Department = "test", Symbol = "test", Location = "test", + Type = "work" }); e.Phones = new List(); diff --git a/src/Lithnet.GoogleApps.MA.UnitTests/app.config b/src/Lithnet.GoogleApps.MA.UnitTests/app.config index c6c91e4..8b156b1 100644 --- a/src/Lithnet.GoogleApps.MA.UnitTests/app.config +++ b/src/Lithnet.GoogleApps.MA.UnitTests/app.config @@ -15,7 +15,7 @@ - + @@ -25,6 +25,26 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Lithnet.GoogleApps.MA.UnitTests/packages.config b/src/Lithnet.GoogleApps.MA.UnitTests/packages.config index 86671cb..c5ce245 100644 --- a/src/Lithnet.GoogleApps.MA.UnitTests/packages.config +++ b/src/Lithnet.GoogleApps.MA.UnitTests/packages.config @@ -1,20 +1,20 @@  - - - - - - + + + + + + - + - + - + \ No newline at end of file diff --git a/src/Lithnet.GoogleApps.MA/ApiInterfaces/ApiInterfaceUserAliases.cs b/src/Lithnet.GoogleApps.MA/ApiInterfaces/ApiInterfaceUserAliases.cs index c44dc46..34b731a 100644 --- a/src/Lithnet.GoogleApps.MA/ApiInterfaces/ApiInterfaceUserAliases.cs +++ b/src/Lithnet.GoogleApps.MA/ApiInterfaces/ApiInterfaceUserAliases.cs @@ -135,7 +135,8 @@ private static AttributeChange ApplyUserAliasChanges(CSEntryChange csentry, User } catch (Google.GoogleApiException ex) { - if (ex.HttpStatusCode == System.Net.HttpStatusCode.NotFound) + if (ex.HttpStatusCode == System.Net.HttpStatusCode.NotFound || + ex.Error?.Message == "Invalid Input: resource_id") { Logger.WriteLine($"Alias {alias} does not exist on object"); } diff --git a/src/Lithnet.GoogleApps.MA/AttributeAdapters/AdapterPropertyValue.cs b/src/Lithnet.GoogleApps.MA/AttributeAdapters/AdapterPropertyValue.cs index 6b6b7ae..1c5f63a 100644 --- a/src/Lithnet.GoogleApps.MA/AttributeAdapters/AdapterPropertyValue.cs +++ b/src/Lithnet.GoogleApps.MA/AttributeAdapters/AdapterPropertyValue.cs @@ -129,6 +129,11 @@ public IEnumerable CreateAttributeChanges(string dn, ObjectModi this.propInfo = obj.GetType().GetProperty(this.PropertyName); } + if (this.propInfo == null) + { + throw new InvalidOperationException($"The property {this.PropertyName} was not found on the object of type {obj.GetType().FullName}"); + } + object value = this.propInfo.GetValue(obj); if (this.CastForImport != null) { diff --git a/src/Lithnet.GoogleApps.MA/Lithnet.GoogleApps.MA.csproj b/src/Lithnet.GoogleApps.MA/Lithnet.GoogleApps.MA.csproj index 7204f47..9233290 100644 --- a/src/Lithnet.GoogleApps.MA/Lithnet.GoogleApps.MA.csproj +++ b/src/Lithnet.GoogleApps.MA/Lithnet.GoogleApps.MA.csproj @@ -27,7 +27,8 @@ Properties v4.5.2 - e3a07efa + + @@ -110,36 +111,36 @@ - - ..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll + + ..\packages\BouncyCastle.1.8.1\lib\BouncyCastle.Crypto.dll True - - ..\packages\Google.Apis.1.11.1\lib\net45\Google.Apis.dll + + ..\packages\Google.Apis.1.16.0\lib\net45\Google.Apis.dll True - - ..\packages\Google.Apis.Admin.Directory.directory_v1.1.12.0.447\lib\portable-net45+netcore45+wpa81+wp8\Google.Apis.Admin.Directory.directory_v1.dll + + ..\packages\Google.Apis.Admin.Directory.directory_v1.1.16.0.601\lib\portable-net45+netcore45+wpa81+wp8\Google.Apis.Admin.Directory.directory_v1.dll True - - ..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.dll + + ..\packages\Google.Apis.Auth.1.16.0\lib\net45\Google.Apis.Auth.dll True - - ..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.PlatformServices.dll + + ..\packages\Google.Apis.Auth.1.16.0\lib\net45\Google.Apis.Auth.PlatformServices.dll True - - ..\packages\Google.Apis.Core.1.11.1\lib\net45\Google.Apis.Core.dll + + ..\packages\Google.Apis.Core.1.16.0\lib\net45\Google.Apis.Core.dll True - - ..\packages\Google.Apis.Groupssettings.v1.1.12.0.447\lib\portable-net45+netcore45+wpa81+wp8\Google.Apis.Groupssettings.v1.dll + + ..\packages\Google.Apis.Groupssettings.v1.1.16.0.510\lib\portable-net45+netcore45+wpa81+wp8\Google.Apis.Groupssettings.v1.dll True - - ..\packages\Google.Apis.1.11.1\lib\net45\Google.Apis.PlatformServices.dll + + ..\packages\Google.Apis.1.16.0\lib\net45\Google.Apis.PlatformServices.dll True @@ -158,16 +159,16 @@ ..\packages\Google.GData.Extensions.2.2.0.0\lib\Google.GData.Extensions.dll True - - ..\packages\Lithnet.GoogleApps.1.0.6027.26510\lib\net452\Lithnet.GoogleApps.dll + + ..\packages\Lithnet.GoogleApps.1.0.6086.35275\lib\net452\Lithnet.GoogleApps.dll True ..\packages\Lithnet.Logging.1.0.5774.20685\lib\net40\Lithnet.Logging.dll True - - ..\packages\Lithnet.MetadirectoryServices.1.0.6006.11723\lib\net40\Lithnet.MetadirectoryServices.dll + + ..\packages\Lithnet.MetadirectoryServices.1.0.6017.24789\lib\net40\Lithnet.MetadirectoryServices.dll True @@ -175,8 +176,8 @@ True - - ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll + + ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll True @@ -213,9 +214,8 @@ This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + - @@ -252,4 +252,5 @@ foreach (var item in filesToCleanup) + \ No newline at end of file diff --git a/src/Lithnet.GoogleApps.MA/Schema/SchemaBuilder.cs b/src/Lithnet.GoogleApps.MA/Schema/SchemaBuilder.cs index 514aa1e..45af377 100644 --- a/src/Lithnet.GoogleApps.MA/Schema/SchemaBuilder.cs +++ b/src/Lithnet.GoogleApps.MA/Schema/SchemaBuilder.cs @@ -1036,6 +1036,38 @@ private static void AddGroupMembers(MASchemaType type) private static void AddGroupSettings(MASchemaType type) { + AdapterPropertyValue includeCustomFooter = new AdapterPropertyValue + { + AttributeType = AttributeType.Boolean, + FieldName = "includeCustomFooter", + IsMultivalued = false, + Operation = AttributeOperation.ImportExport, + AttributeName = "includeCustomFooter", + PropertyName = "IncludeCustomFooter", + Api = "groupsettings", + SupportsPatch = true, + UseNullPlaceHolder = true, + IsArrayAttribute = false + }; + + type.Attributes.Add(includeCustomFooter); + + AdapterPropertyValue customFooterText = new AdapterPropertyValue + { + AttributeType = AttributeType.String, + FieldName = "customFooterText", + IsMultivalued = false, + Operation = AttributeOperation.ImportExport, + AttributeName = "customFooterText", + PropertyName = "CustomFooterText", + Api = "groupsettings", + SupportsPatch = true, + UseNullPlaceHolder = true, + IsArrayAttribute = false + }; + + type.Attributes.Add(customFooterText); + AdapterPropertyValue whoCanJoin = new AdapterPropertyValue { AttributeType = AttributeType.String, @@ -1100,20 +1132,21 @@ private static void AddGroupSettings(MASchemaType type) type.Attributes.Add(whoCanInvite); - //MASchemaAttribute whoCanAdd = new MASchemaAttribute - //{ - // AttributeType = AttributeType.String, - // FieldName = "whoCanAdd", - // IsMultivalued = false, - // Operation = AttributeOperation.ImportExport, - // AttributeName = "whoCanAdd", - // PropertyName = "WhoCanAdd", - // Api = "groupsettings", - // SupportsPatch = true, - // IsArrayAttribute = false - //}; - // - //type.Attributes.Add(whoCanAdd); + AdapterPropertyValue whoCanAdd = new AdapterPropertyValue + { + AttributeType = AttributeType.String, + FieldName = "whoCanAdd", + IsMultivalued = false, + Operation = AttributeOperation.ImportExport, + AttributeName = "whoCanAdd", + PropertyName = "WhoCanAdd", + Api = "groupsettings", + SupportsPatch = true, + UseNullPlaceHolder = true, + IsArrayAttribute = false + }; + + type.Attributes.Add(whoCanAdd); AdapterPropertyValue allowExternalMembers = new AdapterPropertyValue { diff --git a/src/Lithnet.GoogleApps.MA/app.config b/src/Lithnet.GoogleApps.MA/app.config index 274e829..5726040 100644 --- a/src/Lithnet.GoogleApps.MA/app.config +++ b/src/Lithnet.GoogleApps.MA/app.config @@ -4,7 +4,7 @@ - + diff --git a/src/Lithnet.GoogleApps.MA/packages.config b/src/Lithnet.GoogleApps.MA/packages.config index 1e685d6..82b2f18 100644 --- a/src/Lithnet.GoogleApps.MA/packages.config +++ b/src/Lithnet.GoogleApps.MA/packages.config @@ -1,22 +1,22 @@  - + - - - - - - + + + + + + - + - + - + \ No newline at end of file