// Copyright Keysight Technologies 2012-2019 // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, you can obtain one at http://mozilla.org/MPL/2.0/. using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Threading; namespace OpenTap { /// /// Represents a reference to a resource. A reference is defined as something in the TestPlan that references a Resource, and thus causes it to get opened. Used by /// public class ResourceReference { /// /// The TestStep or other Resource that is using some Resource /// public object Instance { get; } /// /// The property on that references the Resource /// public PropertyInfo Property { get; } /// The property that references the Resource. public IMemberData Member { get; } /// Creates an immutable instance of this class. public ResourceReference(object obj, PropertyInfo prop) { Instance = obj; Property = prop; Member = MemberData.Create(prop); } /// Creates an immutable instance of this class. public ResourceReference(object obj, IMemberData prop) { Instance = obj; Member = prop; if (prop is MemberData md) Property = md.Member as PropertyInfo; } } /// /// Used in to represents a resource and its references /// public interface IResourceReferences { /// /// The resource this item represents. /// IResource Resource { get; set; } /// /// References to from TestSteps (or other Resources). These references are the reason this resources needs to be opened when running a TestPlan. /// List References { get; } } /// /// Implementing this interface will enable hooks before and after resources are opened and closed. /// public interface ILockManager : ITapPlugin { /// /// This hook is triggered before is executed. Only called once when e.g. a TestStep with mulitple resources starts. /// /// The resources that will be opened. /// A token that will be signalled if the locking action should be cancelled. void BeforeOpen(IEnumerable resources, CancellationToken abortToken); /// /// This hook is triggered after the TestStep or TestPlan is done executing. If triggered by a TestStep, defered actions may still be running. /// /// This will contain the same resources as given to ". /// A token that will be signalled if the locking action should be cancelled. void AfterClose(IEnumerable resources, CancellationToken abortToken); } class LockManager { readonly ILockManager[] managers; static readonly TraceSource log = Log.CreateSource("LockManager"); public LockManager() { managers = PluginManager.GetPlugins() .OrderByDescending(t => t.GetDisplayAttribute().Order) .TrySelect(t => (ILockManager)t.CreateInstance(), (ex, t) => { log.Error("Unable to create an instance of {0}: {1}", t, ex.Message); log.Debug(ex); }) .ToArray(); } internal void BeforeOpen(IEnumerable resources, CancellationToken cancellationToken) { foreach (ILockManager lockManager in managers) { lockManager.BeforeOpen(resources, cancellationToken); } } internal void AfterClose(IEnumerable resources, CancellationToken cancellationToken) { foreach (ILockManager lockManager in Enumerable.Reverse(managers)) { lockManager.AfterClose(resources, cancellationToken); } } } }