public override void ExtensionActivated(ExtensionLoadingContext ctx, ExtensionDescriptor extension)
 {
     if (_reloadWorkaround.AppDomainRestartNeeded) {
         Logger.Information("ExtensionActivated: Module \"{0}\" has changed, forcing AppDomain restart", extension.Id);
         ctx.RestartAppDomain = _reloadWorkaround.AppDomainRestartNeeded;
     }
 }
        public override ExtensionProbeEntry Probe(ExtensionDescriptor descriptor)
        {
            if (Disabled)
                return null;

            if (descriptor.Location == "~/Themes") {
                string projectPath = _virtualPathProvider.Combine(descriptor.Location, descriptor.Id,
                                           descriptor.Id + ".csproj");

                // ignore themes including a .csproj in this loader
                if ( _virtualPathProvider.FileExists(projectPath) ) {
                    return null;
                }

                var assemblyPath = _virtualPathProvider.Combine(descriptor.Location, descriptor.Id, "bin",
                                                descriptor.Id + ".dll");

                // ignore themes with /bin in this loader
                if ( _virtualPathProvider.FileExists(assemblyPath) )
                    return null;

                return new ExtensionProbeEntry {
                    Descriptor = descriptor,
                    Loader = this,
                    VirtualPath = "~/Theme/" + descriptor.Id,
                    VirtualPathDependencies = Enumerable.Empty<string>(),
                };
            }
            return null;
        }
 public ExtensionEntry Load(ExtensionDescriptor descriptor)
 {
     var dependency = _dependenciesFolder.GetDescriptor(descriptor.Id);
     if (dependency != null && dependency.LoaderName == this.Name) {
         return LoadWorker(descriptor);
     }
     return null;
 }
        protected override ExtensionEntry LoadWorker(ExtensionDescriptor descriptor)
        {
            if (Disabled)
                return null;

            Logger.Information("Loaded no-code theme \"{0}\"", descriptor.Name);

            return new ExtensionEntry {
                Descriptor = descriptor,
                Assembly = GetType().Assembly,
                ExportedTypes = new Type[0]
            };
        }
        public override ExtensionProbeEntry Probe(ExtensionDescriptor descriptor)
        {
            if (Disabled)
                return null;

            if (descriptor.Location == "~/Core") {
                return new ExtensionProbeEntry {
                    Descriptor = descriptor,
                    Loader = this,
                    Priority = 100, // Higher priority because assemblies in ~/bin always take precedence
                    VirtualPath = "~/Core/" + descriptor.Id,
                    VirtualPathDependencies = Enumerable.Empty<string>(),
                };
            }
            return null;
        }
        public override ExtensionProbeEntry Probe(ExtensionDescriptor descriptor)
        {
            if (Disabled)
                return null;

            var assembly = _buildManager.GetReferencedAssembly(descriptor.Id);
            if (assembly == null)
                return null;

            var assemblyPath = _virtualPathProvider.Combine("~/bin", descriptor.Id + ".dll");

            return new ExtensionProbeEntry {
                Descriptor = descriptor,
                Loader = this,
                Priority = 100, // Higher priority because assemblies in ~/bin always take precedence
                VirtualPath = assemblyPath,
                VirtualPathDependencies = new[] { assemblyPath },
            };
        }
        public override void ExtensionActivated(ExtensionLoadingContext ctx, ExtensionDescriptor extension)
        {
            string sourceFileName = _virtualPathProvider.MapPath(GetAssemblyPath(extension));

            // Copy the assembly if it doesn't exist or if it is older than the source file.
            bool copyAssembly =
                !_assemblyProbingFolder.AssemblyExists(extension.Id) ||
                File.GetLastWriteTimeUtc(sourceFileName) > _assemblyProbingFolder.GetAssemblyDateTimeUtc(extension.Id);

            if (copyAssembly) {
                ctx.CopyActions.Add(() => _assemblyProbingFolder.StoreAssembly(extension.Id, sourceFileName));

                // We need to restart the appDomain if the assembly is loaded
                if (_hostEnvironment.IsAssemblyLoaded(extension.Id)) {
                    Logger.Information("ExtensionRemoved: Module \"{0}\" is activated with newer file and its assembly is loaded, forcing AppDomain restart", extension.Id);
                    ctx.RestartAppDomain = true;
                }
            }
        }
        protected override ExtensionEntry LoadWorker(ExtensionDescriptor descriptor)
        {
            if (Disabled)
                return null;

            var assembly = _assemblyLoader.Load(CoreAssemblyName);
            if (assembly == null) {
                Logger.Error("Core modules cannot be activated because assembly '{0}' could not be loaded", CoreAssemblyName);
                return null;
            }

            Logger.Information("Loaded core module \"{0}\": assembly name=\"{1}\"", descriptor.Name, assembly.FullName);

            return new ExtensionEntry {
                Descriptor = descriptor,
                Assembly = assembly,
                ExportedTypes = assembly.GetExportedTypes().Where(x => IsTypeFromModule(x, descriptor))
            };
        }
        protected override ExtensionEntry LoadWorker(ExtensionDescriptor descriptor)
        {
            if (Disabled)
                return null;

            Logger.Information("Start loading pre-compiled extension \"{0}\"", descriptor.Name);

            var assembly = _assemblyProbingFolder.LoadAssembly(descriptor.Id);
            if (assembly == null)
                return null;

            Logger.Information("Done loading pre-compiled extension \"{0}\": assembly name=\"{1}\"", descriptor.Name, assembly.FullName);

            return new ExtensionEntry {
                Descriptor = descriptor,
                Assembly = assembly,
                ExportedTypes = assembly.GetExportedTypes()
            };
        }
        public override IEnumerable<ExtensionReferenceProbeEntry> ProbeReferences(ExtensionDescriptor descriptor)
        {
            if (Disabled)
                return Enumerable.Empty<ExtensionReferenceProbeEntry>();

            Logger.Information("Probing references for module '{0}'", descriptor.Id);

            var assemblyPath = GetAssemblyPath(descriptor);
            if (assemblyPath == null)
                return Enumerable.Empty<ExtensionReferenceProbeEntry>();

            var result = _virtualPathProvider
                .ListFiles(_virtualPathProvider.GetDirectoryName(assemblyPath))
                .Where(s => StringComparer.OrdinalIgnoreCase.Equals(Path.GetExtension(s), ".dll"))
                .Where(s => !StringComparer.OrdinalIgnoreCase.Equals(Path.GetFileNameWithoutExtension(s), descriptor.Id))
                .Select(path => new ExtensionReferenceProbeEntry {
                    Descriptor = descriptor,
                    Loader = this,
                    Name = Path.GetFileNameWithoutExtension(path),
                    VirtualPath = path
                } )
                .ToList();

            Logger.Information("Done probing references for module '{0}'", descriptor.Id);
            return result;
        }
        public override ExtensionProbeEntry Probe(ExtensionDescriptor descriptor)
        {
            if (Disabled)
                return null;

            Logger.Information("Probing for module '{0}'", descriptor.Id);

            var assemblyPath = GetAssemblyPath(descriptor);
            if (assemblyPath == null)
                return null;

            var result = new ExtensionProbeEntry {
                Descriptor = descriptor,
                Loader = this,
                VirtualPath = assemblyPath,
                VirtualPathDependencies = new[] { assemblyPath },
            };

            Logger.Information("Done probing for module '{0}'", descriptor.Id);
            return result;
        }
 private IEnumerable<IViewEngine> CreateThemeViewEngines(ExtensionDescriptor theme)
 {
     var themeLocation = theme.Location + "/" + theme.Id;
     var themeParams = new CreateThemeViewEngineParams {VirtualPath = themeLocation};
     return _viewEngineProviders.Select(vep => vep.CreateThemeViewEngine(themeParams));
 }
 public ExtensionProbeEntry Probe(ExtensionDescriptor descriptor)
 {
     return new ExtensionProbeEntry { Descriptor = descriptor, Loader = this };
 }
        private IEnumerable<ExtensionDescriptor> GetBaseThemes(ExtensionDescriptor themeExtension)
        {
            if (themeExtension.Id.Equals("TheAdmin", StringComparison.OrdinalIgnoreCase)) {
                // Special case: conceptually, the base themes of "TheAdmin" is the list of all
                // enabled themes. This is so that any enabled theme can have controller/action/views
                // in the Admin of the site.
                return _extensionManager
                    .EnabledFeatures(_shellDescriptor)
                    .Reverse()  // reverse from (C <= B <= A) to (A => B => C)
                    .Select(fd => fd.Extension)
                    .Where(fd => DefaultExtensionTypes.IsTheme(fd.ExtensionType));
            }
            else {
                var availableFeatures = _extensionManager.AvailableFeatures();
                var list = new List<ExtensionDescriptor>();
                while(true) {
                    if (themeExtension == null)
                        break;

                    if (String.IsNullOrEmpty(themeExtension.BaseTheme))
                        break;

                    var baseFeature = availableFeatures.FirstOrDefault(fd => fd.Id == themeExtension.BaseTheme);
                    if (baseFeature == null) {
                        Logger.Error("Base theme '{0}' of theme '{1}' not found in list of features", themeExtension.BaseTheme, themeExtension.Id);
                        break;
                    }

                    // Protect against potential infinite loop
                    if (list.Contains(baseFeature.Extension)) {
                        Logger.Error("Base theme '{0}' of theme '{1}' ignored, as it seems there is recursion in base themes", themeExtension.BaseTheme, themeExtension.Id);
                        break;
                    }

                    list.Add(baseFeature.Extension);

                    themeExtension = baseFeature.Extension;
                }
                return list;
            }
        }
 public void ExtensionDeactivated(ExtensionLoadingContext ctx, ExtensionDescriptor extension)
 {
     throw new NotImplementedException();
 }
 public override void ExtensionDeactivated(ExtensionLoadingContext ctx, ExtensionDescriptor extension)
 {
     DeleteAssembly(ctx, extension.Id);
 }
        private void ProcessExtension(ExtensionLoadingContext context, ExtensionDescriptor extension)
        {
            var extensionProbes = context.AvailableExtensionsProbes.ContainsKey(extension.Id) ?
                context.AvailableExtensionsProbes[extension.Id] :
                Enumerable.Empty<ExtensionProbeEntry>();

            // materializes the list
            extensionProbes = extensionProbes.ToArray();

            if (Logger.IsEnabled(LogLevel.Debug)) {
                Logger.Debug("Loaders for extension \"{0}\": ", extension.Id);
                foreach (var probe in extensionProbes) {
                    Logger.Debug("  Loader: {0}", probe.Loader.Name);
                    Logger.Debug("    VirtualPath: {0}", probe.VirtualPath);
                    Logger.Debug("    VirtualPathDependencies: {0}", string.Join(", ", probe.VirtualPathDependencies));
                }
            }

            var moduleReferences =
                context.AvailableExtensions
                    .Where(e =>
                           context.ReferencesByModule.ContainsKey(extension.Id) &&
                           context.ReferencesByModule[extension.Id].Any(r => StringComparer.OrdinalIgnoreCase.Equals(e.Id, r.Name)))
                    .ToList();

            var processedModuleReferences =
                moduleReferences
                .Where(e => context.ProcessedExtensions.ContainsKey(e.Id))
                .Select(e => context.ProcessedExtensions[e.Id])
                .ToList();

            var activatedExtension = extensionProbes.FirstOrDefault(
                e => e.Loader.IsCompatibleWithModuleReferences(extension, processedModuleReferences)
                );

            var previousDependency = context.PreviousDependencies.FirstOrDefault(
                d => StringComparer.OrdinalIgnoreCase.Equals(d.Name, extension.Id)
                );

            if (activatedExtension == null) {
                Logger.Warning("No loader found for extension \"{0}\"!", extension.Id);
            }

            var references = ProcessExtensionReferences(context, activatedExtension);

            foreach (var loader in _loaders) {
                if (activatedExtension != null && activatedExtension.Loader.Name == loader.Name) {
                    Logger.Information("Activating extension \"{0}\" with loader \"{1}\"", activatedExtension.Descriptor.Id, loader.Name);
                    loader.ExtensionActivated(context, extension);
                }
                else if (previousDependency != null && previousDependency.LoaderName == loader.Name) {
                    Logger.Information("Deactivating extension \"{0}\" from loader \"{1}\"", previousDependency.Name, loader.Name);
                    loader.ExtensionDeactivated(context, extension);
                }
            }

            if (activatedExtension != null) {
                context.NewDependencies.Add(new DependencyDescriptor {
                    Name = extension.Id,
                    LoaderName = activatedExtension.Loader.Name,
                    VirtualPath = activatedExtension.VirtualPath,
                    References = references
                });
            }

            // Keep track of which loader we use for every extension
            // This will be needed for processing references from other dependent extensions
            context.ProcessedExtensions.Add(extension.Id, activatedExtension);
        }
 private IViewEngine ShallowEngines(ExtensionDescriptor theme)
 {
     //return _configuredEnginesCache.BindShallowEngines(theme.ThemeName, () => new ViewEngineCollectionWrapper(_viewEngineProviders.Select(vep => vep.CreateBareViewEngine())));
     return DeepEngines(theme);
 }
        public override void ExtensionDeactivated(ExtensionLoadingContext ctx, ExtensionDescriptor extension)
        {
            if (_assemblyProbingFolder.AssemblyExists(extension.Id)) {
                ctx.DeleteActions.Add(
                    () => {
                        Logger.Information("ExtensionDeactivated: Deleting assembly \"{0}\" from probing directory", extension.Id);
                        _assemblyProbingFolder.DeleteAssembly(extension.Id);
                    });

                // We need to restart the appDomain if the assembly is loaded
                if (_hostEnvironment.IsAssemblyLoaded(extension.Id)) {
                    Logger.Information("ExtensionDeactivated: Module \"{0}\" is deactivated and its assembly is loaded, forcing AppDomain restart", extension.Id);
                    ctx.RestartAppDomain = true;
                }
            }
        }
 public ExtensionEntry Load(ExtensionDescriptor descriptor)
 {
     return new ExtensionEntry { Descriptor = descriptor, ExportedTypes = new[] { typeof(Alpha), typeof(Beta), typeof(Phi) } };
 }
        protected override ExtensionEntry LoadWorker(ExtensionDescriptor descriptor)
        {
            if (Disabled)
                return null;

            var assembly = _buildManager.GetReferencedAssembly(descriptor.Id);
            if (assembly == null)
                return null;

            Logger.Information("Loaded referenced extension \"{0}\": assembly name=\"{1}\"", descriptor.Name, assembly.FullName);

            return new ExtensionEntry {
                Descriptor = descriptor,
                Assembly = assembly,
                ExportedTypes = assembly.GetExportedTypes()
            };
        }
        private IViewEngine DeepEngines(ExtensionDescriptor theme)
        {
            return _configuredEnginesCache.BindDeepEngines(theme.Id, () => {
                // The order for searching for views is:
                // 1. Current "theme"
                // 2. Base themes of the current theme (in "base" order)
                // 3. Active features from modules in dependency order

                var engines = Enumerable.Empty<IViewEngine>();
                // 1. current theme
                engines = engines.Concat(CreateThemeViewEngines(theme));

                // 2. Base themes of the current theme (in "base" order)
                engines = GetBaseThemes(theme).Aggregate(engines, (current, baseTheme) => current.Concat(CreateThemeViewEngines(baseTheme)));

                // 3. Active features from modules in dependency order
                var enabledModules = _extensionManager.EnabledFeatures(_shellDescriptor)
                    .Reverse()  // reverse from (C <= B <= A) to (A => B => C)
                    .Where(fd => DefaultExtensionTypes.IsModule(fd.Extension.ExtensionType));

                var allLocations = enabledModules.Concat(enabledModules)
                    .Select(fd => fd.Extension.Location + "/" + fd.Extension.Id)
                    .Distinct(StringComparer.OrdinalIgnoreCase)
                    .ToList();

                var moduleParams = new CreateModulesViewEngineParams { VirtualPaths = allLocations };
                engines = engines.Concat(_viewEngineProviders.Select(vep => vep.CreateModulesViewEngine(moduleParams)));

                return new ViewEngineCollectionWrapper(engines);
            });
        }
 private static bool IsTypeFromModule(Type type, ExtensionDescriptor descriptor)
 {
     return (type.Namespace + ".").StartsWith(CoreAssemblyName + "." + descriptor.Id + ".");
 }
 public IEnumerable<ExtensionDescriptor> AvailableExtensions()
 {
     var ext = new ExtensionDescriptor { Id = "Coevery.Framework" };
     ext.Features = new[] { new FeatureDescriptor { Extension = ext, Id = ext.Id } };
     yield return ext;
 }
 public bool IsCompatibleWithModuleReferences(ExtensionDescriptor extension, IEnumerable<ExtensionProbeEntry> references)
 {
     throw new NotImplementedException();
 }
        public string GetAssemblyPath(ExtensionDescriptor descriptor)
        {
            var assemblyPath = _virtualPathProvider.Combine(descriptor.Location, descriptor.Id, "bin",
                                                            descriptor.Id + ".dll");
            if (!_virtualPathProvider.FileExists(assemblyPath))
                return null;

            return assemblyPath;
        }
 public void Monitor(ExtensionDescriptor extension, Action<IVolatileToken> monitor)
 {
 }
 public override bool IsCompatibleWithModuleReferences(ExtensionDescriptor extension, IEnumerable<ExtensionProbeEntry> references)
 {
     // A pre-compiled module is _not_ compatible with a dynamically loaded module
     // because a pre-compiled module usually references a pre-compiled assembly binary
     // which will have a different identity (i.e. name) from the dynamic module.
     bool result = references.All(r => r.Loader.GetType() != typeof(DynamicExtensionLoader));
     if (!result) {
         Logger.Information("Extension \"{0}\" will not be loaded as pre-compiled extension because one or more referenced extension is dynamically compiled", extension.Id);
     }
     return result;
 }
 public IEnumerable<ExtensionReferenceProbeEntry> ProbeReferences(ExtensionDescriptor extensionDescriptor)
 {
     throw new NotImplementedException();
 }
        public override void Monitor(ExtensionDescriptor descriptor, Action<IVolatileToken> monitor)
        {
            if (Disabled)
                return;

            if (DisableMonitoring)
                return;

            // If the assembly exists, monitor it
            string assemblyPath = GetAssemblyPath(descriptor);
            if (assemblyPath != null) {
                Logger.Debug("Monitoring virtual path \"{0}\"", assemblyPath);
                monitor(_virtualPathMonitor.WhenPathChanges(assemblyPath));
                return;
            }

            // If the assembly doesn't exist, we monitor the containing "bin" folder, as the assembly
            // may exist later if it is recompiled in Visual Studio for example, and we need to
            // detect that as a change of configuration.
            var assemblyDirectory = _virtualPathProvider.Combine(descriptor.Location, descriptor.Id, "bin");
            if (_virtualPathProvider.DirectoryExists(assemblyDirectory)) {
                Logger.Debug("Monitoring virtual path \"{0}\"", assemblyDirectory);
                monitor(_virtualPathMonitor.WhenPathChanges(assemblyDirectory));
            }
        }