Example #1
0
        /// <summary>
        /// Reads all items from the database and stores in local cache
        /// </summary>
        private static void EnsureCache()
        {
            using (var lck = new UpgradeableReadLock(Locker))
            {
                if (_cacheIsEnsured) return;
                
                lck.UpgradeToWriteLock();

                using (var dr = SqlHelper.ExecuteReader("Select pk, id, [key], parent from cmsDictionary"))
                {
                    while (dr.Read())
                    {
                        //create new dictionaryitem object and put in cache
                        var item = new DictionaryItem(dr.GetInt("pk"),
                                                      dr.GetString("key"),
                                                      dr.GetGuid("id"),
                                                      dr.GetGuid("parent"));

                        DictionaryItems.TryAdd(item.key, item);
                    }
                }

                _cacheIsEnsured = true;
            }            
        }
        static void UmbracoModuleRouteAttempt(object sender, Routing.RoutableAttemptEventArgs e)
        {
            if (e.HttpContext.Request == null || e.HttpContext.Request.Url == null) return;

            if (e.Outcome == EnsureRoutableOutcome.IsRoutable)
            {
                using (var lck = new UpgradeableReadLock(Locker))
                {
                    //we only want to do the initial update once
                    if (!_initUpdated)
                    {
                        lck.UpgradeToWriteLock();
                        _initUpdated = true;
                        UpdateServerEntry(e.HttpContext, e.UmbracoContext.Application);
                        return;
                    }
                }
            }

            //if it is not a document request, we'll check if it is a back end request
            if (e.Outcome == EnsureRoutableOutcome.NotDocumentRequest)
            {
                //check if this is in the umbraco back office
                if (e.HttpContext.Request.Url.IsBackOfficeRequest())
                {
                    //yup it's a back office request!
                    using (var lck = new UpgradeableReadLock(Locker))
                    {
                        //we don't want to update if it's not been at least a minute since last time
                        var isItAMinute = DateTime.Now.Subtract(_lastUpdated).TotalSeconds >= 60;
                        if (isItAMinute)
                        {
                            lck.UpgradeToWriteLock();
                            _initUpdated = true;
                            _lastUpdated = DateTime.Now;
                            UpdateServerEntry(e.HttpContext, e.UmbracoContext.Application);
                        }
                    }
                }
            }
        }
Example #3
0
        /// <summary>
        /// Return a list of found local Assemblies excluding the known assemblies we don't want to scan
        /// and exluding the ones passed in and excluding the exclusion list filter, the results of this are
        /// cached for perforance reasons.
        /// </summary>
        /// <param name="excludeFromResults"></param>
        /// <returns></returns>
        internal static HashSet <Assembly> GetAssembliesWithKnownExclusions(
            IEnumerable <Assembly> excludeFromResults = null)
        {
            using (var lck = new UpgradeableReadLock(LocalFilteredAssemblyCacheLocker))
            {
                if (LocalFilteredAssemblyCache.Any())
                {
                    return(LocalFilteredAssemblyCache);
                }

                lck.UpgradeToWriteLock();

                var assemblies = GetFilteredAssemblies(excludeFromResults, KnownAssemblyExclusionFilter);
                foreach (var a in assemblies)
                {
                    LocalFilteredAssemblyCache.Add(a);
                }

                return(LocalFilteredAssemblyCache);
            }
        }
