コード例 #1
0
        protected bool TryRegisterAddin(ResolutionResult resolutionResult, ResolutionContext ctx, AddinResolution adnResolution,
                                        AddinCollision addinCollision)
        {
            AddinResolution existingAddin;

            if (ctx.TryRegisterAddin(resolutionResult, adnResolution.AddinId, adnResolution, out existingAddin))
            {
                return(true);
            }
            var key = new AddinCollisionKey(existingAddin.Guid);

            addinCollision.Add(key, adnResolution, existingAddin);
            return(false);
        }
コード例 #2
0
        // this method should split the existing addins into the following kind:
        // 1. updated addins
        // 2. unaffected addins
        // 3. directly affected addins
        // 4. indirectly affected addins
        // then, decide how to register assets of these addins and whether they need resolution, according to each kind.
        // and finally, return the addin list that need to be resolved.
        protected List <AddinResolution> RegisterExistingAssets(ResolutionResult resolutionResult, ResolutionContext ctx, AddinCollision addinCollision)
        {
            // =================================================
            // 1. 首先确定 AddinStorage 中各个现有 addin 的状态:未受影响的、已更新的、间接受影响的
            // check whether there are updated addins.
            // and if there are any, mark their operation status as updated.
            List <AddinRecord> updatedAddins = null;

            for (int i = AddinStorage.AddinRecordCount - 1; i >= 0; i--)
            {
                var             existingAddin = AddinStorage.Get(i);
                var             addinId       = existingAddin.AddinId;
                AddinResolution adnResolution;
                // 如果 ResolutionContext 中已存在相同 guid 的插件,则表明这是一个更新的插件
                if (!ctx.TryGetAddin(addinId, out adnResolution))
                {
                    continue;
                }

                AddinStorage.Remove(existingAddin);
                //AddinRelationManager.RemoveRelationMap(existingAddin);
                //adnResolution.OperationStatus = AddinOperationStatus.Updated;

                updatedAddins = updatedAddins ?? new List <AddinRecord>();
                updatedAddins.Add(existingAddin);
            }

            if (AddinStorage.AddinRecordCount == 0)
            {
                return(null); // all addins are updated addins.
            }
            // mark directly affected and indirectly affected addins.
            List <AddinRecord> directlyAffectedAddins = null, indirectlyAffectedAddins = null;

            if (updatedAddins != null)
            {
                directlyAffectedAddins = AddinRelationManager.TryGetAffectingAddins(updatedAddins);
                if (directlyAffectedAddins != null)
                {
                    indirectlyAffectedAddins = AddinRelationManager.TryGetAllAffectingAddins(directlyAffectedAddins);
                    //if (indirectlyAffectedAddins != null)
                    //{
                    //    for (int i = indirectlyAffectedAddins.Count - 1; i >= 0; i--)
                    //    {
                    //        if (directlyAffectedAddins.Contains(indirectlyAffectedAddins[i]))
                    //            indirectlyAffectedAddins.RemoveAt(i);
                    //    }
                    //}
                }
            }

            // =================================================
            // 2. 根据 AddinStorage 中各个现有 addin 的状态,将它们注册到 ResolutionContext
            if (updatedAddins != null)
            {
                foreach (var updatedAddin in updatedAddins)
                {
                    var ebs = updatedAddin.GetAllExtensionBuilders();
                    if (ebs != null)
                    {
                        foreach (var eb in ebs)
                        {
                            if (eb.ExtensionBuilderKind == ExtensionBuilderKind.Declared)
                            {
                                // 将已更新插件的 ExtensionBuilderPath 映射注册到 context。
                                // 因为在解析 Extension 时,是根据 ExtensionBuilderPath 查找 ExtensionBuilder 的,但对于 [directlyAffectedAddins 插件的 Extension] 来说,它们并不
                                // 保存自身依赖的 updateAddins 的 ExtensionBuilder 的 ExtensionBuilderPath。
                                // 所以,只能在解析前先将 updateAddins 的 ExtensionBuilder 的 ExtensionBuilderPath 注册到 context,后面解析 [directlyAffectedAddins 插件的 Extension]
                                // 时,才能通过 uid 获得目标 ExtensionBuilder 的 path,继而找到 ExtensionBuilder
                                ctx.RegisterExtensionBuilderPath(eb.Uid, eb.GetPath());
                            }
                        }
                    }
                }
            }

            List <AddinResolution> resolableAddins = null;

            // decide how to register assets of these addins and whether to resolve these addins according to their operation status.
            if (directlyAffectedAddins != null)
            {
                foreach (var directlyAffectedAddin in directlyAffectedAddins)
                {
                    AddinStorage.Remove(directlyAffectedAddin);
                    var resolvableAddin = DoRegisterExistingAddin(resolutionResult, ctx, addinCollision, directlyAffectedAddin, AddinOperationStatus.DirectlyAffected);
                    resolableAddins = resolableAddins ?? new AddinResolutionSet();
                    resolableAddins.Add(resolvableAddin);
                }
            }

            if (indirectlyAffectedAddins != null)
            {
                foreach (var indirectlyAffectedAddin in indirectlyAffectedAddins)
                {
                    AddinStorage.Remove(indirectlyAffectedAddin);
                    var resolvableAddin = DoRegisterExistingAddin(resolutionResult, ctx, addinCollision, indirectlyAffectedAddin, AddinOperationStatus.IndirectlyAffected);
                    resolableAddins = resolableAddins ?? new AddinResolutionSet();
                    resolableAddins.Add(resolvableAddin);
                }
            }

            // since the updated, directly affected and indirectly affected, they are all removed, so the rest is unaffected
            for (int i = AddinStorage.AddinRecordCount - 1; i >= 0; i--)
            {
                var unaffectedAddin = AddinStorage.Get(i);
                AddinStorage.Remove(unaffectedAddin);
                var resolvableAddin = DoRegisterExistingAddin(resolutionResult, ctx, addinCollision, unaffectedAddin, AddinOperationStatus.Unaffected);
                resolableAddins = resolableAddins ?? new AddinResolutionSet();
                resolableAddins.Add(resolvableAddin);
            }

            return(resolableAddins);
        }
