Free cookie consent management tool by TermsFeed Policy Generator

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

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

Minor changes in plugin infrastructure. #799

File size: 5.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;
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 EventHandler<PluginInfrastructureEventArgs> Action;
42
43    private string pluginDir;
44
45    public PluginManager(string pluginDir) {
46      this.pluginDir = pluginDir;
47    }
48
49    private List<PluginDescription> plugins;
50
51    private List<ApplicationDescription> applications;
52    /// <summary>
53    /// Gets all installed applications.
54    /// </summary>
55    public IEnumerable<ApplicationDescription> Applications {
56      get { return applications; }
57    }
58
59    /// <summary>
60    /// Determines installed plugins and checks if all plugins are loadable.
61    /// </summary>
62    public void DiscoverAndCheckPlugins() {
63      FireAction("Initializing", "PluginInfrastructure");
64      AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
65      setup.PrivateBinPath = pluginDir;
66      AppDomain pluginDomain = null;
67      try {
68        pluginDomain = AppDomain.CreateDomain("plugin domain", null, setup);
69        Loader remoteLoader = (Loader)pluginDomain.CreateInstanceAndUnwrap("HeuristicLab.PluginInfraStructure.Manager", "HeuristicLab.PluginInfrastructure.Manager.Loader");
70        remoteLoader.PluginDir = pluginDir;
71        // forward all events from the remoteLoader to listeners
72        remoteLoader.PluginLoaded += delegate(object sender, PluginInfrastructureEventArgs args) { FireAction(args.Action, args.Entity); };
73        this.plugins = new List<PluginDescription>(remoteLoader.Plugins);
74        this.applications = new List<ApplicationDescription>(remoteLoader.Applications);
75        FireAction("Initialized", "PluginInfrastructure");
76      }
77      finally {
78        // discard the AppDomain that was used for plugin discovery
79        UnloadAppDomain(pluginDomain);
80      }
81    }
82
83
84    /// <summary>
85    /// Creates a separate AppDomain.
86    /// Loads all active plugin assemblies and starts the application in the new AppDomain via a PluginRunner instance activated in the new AppDomain
87    /// </summary>
88    /// <param name="appInfo">application to run</param>
89    public void Run(ApplicationDescription appInfo) {
90      // create a separate AppDomain for the application
91      // initialize the static ApplicationManager in the AppDomain
92      // and remotely tell it to start the application
93
94      FireAction("Starting application", appInfo.Name);
95      AppDomain applicationDomain = null;
96      try {
97        AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
98        setup.PrivateBinPath = pluginDir;
99        applicationDomain = AppDomain.CreateDomain(appInfo.Name, null, setup);
100        DefaultApplicationManager applicationManager =
101          (DefaultApplicationManager)applicationDomain.CreateInstanceAndUnwrap("HeuristicLab.PluginInfraStructure.Manager", "HeuristicLab.PluginInfrastructure.Manager.DefaultApplicationManager");
102        applicationManager.PluginLoaded += applicationManager_PluginLoaded;
103        applicationManager.PrepareApplicationDomain(
104          new List<IApplicationDescription>(applications.Cast<IApplicationDescription>()),
105          new List<IPluginDescription>(plugins.Cast<IPluginDescription>()));
106        FireAction("Started application", appInfo.Name);
107        applicationManager.Run(appInfo);
108      }
109      finally {
110        // make sure domain is unloaded in all cases
111        UnloadAppDomain(applicationDomain);
112      }
113    }
114
115    void applicationManager_PluginLoaded(object sender, PluginInfrastructureEventArgs e) {
116      // load the matching plugin description (
117      PluginDescription desc = (PluginDescription)e.Entity;
118      foreach (var myDesc in plugins) {
119        if (myDesc.Equals(desc)) myDesc.Load();
120      }
121      FireAction(e.Action, e.Entity);
122    }
123
124    private void UnloadAppDomain(AppDomain appDomain) {
125      AppDomain.Unload(appDomain);
126
127      // TODO: Update plugin descriptions in all active AppDomains
128
129      // unload all plugins
130      foreach (var pluginDescription in plugins)
131        pluginDescription.Unload();
132    }
133
134    private void FireAction(string action, object entity) {
135      if (Action != null) {
136        Action(this, new PluginInfrastructureEventArgs(action, entity));
137      }
138    }
139  }
140}
Note: See TracBrowser for help on using the repository browser.