Example #4
0
        private IEnumerable <Type> ResolveTypes <T>(
            Func <IEnumerable <Type> > finder,
            TypeResolutionKind resolutionType,
            bool cacheResult)
        {
            using (var readLock = new UpgradeableReadLock(_lock))
            {
                using (DisposableTimer.TraceDuration <PluginManager>(
                           String.Format("Starting resolution types of {0}", typeof(T).FullName),
                           String.Format("Completed resolution of types of {0}", typeof(T).FullName)))
                {
                    //check if the TypeList already exists, if so return it, if not we'll create it
                    var typeList = _types.SingleOrDefault(x => x.IsTypeList <T>(resolutionType));
                    //if we're not caching the result then proceed, or if the type list doesn't exist then proceed
                    if (!cacheResult || typeList == null)
                    {
                        //upgrade to a write lock since we're adding to the collection
                        readLock.UpgradeToWriteLock();

                        typeList = new TypeList <T>(resolutionType);

                        foreach (var t in finder())
                        {
                            typeList.AddType(t);
                        }

                        //only add the cache if we are to cache the results
                        if (cacheResult)
                        {
                            //add the type list to the collection
                            _types.Add(typeList);
                        }
                    }
                    return(typeList.GetTypes());
                }
            }
        }
        private IEnumerable <Type> ResolveTypes <T>(
            Func <IEnumerable <Type> > finder,
            TypeResolutionKind resolutionType,
            bool cacheResult)
        {
            using (var readLock = new UpgradeableReadLock(Locker))
            {
                var typesFound = new List <Type>();

                using (_logger.TraceDuration <PluginManager>(
                           String.Format("Starting resolution types of {0}", typeof(T).FullName),
                           String.Format("Completed resolution of types of {0}, found {1}", typeof(T).FullName, typesFound.Count)))
                {
                    //check if the TypeList already exists, if so return it, if not we'll create it
                    var typeList = _types.SingleOrDefault(x => x.IsTypeList <T>(resolutionType));

                    //need to put some logging here to try to figure out why this is happening: http://issues.umbraco.org/issue/U4-3505
                    if (cacheResult && typeList != null)
                    {
                        _logger.Logger.Debug <PluginManager>("Existing typeList found for {0} with resolution type {1}", () => typeof(T), () => resolutionType);
                    }

                    //if we're not caching the result then proceed, or if the type list doesn't exist then proceed
                    if (cacheResult == false || typeList == null)
                    {
                        //upgrade to a write lock since we're adding to the collection
                        readLock.UpgradeToWriteLock();

                        typeList = new TypeList <T>(resolutionType);

                        //we first need to look into our cache file (this has nothing to do with the 'cacheResult' parameter which caches in memory).
                        //if assemblies have not changed and the cache file actually exists, then proceed to try to lookup by the cache file.
                        if (RequiresRescanning == false && File.Exists(GetPluginListFilePath()))
                        {
                            var fileCacheResult = TryGetCachedPluginsFromFile <T>(resolutionType);

                            //here we need to identify if the CachedPluginNotFoundInFile was the exception, if it was then we need to re-scan
                            //in some cases the plugin will not have been scanned for on application startup, but the assemblies haven't changed
                            //so in this instance there will never be a result.
                            if (fileCacheResult.Exception != null && fileCacheResult.Exception is CachedPluginNotFoundInFileException)
                            {
                                _logger.Logger.Debug <PluginManager>("Tried to find typelist for type {0} and resolution {1} in file cache but the type was not found so loading types by assembly scan ", () => typeof(T), () => resolutionType);

                                //we don't have a cache for this so proceed to look them up by scanning
                                LoadViaScanningAndUpdateCacheFile <T>(typeList, resolutionType, finder);
                            }
                            else
                            {
                                if (fileCacheResult.Success)
                                {
                                    var successfullyLoadedFromCache = true;
                                    //we have a previous cache for this so we don't need to scan we just load what has been found in the file
                                    foreach (var t in fileCacheResult.Result)
                                    {
                                        try
                                        {
                                            //we use the build manager to ensure we get all types loaded, this is slightly slower than
                                            //Type.GetType but if the types in the assembly aren't loaded yet then we have problems with that.
                                            var type = BuildManager.GetType(t, true);
                                            typeList.AddType(type);
                                        }
                                        catch (Exception ex)
                                        {
                                            //if there are any exceptions loading types, we have to exist, this should never happen so
                                            //we will need to revert to scanning for types.
                                            successfullyLoadedFromCache = false;
                                            _logger.Logger.Error <PluginManager>("Could not load a cached plugin type: " + t + " now reverting to re-scanning assemblies for the base type: " + typeof(T).FullName, ex);
                                            break;
                                        }
                                    }
                                    if (successfullyLoadedFromCache == false)
                                    {
                                        //we need to manually load by scanning if loading from the file was not successful.
                                        LoadViaScanningAndUpdateCacheFile <T>(typeList, resolutionType, finder);
                                    }
                                    else
                                    {
                                        _logger.Logger.Debug <PluginManager>("Loaded plugin types {0} with resolution {1} from persisted cache", () => typeof(T), () => resolutionType);
                                    }
                                }
                            }
                        }
                        else
                        {
                            _logger.Logger.Debug <PluginManager>("Assembly changes detected, loading types {0} for resolution {1} by assembly scan", () => typeof(T), () => resolutionType);

                            //we don't have a cache for this so proceed to look them up by scanning
                            LoadViaScanningAndUpdateCacheFile <T>(typeList, resolutionType, finder);
                        }

                        //only add the cache if we are to cache the results
                        if (cacheResult)
                        {
                            //add the type list to the collection
                            var added = _types.Add(typeList);

                            _logger.Logger.Debug <PluginManager>("Caching of typelist for type {0} and resolution {1} was successful = {2}", () => typeof(T), () => resolutionType, () => added);
                        }
                    }
                    typesFound = typeList.GetTypes().ToList();
                }

                return(typesFound);
            }
        }