コード例 #3
0
        // @return: whether there is collisions.
        protected bool TryRegisterAssets(ResolutionResult resolutionResult, ResolutionContext ctx, AddinResolution adnResolution,
                                         AddinCollision addinCollision)
        {
            var success = true;

            if (adnResolution.Assemblies != null)
            {
                for (int i = 0; i < adnResolution.Assemblies.Count; i++)
                {
                    var asm = adnResolution.Assemblies[i];
                    if (ctx.TryRegisterAssembly(resolutionResult, asm))
                    {
                        continue;
                    }
                    // if the assembly loading (with mono.cecil) is failed, it's because this is not a valid managed assembly (might be a native library),
                    // just remove it from the assembly list, and add it to the data file list instead.
                    adnResolution.Assemblies.RemoveAt(i);
                    i -= 1;
                    adnResolution.DataFiles.Add(new DataFileResolution {
                        FilePath = asm.AssemblyFile.FilePath
                    });
                }
                //foreach (var asm in adnResolution.Assemblies)
                //	ctx.TryRegisterAssembly(resolutionResult, asm);
            }

            if (adnResolution.ExtensionPoints != null)
            {
                foreach (var extensionPoint in adnResolution.ExtensionPoints)
                {
                    ExtensionPointResolution existingExtensionPoint;
                    if (!ctx.TryRegisterExtensionPoint(resolutionResult, extensionPoint, out existingExtensionPoint))
                    {
                        var key = new ExtensionPointCollisionKey(existingExtensionPoint.Name);
                        addinCollision.Add(key, adnResolution, existingExtensionPoint.DeclaringAddin);
                        success = false;
                    }
                }
            }

            // get all extension builders defined under extension point and extension builder set
            var extensionBuilders = adnResolution.GetAllExtensionBuilders();

            if (extensionBuilders != null)
            {
                foreach (var extensionBuilder in extensionBuilders)
                {
                    if (extensionBuilder.ExtensionBuilderKind == ExtensionBuilderKind.Referenced)
                    {
                        continue;
                    }
                    ExtensionBuilderResolution existingExtensionBuilder;
                    if (!ctx.TryRegisterExtensionBuilder(resolutionResult, extensionBuilder, out existingExtensionBuilder))
                    {
                        var key = new ExtensionBuilderCollisionKey(existingExtensionBuilder.Name);
                        addinCollision.Add(key, adnResolution, existingExtensionBuilder.DeclaringAddin);
                        success = false;
                    }
                }
            }

            var extensions = adnResolution.GetAllExtensions();

            if (extensions != null)
            {
                foreach (var extension in extensions)
                {
                    ExtensionResolution existingExtension;
                    if (!ctx.TryRegisterExtension(resolutionResult, extension, out existingExtension))
                    {
                        var key = new ExtensionCollisionKey(existingExtension.Head.Path);
                        addinCollision.Add(key, adnResolution, existingExtension.DeclaringAddin);
                        success = false;
                    }
                }
            }

            return(success);
        }
