Free cookie consent management tool by TermsFeed Policy Generator

source: branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure/ApplicationManager.cs @ 2591

Last change on this file since 2591 was 2587, checked in by gkronber, 15 years ago

Fixed projects to work with new plugin infrastructure. #799

File size: 11.6 KB
RevLine 
[2488]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;
[2527]30using HeuristicLab.PluginInfrastructure.Manager;
31using System.IO;
[2488]32
33namespace HeuristicLab.PluginInfrastructure {
34
[2503]35  /// <summary>
36  /// The ApplicationManager has a reference to the application manager singleton.
37  /// The application manager provides
38  /// </summary>
[2527]39  public sealed class ApplicationManager : MarshalByRefObject, IApplicationManager {
[2488]40    private static IApplicationManager appManager;
[2503]41    /// <summary>
42    /// Gets the application manager singleton.
43    /// </summary>
[2488]44    public static IApplicationManager Manager {
45      get { return appManager; }
46    }
47
[2527]48    internal event EventHandler<PluginInfrastructureEventArgs> PluginLoaded;
49    internal event EventHandler<PluginInfrastructureEventArgs> PluginUnloaded;
50
51    // cache for the AssemblyResolveEvent
52    // which must be handled when assemblies are loaded dynamically after the application start
53    private Dictionary<string, Assembly> loadedAssemblies;
54
55    private List<IPlugin> loadedPlugins;
56
57    private List<PluginDescription> plugins;
[2503]58    /// <summary>
[2527]59    /// Gets all plugins.
60    /// </summary>
61    public IEnumerable<IPluginDescription> Plugins {
62      get { return plugins.Cast<IPluginDescription>(); }
63    }
64
65    private List<ApplicationDescription> applications;
66    /// <summary>
67    /// Gets all installed applications.
68    /// </summary>
69    public IEnumerable<IApplicationDescription> Applications {
70      get { return applications.Cast<IApplicationDescription>(); }
71    }
72
73    internal ApplicationManager()
74      : base() {
75      loadedAssemblies = new Dictionary<string, Assembly>();
76      loadedPlugins = new List<IPlugin>();
77      // needed for the special case when assemblies are loaded dynamically via LoadAssemblies()
78      AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => {
79        if (loadedAssemblies.ContainsKey(args.Name)) {
80          return loadedAssemblies[args.Name];
81        }
82        return null;
83      };
84    }
85
86    internal void PrepareApplicationDomain(IEnumerable<ApplicationDescription> apps, IEnumerable<PluginDescription> plugins) {
87      this.plugins = new List<PluginDescription>(plugins);
88      this.applications = new List<ApplicationDescription>(apps);
89      RegisterApplicationManager((IApplicationManager)this);
90      LoadPlugins(plugins);
91    }
92
93    /// <summary>
[2503]94    /// Registers a new application manager.
95    /// </summary>
96    /// <param name="manager"></param>
97    internal static void RegisterApplicationManager(IApplicationManager manager) {
[2495]98      if (appManager != null) throw new InvalidOperationException("The application manager has already been set.");
[2488]99      appManager = manager;
100    }
[2527]101
102    private void LoadPlugins(IEnumerable<PluginDescription> plugins) {
103      // load all loadable plugins (all dependencies available) into the execution context
104      foreach (var desc in PluginDescriptionIterator.IterateDependenciesBottomUp(plugins.Where(x => x.PluginState != PluginState.Disabled))) {
105        foreach (string assembly in desc.Assemblies) {
106          var asm = Assembly.LoadFrom(assembly);
107
108          // instantiate and load all plugins in this assembly
109          foreach (var plugin in GetInstances<IPlugin>(asm)) {
110            plugin.OnLoad();
111            loadedPlugins.Add(plugin);
112          }
113        }
114        OnPluginLoaded(new PluginInfrastructureEventArgs("Plugin loaded", desc));
115        desc.Load();
116      }
117    }
118
119    internal void Run(ApplicationDescription appInfo) {
120      IApplication runnablePlugin = (IApplication)Activator.CreateInstance(appInfo.DeclaringAssemblyName, appInfo.DeclaringTypeName).Unwrap();
121      try {
122        runnablePlugin.Run();
123      }
124      finally {
125        // unload plugins in reverse order
126        foreach (var plugin in loadedPlugins.Reverse<IPlugin>()) {
127          plugin.OnUnload();
128        }
129        foreach (var desc in PluginDescriptionIterator.IterateDependenciesBottomUp(plugins.Where(x => x.PluginState != PluginState.Disabled))) {
130          desc.Unload();
131          OnPluginUnloaded(new PluginInfrastructureEventArgs("Plugin unloaded", desc));
132        }
133      }
134    }
135
136    /// <summary>
137    /// Loads assemblies dynamically from a byte array
138    /// </summary>
139    /// <param name="plugins">bytearray of all assemblies that should be loaded</param>
[2587]140    internal void LoadAssemblies(IEnumerable<byte[]> assemblies) {
[2527]141      foreach (byte[] asm in assemblies) {
142        Assembly loadedAsm = Assembly.Load(asm);
143        RegisterLoadedAssembly(loadedAsm);
144      }
145    }
146
147    // register assembly in the assembly cache for the AssemblyResolveEvent
148    private void RegisterLoadedAssembly(Assembly asm) {
149      loadedAssemblies.Add(asm.FullName, asm);
150      loadedAssemblies.Add(asm.GetName().Name, asm); // add short name
151    }
152
153    /// <summary>
154    /// Creates an instance of all types that are subtypes or the same type of the specified type and declared in <paramref name="plugin"/>
155    /// </summary>
156    /// <typeparam name="T">Most general type.</typeparam>
157    /// <returns>Enumerable of the created instances.</returns>
[2587]158    internal static IEnumerable<T> GetInstances<T>(IPluginDescription plugin) where T : class {
[2527]159      return from t in GetTypes(typeof(T), plugin)
160             select (T)Activator.CreateInstance(t);
161    }
162    /// <summary>
163    /// 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"/>
164    /// </summary>
165    /// <typeparam name="T">Most general type.</typeparam>
166    /// <param name="asm">Declaring assembly.</param>
167    /// <returns>Enumerable of the created instances.</returns>
168    private static IEnumerable<T> GetInstances<T>(Assembly asm) where T : class {
169      return from t in GetTypes(typeof(T), asm)
170             select (T)Activator.CreateInstance(t);
171    }
172    /// <summary>
173    /// Creates an instance of all types that are subtypes or the same type of the specified type
174    /// </summary>
175    /// <typeparam name="T">Most general type.</typeparam>
176    /// <returns>Enumerable of the created instances.</returns>
[2587]177    internal static IEnumerable<T> GetInstances<T>() where T : class {
[2527]178      return from i in GetInstances(typeof(T))
179             select (T)i;
180    }
181
182    /// <summary>
183    /// Creates an instance of all types that are subtypes or the same type of the specified type
184    /// </summary>
185    /// <typeparam name="type">Most general type.</typeparam>
186    /// <returns>Enumerable of the created instances.</returns>
[2587]187    internal static IEnumerable<object> GetInstances(Type type) {
[2527]188      return from t in GetTypes(type)
189             select Activator.CreateInstance(t);
190    }
191
192    /// <summary>
193    /// Finds all types that are subtypes or equal to the specified type.
194    /// </summary>
195    /// <param name="type">Most general type for which to find matching types.</param>
196    /// <returns>Enumerable of the discovered types.</returns>
[2587]197    internal static IEnumerable<Type> GetTypes(Type type) {
[2527]198      return from asm in AppDomain.CurrentDomain.GetAssemblies()
199             from t in GetTypes(type, asm)
200             select t;
201    }
202
203    /// <summary>
204    /// Finds all types that are subtypes or equal to the specified type if they are part of the given
205    /// <paramref name="plugin"/>.
206    /// </summary>
207    /// <param name="type">Most general type for which to find matching types.</param>
208    /// <param name="plugin">The plugin the subtypes must be part of.</param>
209    /// <returns>Enumerable of the discovered types.</returns>
[2587]210    internal static IEnumerable<Type> GetTypes(Type type, IPluginDescription pluginDescription) {
[2527]211      PluginDescription pluginDesc = (PluginDescription)pluginDescription;
212      return from asm in AppDomain.CurrentDomain.GetAssemblies()
213             where pluginDesc.Assemblies.Any(asmPath => Path.GetFullPath(asmPath) == Path.GetFullPath(asm.Location))
214             from t in GetTypes(type, asm)
215             select t;
216    }
217
218    /// <summary>
219    /// Gets types that are assignable (same of subtype) to the specified type only from the given assembly.
220    /// </summary>
221    /// <param name="type">Most general type we want to find.</param>
222    /// <param name="assembly">Assembly that should be searched for types.</param>
223    /// <returns>Enumerable of the discovered types.</returns>
224    private static IEnumerable<Type> GetTypes(Type type, Assembly assembly) {
225      return GetTypes(type, assembly, false);
226    }
227
228    private static IEnumerable<Type> GetTypes(Type type, Assembly assembly, bool includeNotInstantiableTypes) {
229      return from t in assembly.GetTypes()
230             where type.IsAssignableFrom(t)
231             where includeNotInstantiableTypes || (type.IsAssignableFrom(t) && !t.IsAbstract && !t.IsInterface && !t.HasElementType)
232             select t;
233    }
234
235    private void OnPluginLoaded(PluginInfrastructureEventArgs e) {
236      if (PluginLoaded != null) PluginLoaded(this, e);
237    }
238
239    private void OnPluginUnloaded(PluginInfrastructureEventArgs e) {
240      if (PluginUnloaded != null) PluginUnloaded(this, e);
241    }
242
243    // infinite lease time
244    /// <summary>
245    /// Initializes the life time service with infinite lease time.
246    /// </summary>
247    /// <returns><c>null</c>.</returns>
248    public override object InitializeLifetimeService() {
249      return null;
250    }
251
252    #region IApplicationManager Members
253
254    IEnumerable<T> IApplicationManager.GetInstances<T>(IPluginDescription plugin) {
255      return GetInstances<T>(plugin);
256    }
257
258    IEnumerable<T> IApplicationManager.GetInstances<T>() {
259      return GetInstances<T>();
260    }
261
[2587]262    IEnumerable<object> IApplicationManager.GetInstances(Type type) {
263      return GetInstances(type);
264    }
265
[2527]266    IEnumerable<Type> IApplicationManager.GetTypes(Type type) {
267      return GetTypes(type);
268    }
269
270    IEnumerable<Type> IApplicationManager.GetTypes(Type type, IPluginDescription plugin) {
271      return GetTypes(type, plugin);
272    }
273
[2587]274    /// <summary>
275    /// Finds the plugin that declares the <paramref name="type">type</paramref>.
276    /// </summary>
277    /// <param name="type">The type of interest.</param>
278    /// <returns>The description of the plugin that declares the given type or null if the type has not been declared by a known plugin.</returns>
279    public IPluginDescription GetDeclaringPlugin(Type type) {
280      foreach (PluginDescription info in Plugins) {
281        if (info.Assemblies.Contains(Path.GetFullPath(type.Assembly.Location))) return info;
282      }
283      return null;
284    }
[2527]285    #endregion
[2488]286  }
287}
Note: See TracBrowser for help on using the repository browser.