// 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);
}
}
}
}