コード例 #4
0
        // 根据 existingAddin 的状态,将其 Assets 注册到 ResolutionContext
        AddinResolution DoRegisterExistingAddin(ResolutionResult resolutionResult, ResolutionContext ctx, AddinCollision addinCollision,
                                                AddinRecord existingAddin, AddinOperationStatus operationStatus)
        {
            //AddinRecord addinRecord;
            //if (!AddinRelationManager.TryGetAddin(existingAddin.Guid, out addinRecord))
            //    throw new InconsistentStateException();

            ////AddinRelationManager.RemoveAddin(existingAddin);
            //AddinStorage.Remove(existingAddin);

            //if (operationStatus == AddinOperationStatus.NewOrUpdated)
            //{
            //    var ebs = existingAddin.GetAllExtensionBuilders();
            //    if (ebs != null)
            //    {
            //        foreach (var eb in ebs)
            //        {
            //            if (eb.ExtensionBuilderKind == ExtensionBuilderKind.Declared)
            //                ctx.RegisterExtensionBuilderPath(eb.Uid, eb.GetPath());
            //        }
            //    }
            //    return null;
            //}

            var adnResolution = FromPersistentObject(existingAddin, operationStatus);

            TryRegisterAddin(resolutionResult, ctx, adnResolution, addinCollision);
            DoRegisterExistingAssets(resolutionResult, ctx, adnResolution);
            // if the operation status of an addin not equals to unaffected (i.e, directly/indirectly affected addin), it need to
            // be resolved, so we add it to the addin resolution list.
            return(adnResolution);
            //return operationStatus == AddinOperationStatus.Unaffected ? null : adnResolution;
        }
コード例 #5
0
        // this method should split the existing addins into the following kind:
        // 1. updated addins
        // 2. unaffected addins
        // 3. directly affected addins
        // 4. indirectly affected addins
        // then, decide how to register assets of these addins and whether they need resolution, according to each kind.
        // and finally, return the addin list that need to be resolved.
        protected List <AddinResolution> RegisterExistingAssets(IMessageDialog dialog, ResolutionContext ctx, AddinCollision addinCollision,
                                                                List <AddinResolution> adnResolutions)
        {
            // check whether there are updated addins.
            // and if there are any, mark their operation status as updated.
            List <AddinIndexRecord> updatedAddins = null;

            for (int i = 0; i < _indexManager.AddinCount; i++)
            {
                var             addin   = _indexManager.GetAddin(i);
                var             addinId = addin.AddinId;
                AddinResolution adnResolution;

                if (!ctx.TryGetAddin(addinId, out adnResolution))
                {
                    continue;
                }

                updatedAddins = updatedAddins ?? new List <AddinIndexRecord>();
                updatedAddins.Add(addin);
                addin.OperationStatus = AddinOperationStatus.Updated;
            }

            // mark directly affected and indirectly affected addins.
            if (updatedAddins != null)
            {
                var directlyAffectedAddins = _indexManager.TryGetAffectedAddins(updatedAddins);
                if (directlyAffectedAddins != null)
                {
                    foreach (var directlyAffectedAddin in directlyAffectedAddins)
                    {
                        if (directlyAffectedAddin.OperationStatus != AddinOperationStatus.Updated)
                        {
                            directlyAffectedAddin.OperationStatus = AddinOperationStatus.DirectlyAffected;
                        }
                    }
                    var indirectlyAffectedAddins = _indexManager.TryGetAllAffectedAddins(directlyAffectedAddins);
                    if (indirectlyAffectedAddins != null)
                    {
                        foreach (var indirectlyAffectedAddin in indirectlyAffectedAddins)
                        {
                            if (indirectlyAffectedAddin.OperationStatus == AddinOperationStatus.Unaffected)
                            {
                                indirectlyAffectedAddin.OperationStatus = AddinOperationStatus.IndirectlyAffected;
                            }
                        }
                    }
                }
            }

            List <AddinResolution> resolableAddins = null;

            // decide how to register assets of these addins and whether to resolve these addins according to their operation status.
            for (int i = _indexManager.AddinCount - 1; i >= 0; i--)
            {
                var addin           = _indexManager.GetAddin(i);
                var resolvableAddin = DoRegisterExistingAddin(dialog, ctx, addinCollision, addin, adnResolutions);
                if (resolvableAddin != null)
                {
                    resolableAddins = resolableAddins ?? new AddinResolutionSet();
                    resolableAddins.Add(resolvableAddin);
                }
            }

            return(resolableAddins);
        }
