/// <summary>
                ///     Loads the path from the specified XML element.
                /// </summary>
                /// <param name="element">The XML element to load from.</param>
                /// <param name="helper">The XML configuration helper being used.</param>
                internal void LoadFromXmlElement(XElement element, ConfigurationFileHelper helper)
                {
                    if (element == null)
                    {
                        return;
                    }

                    //Read source
                    Source = helper.ReadStringAttribute(
                        element,
                        "src"
                        );

                    //Read port
                    CreateDirectory = helper.ReadBooleanAttribute(
                        element,
                        "createDir",
                        false
                        );

                    // Read dependency resolution strategy
                    DependencyResolutionStrategy = helper.ReadDependencyResolutionStrategy(
                        element,
                        "dependencyResolutionStrategy",
                        DependencyResolutionStrategy.RecursiveFromFile
                        );
                }
        /// <summary>
        /// Adds a path to the DarkRift server that will be searched for plugins.
        /// </summary>
        /// <param name="source">The path to search.</param>
        /// <param name="dependencyResolutionStrategy">How dependencies for plugins loaded from this path should be resolved.</param>
        /// <returns>The configuration builder to continue construction.</returns>
        public DarkRiftServerConfigurationBuilder AddPluginSearchPath(string source, DependencyResolutionStrategy dependencyResolutionStrategy)
        {
            ServerSpawnData.PluginSearchSettings.PluginSearchPath pluginSearchPath = new ServerSpawnData.PluginSearchSettings.PluginSearchPath
            {
                Source = source,
                DependencyResolutionStrategy = dependencyResolutionStrategy
            };

            ServerSpawnData.PluginSearch.PluginSearchPaths.Add(pluginSearchPath);

            return(this);
        }
Пример #3
0
        /// <summary>
        ///     Adds a directory of plugin files to the index.
        /// </summary>
        /// <param name="directory">The directory to add.</param>
        /// <param name="create">Whether to create the directory if not present.</param>
        /// <param name="dependencyResolutionStrategy">The way to resolve dependencies for the plugin.</param>
        internal void AddDirectory(string directory, bool create, DependencyResolutionStrategy dependencyResolutionStrategy)
        {
            //Create plugin directory if not present
            if (Directory.Exists(directory))
            {
                //Get the names of all files to try and load
                string[] pluginSourceFiles = Directory.GetFiles(directory, "*.dll", SearchOption.AllDirectories);

                AddFiles(pluginSourceFiles, dependencyResolutionStrategy, directory);
            }
            else
            {
                if (create)
                    Directory.CreateDirectory(directory);
            }
        }
        /// <summary>
        ///     Reads a DependencyResolutionStrategy value from the XML element supplied.
        /// </summary>
        /// <param name="element">The element to read from.</param>
        /// <param name="attributeName">The name of the attribute to read.</param>
        /// <param name="defaultValue">The default value to return if the attribute isn't present.</param>
        /// <returns>The string read.</returns>
        internal DependencyResolutionStrategy ReadDependencyResolutionStrategy(XElement element, string attributeName, DependencyResolutionStrategy defaultValue)
        {
            var attribute = element.Attribute(attributeName);

            if (attribute == null)
            {
                return(defaultValue);
            }

            switch (ResolveVariables(attribute.Value, attribute).Trim().ToLower())
            {
            case "standard":
                return(DependencyResolutionStrategy.Standard);

            case "recursivefromfile":
                return(DependencyResolutionStrategy.RecursiveFromFile);

            case "recursivefromdirectory":
                return(DependencyResolutionStrategy.RecursiveFromDirectory);

            default:
                // TODO docs
                throw new XmlConfigurationException($"<{element.Name}> attribute '{attributeName}' is not a dependency resolution strategy. Expected 'standard', 'recursivefromfile' or 'recursivefromdirectory'.", $"{configurationDocsRoot}{element.Name}.html", attribute);
            }
        }
