Free cookie consent management tool by TermsFeed Policy Generator

source: branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager/PluginManager.cs @ 2488

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

Worked on plugin infrastructure refactoring. (Fully functional revision). #799

File size: 11.1 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;
30
31namespace HeuristicLab.PluginInfrastructure.Manager {
32
33  // must extend MarshalByRefObject because of event passing between Loader and PluginManager (each in it's own AppDomain)
34  /// <summary>
35  /// Class to manage different plugins.
36  /// </summary>
37  public class PluginManager : MarshalByRefObject {
38    /// <summary>
39    /// Event handler for actions in the plugin manager.
40    /// </summary>
41    public event PluginManagerActionEventHandler Action;
42
43    private string pluginDir;
44
45    // singleton pattern
46    public PluginManager(string pluginDir) {
47      this.pluginDir = pluginDir;
48    }
49
50    ///// <summary>
51    ///// Gets all installed plugins.
52    ///// </summary>
53    ///// <remarks>This information is provided by a <see cref="Loader"/>.</remarks>
54    //public ICollection<PluginInfo> InstalledPlugins {
55    //  get { return remoteLoader.InstalledPlugins; }
56    //}
57
58    ///// <summary>
59    ///// Gets all disabled plugins.
60    ///// </summary>
61    ///// <remarks>This information is provided by a <see cref="Loader"/>.</remarks>
62    //public ICollection<PluginInfo> DisabledPlugins {
63    //  get { return remoteLoader.DisabledPlugins; }
64    //}
65
66    ///// <summary>
67    ///// Gets all active plugins.
68    ///// </summary>
69    ///// <remarks>This information is provided by a <see cref="Loader"/>.</remarks>
70    //public ICollection<PluginInfo> ActivePlugins {
71    //  get { return remoteLoader.ActivePlugins; }
72    //}
73
74    //private ICollection<PluginInfo> loadedPlugins;
75    ///// <summary>
76    ///// Gets or (internally) sets the loaded plugins.
77    ///// </summary>
78    //public ICollection<PluginInfo> LoadedPlugins {
79    //  get { return loadedPlugins; }
80    //  internal set { loadedPlugins = value; }
81    //}
82
83    private List<PluginDescription> plugins;
84    //public IEnumerable<PluginDescription> Plugins {
85    //  get { return plugins; }
86    //}
87
88    private List<ApplicationDescription> applications;
89    /// <summary>
90    /// Gets all installed applications.
91    /// </summary>
92    public IEnumerable<ApplicationDescription> Applications {
93      get { return applications; }
94    }
95
96    /// <summary>
97    /// Determines installed plugins and checks if all plugins are loadable.
98    /// </summary>
99    public void Initialize() {
100      NotifyListeners(PluginManagerAction.Initializing, "-");
101      AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
102      setup.PrivateBinPath = pluginDir;
103      AppDomain pluginDomain = AppDomain.CreateDomain("plugin domain", null, setup);
104      Loader remoteLoader = (Loader)pluginDomain.CreateInstanceAndUnwrap("HeuristicLab.PluginInfraStructure.Manager", "HeuristicLab.PluginInfrastructure.Manager.Loader");
105      remoteLoader.PluginDir = pluginDir;
106      remoteLoader.PluginAction += delegate(object sender, PluginManagerActionEventArgs args) { if (Action != null) Action(this, args); };
107      remoteLoader.Init();
108      NotifyListeners(PluginManagerAction.Initialized, "-");
109
110      plugins = new List<PluginDescription>(remoteLoader.Plugins);
111      applications = new List<ApplicationDescription>(remoteLoader.Applications);
112
113      // discard the AppDomain that was used for plugin discovery
114      UnloadAppDomain(pluginDomain);
115    }
116
117    private void UnloadAppDomain(AppDomain appDomain) {
118      AppDomain.Unload(appDomain);
119
120      // set all loaded plugins back to enabled
121      foreach (var pluginDescription in plugins)
122        pluginDescription.Unload();
123    }
124
125
126    ///// <summary>
127    ///// Creates a new AppDomain with all plugins preloaded.
128    ///// </summary>
129    ///// <param name="friendlyName">Name of the new AppDomain</param>
130    ///// <returns>the new AppDomain with all plugins preloaded.</returns>
131    //public AppDomain CreateAndInitAppDomain(string friendlyName) {
132
133    //  return applicationDomain;
134    //}
135
136    /// <summary>
137    /// Creates a separate AppDomain.
138    /// Loads all active plugin assemblies and starts the application in the new AppDomain via a PluginRunner instance activated in the new AppDomain
139    /// </summary>
140    /// <param name="appInfo">application to run</param>
141    public void Run(ApplicationDescription appInfo) {
142      // create a separate AppDomain for the application
143      // initialize the static ApplicationManager in the AppDomain
144      // and remotely tell it to start the application
145
146      NotifyListeners(PluginManagerAction.ApplicationStart, appInfo.Name);
147      AppDomain applicationDomain = null;
148      try {
149        AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
150        setup.PrivateBinPath = pluginDir;
151        applicationDomain = AppDomain.CreateDomain(appInfo.Name, null, setup);
152        ApplicationManager applicationManager =
153          (ApplicationManager)applicationDomain.CreateInstanceAndUnwrap("HeuristicLab.PluginInfraStructure.Manager", "HeuristicLab.PluginInfrastructure.Manager.ApplicationManager");
154        //applicationManager.PluginAction += delegate(object sender, PluginManagerActionEventArgs args) { if (Action != null) Action(this, args); };
155        applicationManager.PrepareApplicationDomain(
156          new List<IApplicationDescription>(applications.Cast<IApplicationDescription>()),
157          new List<IPluginDescription>(plugins.Cast<IPluginDescription>()));
158        NotifyListeners(PluginManagerAction.Initialized, "All plugins");
159        applicationManager.Run(appInfo);
160      }
161      finally {
162        // make sure domain is unloaded in all cases
163        if (applicationDomain != null) AppDomain.Unload(applicationDomain);
164      }
165    }
166
167    ///// <summary>
168    ///// Creates a new AppDomain with all plugins preloaded and Sandboxing capability.
169    ///// </summary>
170    ///// <param name="assembly">Assembly reference</param>
171    ///// <returns>the strongname of the assembly</returns>
172    //private StrongName CreateStrongName(Assembly assembly) {
173    //  if (assembly == null)
174    //    throw new ArgumentNullException("assembly");
175
176    //  AssemblyName assemblyName = assembly.GetName();
177    //  Debug.Assert(assemblyName != null, "Could not get assembly name");
178
179    //  // get the public key blob
180    //  byte[] publicKey = assemblyName.GetPublicKey();
181    //  if (publicKey == null || publicKey.Length == 0)
182    //    throw new InvalidOperationException("Assembly is not strongly named");
183
184    //  StrongNamePublicKeyBlob keyBlob = new StrongNamePublicKeyBlob(publicKey);
185
186    //  // and create the StrongName
187    //  return new StrongName(keyBlob, assemblyName.Name, assemblyName.Version);
188    //}
189
190    //public AppDomain CreateAndInitAppDomainWithSandbox(string friendlyName, bool sandboxed, Type jobType, ICollection<byte[]> assemblyFiles) {
191    //  PermissionSet pset;
192
193
194
195    //  //DiscoveryService dService = new DiscoveryService();
196    //  //get the declaring plugin of the job
197    //  //PluginInfo jobPlugin = dService.GetDeclaringPlugin(jobType);
198
199    //  //get all the plugins that have dependencies with the jobplugin
200    //  //List<PluginInfo> depPlugins = GetDependentPluginsRec(jobPlugin);
201    //  //insert all jobs into one list
202    //  //depPlugins.Add(jobPlugin);
203
204    //  if (sandboxed) {
205    //    pset = new PermissionSet(PermissionState.None);
206    //    pset.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
207    //    pset.AddPermission(new ReflectionPermission(PermissionState.Unrestricted));
208    //    FileIOPermission fPerm = new FileIOPermission(PermissionState.None);
209
210    //    /*foreach (PluginInfo plugin in depPlugins) {
211    //        foreach(String assemblies in plugin.Assemblies)
212    //          fPerm.AddPathList(FileIOPermissionAccess.AllAccess, assemblies);
213    //    }
214
215    //    pset.AddPermission(fPerm);*/
216
217    //  } else {
218    //    pset = new PermissionSet(PermissionState.Unrestricted);
219    //  }
220    //  AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
221    //  setup.PrivateBinPath = pluginDir;
222    //  setup.ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
223    //  AppDomain applicationDomain = AppDomain.CreateDomain(friendlyName, AppDomain.CurrentDomain.Evidence, setup, pset, CreateStrongName(Assembly.GetExecutingAssembly()));
224    //  Runner remoteRunner = (Runner)applicationDomain.CreateInstanceAndUnwrap(typeof(Runner).Assembly.GetName().Name, typeof(Runner).FullName);
225    //  NotifyListeners("Initializing", "All plugins");
226
227    //  if (assemblyFiles != null && assemblyFiles.Count > 0)
228    //    remoteRunner.LoadAssemblies(assemblyFiles);
229
230    //  //if (depPlugins != null && depPlugins.Count > 0) {       
231    //  //remoteRunner.LoadPlugins(ActivePlugins);
232    //  //}
233    //  NotifyListeners("Initialized", "All plugins");
234    //  return applicationDomain;
235    //}
236
237    ///// <summary>
238    ///// Calculates a set of plugins that directly or transitively depend on the plugin given in the argument.
239    ///// </summary>
240    ///// <param name="pluginInfo">The plugin the other depend on.</param>
241    ///// <returns>a list of plugins that are directly of transitively dependent.</returns>
242    //public List<PluginDescription> GetDependentPlugins(PluginDescription pluginInfo) {
243    //  List<PluginDescription> mergedList = new List<PluginDescription>();
244    //  foreach (PluginDescription plugin in Plugins) {
245    //    if (plugin.Dependencies.Contains(pluginInfo)) {
246    //      if (!mergedList.Contains(plugin)) {
247    //        mergedList.Add(plugin);
248    //      }
249    //      // for each of the dependent plugins add the list of transitively dependent plugins
250    //      // make sure that only one entry for each plugin is added to the merged list
251    //      foreach (PluginDescription dependentPlugin in GetDependentPlugins(plugin)) {
252    //        if (!mergedList.Contains(dependentPlugin)) {
253    //          mergedList.Add(dependentPlugin);
254    //        }
255    //      }
256    //    }
257    //  }
258    //  return mergedList;
259    //}
260
261    private void NotifyListeners(PluginManagerAction action, string text) {
262      if (Action != null) {
263        Action(this, new PluginManagerActionEventArgs(text, action));
264      }
265    }
266  }
267}
Note: See TracBrowser for help on using the repository browser.