Exemplo n.º 1
0
 public IEnumerable <ExtensionDescriptor> AvailableExtensions()
 {
     return(_cacheManager.Get("AvailableExtensions", true, ctx =>
                              _parallelCacheContext
                              .RunInParallel(_folders, folder => folder.AvailableExtensions().ToList())
                              .SelectMany(descriptors => descriptors)
                              .ToReadOnlyCollection()));
 }
Exemplo n.º 2
0
 /// <summary>
 ///     可用的扩展。
 /// </summary>
 /// <returns>扩展描述符条目集合。</returns>
 public IEnumerable <ExtensionDescriptorEntry> AvailableExtensions()
 {
     return(_cacheManager.Get("AvailableExtensions", ctx => _parallelCacheContext
                              .RunInParallel(_folders, folder => folder.AvailableExtensions().Where(i => _extensionDescriptorFilters.All(f =>
     {
         var context = new ExtensionDescriptorEntryFilterContext(i);
         f.OnDiscovery(context);
         return context.Valid;
     })).ToArray())
                              .SelectMany(entrys => entrys).ToArray()));
 }
Exemplo n.º 3
0
        public IEnumerable <ClientRouteDescriptor> GetRouteTable(bool isFrontEnd)
        {
            Logger.Information("Start building shape table");

            var alterationSets = _parallelCacheContext.RunInParallel(
                _clientRouteProviders.Where(provider => provider.Value.IsFrontEnd == isFrontEnd), provider => {
                var feature = provider.Metadata.ContainsKey("Feature") ?
                              (Feature)provider.Metadata["Feature"] :
                              null;

                var builder = new ClientRouteTableBuilder(feature);
                provider.Value.Discover(builder);
                return(builder.BuildAlterations().ToReadOnlyCollection());
            });

            var alterations = alterationSets
                              .SelectMany(shapeAlterations => shapeAlterations)
                              .ToList();
            var distinctRouteNames = alterations.GroupBy(item => item.RouteName, StringComparer.OrdinalIgnoreCase)
                                     .Select(item => item.Key).ToList();

            var routes = GenerateRoutes(distinctRouteNames, alterations);

            Logger.Information("Done building shape table");
            return(routes);
        }
        public ShapeTable GetShapeTable(string themeName)
        {
            return(_cacheManager.Get(themeName ?? "", x =>
            {
                Logger.Info("Start building shape table");

                var alterationSets = _parallelCacheContext.RunInParallel(_bindingStrategies, bindingStrategy =>
                {
                    Feature strategyDefaultFeature = bindingStrategy.Metadata.ContainsKey("Feature") ?
                                                     (Feature)bindingStrategy.Metadata["Feature"] :
                                                     null;

                    var builder = new ShapeTableBuilder(strategyDefaultFeature);
                    bindingStrategy.Value.Discover(builder);
                    return builder.BuildAlterations().ToReadOnlyCollection();
                });

                var alterations = alterationSets
                                  .SelectMany(shapeAlterations => shapeAlterations)
                                  .Where(alteration => IsModuleOrRequestedTheme(alteration, themeName))
                                  .OrderByDependenciesAndPriorities(AlterationHasDependency, GetPriority)
                                  .ToList();

                var descriptors = alterations.GroupBy(alteration => alteration.ShapeType, StringComparer.OrdinalIgnoreCase)
                                  .Select(group => group.Aggregate(
                                              new ShapeDescriptor {
                    ShapeType = group.Key
                },
                                              (descriptor, alteration) =>
                {
                    alteration.Alter(descriptor);
                    return descriptor;
                })).ToList();

                foreach (var descriptor in descriptors)
                {
                    foreach (var alteration in alterations.Where(a => a.ShapeType == descriptor.ShapeType).ToList())
                    {
                        var local = new ShapeDescriptor {
                            ShapeType = descriptor.ShapeType
                        };
                        alteration.Alter(local);
                        descriptor.BindingSources.Add(local.BindingSource);
                    }
                }

                var result = new ShapeTable
                {
                    Descriptors = descriptors.ToDictionary(sd => sd.ShapeType, StringComparer.OrdinalIgnoreCase),
                    Bindings = descriptors.SelectMany(sd => sd.Bindings).ToDictionary(kv => kv.Key, kv => kv.Value, StringComparer.OrdinalIgnoreCase),
                };

                _shapeTableEventHandlers.Invoke(ctx => ctx.ShapeTableCreated(result), Logger);

                Logger.Info("Done building shape table");
                return result;
            }));
        }
        public IEnumerable <string> HarvestReactEnabledModules()
        {
            var availableFeatures    = _extensionManager.AvailableFeatures();
            var activeFeatures       = availableFeatures.Where(FeatureIsEnabled);
            var activeExtensions     = Once(activeFeatures).ToList();
            var modulesWithReactCode = _parallelCacheContext.RunInParallel(activeExtensions, extensionDescriptor => {
                var containsReact = ReactFolderPaths().Select(folderPath => {
                    var basePath    = Path.Combine(extensionDescriptor.Location, extensionDescriptor.Id).Replace(Path.DirectorySeparatorChar, '/');
                    var virtualPath = Path.Combine(basePath, folderPath).Replace(Path.DirectorySeparatorChar, '/');
                    return(_virtualPathProvider.DirectoryExists(virtualPath) ? virtualPath : null);
                }).Where(x => x != null).ToList();
                return(containsReact.Count > 0 ? containsReact.FirstOrDefault() : null);
            }).Where(x => x != null).ToList();

            return(modulesWithReactCode);
        }
        private ExtensionLoadingContext CreateLoadingContext()
        {
            var availableExtensions = _extensionManager
                                      .AvailableExtensions()
                                      .Where(d => DefaultExtensionTypes.IsModule(d.ExtensionType))
                                      .OrderBy(d => d.Id)
                                      .ToList();

            // Check there are no duplicates
            var duplicates = availableExtensions.GroupBy(ed => ed.Id).Where(g => g.Count() >= 2).ToList();

            if (duplicates.Any())
            {
                var sb = new StringBuilder();
                sb.Append("There are multiple extensions with the same name installed in this instance of Orchard.\r\n");
                foreach (var dup in duplicates)
                {
                    sb.Append(string.Format("Extension '{0}' has been found from the following locations: {1}.\r\n", dup.Key, string.Join(", ", dup.Select(e => e.Location + "/" + e.Id))));
                }
                sb.Append("This issue can be usually solved by removing or renaming the conflicting extension.");
                Logger.Error(sb.ToString());
                throw new CoreException(sb.ToString());
            }

            var previousDependencies = _dependenciesFolder.LoadDescriptors().ToList();

            var virtualPathModficationDates = new ConcurrentDictionary <string, DateTime>(StringComparer.OrdinalIgnoreCase);

            Logger.Information("Probing extensions");
            var availableExtensionsProbes1 = _parallelCacheContext
                                             .RunInParallel(availableExtensions, extension =>
                                                            _loaders.Select(loader => loader.Probe(extension)).Where(entry => entry != null).ToArray())
                                             .SelectMany(entries => entries)
                                             .GroupBy(entry => entry.Descriptor.Id);

            var availableExtensionsProbes = _parallelCacheContext
                                            .RunInParallel(availableExtensionsProbes1, g =>
                                                           new { Id = g.Key, Entries = SortExtensionProbeEntries(g, virtualPathModficationDates) })
                                            .ToDictionary(g => g.Id, g => g.Entries, StringComparer.OrdinalIgnoreCase);

            Logger.Information("Done probing extensions");

            var deletedDependencies = previousDependencies
                                      .Where(e => !availableExtensions.Any(e2 => StringComparer.OrdinalIgnoreCase.Equals(e2.Id, e.Name)))
                                      .ToList();

            // Collect references for all modules
            Logger.Information("Probing extension references");
            var references = _parallelCacheContext
                             .RunInParallel(availableExtensions, extension => _loaders.SelectMany(loader => loader.ProbeReferences(extension)).ToList())
                             .SelectMany(entries => entries)
                             .ToList();

            Logger.Information("Done probing extension references");

            var referencesByModule = references
                                     .GroupBy(entry => entry.Descriptor.Id, StringComparer.OrdinalIgnoreCase)
                                     .ToDictionary(g => g.Key, g => g.AsEnumerable(), StringComparer.OrdinalIgnoreCase);

            var referencesByName = references
                                   .GroupBy(reference => reference.Name, StringComparer.OrdinalIgnoreCase)
                                   .ToDictionary(g => g.Key, g => g.AsEnumerable(), StringComparer.OrdinalIgnoreCase);

            var sortedAvailableExtensions =
                availableExtensions.OrderByDependenciesAndPriorities(
                    (item, dep) => referencesByModule.ContainsKey(item.Id) &&
                    referencesByModule[item.Id].Any(r => StringComparer.OrdinalIgnoreCase.Equals(dep.Id, r.Name)),
                    item => 0)
                .ToList();

            return(new ExtensionLoadingContext
            {
                AvailableExtensions = sortedAvailableExtensions,
                PreviousDependencies = previousDependencies,
                DeletedDependencies = deletedDependencies,
                AvailableExtensionsProbes = availableExtensionsProbes,
                ReferencesByName = referencesByName,
                ReferencesByModule = referencesByModule,
                VirtualPathModficationDates = virtualPathModficationDates,
            });
        }
        public void Discover(ShapeTableBuilder builder)
        {
            Logger.Information("Start discovering shapes");

            var harvesterInfos = _harvesters.Select(harvester => new { harvester, subPaths = harvester.SubPaths() });

            var availableFeatures = _extensionManager.AvailableFeatures();
            var activeFeatures    = availableFeatures.Where(FeatureIsEnabled);
            var activeExtensions  = Once(activeFeatures);

            var hits = _parallelCacheContext.RunInParallel(activeExtensions, extensionDescriptor => {
                Logger.Information("Start discovering candidate views filenames");
                var pathContexts = harvesterInfos.SelectMany(harvesterInfo => harvesterInfo.subPaths.Select(subPath => {
                    var basePath    = Path.Combine(extensionDescriptor.Location, extensionDescriptor.Id).Replace(Path.DirectorySeparatorChar, '/');
                    var virtualPath = Path.Combine(basePath, subPath).Replace(Path.DirectorySeparatorChar, '/');
                    var fileNames   = _cacheManager.Get(virtualPath, ctx => {
                        ctx.Monitor(_virtualPathMonitor.WhenPathChanges(virtualPath));
                        return(_virtualPathProvider.ListFiles(virtualPath).Select(Path.GetFileName).ToReadOnlyCollection());
                    });
                    return(new { harvesterInfo.harvester, basePath, subPath, virtualPath, fileNames });
                })).ToList();
                Logger.Information("Done discovering candidate views filenames");

                var fileContexts = pathContexts.SelectMany(pathContext => _shapeTemplateViewEngines.SelectMany(ve => {
                    var fileNames = ve.DetectTemplateFileNames(pathContext.fileNames);
                    return(fileNames.Select(
                               fileName => new {
                        fileName = Path.GetFileNameWithoutExtension(fileName),
                        fileVirtualPath = Path.Combine(pathContext.virtualPath, fileName).Replace(Path.DirectorySeparatorChar, '/'),
                        pathContext
                    }));
                }));

                var shapeContexts = fileContexts.SelectMany(fileContext => {
                    var harvestShapeInfo = new HarvestShapeInfo {
                        SubPath             = fileContext.pathContext.subPath,
                        FileName            = fileContext.fileName,
                        TemplateVirtualPath = fileContext.fileVirtualPath
                    };
                    var harvestShapeHits = fileContext.pathContext.harvester.HarvestShape(harvestShapeInfo);
                    return(harvestShapeHits.Select(harvestShapeHit => new { harvestShapeInfo, harvestShapeHit, fileContext }));
                });

                return(shapeContexts.Select(shapeContext => new { extensionDescriptor, shapeContext }).ToList());
            }).SelectMany(hits2 => hits2);


            foreach (var iter in hits)
            {
                // templates are always associated with the namesake feature of module or theme
                var hit = iter;
                var featureDescriptors = iter.extensionDescriptor.Features.Where(fd => fd.Id == hit.extensionDescriptor.Id);
                foreach (var featureDescriptor in featureDescriptors)
                {
                    Logger.Debug("Binding {0} as shape [{1}] for feature {2}",
                                 hit.shapeContext.harvestShapeInfo.TemplateVirtualPath,
                                 iter.shapeContext.harvestShapeHit.ShapeType,
                                 featureDescriptor.Id);

                    builder.Describe(iter.shapeContext.harvestShapeHit.ShapeType)
                    .From(new Feature {
                        Descriptor = featureDescriptor
                    })
                    .BoundAs(
                        hit.shapeContext.harvestShapeInfo.TemplateVirtualPath,
                        shapeDescriptor => displayContext => Render(shapeDescriptor, displayContext, hit.shapeContext.harvestShapeInfo, hit.shapeContext.harvestShapeHit));
                }
            }

            Logger.Information("Done discovering shapes");
        }
        private ExtensionLoadingContext CreateLoadingContext()
        {
            var availableExtensions = _extensionManager
                                      .AvailableExtensions()
                                      //                .Where(d => DefaultExtensionTypes.IsModule(d.ExtensionType) || DefaultExtensionTypes.IsTheme(d.ExtensionType))
                                      .OrderBy(d => d.Id)
                                      .ToList();

            //检查重复项
            var duplicates = availableExtensions.GroupBy(ed => ed.Id).Where(g => g.Count() >= 2).ToList();

            if (duplicates.Any())
            {
                var sb = new StringBuilder();
                sb.Append("有多个具有相同名称的扩展。\r\n");
                foreach (var dup in duplicates)
                {
                    sb.AppendFormat("扩展 '{0}' 从下列位置已被发现: {1}.\r\n", dup.Key, string.Join(", ", dup.Select(e => e.Location + "/" + e.Id)));
                }
                sb.Append("这个问题通常可以通过删除或重命名冲突的扩展解决。");
                var message = sb.ToString();
                Logger.Error(message);
                throw new RabbitException(new LocalizedString(message));
            }

            var previousDependencies = _dependenciesFolder.LoadDescriptors().ToList();

            var virtualPathModficationDates = new ConcurrentDictionary <string, DateTime>(StringComparer.OrdinalIgnoreCase);

            Logger.Information("准备探测扩展");
            var availableExtensionsProbes1 = _parallelCacheContext
                                             .RunInParallel(availableExtensions, extension =>
                                                            _loaders.Select(loader => loader.Probe(extension)).Where(entry => entry != null).ToArray())
                                             .SelectMany(entries => entries)
                                             .GroupBy(entry => entry.Descriptor.Id);

            var availableExtensionsProbes = _parallelCacheContext
                                            .RunInParallel(availableExtensionsProbes1, g =>
                                                           new { Id = g.Key, Entries = SortExtensionProbeEntries(g, virtualPathModficationDates) })
                                            .ToDictionary(g => g.Id, g => g.Entries, StringComparer.OrdinalIgnoreCase);

            Logger.Information("探测扩展完成");

            var deletedDependencies = previousDependencies
                                      .Where(e => !availableExtensions.Any(e2 => StringComparer.OrdinalIgnoreCase.Equals(e2.Id, e.Name)))
                                      .ToList();

            //收集所有模块中的引用
            Logger.Information("准备探测扩展引用");
            var references = _parallelCacheContext
                             .RunInParallel(availableExtensions, extension => _loaders.SelectMany(loader => loader.ProbeReferences(extension)).ToList())
                             .SelectMany(entries => entries)
                             .ToList();

            Logger.Information("探测扩展引用完成");

            var referencesByModule = references
                                     .GroupBy(entry => entry.Descriptor.Id, StringComparer.OrdinalIgnoreCase)
                                     .ToDictionary(g => g.Key, g => g.AsEnumerable(), StringComparer.OrdinalIgnoreCase);

            var referencesByName = references
                                   .GroupBy(reference => reference.Name, StringComparer.OrdinalIgnoreCase)
                                   .ToDictionary(g => g.Key, g => g.AsEnumerable(), StringComparer.OrdinalIgnoreCase);

            var sortedAvailableExtensions =
                availableExtensions.OrderByDependenciesAndPriorities(
                    (item, dep) => referencesByModule.ContainsKey(item.Id) &&
                    referencesByModule[item.Id].Any(r => StringComparer.OrdinalIgnoreCase.Equals(dep.Id, r.Name)),
                    item => 0)
                .ToList();

            return(new ExtensionLoadingContext
            {
                AvailableExtensions = sortedAvailableExtensions,
                PreviousDependencies = previousDependencies,
                DeletedDependencies = deletedDependencies,
                AvailableExtensionsProbes = availableExtensionsProbes,
                ReferencesByName = referencesByName,
                ReferencesByModule = referencesByModule,
                VirtualPathModficationDates = virtualPathModficationDates,
            });
        }