コード例 #6
0
        // @return: whether there is collisions.
        protected bool TryRegisterAssets(IMessageDialog dialog, ResolutionContext ctx, AddinResolution adnResolution,
                                         AddinCollision addinCollision)
        {
            var success = true;

            if (adnResolution.Assemblies != null)
            {
                foreach (var asm in adnResolution.Assemblies)
                {
                    ctx.TryRegisterAssembly(dialog, asm);
                }
            }

            if (adnResolution.ExtensionPoints != null)
            {
                foreach (var extensionPoint in adnResolution.ExtensionPoints)
                {
                    ExtensionPointResolution existingExtensionPoint;
                    if (!ctx.TryRegisterExtensionPoint(dialog, extensionPoint, out existingExtensionPoint))
                    {
                        var key = new ExtensionPointCollisionKey(existingExtensionPoint.Id);
                        addinCollision.Add(key, adnResolution, existingExtensionPoint.DeclaringAddin);
                        success = false;
                    }
                }
            }

            // get all extension builders defined under extension point and extension builder set
            var extensionBuilders = adnResolution.GetAllExtensionBuilders();

            if (extensionBuilders != null)
            {
                foreach (var extensionBuilder in extensionBuilders)
                {
                    if (extensionBuilder.ExtensionBuilderKind == ExtensionBuilderKind.Referenced)
                    {
                        continue;
                    }
                    ExtensionBuilderResolution existingExtensionBuilder;
                    if (!ctx.TryRegisterExtensionBuilder(dialog, extensionBuilder, out existingExtensionBuilder))
                    {
                        var key = new ExtensionBuilderCollisionKey(existingExtensionBuilder.Id);
                        addinCollision.Add(key, adnResolution, existingExtensionBuilder.DeclaringAddin);
                        success = false;
                    }
                }
            }

            var extensions = adnResolution.GetAllExtensions();

            if (extensions != null)
            {
                foreach (var extension in extensions)
                {
                    ExtensionResolution existingExtension;
                    if (!ctx.TryRegisterExtension(dialog, extension, out existingExtension))
                    {
                        var key = new ExtensionCollisionKey(existingExtension.Head.Path);
                        addinCollision.Add(key, adnResolution, existingExtension.DeclaringAddin);
                        success = false;
                    }
                }
            }

            return(success);
        }
コード例 #7
0
        AddinResolution DoRegisterExistingAddin(IMessageDialog dialog, ResolutionContext ctx, AddinCollision addinCollision,
                                                AddinIndexRecord existingAddin, List <AddinResolution> adnResolutions)
        {
            AddinBodyRecord addinBody;

            if (!_bodyRepo.TryGet(existingAddin.Guid, out addinBody))
            {
                throw new InconsistentStateException();
            }

            _indexManager.RemoveAddin(existingAddin);
            _bodyRepo.Remove(addinBody);

            if (existingAddin.OperationStatus == AddinOperationStatus.Updated)
            {
                var ebs = addinBody.GetAllExtensionBuilders();
                if (ebs != null)
                {
                    foreach (var eb in ebs)
                    {
                        if (eb.ExtensionBuilderKind == ExtensionBuilderKind.Declared)
                        {
                            ctx.RegisterExtensionBuilderPath(eb.Uid, eb.GetPath());
                        }
                    }
                }
                return(null);
            }

            var adnResolution = FromPersistentObject(new AddinRecord {
                AddinBody = addinBody, AddinIndex = existingAddin
            });

            TryRegisterAddin(dialog, ctx, adnResolution, addinCollision);
            DoRegisterExistingAssets(dialog, ctx, adnResolution);
            // if the operation status of an addin not equals to unaffected (i.e, directly/indirectly affected addin), it need to
            // be resolved, so we add it to the addin resolution list.
            return(existingAddin.OperationStatus == AddinOperationStatus.Unaffected ? null : adnResolution);
        }
