Free cookie consent management tool by TermsFeed Policy Generator

source: branches/3.1/sources/HeuristicLab.PluginInfrastructure/PluginManager.cs @ 9013

Last change on this file since 9013 was 316, checked in by gkronber, 16 years ago

removed unnecessary catch statement because exception is not handled anyway

File size: 6.6 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      try {
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      } finally {
112        // make sure domain is unloaded in all cases
113        AppDomain.Unload(applicationDomain);
114      }
115    }
116
117    /// <summary>
118    /// Calculates a set of plugins that directly or transitively depend on the plugin given in the argument.
119    /// </summary>
120    /// <param name="pluginInfo"></param>
121    /// <returns>a list of plugins that are directly of transitively dependent.</returns>
122    public List<PluginInfo> GetDependentPlugins(PluginInfo pluginInfo) {
123      List<PluginInfo> mergedList = new List<PluginInfo>();
124      foreach(PluginInfo plugin in InstalledPlugins) {
125        if(plugin.Dependencies.Contains(pluginInfo)) {
126          if(!mergedList.Contains(plugin)) {
127            mergedList.Add(plugin);
128          }
129          // for each of the dependent plugins add the list of transitively dependent plugins
130          // make sure that only one entry for each plugin is added to the merged list
131          GetDependentPlugins(plugin).ForEach(delegate(PluginInfo dependentPlugin) {
132            if(!mergedList.Contains(dependentPlugin)) {
133              mergedList.Add(dependentPlugin);
134            }
135          });
136        }
137      }
138      return mergedList;
139    }
140
141    public void UnloadAllPlugins() {
142      AppDomain.Unload(pluginDomain);
143    }
144
145    public void LoadAllPlugins() {
146      Initialize();
147    }
148
149    public void OnDelete(PluginInfo pluginInfo) {
150      remoteLoader.OnDelete(pluginInfo);
151    }
152
153    public void OnInstall(PluginInfo pluginInfo) {
154      remoteLoader.OnInstall(pluginInfo);
155    }
156
157    public void OnPreUpdate(PluginInfo pluginInfo) {
158      remoteLoader.OnPreUpdate(pluginInfo);
159    }
160
161    public void OnPostUpdate(PluginInfo pluginInfo) {
162      remoteLoader.OnPostUpdate(pluginInfo);
163    }
164
165    private void NotifyListeners(PluginManagerAction action, string text) {
166      if(Action != null) {
167        Action(this, new PluginManagerActionEventArgs(text, action));
168      }
169    }
170  }
171}
Note: See TracBrowser for help on using the repository browser.