Example #6
0
        /// <summary>
        /// lazily load a reference to all assemblies and only local assemblies.
        /// This is a modified version of: http://www.dominicpettifer.co.uk/Blog/44/how-to-get-a-reference-to-all-assemblies-in-the--bin-folder
        /// </summary>
        /// <remarks>
        /// We do this because we cannot use AppDomain.Current.GetAssemblies() as this will return only assemblies that have been
        /// loaded in the CLR, not all assemblies.
        /// See these threads:
        /// http://issues.umbraco.org/issue/U5-198
        /// http://stackoverflow.com/questions/3552223/asp-net-appdomain-currentdomain-getassemblies-assemblies-missing-after-app
        /// http://stackoverflow.com/questions/2477787/difference-between-appdomain-getassemblies-and-buildmanager-getreferencedassembl
        /// </remarks>
        internal static HashSet <Assembly> GetAllAssemblies()
        {
            using (var lck = new UpgradeableReadLock(Locker))
            {
                if (_allAssemblies == null)
                {
                    lck.UpgradeToWriteLock();

                    HashSet <Assembly> assemblies = null;
                    try
                    {
                        var isHosted = HttpContext.Current != null;

                        try
                        {
                            if (isHosted)
                            {
                                assemblies = new HashSet <Assembly>(BuildManager.GetReferencedAssemblies().Cast <Assembly>());
                            }
                        }
                        catch (InvalidOperationException e)
                        {
                            if (!(e.InnerException is SecurityException))
                            {
                                throw;
                            }
                        }


                        if (assemblies == null)
                        {
                            //NOTE: we cannot use AppDomain.CurrentDomain.GetAssemblies() because this only returns assemblies that have
                            // already been loaded in to the app domain, instead we will look directly into the bin folder and load each one.
                            var binFolder        = IOHelper.GetRootDirectoryBinFolder();
                            var binAssemblyFiles = Directory.GetFiles(binFolder, "*.dll", SearchOption.TopDirectoryOnly).ToList();
                            //var binFolder = Assembly.GetExecutingAssembly().GetAssemblyFile().Directory;
                            //var binAssemblyFiles = Directory.GetFiles(binFolder.FullName, "*.dll", SearchOption.TopDirectoryOnly).ToList();
                            assemblies = new HashSet <Assembly>();
                            foreach (var a in binAssemblyFiles)
                            {
                                try
                                {
                                    var assName = AssemblyName.GetAssemblyName(a);
                                    var ass     = Assembly.Load(assName);
                                    assemblies.Add(ass);
                                }
                                catch (Exception e)
                                {
                                    if (e is SecurityException || e is BadImageFormatException)
                                    {
                                        //swallow these exceptions
                                    }
                                    else
                                    {
                                        throw;
                                    }
                                }
                            }
                        }

                        //if for some reason they are still no assemblies, then use the AppDomain to load in already loaded assemblies.
                        if (!assemblies.Any())
                        {
                            foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
                            {
                                assemblies.Add(a);
                            }
                        }

                        //here we are trying to get the App_Code assembly
                        var fileExtensions = new[] { ".cs", ".vb" }; //only vb and cs files are supported
                        var appCodeFolder  = new DirectoryInfo(IOHelper.MapPath(IOHelper.ResolveUrl("~/App_code")));
                        //check if the folder exists and if there are any files in it with the supported file extensions
                        if (appCodeFolder.Exists && (fileExtensions.Any(x => appCodeFolder.GetFiles("*" + x).Any())))
                        {
                            var appCodeAssembly = Assembly.Load("App_Code");
                            if (!assemblies.Contains(appCodeAssembly)) // BuildManager will find App_Code already
                            {
                                assemblies.Add(appCodeAssembly);
                            }
                        }

                        //now set the _allAssemblies
                        _allAssemblies = new HashSet <Assembly>(assemblies);
                    }
                    catch (InvalidOperationException e)
                    {
                        if (!(e.InnerException is SecurityException))
                        {
                            throw;
                        }

                        _binFolderAssemblies = _allAssemblies;
                    }
                }

                return(_allAssemblies);
            }
        }