| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 | #pragma warning disable CS1591using System;using System.Collections.Generic;using System.Threading.Tasks;using Emby.Server.Implementations.HttpServer;using MediaBrowser.Model.Services;using Microsoft.Extensions.Logging;namespace Emby.Server.Implementations.Services{    public delegate object ActionInvokerFn(object intance, object request);    public delegate void VoidActionInvokerFn(object intance, object request);    public class ServiceController    {        private readonly ILogger<ServiceController> _logger;        /// <summary>        /// Initializes a new instance of the <see cref="ServiceController"/> class.        /// </summary>        /// <param name="logger">The <see cref="ServiceController"/> logger.</param>        public ServiceController(ILogger<ServiceController> logger)        {            _logger = logger;        }        public void Init(HttpListenerHost appHost, IEnumerable<Type> serviceTypes)        {            foreach (var serviceType in serviceTypes)            {                RegisterService(appHost, serviceType);            }        }        public void RegisterService(HttpListenerHost appHost, Type serviceType)        {            // Make sure the provided type implements IService            if (!typeof(IService).IsAssignableFrom(serviceType))            {                _logger.LogWarning("Tried to register a service that does not implement IService: {ServiceType}", serviceType);                return;            }            var processedReqs = new HashSet<Type>();            var actions = ServiceExecGeneral.Reset(serviceType);            foreach (var mi in serviceType.GetActions())            {                var requestType = mi.GetParameters()[0].ParameterType;                if (processedReqs.Contains(requestType))                {                    continue;                }                processedReqs.Add(requestType);                ServiceExecGeneral.CreateServiceRunnersFor(requestType, actions);                // var returnMarker = GetTypeWithGenericTypeDefinitionOf(requestType, typeof(IReturn<>));                // var responseType = returnMarker != null ?                //      GetGenericArguments(returnMarker)[0]                //    : mi.ReturnType != typeof(object) && mi.ReturnType != typeof(void) ?                //      mi.ReturnType                //    : Type.GetType(requestType.FullName + "Response");                RegisterRestPaths(appHost, requestType, serviceType);                appHost.AddServiceInfo(serviceType, requestType);            }        }        public readonly RestPath.RestPathMap RestPathMap = new RestPath.RestPathMap();        public void RegisterRestPaths(HttpListenerHost appHost, Type requestType, Type serviceType)        {            var attrs = appHost.GetRouteAttributes(requestType);            foreach (var attr in attrs)            {                var restPath = new RestPath(appHost.CreateInstance, appHost.GetParseFn, requestType, serviceType, attr.Path, attr.Verbs, attr.IsHidden, attr.Summary, attr.Description);                RegisterRestPath(restPath);            }        }        private static readonly char[] InvalidRouteChars = new[] { '?', '&' };        public void RegisterRestPath(RestPath restPath)        {            if (restPath.Path[0] != '/')            {                throw new ArgumentException(string.Format("Route '{0}' on '{1}' must start with a '/'", restPath.Path, restPath.RequestType.GetMethodName()));            }            if (restPath.Path.IndexOfAny(InvalidRouteChars) != -1)            {                throw new ArgumentException(string.Format("Route '{0}' on '{1}' contains invalid chars. ", restPath.Path, restPath.RequestType.GetMethodName()));            }            if (RestPathMap.TryGetValue(restPath.FirstMatchHashKey, out List<RestPath> pathsAtFirstMatch))            {                pathsAtFirstMatch.Add(restPath);            }            else            {                RestPathMap[restPath.FirstMatchHashKey] = new List<RestPath>() { restPath };            }        }        public RestPath GetRestPathForRequest(string httpMethod, string pathInfo)        {            var matchUsingPathParts = RestPath.GetPathPartsForMatching(pathInfo);            List<RestPath> firstMatches;            var yieldedHashMatches = RestPath.GetFirstMatchHashKeys(matchUsingPathParts);            foreach (var potentialHashMatch in yieldedHashMatches)            {                if (!this.RestPathMap.TryGetValue(potentialHashMatch, out firstMatches))                {                    continue;                }                var bestScore = -1;                RestPath bestMatch = null;                foreach (var restPath in firstMatches)                {                    var score = restPath.MatchScore(httpMethod, matchUsingPathParts);                    if (score > bestScore)                    {                        bestScore = score;                        bestMatch = restPath;                    }                }                if (bestScore > 0 && bestMatch != null)                {                    return bestMatch;                }            }            var yieldedWildcardMatches = RestPath.GetFirstMatchWildCardHashKeys(matchUsingPathParts);            foreach (var potentialHashMatch in yieldedWildcardMatches)            {                if (!this.RestPathMap.TryGetValue(potentialHashMatch, out firstMatches))                {                    continue;                }                var bestScore = -1;                RestPath bestMatch = null;                foreach (var restPath in firstMatches)                {                    var score = restPath.MatchScore(httpMethod, matchUsingPathParts);                    if (score > bestScore)                    {                        bestScore = score;                        bestMatch = restPath;                    }                }                if (bestScore > 0 && bestMatch != null)                {                    return bestMatch;                }            }            return null;        }        public Task<object> Execute(HttpListenerHost httpHost, object requestDto, IRequest req)        {            var requestType = requestDto.GetType();            req.OperationName = requestType.Name;            var serviceType = httpHost.GetServiceTypeByRequest(requestType);            var service = httpHost.CreateInstance(serviceType);            var serviceRequiresContext = service as IRequiresRequest;            if (serviceRequiresContext != null)            {                serviceRequiresContext.Request = req;            }            // Executes the service and returns the result            return ServiceExecGeneral.Execute(serviceType, req, service, requestDto, requestType.GetMethodName());        }    }}
 |