Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.PluginInfrastructure/PluginManager.cs @ 91

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