コード例 #8
0
        internal override bool Resolve(IMessageDialog dialog, FilePackResult filePackResult)
        {
            // try parsing the new (or updated) addin manifests (configuration)
            var adnResolutions = TryParseAddins(dialog, filePackResult.AddinFilePacks);

            if (adnResolutions == null)
            {
                return(false);
            }

            var ctx            = new ResolutionContext();
            var addinCollision = new AddinCollision();

            // try to register id of new addins at first, so that we can tell whether there are
            // any updated addins when registering that of the existing addins.
            foreach (var adnResolution in adnResolutions)
            {
                TryRegisterAddin(dialog, ctx, adnResolution, addinCollision);
            }

            // register all assets of existing addins to the context (skipping updated addins)
            List <AddinResolution> resolableAddins = null;

            if (_indexManager.AddinCount > 0)
            {
                resolableAddins = RegisterExistingAssets(dialog, ctx, addinCollision, adnResolutions);
            }

            // try to register assets of new and updated addins to the context
            foreach (var adnResolution in adnResolutions)
            {
                TryRegisterAssets(dialog, ctx, adnResolution, addinCollision);
            }

            if (resolableAddins != null)
            {
                adnResolutions.AddRange(resolableAddins);
            }

            // tries to resolve all addin, and make sure:
            // 1. there is no cirular dependencies between the resolved addins.
            // 2. the resolved addin list is sorted by the dependency.
            adnResolutions = TryResolveAddins(dialog, _convertionManager, ctx, adnResolutions);
            if (ResolutionFailed(dialog, ctx, adnResolutions))
            {
                return(false);
            }

            // if there is any conflicting addins, trim them and all addins that depends on them.
            if (addinCollision.Count > 0)
            {
                TrimConflictingAddins(addinCollision, adnResolutions);
                if (ResolutionFailed(dialog, ctx, adnResolutions))
                {
                    return(false);
                }
            }

            // save all new and/or updated addin records to persistent file.
            PersistAddinRecords(ctx, adnResolutions);

            ctx.Dispose();
            return(true);
        }
コード例 #9
0
        internal override ResolutionResult Resolve(INameConvention nameConvention, ResolutionContext ctx, ScanFilePackResult scanFilePackResult)
        {
            var resolutionResult = new ResolutionResult();
            // try parsing the new (or updated) addin manifests (configuration)
            var adnResolutions = TryParseAddins(nameConvention, resolutionResult, scanFilePackResult.ScanFilePacks);

            if (adnResolutions == null)
            {
                resolutionResult.NewAddinsFound = false;
                return(resolutionResult);
            }

            var addinCollision = new AddinCollision();

            // try to register id of new addins at first, so that we can tell whether there are
            // any updated addins when registering that of the existing addins.
            foreach (var adnResolution in adnResolutions)
            {
                TryRegisterAddin(resolutionResult, ctx, adnResolution, addinCollision);
            }

            // register all assets of existing addins to the context (skipping updated addins)
            List <AddinResolution> resolableAddins = null;

            if (AddinStorage.AddinRecordCount > 0)
            {
                resolableAddins = RegisterExistingAssets(resolutionResult, ctx, addinCollision);
            }

            // try to register assets of new and updated addins to the context
            foreach (var adnResolution in adnResolutions)
            {
                TryRegisterAssets(resolutionResult, ctx, adnResolution, addinCollision);
            }

            if (resolableAddins != null)
            {
                adnResolutions.AddRange(resolableAddins);
            }

            // tries to resolve all addin, and make sure:
            // 1. there is no cirular dependencies between the resolved addins.
            // 2. the resolved addin list is sorted by the dependency.
            var resolvedAddins = TryResolveAddins(resolutionResult, ConvertionManager, ctx, adnResolutions);

            if (adnResolutions.Count > 0)
            {
                StoreUnresolvableAddins(adnResolutions); // 剩余的 adnResolutions 即为未成功解析的插件,此处也要将它们持久化
            }
            if (ResolutionFailed(resolutionResult, ctx, resolvedAddins))
            {
                resolutionResult.NewAddinsFound = false;
                return(resolutionResult);
            }

            // if there is any conflicting addins, trim them and all addins that depends on them.
            if (addinCollision.Count > 0)
            {
                TrimConflictingAddins(addinCollision, resolvedAddins); // recursively
                if (ResolutionFailed(resolutionResult, ctx, resolvedAddins))
                {
                    resolutionResult.NewAddinsFound = false;
                    return(resolutionResult);
                }
            }

            // save all resolvable addin records to persistent file.
            StoreResolvedAddins(resolutionResult, ctx, resolvedAddins);

            PersistAddinStorage(resolutionResult);

            ctx.Dispose();

            resolutionResult.NewAddinsFound = true;
            return(resolutionResult);
        }