public void NoConflicts() { var accessPointA = new MockAccessPoint { ID = "a" }; var appEntry1 = new AppEntry { Name = "App1", InterfaceUri = FeedTest.Test1Uri, AccessPoints = new AccessPointList { Entries = { accessPointA } } }; var accessPointB = new MockAccessPoint { ID = "b" }; var appEntry2 = new AppEntry { Name = "App2", InterfaceUri = FeedTest.Test2Uri }; var appList = new AppList { Entries = { appEntry1 } }; appList.CheckForConflicts(new[] { accessPointB }, appEntry2); }
/// <inheritdoc/> protected override void RemoveAccessPointsInternal(AppEntry appEntry, IEnumerable <AccessPoint> accessPoints) { #region Sanity checks if (appEntry == null) { throw new ArgumentNullException("appEntry"); } if (accessPoints == null) { throw new ArgumentNullException("accessPoints"); } #endregion if (appEntry.AccessPoints == null) { return; } foreach (var accessPoint in accessPoints) { accessPoint.Unapply(appEntry, MachineWide); } // Remove the access points from the AppList appEntry.AccessPoints.Entries.RemoveRange(accessPoints); appEntry.Timestamp = DateTime.UtcNow; }
/// <inheritdoc/> public void RemoveAccessPoints(AppEntry appEntry, IEnumerable <AccessPoint> accessPoints) { #region Sanity checks if (appEntry == null) { throw new ArgumentNullException(nameof(appEntry)); } if (accessPoints == null) { throw new ArgumentNullException(nameof(accessPoints)); } #endregion try { RemoveAccessPointsInternal(appEntry, accessPoints); } catch (KeyNotFoundException ex) { // Wrap exception since only certain exception types are allowed throw new InvalidDataException(ex.Message, ex); } finally { Finish(); } }
/// <inheritdoc/> public void UpdateApp(AppEntry appEntry, Feed feed, Requirements requirements) { #region Sanity checks if (appEntry == null) { throw new ArgumentNullException(nameof(appEntry)); } if (feed == null) { throw new ArgumentNullException(nameof(feed)); } if (requirements == null) { throw new ArgumentNullException(nameof(requirements)); } #endregion try { appEntry.Requirements = requirements; UpdateAppInternal(appEntry, feed); } catch (KeyNotFoundException ex) { // Wrap exception since only certain exception types are allowed throw new InvalidDataException(ex.Message, ex); } finally { Finish(); } }
/// <summary> /// Tests the sync logic with pre-defined <see cref="AppList"/>s. /// local add: appEntry1, local remove: appEntry2, remote add: appEntry3, remote remove: appEntry4 /// </summary> /// <param name="resetMode">The <see cref="SyncResetMode"/> to pass to <see cref="SyncIntegrationManager.Sync"/>.</param> /// <param name="ap1Applied">The flag file used to indicate that <see cref="MockAccessPoint.Apply"/> was called for appEntry1.</param> /// <param name="ap1NotApplied">The flag file used to indicate that <see cref="MockAccessPoint.Unapply"/> was called for appEntry1.</param> /// <param name="ap2Applied">The flag file used to indicate that <see cref="MockAccessPoint.Apply"/> was called for appEntry2.</param> /// <param name="ap2NotApplied">The flag file used to indicate that <see cref="MockAccessPoint.Unapply"/> was called for appEntry2.</param> /// <param name="ap3Applied">The flag file used to indicate that <see cref="MockAccessPoint.Apply"/> was called for appEntry3.</param> /// <param name="ap3NotApplied">The flag file used to indicate that <see cref="MockAccessPoint.Unapply"/> was called for appEntry3.</param> /// <param name="ap4Applied">The flag file used to indicate that <see cref="MockAccessPoint.Apply"/> was called for appEntry4.</param> /// <param name="ap4NotApplied">The flag file used to indicate that <see cref="MockAccessPoint.Unapply"/> was called for appEntry4.</param> private static void TestSync(SyncResetMode resetMode, TemporaryFlagFile ap1Applied, TemporaryFlagFile ap1NotApplied, TemporaryFlagFile ap2Applied, TemporaryFlagFile ap2NotApplied, TemporaryFlagFile ap3Applied, TemporaryFlagFile ap3NotApplied, TemporaryFlagFile ap4Applied, TemporaryFlagFile ap4NotApplied) { var appEntry1 = new AppEntry { InterfaceUri = FeedTest.Test1Uri, AccessPoints = new AccessPointList { Entries = { new MockAccessPoint { ApplyFlagPath = ap1Applied, UnapplyFlagPath = ap1NotApplied } } } }; var appEntry2 = new AppEntry { InterfaceUri = FeedTest.Test2Uri, AccessPoints = new AccessPointList { Entries = { new MockAccessPoint { ApplyFlagPath = ap2Applied, UnapplyFlagPath = ap2NotApplied } } } }; var appEntry3 = new AppEntry { InterfaceUri = FeedTest.Test3Uri, AccessPoints = new AccessPointList { Entries = { new MockAccessPoint { ApplyFlagPath = ap3Applied, UnapplyFlagPath = ap3NotApplied } } } }; var appEntry4 = new AppEntry { InterfaceUri = new FeedUri("http://example.com/test4.xml"), AccessPoints = new AccessPointList { Entries = { new MockAccessPoint { ApplyFlagPath = ap4Applied, UnapplyFlagPath = ap4NotApplied } } } }; var appListLocal = new AppList { Entries = { appEntry1, appEntry4 } }; var appListLast = new AppList { Entries = { appEntry2, appEntry4 } }; var appListServer = new AppList { Entries = { appEntry2, appEntry3 } }; TestSync(resetMode, appListLocal, appListLast, appListServer); }
public void AccessPointCandidatesInternalConflict() { var accessPoints = new AccessPoint[] { new MockAccessPoint { ID = "a" }, new MockAccessPoint { ID = "a" } }; var appEntry = new AppEntry { Name = "App" }; Assert.Throws <ConflictException>(() => accessPoints.GetConflictData(appEntry)); }
public void AccessPointCandidatesInternalConflict() { var accessPoints = new AccessPoint[] { new MockAccessPoint { ID = "a" }, new MockAccessPoint { ID = "a" } }; var appEntry = new AppEntry { Name = "App" }; accessPoints.Invoking(x => x.GetConflictData(appEntry)).ShouldThrow <ConflictException>(); }
/// <summary> /// Toggles registry entries indicating whether icons for the application are currently visible. /// </summary> /// <param name="appEntry">The application being modified.</param> /// <param name="iconsVisible"><c>true</c> if the icons are currently visible, <c>false</c> if the icons are currently not visible.</param> /// <remarks>This is a special handler to support <see cref="Windows.DefaultProgram"/>.</remarks> private static void ToggleIconsVisible(AppEntry appEntry, bool iconsVisible) { #region Sanity checks if (appEntry == null) { throw new ArgumentNullException(nameof(appEntry)); } #endregion foreach (var defaultProgram in appEntry.CapabilityLists.CompatibleCapabilities().OfType <Store.Model.Capabilities.DefaultProgram>()) { Windows.DefaultProgram.ToggleIconsVisible(defaultProgram, iconsVisible); } }
/// <inheritdoc/> protected override void AddAccessPointsInternal(AppEntry appEntry, Feed feed, IEnumerable <AccessPoint> accessPoints) { #region Sanity checks if (appEntry == null) { throw new ArgumentNullException("appEntry"); } if (feed == null) { throw new ArgumentNullException("feed"); } if (accessPoints == null) { throw new ArgumentNullException("accessPoints"); } if (appEntry.AccessPoints != null && appEntry.AccessPoints.Entries == accessPoints) { throw new ArgumentException("Must not be equal to appEntry.AccessPoints.Entries", "accessPoints"); } #endregion // Skip entries with mismatching hostname if (appEntry.Hostname != null && !Regex.IsMatch(Environment.MachineName, appEntry.Hostname)) { return; } if (appEntry.AccessPoints == null) { appEntry.AccessPoints = new AccessPointList(); } AppList.CheckForConflicts(accessPoints, appEntry); accessPoints.ApplyWithRollback( accessPoint => accessPoint.Apply(appEntry, feed, Handler, MachineWide), accessPoint => { // Don't perform rollback if the access point was already applied previously and this was only a refresh if (!appEntry.AccessPoints.Entries.Contains(accessPoint)) { accessPoint.Unapply(appEntry, MachineWide); } }); appEntry.AccessPoints.Entries.RemoveRange(accessPoints); // Replace pre-existing entries appEntry.AccessPoints.Entries.AddRange(accessPoints); appEntry.Timestamp = DateTime.UtcNow; }
public void AccessPointCandidates() { var accessPoints = new AccessPoint[] { new MockAccessPoint { ID = "a" }, new MockAccessPoint { ID = "b" } }; var appEntry = new AppEntry { Name = "App" }; accessPoints.GetConflictData(appEntry).Should().Equal(new Dictionary <string, ConflictData>() { { "mock:a", new ConflictData(accessPoints[0], appEntry) }, { "mock:b", new ConflictData(accessPoints[1], appEntry) } }); }
public void TestAddApp() { var capabilityList = CapabilityListTest.CreateTestCapabilityList(); var target = new FeedTarget(FeedTest.Test1Uri, new Feed { Name = "Test", CapabilityLists = { capabilityList } }); _integrationManager.AddApp(target); var expectedAppEntry = new AppEntry { InterfaceUri = FeedTest.Test1Uri, Name = target.Feed.Name, CapabilityLists = { capabilityList } }; CollectionAssert.AreEqual(new[] { expectedAppEntry }, _integrationManager.AppList.Entries); Assert.Throws <InvalidOperationException>(() => _integrationManager.AddApp(target), "Do not allow adding applications to AppList more than once."); }
public void TestFindAppAlias() { var appAlias = new AppAlias { Name = "foobar" }; var appEntry = new AppEntry { AccessPoints = new AccessPointList { Entries = { appAlias } } }; var appList = new AppList { Entries = { appEntry } }; appList.FindAppAlias("foobar").Should().Be((appAlias, appEntry)); appList.FindAppAlias("other").Should().BeNull(); }
/// <inheritdoc/> protected override void UpdateAppInternal(AppEntry appEntry, Feed feed) { #region Sanity checks if (appEntry == null) { throw new ArgumentNullException("appEntry"); } if (feed == null) { throw new ArgumentNullException("feed"); } #endregion // Temporarily remove capability-based access points but remember them for later reapplication var toReapply = new List <AccessPoint>(); if (appEntry.AccessPoints != null) { toReapply.AddRange(appEntry.AccessPoints.Entries.Where(accessPoint => accessPoint is DefaultAccessPoint || accessPoint is CapabilityRegistration)); } RemoveAccessPointsInternal(appEntry, toReapply); // Update metadata and capabilities appEntry.Name = feed.Name; appEntry.CapabilityLists.Clear(); appEntry.CapabilityLists.AddRange(feed.CapabilityLists.CloneElements()); // Reapply removed access points dumping any that have become incompatible foreach (var accessPoint in toReapply) { try { AddAccessPointsInternal(appEntry, feed, new[] { accessPoint }); } #region Error handling catch (KeyNotFoundException) { Log.Warn(string.Format("Access point '{0}' no longer compatible with interface '{1}'.", accessPoint, appEntry.InterfaceUri)); } #endregion } WriteAppDir(appEntry); appEntry.Timestamp = DateTime.UtcNow; }
//--------------------// #region Apps /// <inheritdoc/> protected override AppEntry AddAppInternal(FeedTarget target) { // Prevent double entries if (AppList.ContainsEntry(target.Uri)) { throw new InvalidOperationException(string.Format(Resources.AppAlreadyInList, target.Feed.Name)); } // Get basic metadata and copy of capabilities from feed var appEntry = new AppEntry { InterfaceUri = target.Uri, Name = target.Feed.Name, Timestamp = DateTime.UtcNow }; appEntry.CapabilityLists.AddRange(target.Feed.CapabilityLists.CloneElements()); AppList.Entries.Add(appEntry); WriteAppDir(appEntry); return(appEntry); }
public void AccessPointCandidates() { var accessPoints = new AccessPoint[] { new MockAccessPoint { ID = "a" }, new MockAccessPoint { ID = "b" } }; var appEntry = new AppEntry { Name = "App" }; CollectionAssert.AreEqual( expected: new[] { new KeyValuePair <string, ConflictData>("mock:a", new ConflictData(accessPoints[0], appEntry)), new KeyValuePair <string, ConflictData>("mock:b", new ConflictData(accessPoints[1], appEntry)) }, actual: accessPoints.GetConflictData(appEntry)); }
public void TestSearch() { var appA = new AppEntry { InterfaceUri = FeedTest.Test1Uri, Name = "AppA" }; var appB = new AppEntry { InterfaceUri = FeedTest.Test2Uri, Name = "AppB" }; var lib = new AppEntry { InterfaceUri = FeedTest.Test3Uri, Name = "Lib" }; var appList = new AppList { Entries = { appA, appB, lib } }; appList.Search("").Should().Equal(appA, appB, lib); appList.Search("App").Should().Equal(appA, appB); appList.Search("AppA").Should().Equal(appA); appList.Search("AppB").Should().Equal(appB); }
/// <inheritdoc/> protected override void RepairAppInternal(AppEntry appEntry, Feed feed) { #region Sanity checks if (appEntry == null) { throw new ArgumentNullException("appEntry"); } if (feed == null) { throw new ArgumentNullException("feed"); } #endregion var toReAdd = (appEntry.AccessPoints == null) ? Enumerable.Empty <AccessPoint>() : appEntry.AccessPoints.Entries.ToList(); AddAccessPointsInternal(appEntry, feed, toReAdd); WriteAppDir(appEntry); }
public void TestSearch() { var appA = new AppEntry { InterfaceUri = FeedTest.Test1Uri, Name = "AppA" }; var appB = new AppEntry { InterfaceUri = FeedTest.Test2Uri, Name = "AppB" }; var lib = new AppEntry { InterfaceUri = FeedTest.Test3Uri, Name = "Lib" }; var appList = new AppList { Entries = { appA, appB, lib } }; CollectionAssert.AreEqual(expected: new[] { appA, appB, lib }, actual: appList.Search("")); CollectionAssert.AreEqual(expected: new[] { appA, appB }, actual: appList.Search("App")); CollectionAssert.AreEqual(expected: new[] { appA }, actual: appList.Search("AppA")); CollectionAssert.AreEqual(expected: new[] { appB }, actual: appList.Search("AppB")); }
/// <inheritdoc/> protected override void AddAppInternal(AppEntry prototype, Converter <FeedUri, Feed> feedRetriever) { #region Sanity checks if (prototype == null) { throw new ArgumentNullException("prototype"); } if (feedRetriever == null) { throw new ArgumentNullException("feedRetriever"); } #endregion var appEntry = prototype.Clone(); AppList.Entries.Add(appEntry); WriteAppDir(appEntry); if (appEntry.AccessPoints != null) { AddAccessPointsInternal(appEntry, feedRetriever(appEntry.InterfaceUri), appEntry.AccessPoints.Clone().Entries); } }
/// <inheritdoc/> protected override void RemoveAppInternal(AppEntry appEntry) { #region Sanity checks if (appEntry == null) { throw new ArgumentNullException("appEntry"); } #endregion DeleteAppDir(appEntry); if (appEntry.AccessPoints != null) { // Unapply any remaining access points foreach (var accessPoint in appEntry.AccessPoints.Entries) { accessPoint.Unapply(appEntry, MachineWide); } } AppList.Entries.Remove(appEntry); }
/// <inheritdoc/> public void RemoveApp(AppEntry appEntry) { #region Sanity checks if (appEntry == null) { throw new ArgumentNullException("appEntry"); } #endregion try { RemoveAppInternal(appEntry); } catch (KeyNotFoundException ex) { // Wrap exception since only certain exception types are allowed throw new InvalidDataException(ex.Message, ex); } finally { Finish(); } }
public void Conflict() { var accessPointA = new MockAccessPoint { ID = "a" }; var appEntry1 = new AppEntry { Name = "App1", InterfaceUri = FeedTest.Test1Uri, AccessPoints = new AccessPointList { Entries = { accessPointA } } }; var appEntry2 = new AppEntry { Name = "App2", InterfaceUri = FeedTest.Test2Uri }; var appList = new AppList { Entries = { appEntry1 } }; Assert.Throws <ConflictException>(() => appList.CheckForConflicts(new[] { accessPointA }, appEntry2)); }
public void Conflict() { var accessPointA = new MockAccessPoint { ID = "a" }; var appEntry1 = new AppEntry { Name = "App1", InterfaceUri = FeedTest.Test1Uri, AccessPoints = new AccessPointList { Entries = { accessPointA } } }; var appEntry2 = new AppEntry { Name = "App2", InterfaceUri = FeedTest.Test2Uri }; var appList = new AppList { Entries = { appEntry1 } }; appList.Invoking(x => x.CheckForConflicts(new[] { accessPointA }, appEntry2)) .ShouldThrow <ConflictException>(); }
/// <summary> /// Reapplies all <see cref="AccessPoint"/>s for a specific <see cref="AppEntry"/>. /// </summary> /// <param name="appEntry">The application entry to repair.</param> /// <param name="feed">The feed providing additional metadata, capabilities, etc. for the application.</param> /// <exception cref="OperationCanceledException">The user canceled the task.</exception> /// <exception cref="ConflictException"><paramref name="appEntry"/> conflicts with the rest of the <see cref="AppList"/>.</exception> /// <exception cref="InvalidDataException">One of the <see cref="AccessPoint"/>s or <see cref="Capability"/>s is invalid.</exception> /// <exception cref="WebException">A problem occurred while downloading additional data (such as icons).</exception> /// <exception cref="IOException">A problem occurred while writing to the filesystem or registry.</exception> /// <exception cref="UnauthorizedAccessException">Write access to the filesystem or registry is not permitted.</exception> protected abstract void RepairAppInternal(AppEntry appEntry, Feed feed);
/// <summary> /// Removes already applied <see cref="AccessPoint"/>s for an application. /// </summary> /// <param name="appEntry">The <see cref="AppEntry"/> containing the <paramref name="accessPoints"/>.</param> /// <param name="accessPoints">The access points to unapply.</param> /// <exception cref="KeyNotFoundException">An <see cref="AccessPoint"/> reference to a <see cref="Capability"/> is invalid.</exception> /// <exception cref="InvalidDataException">One of the <see cref="AccessPoint"/>s or <see cref="Capability"/>s is invalid.</exception> /// <exception cref="IOException">A problem occurred while writing to the filesystem or registry.</exception> /// <exception cref="UnauthorizedAccessException">Write access to the filesystem or registry is not permitted.</exception> protected abstract void RemoveAccessPointsInternal(AppEntry appEntry, IEnumerable <AccessPoint> accessPoints);
/// <summary> /// Applies <see cref="AccessPoint"/>s for an application. /// </summary> /// <param name="appEntry">The application being integrated.</param> /// <param name="feed">The feed providing additional metadata, icons, etc. for the application.</param> /// <param name="accessPoints">The access points to apply.</param> /// <exception cref="ArgumentException"><see cref="AccessPointList.Entries"/> from <paramref name="appEntry"/> is the same reference as <paramref name="accessPoints"/>.</exception> /// <exception cref="OperationCanceledException">The user canceled the task.</exception> /// <exception cref="KeyNotFoundException">An <see cref="AccessPoint"/> reference to a <see cref="Capability"/> is invalid.</exception> /// <exception cref="ConflictException">One or more of the <paramref name="accessPoints"/> would cause a conflict with the existing <see cref="AccessPoint"/>s in <see cref="IIntegrationManager.AppList"/>.</exception> /// <exception cref="InvalidDataException">One of the <see cref="AccessPoint"/>s or <see cref="Capability"/>s is invalid.</exception> /// <exception cref="WebException">A problem occurred while downloading additional data (such as icons).</exception> /// <exception cref="IOException">A problem occurred while writing to the filesystem or registry.</exception> /// <exception cref="UnauthorizedAccessException">Write access to the filesystem or registry is not permitted.</exception> protected abstract void AddAccessPointsInternal(AppEntry appEntry, Feed feed, IEnumerable <AccessPoint> accessPoints);
/// <summary> /// Updates an <see cref="AppEntry"/> with new metadata and capabilities from a <see cref="Feed"/>. This may unapply and remove some existing <see cref="AccessPoint"/>s. /// </summary> /// <exception cref="KeyNotFoundException">An <see cref="AccessPoint"/> reference to a <see cref="Capability"/> is invalid.</exception> /// <exception cref="InvalidDataException">One of the <see cref="AccessPoint"/>s or <see cref="Capability"/>s is invalid.</exception> /// <param name="appEntry">The application entry to update.</param> /// <param name="feed">The feed providing additional metadata, capabilities, etc. for the application.</param> protected abstract void UpdateAppInternal(AppEntry appEntry, Feed feed);
/// <summary> /// Removes an <see cref="AppEntry"/> from the <see cref="AppList"/> while unapplying any remaining <see cref="AccessPoint"/>s. /// </summary> /// <param name="appEntry">The application to remove.</param> /// <exception cref="KeyNotFoundException">An <see cref="AccessPoint"/> reference to a <see cref="Capability"/> is invalid.</exception> /// <exception cref="InvalidDataException">One of the <see cref="AccessPoint"/>s or <see cref="Capability"/>s is invalid.</exception> /// <exception cref="IOException">A problem occurred while writing to the filesystem or registry.</exception> /// <exception cref="UnauthorizedAccessException">Write access to the filesystem or registry is not permitted.</exception> protected abstract void RemoveAppInternal(AppEntry appEntry);
/// <summary> /// Creates a new <see cref="AppEntry"/> based on an existing prototype (applying any <see cref="AccessPoint"/>s) and adds it to the <see cref="AppList"/>. /// </summary> /// <param name="prototype">An existing <see cref="AppEntry"/> to use as a prototype.</param> /// <param name="feedRetriever">Callback method used to retrieve additional <see cref="Feed"/>s on demand.</param> protected abstract void AddAppInternal(AppEntry prototype, Converter <FeedUri, Feed> feedRetriever);
/// <summary> /// Reapplies all <see cref="AccessPoint"/>s for a specific <see cref="AppEntry"/>. /// </summary> /// <param name="appEntry">The application entry to repair.</param> /// <param name="feed">The feed providing additional metadata, capabilities, etc. for the application.</param> /// <exception cref="OperationCanceledException">The user canceled the task.</exception> /// <exception cref="ConflictException"><paramref name="appEntry"/> conflicts with the rest of the <see cref="AppList"/>.</exception> /// <exception cref="InvalidDataException">One of the <see cref="AccessPoint"/>s or <see cref="Store.Model.Capabilities.Capability"/>s is invalid.</exception> /// <exception cref="WebException">A problem occured while downloading additional data (such as icons).</exception> /// <exception cref="IOException">A problem occurs while writing to the filesystem or registry.</exception> /// <exception cref="UnauthorizedAccessException">Write access to the filesystem or registry is not permitted.</exception> protected abstract void RepairAppInternal([NotNull] AppEntry appEntry, [NotNull] Feed feed);