Exemple #1
0
        /// <summary>
        /// Triggers ServiceLocator bootstrapping (scans the GAC for assemblies with a name
        /// that matches *.ServiceLocator.DLL, by convention).
        /// </summary>
        /// <param name="web">The context's SPWeb. Keep null if none available.</param>
        /// <param name="site">The context's SPSite. Keep null if none available.</param>
        /// <param name="webApplication">The context's SPWebApplication. Keep null if none available.</param>
        /// <param name="farm">The context's SPFarm. Keep null if none available.</param>
        private void EnsureServiceLocatorAccessor(SPWeb web, SPSite site, SPWebApplication webApplication, SPFarm farm)
        {
            if (this.locatorAccessor == null)
            {
                lock (this.lockObject)
                {
                    if (this.locatorAccessor == null)
                    {
                        try
                        {
                            // 1) Scan the GAC for any DLL matching the *.ServiceLocator.DLL pattern
                            var matchingAssemblies = GacAssemblyLocator.GetAssemblies(new List <string>()
                            {
                                "GAC_MSIL"
                            }, assemblyFileName => assemblyFileName.Contains(".ServiceLocator"));

                            Assembly serviceLocatorAssembly = null;
                            Type     accessorType           = null;

                            if (matchingAssemblies.Any())
                            {
                                if (matchingAssemblies.Count > 1)
                                {
                                    // 2) If more than one service locator is found, we must disambiguate. We have to use the
                                    //    contextual SPWeb, SPSite, SPWebApp or SPFarm objects and extract the preferred service
                                    //    locator assembly name setting from their property bag.
                                    //    The SPWeb's property bag is inspected first, if available, then the SPSite's RootWeb property
                                    //    bag, then the SPWebApp's, then the SPFarm's property bag as a last resort.
                                    string contextObjectWhereDiscriminatorWasFound;
                                    string serviceLocatorAssemblyNameDiscriminator = FindServiceLocatorAccessorTypeNameFromMostSpecificPropertyBag(web, site, webApplication, farm, out contextObjectWhereDiscriminatorWasFound);

                                    string allServiceLocatorAssemblyNames  = string.Join(";", matchingAssemblies.Select(locatorAssembly => locatorAssembly.FullName).ToArray());
                                    string basicDisambiguationErrorMessage = string.Format(
                                        CultureInfo.InvariantCulture,
                                        "Failed to disambiguate between all DLLs in the GAC that match the *.ServiceLocator.DLL filename pattern. All matching assemblies in GAC: {0}.",
                                        allServiceLocatorAssemblyNames);

                                    if (!string.IsNullOrEmpty(serviceLocatorAssemblyNameDiscriminator))
                                    {
                                        // We found a ServiceLocator assembly name in one of the context's Property Bags.
                                        serviceLocatorAssembly = matchingAssemblies.FirstOrDefault(assembly => assembly.FullName.Contains(serviceLocatorAssemblyNameDiscriminator));

                                        if (serviceLocatorAssembly == null)
                                        {
                                            throw new InvalidOperationException(basicDisambiguationErrorMessage +
                                                                                " The discriminator found in one of the context's Property Bags (value=" + serviceLocatorAssemblyNameDiscriminator +
                                                                                ", property bag location=" + contextObjectWhereDiscriminatorWasFound + ") did not match either of the " +
                                                                                matchingAssemblies.Count + " ServiceLocator DLLs available in GAC. The discriminator value should match one of the DLLs so that we can determine which to use.");
                                        }
                                    }
                                    else
                                    {
                                        // We failed to find a discriminator setting in all of the context's Property Bags
                                        throw new InvalidOperationException(basicDisambiguationErrorMessage +
                                                                            " You cannot begin injection from the root application container if more that one ServiceLocator assembly exists in the GAC." +
                                                                            " You must begin injection with one of the following methods on your ISharePointServiceLocator: BeginLifetimeScope(SPFeature) or" +
                                                                            " BeginLifetimeScope(SPWeb) or BeginLifetimeScope(SPSite) or BeginLifetimeScope(SPWebApplication) or BeginLifetimeScope(SPFarm)," +
                                                                            " depending on your context. IMPORTANT: The property bags on the context' SPWeb, SPSite, SPWebApplication and SPFarm will be inspected" +
                                                                            " (in that order) to find a value for the key '" + KeyServiceLocatorAssemblyName + "'. This discriminator value will indicate to Dynamite's" +
                                                                            " AddOnProvidedServiceLocator which concrete add-on's ServiceLocator DLL to use in the current context.");
                                    }
                                }

                                if (serviceLocatorAssembly != null)
                                {
                                    // Only one matching assembly, find its accessor class
                                    accessorType = FindServiceLocatorAccessorType(serviceLocatorAssembly);
                                }
                                else
                                {
                                    // Only one ServiceLocator DLL found in GAC. There is no ambiguity: use this locator.
                                    serviceLocatorAssembly = matchingAssemblies[0];
                                }

                                if (serviceLocatorAssembly != null)
                                {
                                    // At this point we figured out the right matching assembly: find its accessor class within its types
                                    accessorType = FindServiceLocatorAccessorType(serviceLocatorAssembly);
                                }
                            }
                            else
                            {
                                // Not even one DLL in GAC matches the *.ServiceLocator.DLL pattern
                                throw new InvalidOperationException("Failed to find any assembly in the GAC that matches the *.ServiceLocator.DLL pattern.");
                            }

                            if (accessorType != null)
                            {
                                // 3) Create the accessor instance
                                this.locatorAccessor = (ISharePointServiceLocatorAccessor)Activator.CreateInstance(accessorType);
                            }
                            else
                            {
                                throw new InvalidOperationException("Failed to find implementation of ISharePointServiceLocatorAccessor for AddOnProvidedServiceLocator. Your ServiceLocator assembly (" + serviceLocatorAssembly.FullName + ") should expose its static container through that interface.");
                            }
                        }
                        catch (InvalidOperationException exception)
                        {
                            var logger = new TraceLogger("GSoft.Dynamite", "GSoft.Dynamite", false);
                            logger.Error(
                                "AddOnProvidedServiceLocator Initialization Error - An error occured while trying to find a DLL matching the pattern *ServiceLocator.dll in the GAC. The FallbackServiceLocator will be used instead as a last resort (no AddOn registration module will be registered). Exception: {0}",
                                exception.ToString());

                            // Either no assembly in the GAC matches the pattern *.ServiceLocator.DLL pattern,
                            // or in the matching assembly that was found, no class implements ISharePointServiceLocatorAccessor.
                            // In this case, use our default all-available-Dynamite-modules-only service locator
                            this.locatorAccessor = new FallbackServiceLocator();
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Adds the locator accessor to the available accessors.
        /// If all parameters are null or an accessor already exists with that context, an exception is thrown.
        /// </summary>
        /// <param name="web">The context's SPWeb. Keep null if none available.</param>
        /// <param name="site">The context's SPSite. Keep null if none available.</param>
        /// <param name="webApplication">The context's SPWebApplication. Keep null if none available.</param>
        /// <param name="farm">The context's SPFarm. Keep null if none available.</param>
        /// <param name="locatorAccessor">The SharePoint locator accessor we want to add.</param>
        private void AddLocatorAccessor(SPWeb web, SPSite site, SPWebApplication webApplication, SPFarm farm, ISharePointServiceLocatorAccessor locatorAccessor)
        {
            // Get the identifier that represents the most specific context.
            Guid? mostSpecificIdentifier = GetMostSpecificIdentifier(web, site, webApplication, farm);
            if (!mostSpecificIdentifier.HasValue)
            {
                throw new NotSupportedException("Unable to get the most specific identifier for the context. Make sure at lest one parameter is not null.");
            }

            if (this.GetLocatorAccessor(web, site, webApplication, farm) != null)
            {
                throw new NotSupportedException("Trying to add a SharePoint Locator Accessor for a context that is already added.");
            }

            // Add the accessor to the dictionary.
            this.locatorAccessors.Add(mostSpecificIdentifier.Value, locatorAccessor);
        }
Exemple #3
0
        /// <summary>
        /// Adds the locator accessor to the available accessors.
        /// If all parameters are null or an accessor already exists with that context, an exception is thrown.
        /// </summary>
        /// <param name="web">The context's SPWeb. Keep null if none available.</param>
        /// <param name="site">The context's SPSite. Keep null if none available.</param>
        /// <param name="webApplication">The context's SPWebApplication. Keep null if none available.</param>
        /// <param name="farm">The context's SPFarm. Keep null if none available.</param>
        /// <param name="locatorAccessor">The SharePoint locator accessor we want to add.</param>
        private void AddLocatorAccessor(SPWeb web, SPSite site, SPWebApplication webApplication, SPFarm farm, ISharePointServiceLocatorAccessor locatorAccessor)
        {
            // Get the identifier that represents the most specific context.
            Guid?mostSpecificIdentifier = GetMostSpecificIdentifier(web, site, webApplication, farm);

            if (!mostSpecificIdentifier.HasValue)
            {
                throw new NotSupportedException("Unable to get the most specific identifier for the context. Make sure at lest one parameter is not null.");
            }

            if (this.GetLocatorAccessor(web, site, webApplication, farm) != null)
            {
                throw new NotSupportedException("Trying to add a SharePoint Locator Accessor for a context that is already added.");
            }

            // Add the accessor to the dictionary.
            this.locatorAccessors.Add(mostSpecificIdentifier.Value, locatorAccessor);
        }
        private void EnsureServiceLocatorAccessorForCurrentSiteContext(SPSite site)
        {
            if (locatorAccessor == null)
            {
                lock (lockObject)
                {
                    if (this.locatorAccessor == null)
                    {
                        // 1) Scan the GAC for any DLL matching the *.ServiceLocator.DLL pattern
                        var assemblyScanner = new GacAssemblyLocator();
                        var matchingAssemblies = assemblyScanner.GetAssemblies(new List<string>() { "GAC_MSIL" }, assemblyFileName => assemblyFileName.Contains(".ServiceLocator"));

                        Type accessorType = null;

                        if (matchingAssemblies.Any())
                        {
                            var serviceLocatorAssembly = matchingAssemblies[0];

                            if (matchingAssemblies.Count > 1)
                            {
                                // 2) If more than one service locator is found, gotta use the contextual SPSite object
                                //    and extract the preferred service locator setting from its property bag.
                                if (site != null)
                                {
                                    using (var rootWeb = site.OpenWeb())
                                    {
                                        string serviceLocatorAssemlyName = rootWeb.Properties[KeyServiceLocatorAssemblyName];

                                        serviceLocatorAssembly = matchingAssemblies.FirstOrDefault(assembly => assembly.FullName.Contains(serviceLocatorAssemlyName));
                                    }
                                }
                                else
                                {
                                    throw new ArgumentNullException("site");
                                }
                            }

                            if (serviceLocatorAssembly != null)
                            {
                                // Only one matching assembly, find its accessor class
                                accessorType = this.FindServiceLocatorAccessorType(serviceLocatorAssembly);
                            }
                            else
                            {
                                throw new InvalidOperationException("Failed to find an assembly matching the *.ServiceLocator.DLL pattern to provide a service locator.");
                            }
                        }

                        if (accessorType != null)
                        {
                            // 3) Create the accessor instance
                            this.locatorAccessor = (ISharePointServiceLocatorAccessor)Activator.CreateInstance(accessorType);
                        }
                        else
                        {
                            throw new InvalidOperationException("Failed to find implementation of ISharePointServiceLocatorAccessor for AddOnProvidedServiceLocator. Your *.ServiceLocator.DLL assembly should expose its static container through that interface.");
                        }

                    }
                }
            }
        }
        /// <summary>
        /// Triggers ServiceLocator bootstrapping (scans the GAC for assemblies with a name
        /// that matches *.ServiceLocator.DLL, by convention).
        /// </summary>
        /// <param name="web">The context's SPWeb. Keep null if none available.</param>
        /// <param name="site">The context's SPSite. Keep null if none available.</param>
        /// <param name="webApplication">The context's SPWebApplication. Keep null if none available.</param>
        /// <param name="farm">The context's SPFarm. Keep null if none available.</param>
        private void EnsureServiceLocatorAccessor(SPWeb web, SPSite site, SPWebApplication webApplication, SPFarm farm)
        {
            if (locatorAccessor == null)
            {
                lock (lockObject)
                {
                    if (this.locatorAccessor == null)
                    {
                        try
                        {
                            // 1) Scan the GAC for any DLL matching the *.ServiceLocator.DLL pattern
                            var assemblyScanner = new GacAssemblyLocator();
                            var matchingAssemblies = assemblyScanner.GetAssemblies(new List<string>() { "GAC_MSIL" }, assemblyFileName => assemblyFileName.Contains(".ServiceLocator"));

                            Assembly serviceLocatorAssembly = null;
                            Type accessorType = null;

                            if (matchingAssemblies.Any())
                            {

                                if (matchingAssemblies.Count > 1)
                                {
                                    // 2) If more than one service locator is found, we must disambiguate. We have to use the
                                    //    contextual SPWeb, SPSite, SPWebApp or SPFarm objects and extract the preferred service
                                    //    locator assembly name setting from their property bag.
                                    //    The SPWeb's property bag is inspected first, if available, then the SPSite's RootWeb property
                                    //    bag, then the SPWebApp's, then the SPFarm's property bag as a last resort.
                                    string contextObjectWhereDiscriminatorWasFound;
                                    string serviceLocatorAssemblyNameDiscriminator = this.FindServiceLocatorAccessorTypeNameFromMostSpecificPropertyBag(web, site, webApplication, farm, out contextObjectWhereDiscriminatorWasFound);

                                    string allServiceLocatorAssemblyNames = string.Join(";", matchingAssemblies.Select(locatorAssembly => locatorAssembly.FullName).ToArray());
                                    string basicDisambiguationErrorMessage = string.Format(
                                        CultureInfo.InvariantCulture,
                                        "Failed to disambiguate between all DLLs in the GAC that match the *.ServiceLocator.DLL filename pattern. All matching assemblies in GAC: {0}.",
                                        allServiceLocatorAssemblyNames);

                                    if (!string.IsNullOrEmpty(serviceLocatorAssemblyNameDiscriminator))
                                    {
                                        // We found a ServiceLocator assembly name in one of the context's Property Bags.
                                        serviceLocatorAssembly = matchingAssemblies.FirstOrDefault(assembly => assembly.FullName.Contains(serviceLocatorAssemblyNameDiscriminator));

                                        if (serviceLocatorAssembly == null)
                                        {
                                            throw new InvalidOperationException(basicDisambiguationErrorMessage +
                                                " The discriminator found in one of the context's Property Bags (value=" + serviceLocatorAssemblyNameDiscriminator +
                                                ", property bag location=" + contextObjectWhereDiscriminatorWasFound + ") did not match either of the " +
                                                matchingAssemblies.Count + " ServiceLocator DLLs available in GAC. The discriminator value should match one of the DLLs so that we can determine which to use.");
                                        }
                                    }
                                    else
                                    {
                                        // We failed to find a disambiguator setting in all of the context's Property Bags
                                        throw new InvalidOperationException(basicDisambiguationErrorMessage +
                                            " You cannot begin injection from the root application container if more that one ServiceLocator assembly exists in the GAC." +
                                            " You must begin injection with one of the following methods on your ISharePointServiceLocator: BeginLifetimeScope(SPFeature) or" +
                                            " BeginLifetimeScope(SPWeb) or BeginLifetimeScope(SPSite) or BeginLifetimeScope(SPWebApplication) or BeginLifetimeScope(SPFarm)," +
                                            " depending on your context. IMPORTANT: The property bags on the context' SPWeb, SPSite, SPWebApplication and SPFarm will be inspected" +
                                            " (in that order) to find a value for the key '" + KeyServiceLocatorAssemblyName + "'. This discriminator value will indicate to Dynamite's" +
                                            " AddOnProvidedServiceLocator which concrete add-on's ServiceLocator DLL to use in the current context.");
                                    }
                                }
                                else
                                {
                                    // Only one ServiceLocator DLL found in GAC. There is no ambiguity: use this locator.
                                    serviceLocatorAssembly = matchingAssemblies[0];
                                }

                                if (serviceLocatorAssembly != null)
                                {
                                    // At this point we figured out the right matching assembly: find its accessor class within its types
                                    accessorType = this.FindServiceLocatorAccessorType(serviceLocatorAssembly);
                                }
                            }
                            else
                            {
                                // Not even one DLL in GAC matches the *.ServiceLocator.DLL pattern
                                throw new InvalidOperationException("Failed to find any assembly in the GAC that matches the *.ServiceLocator.DLL pattern.");
                            }

                            if (accessorType != null)
                            {
                                // 3) Create the accessor instance
                                this.locatorAccessor = (ISharePointServiceLocatorAccessor)Activator.CreateInstance(accessorType);
                            }
                            else
                            {
                                throw new InvalidOperationException("Failed to find implementation of ISharePointServiceLocatorAccessor for AddOnProvidedServiceLocator. Your ServiceLocator assembly (" + serviceLocatorAssembly.FullName + ") should expose its static container through that interface.");
                            }
                        }
                        catch (InvalidOperationException exception)
                        {
                            var logger = new TraceLogger("GSoft.Dynamite", "GSoft.Dynamite", false);
                            logger.Error(
                                "AddOnProvidedServiceLocator Initialization Error - An error occured while trying to find a DLL matching the pattern *ServiceLocator.dll in the GAC. The FallbackServiceLocator will be used instead as a last resort (no AddOn registration module will be registered). Exception: {0}",
                                exception.ToString());

                            // Either no assembly in the GAC matches the pattern *.ServiceLocator.DLL pattern,
                            // or in the matching assembly that was found, no class implements ISharePointServiceLocatorAccessor.
                            // In this case, use our default all-available-Dynamite-modules-only service locator
                            this.locatorAccessor = new FallbackServiceLocator();
                        }

                    }
                }
            }
        }