Free cookie consent management tool by TermsFeed Policy Generator

source: branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager/ApplicationManager.cs @ 2495

Last change on this file since 2495 was 2495, checked in by gkronber, 14 years ago

Fixed loading of plugins in correct order as defined by plugin dependencies in AppDomains for applications. (ApplicationManager) #799

File size: 8.9 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Security.Policy;
25using System.Reflection;
26using System.Diagnostics;
27using System.Security.Permissions;
28using System.Security;
29using System.Linq;
30using System.IO;
31
32namespace HeuristicLab.PluginInfrastructure.Manager {
33
34  public class DefaultApplicationManager : MarshalByRefObject, IApplicationManager {
35    internal event EventHandler<PluginInfrastructureEventArgs> PluginLoaded;
36    // cache for the AssemblyResolveEvent
37    // which must be handled when assemblies are loaded dynamically after the application start
38    private Dictionary<string, Assembly> loadedAssemblies;
39
40    private List<IPluginDescription> plugins;
41    /// <summary>
42    /// Gets all plugins.
43    /// </summary>
44    public IEnumerable<IPluginDescription> Plugins {
45      get { return plugins; }
46    }
47
48    private List<IApplicationDescription> applications;
49    /// <summary>
50    /// Gets all installed applications.
51    /// </summary>
52    public IEnumerable<IApplicationDescription> Applications {
53      get { return applications; }
54    }
55
56    public DefaultApplicationManager()
57      : base() {
58      loadedAssemblies = new Dictionary<string, Assembly>();
59      // needed for the special case when assemblies are loaded dynamically via LoadAssemblies()
60      AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => {
61        if (loadedAssemblies.ContainsKey(args.Name)) {
62          return loadedAssemblies[args.Name];
63        }
64        return null;
65      };
66    }
67
68    internal void PrepareApplicationDomain(IEnumerable<IApplicationDescription> apps, IEnumerable<IPluginDescription> plugins) {
69      this.plugins = new List<IPluginDescription>(plugins);
70      this.applications = new List<IApplicationDescription>(apps);
71      PluginInfrastructure.ApplicationManager.RegisterApplicationManager(this);
72      LoadPlugins(plugins);
73    }
74
75    private void LoadPlugins(IEnumerable<IPluginDescription> plugins) {
76      // load all loadable plugins (all dependencies available) into the execution context
77      foreach (var desc in PluginDescriptionIterator.IterateInDependencyOrder(plugins.Where(x => x.PluginState != PluginState.Disabled))) {
78        foreach (string assembly in desc.Assemblies) {
79          var asm = Assembly.LoadFrom(assembly);
80
81          // instantiate and load all plugins in this assembly
82          foreach (var plugin in GetInstances<IPlugin>(asm)) {
83            plugin.OnLoad();
84            FirePluginLoaded(plugin.Name);
85          }
86        }
87        desc.Load();
88      }
89
90    }
91
92    internal void Run(IApplicationDescription appInfo) {
93      IApplication runnablePlugin = (IApplication)Activator.CreateInstance(appInfo.DeclaringAssemblyName, appInfo.DeclaringTypeName).Unwrap();
94      try {
95        runnablePlugin.Run();
96      }
97      catch (Exception e) {
98        throw new Exception(String.Format(
99          "Unexpected exception caught: \"{0}\"\r\n" +
100          "Type: {1}\r\n" +
101          "Plugin {2}:\r\n{3}",
102          e.Message,
103          e.GetType().FullName,
104          appInfo.Name,
105          e.ToString()));
106      }
107    }
108
109    /// <summary>
110    /// Loads assemblies dynamically from a byte array
111    /// </summary>
112    /// <param name="plugins">bytearray of all assemblies that should be loaded</param>
113    public void LoadAssemblies(IEnumerable<byte[]> assemblies) {
114      foreach (byte[] asm in assemblies) {
115        Assembly loadedAsm = Assembly.Load(asm);
116        RegisterLoadedAssembly(loadedAsm);
117      }
118    }
119
120    // register assembly in the assembly cache for the AssemblyResolveEvent
121    private void RegisterLoadedAssembly(Assembly asm) {
122      loadedAssemblies.Add(asm.FullName, asm);
123      loadedAssemblies.Add(asm.GetName().Name, asm); // add short name
124    }
125
126    /// <summary>
127    /// Creates an instance of all types that are subtypes or the same type of the specified type and declared in <paramref name="plugin"/>
128    /// </summary>
129    /// <typeparam name="T">Most general type.</typeparam>
130    /// <returns>Enumerable of the created instances.</returns>
131    public IEnumerable<T> GetInstances<T>(IPluginDescription plugin) where T : class {
132      return from t in GetTypes(typeof(T), plugin)
133             where !t.IsAbstract && !t.IsInterface && !t.HasElementType
134             select (T)Activator.CreateInstance(t);
135    }
136    /// <summary>
137    /// Creates an instance of all types declared in assembly <param name="asm"/> that are subtypes or the same type of the specified type and declared in <paramref name="plugin"/>
138    /// </summary>
139    /// <typeparam name="T">Most general type.</typeparam>
140    /// <param name="asm">Declaring assembly.</param>
141    /// <returns>Enumerable of the created instances.</returns>
142    public IEnumerable<T> GetInstances<T>(Assembly asm) where T : class {
143      return from t in GetTypes(typeof(T), asm)
144             where !t.IsAbstract && !t.IsInterface && !t.HasElementType
145             select (T)Activator.CreateInstance(t);
146    }
147    /// <summary>
148    /// Creates an instance of all types that are subtypes or the same type of the specified type
149    /// </summary>
150    /// <typeparam name="T">Most general type.</typeparam>
151    /// <returns>Enumerable of the created instances.</returns>
152    public IEnumerable<T> GetInstances<T>() where T : class {
153      return from i in GetInstances(typeof(T))
154             select (T)i;
155    }
156
157    /// <summary>
158    /// Creates an instance of all types that are subtypes or the same type of the specified type
159    /// </summary>
160    /// <typeparam name="type">Most general type.</typeparam>
161    /// <returns>Enumerable of the created instances.</returns>
162    public IEnumerable<object> GetInstances(Type type) {
163      return from t in GetTypes(type)
164             where !t.IsAbstract && !t.IsInterface && !t.HasElementType
165             select Activator.CreateInstance(t);
166    }
167
168    /// <summary>
169    /// Finds all types that are subtypes or equal to the specified type.
170    /// </summary>
171    /// <param name="type">Most general type for which to find matching types.</param>
172    /// <returns>Enumerable of the discovered types.</returns>
173    public IEnumerable<Type> GetTypes(Type type) {
174      return from asm in AppDomain.CurrentDomain.GetAssemblies()
175             from t in GetTypes(type, asm)
176             select t;
177    }
178
179    /// <summary>
180    /// Finds all types that are subtypes or equal to the specified type if they are part of the given
181    /// <paramref name="plugin"/>.
182    /// </summary>
183    /// <param name="type">Most general type for which to find matching types.</param>
184    /// <param name="plugin">The plugin the subtypes must be part of.</param>
185    /// <returns>Enumerable of the discovered types.</returns>
186    public IEnumerable<Type> GetTypes(Type type, IPluginDescription pluginDescription) {
187      return from asm in AppDomain.CurrentDomain.GetAssemblies()
188             where pluginDescription.Assemblies.Any(asmPath => Path.GetFullPath(asmPath) == Path.GetFullPath(asm.Location))
189             from t in GetTypes(type, asm)
190             select t;
191    }
192
193    /// <summary>
194    /// Gets types that are assignable (same of subtype) to the specified type only from the given assembly.
195    /// </summary>
196    /// <param name="type">Most general type we want to find.</param>
197    /// <param name="assembly">Assembly that should be searched for types.</param>
198    /// <returns>Enumerable of the discovered types.</returns>
199    private IEnumerable<Type> GetTypes(Type type, Assembly assembly) {
200      return from t in assembly.GetTypes()
201             where type.IsAssignableFrom(t)
202             select t;
203    }
204
205    private void FirePluginLoaded(string name) {
206      if (PluginLoaded != null) PluginLoaded(this, new PluginInfrastructureEventArgs("Plugin loaded", name));
207    }
208
209    // infinite lease time
210    /// <summary>
211    /// Initializes the life time service with infinite lease time.
212    /// </summary>
213    /// <returns><c>null</c>.</returns>
214    public override object InitializeLifetimeService() {
215      return null;
216    }
217  }
218}
219
Note: See TracBrowser for help on using the repository browser.