Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HL-3.2-MonoMigration/HeuristicLab.PluginInfrastructure/PluginManager.cs @ 638

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

created a branch for changes needed to run HL3 on Mono 2.0
(ticket #298)

File size: 7.4 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;
24
25namespace HeuristicLab.PluginInfrastructure {
26
27  // must extend MarshalByRefObject because of event passing between Loader and PluginManager (each in it's own AppDomain)
28  public class PluginManager : MarshalByRefObject {
29    // singleton: only one manager allowed in each AppDomain
30    private static readonly PluginManager manager = PluginManager.manager==null?new PluginManager():PluginManager.manager;
31    static PluginManager() { Console.WriteLine("static ctor called "); }
32    public static PluginManager Manager {
33      get {
34        return manager;
35      }
36    }
37
38    // singleton: only one control manager allowed in each application (i.e. AppDomain)
39    private static IControlManager controlManager;
40    public static IControlManager ControlManager {
41      get { return controlManager; }
42      set { controlManager = value; }
43    }
44
45    public event PluginManagerActionEventHandler Action;
46
47    // holds a proxy for the loader in the special AppDomain for PluginManagament
48    private Loader remoteLoader;
49    private AppDomain pluginDomain;
50    private string pluginDir;
51
52    // singleton pattern
53    private PluginManager() {
54      this.pluginDir = HeuristicLab.PluginInfrastructure.Properties.Settings.Default.PluginDir;
55    }
56
57    public ICollection<PluginInfo> InstalledPlugins {
58      get { return remoteLoader.InstalledPlugins; }
59    }
60
61    public ICollection<PluginInfo> DisabledPlugins {
62      get { return remoteLoader.DisabledPlugins; }
63    }
64
65    public ICollection<PluginInfo> ActivePlugins {
66      get { return remoteLoader.ActivePlugins; }
67    }
68
69    public ICollection<ApplicationInfo> InstalledApplications {
70      get { return remoteLoader.InstalledApplications; }
71    }
72
73    private ICollection<PluginInfo> loadedPlugins;
74    public ICollection<PluginInfo> LoadedPlugins {
75      get {
76        Console.WriteLine(AppDomain.CurrentDomain.Id);
77        Console.WriteLine(this.GetHashCode());
78        if(loadedPlugins != null) Console.WriteLine(loadedPlugins.Count); else Console.WriteLine("Loaded plugins==null!");
79        return loadedPlugins;
80      }
81      internal set {
82        Console.WriteLine(AppDomain.CurrentDomain.Id);
83        Console.WriteLine(value.Count);
84        Console.WriteLine(this.GetHashCode());
85        loadedPlugins = new List<PluginInfo>(value);
86      }
87    }
88
89    /// <summary>
90    /// Creates a dedicated AppDomain for loading all plugins and checking dependencies.
91    /// </summary>
92    public void Initialize() {
93      NotifyListeners(PluginManagerAction.Initializing, "-");
94      AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
95      setup.PrivateBinPath = pluginDir;
96      pluginDomain = AppDomain.CreateDomain("plugin domain");
97      pluginDomain.SetupInformation.PrivateBinPath = pluginDir;
98      remoteLoader = (Loader)pluginDomain.CreateInstanceAndUnwrap("HeuristicLab.PluginInfraStructure", "HeuristicLab.PluginInfrastructure.Loader");
99      remoteLoader.PluginAction += new PluginManagerActionEventHandler(remoteLoader_PluginAction);
100      remoteLoader.Init();
101      NotifyListeners(PluginManagerAction.Initialized, "-");
102    }
103
104    public void remoteLoader_PluginAction(object sender, PluginManagerActionEventArgs e) {
105      if(Action != null) Action(this, e);
106    }
107
108    /// <summary>
109    /// Creates a separate AppDomain.
110    /// Loads all active plugin assemblies and starts the application in the new AppDomain via a PluginRunner instance activated in the new AppDomain
111    /// </summary>
112    /// <param name="appInfo">application to run</param>
113    public void Run(ApplicationInfo appInfo) {
114      // create a separate AppDomain for the application
115      // activate a PluginRunner instance in the application
116      // and remotely tell it to start the application
117      Console.WriteLine(appInfo);
118      NotifyListeners(PluginManagerAction.Starting, appInfo.Name);
119      AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
120      setup.PrivateBinPath = pluginDir;
121      AppDomain applicationDomain = AppDomain.CreateDomain(appInfo.Name + " AppDomain");
122      applicationDomain.SetupInformation.PrivateBinPath = pluginDir;
123      try {
124        Runner remoteRunner = (Runner)applicationDomain.CreateInstanceAndUnwrap("HeuristicLab.PluginInfrastructure", "HeuristicLab.PluginInfrastructure.Runner");
125        NotifyListeners(PluginManagerAction.Initializing, "All plugins");
126        remoteRunner.LoadPlugins(remoteLoader.ActivePlugins);
127        NotifyListeners(PluginManagerAction.Initialized, "All plugins");
128        remoteRunner.Run(appInfo.PluginAssembly, appInfo.PluginType);
129      } finally {
130        // make sure domain is unloaded in all cases
131        AppDomain.Unload(applicationDomain);
132      }
133    }
134
135    /// <summary>
136    /// Calculates a set of plugins that directly or transitively depend on the plugin given in the argument.
137    /// </summary>
138    /// <param name="pluginInfo"></param>
139    /// <returns>a list of plugins that are directly of transitively dependent.</returns>
140    public List<PluginInfo> GetDependentPlugins(PluginInfo pluginInfo) {
141      List<PluginInfo> mergedList = new List<PluginInfo>();
142      foreach(PluginInfo plugin in InstalledPlugins) {
143        if(plugin.Dependencies.Contains(pluginInfo)) {
144          if(!mergedList.Contains(plugin)) {
145            mergedList.Add(plugin);
146          }
147          // for each of the dependent plugins add the list of transitively dependent plugins
148          // make sure that only one entry for each plugin is added to the merged list
149          GetDependentPlugins(plugin).ForEach(delegate(PluginInfo dependentPlugin) {
150            if(!mergedList.Contains(dependentPlugin)) {
151              mergedList.Add(dependentPlugin);
152            }
153          });
154        }
155      }
156      return mergedList;
157    }
158
159    public void UnloadAllPlugins() {
160      AppDomain.Unload(pluginDomain);
161    }
162
163    public void LoadAllPlugins() {
164      Initialize();
165    }
166
167    public void OnDelete(PluginInfo pluginInfo) {
168      remoteLoader.OnDelete(pluginInfo);
169    }
170
171    public void OnInstall(PluginInfo pluginInfo) {
172      remoteLoader.OnInstall(pluginInfo);
173    }
174
175    public void OnPreUpdate(PluginInfo pluginInfo) {
176      remoteLoader.OnPreUpdate(pluginInfo);
177    }
178
179    public void OnPostUpdate(PluginInfo pluginInfo) {
180      remoteLoader.OnPostUpdate(pluginInfo);
181    }
182
183    private void NotifyListeners(PluginManagerAction action, string text) {
184      if(Action != null) {
185        Action(this, new PluginManagerActionEventArgs(text, action));
186      }
187    }
188  }
189}
Note: See TracBrowser for help on using the repository browser.