Пример #5
0
 /// <summary>
 ///     Adds the given plugin files into the index.
 /// </summary>
 /// <param name="files">An array of filepaths to the plugins.</param>
 /// <param name="dependencyResolutionStrategy">The way to resolve dependencies for the plugin.</param>
 /// <param name="searchedDirectory">the directory that was searched to find this file.</param>
 internal void AddFiles(IEnumerable<string> files, DependencyResolutionStrategy dependencyResolutionStrategy, string searchedDirectory)
 {
     //Load each file to a plugin
     foreach (string pluginSourceFile in files)
         AddFile(pluginSourceFile, dependencyResolutionStrategy, searchedDirectory);
 }
Пример #6
0
        /// <summary>
        ///     Adds all plugin types in the file to the index.
        /// </summary>
        /// <param name="file">The file containing the types.</param>
        /// <param name="dependencyResolutionStrategy">The way to resolve dependencies for the plugin.</param>
        /// <param name="searchedDirectory">the directory that was searched to find this file.</param>
        internal void AddFile(string file, DependencyResolutionStrategy dependencyResolutionStrategy, string searchedDirectory)
        {
            //Check the file is a dll
            if (Path.GetExtension(file) != ".dll")
                throw new ArgumentException("The filepath supplied was not a DLL library.");

            //Check the file exists
            if (!File.Exists(file))
                throw new FileNotFoundException("The specified filepath does not exist.");

            //Log
            logger.Trace($"Searching '{file}' for plugins.");

            // Setup assembly resolver to help find dependencies recursively in the folder heirachy of the plugin
            AppDomain.CurrentDomain.AssemblyResolve += LoadFromSameFolder;

            Assembly LoadFromSameFolder(object sender, ResolveEventArgs args)
            {
                string rootFolderPath;
                if (dependencyResolutionStrategy == DependencyResolutionStrategy.RecursiveFromFile)
                {
                    rootFolderPath = Path.GetDirectoryName(file);
                }
                else if (searchedDirectory != null)
                {
                    rootFolderPath = searchedDirectory;
                }
                else
                {
                    return null;
                }

                string assemblyPath = SearchForFile(rootFolderPath, new AssemblyName(args.Name).Name + ".dll");
                if (assemblyPath == null)
                    return null;

                return Assembly.LoadFrom(assemblyPath);
            }

            //Load the assembly
            Assembly assembly;
            try
            {
                assembly = Assembly.LoadFrom(Path.GetFullPath(file));
            }
            catch (Exception e)
            {
                logger.Error($"{file} could not be loaded as an exception occurred.", e);
                return;
            }

            //Get the types in the assembly
            IEnumerable<Type> enclosedTypes;
            try
            {
                enclosedTypes = assembly.GetTypes();
            }
            catch (ReflectionTypeLoadException e)
            {
                logger.Error(
                    $"Failed to load one or more plugins from DLL file '{file}', see following logs for more info.\n\nIf this file is a DarkRift plugin rebuilding this plugin may help. Make sure it is built against the same .NET target as DarkRift is running and built to a compatible version ({Environment.Version}).\n\nThis exception can also occur when an unmanaged DLL is loaded by DarkRift because it is in a plugin search path. If this is the case, consider moving the unmanaged library out of any plugin search paths (https://docs.microsoft.com/en-us/dotnet/core/dependency-loading/default-probing#unmanaged-native-library-probing) or modify the plugin search path configuration to avoid discovering the library (e.g. reference individual DLL files instead of the containing directory).",
                    e
                );

                foreach (Exception loaderException in e.LoaderExceptions)
                {
                    logger.Error("Additional exception detail from LoaderExceptions property:", loaderException);
                }

                // The types unable to be loaded will be null here!
                enclosedTypes = e.Types.Where(t => t != null);
            }

            //Find the types that are plugins
            foreach (Type enclosedType in enclosedTypes)
            {
                if (enclosedType.IsSubclassOf(typeof(PluginBase)) && !enclosedType.IsAbstract)
                {
                    //Add the plugin
                    AddType(enclosedType);
                }
            }

            // Remove resolver again
            AppDomain.CurrentDomain.AssemblyResolve -= LoadFromSameFolder;
        }