Free cookie consent management tool by TermsFeed Policy Generator

Changeset 2497


Ignore:
Timestamp:
11/16/09 18:30:04 (13 years ago)
Author:
gkronber
Message:

Minor changes in plugin infrastructure. #799

Location:
branches/PluginInfrastructure Refactoring
Files:
9 edited
1 moved

Legend:

Unmodified
Added
Removed
  • branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.GUI/HeuristicLab.PluginInfrastructure.GUI.csproj

    r1474 r2497  
    110110    </Compile>
    111111    <Compile Include="PluginAction.cs" />
    112     <Compile Include="PluginDescription.cs" />
    113112    <Compile Include="PluginNameTransform.cs" />
    114113    <Compile Include="PluginSource.cs" />
  • branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager/ApplicationDescription.cs

    r2488 r2497  
    8484      set { declaringTypeName = value; }
    8585    }
     86
     87    public override string ToString() {
     88      return Name;
     89    }
    8690  }
    8791}
  • branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager/DefaultApplicationManager.cs

    r2495 r2497  
    4444    public IEnumerable<IPluginDescription> Plugins {
    4545      get { return plugins; }
     46      internal set { plugins = new List<IPluginDescription>(value); }
    4647    }
    4748
     
    8283          foreach (var plugin in GetInstances<IPlugin>(asm)) {
    8384            plugin.OnLoad();
    84             FirePluginLoaded(plugin.Name);
    8585          }
    8686        }
     87        FirePluginLoaded(desc);
    8788        desc.Load();
    8889      }
    89 
    9090    }
    9191
     
    203203    }
    204204
    205     private void FirePluginLoaded(string name) {
    206       if (PluginLoaded != null) PluginLoaded(this, new PluginInfrastructureEventArgs("Plugin loaded", name));
     205    private void FirePluginLoaded(IPluginDescription plugin) {
     206      if (PluginLoaded != null) PluginLoaded(this, new PluginInfrastructureEventArgs("Plugin loaded", plugin));
    207207    }
    208208
  • branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager/HeuristicLab.PluginInfrastructure.Manager.csproj

    r2489 r2497  
    4949  <ItemGroup>
    5050    <Compile Include="ApplicationDescription.cs" />
    51     <Compile Include="ApplicationManager.cs">
    52       <SubType>Code</SubType>
    53     </Compile>
     51    <Compile Include="DefaultApplicationManager.cs" />
    5452    <Compile Include="Loader.cs" />
    5553    <Compile Include="PluginDescription.cs" />
  • branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager/Loader.cs

    r2495 r2497  
    3838    internal IEnumerable<ApplicationDescription> Applications {
    3939      get {
     40        if (applications == null) DiscoverAndCheckPlugins();
    4041        return applications;
    4142      }
     
    4546    internal IEnumerable<PluginDescription> Plugins {
    4647      get {
     48        if (plugins == null) DiscoverAndCheckPlugins();
    4749        return plugins;
    4850      }
     
    5254
    5355    public Loader() {
    54       this.applications = new List<ApplicationDescription>();
    55       this.plugins = new List<PluginDescription>();
    5656      this.pluginDependencies = new Dictionary<PluginDescription, List<string>>();
    5757
     58      // ReflectionOnlyAssemblyResolveEvent must be handled because we load assemblies from the plugin path
     59      // (which is not listed in the default assembly lookup locations)
    5860      AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += ReflectionOnlyAssemblyResolveEventHandler;
    5961    }
    6062
    6163    private Assembly ReflectionOnlyAssemblyResolveEventHandler(object sender, ResolveEventArgs args) {
    62       //try {
    6364      return Assembly.ReflectionOnlyLoad(args.Name);
    64       //}
    65       //catch (FileLoadException ex) {
    66       //  return null;
    67       //}
    6865    }
    6966
     
    8077    /// 7. All types implementing IApplication are discovered
    8178    /// </summary>
    82     internal void Init() {
     79    private void DiscoverAndCheckPlugins() {
    8380      pluginDependencies.Clear();
    8481
     
    163160          }
    164161        }
     162        // ignore exceptions. Just don't yield a plugin description when an exception is thrown
    165163        catch (FileNotFoundException) {
    166164        }
     
    310308
    311309    /// <summary>
    312     /// Initializes the life time service with an infinte lease time.
     310    /// Initializes the life time service with an infinite lease time.
    313311    /// </summary>
    314312    /// <returns><c>null</c>.</returns>
  • branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager/PluginDescription.cs

    r2488 r2497  
    135135    }
    136136
    137 
    138     //private string message;
    139     ///// <summary>
    140     ///// Gets or sets the message.
    141     ///// </summary>
    142     //public string Message {
    143     //  get { return message; }
    144     //  set { message = value; }
    145     //}
    146 
    147137    /// <summary>
    148138    /// Gets the string representation of the plugin.
     
    153143    }
    154144
    155     //// equals and hashcode have to be implemented because we want to compare PluginDescriptions from
    156     //// different AppDomains and serialization destroys reference equality
    157     ///// <summary>
    158     ///// Checks whether the given object is equal to the current plugin.
    159     ///// </summary>
    160     ///// <param name="obj">The object to compare.</param>
    161     ///// <returns><c>true</c> if it is equal, <c>false</c> otherwise.</returns>
    162     //public override bool Equals(object obj) {
    163     //  if (!(obj is PluginDescription))
    164     //    return false;
    165     //  PluginDescription other = (PluginDescription)obj;
     145    // equals and hashcode have to be implemented because we want to compare PluginDescriptions from
     146    // different AppDomains and serialization destroys reference equality
     147    /// <summary>
     148    /// Checks whether the given object is equal to the current plugin.
     149    /// </summary>
     150    /// <param name="obj">The object to compare.</param>
     151    /// <returns><c>true</c> if it is equal, <c>false</c> otherwise.</returns>
     152    public override bool Equals(object obj) {
     153      if (!(obj is PluginDescription))
     154        return false;
     155      PluginDescription other = (PluginDescription)obj;
    166156
    167     //  return other.Name == this.Name && other.Version == this.Version;
    168     //}
    169     ///// <summary>
    170     ///// Gets the hash code of the current plugin.
    171     ///// </summary>
    172     ///// <returns>The hash code of the plugin.</returns>
    173     //public override int GetHashCode() {
    174     //  if (version != null) {
    175     //    return name.GetHashCode() + version.GetHashCode();
    176     //  } else return name.GetHashCode();
    177     //}
     157      return other.Name == this.Name && other.Version == this.Version;
     158    }
     159    /// <summary>
     160    /// Gets the hash code of the current plugin.
     161    /// </summary>
     162    /// <returns>The hash code of the plugin.</returns>
     163    public override int GetHashCode() {
     164      if (version != null) {
     165        return name.GetHashCode() + version.GetHashCode();
     166      } else return name.GetHashCode();
     167    }
    178168  }
    179169}
  • branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager/PluginInfrastructureEventArgs.cs

    r2489 r2497  
    2929  public class PluginInfrastructureEventArgs : EventArgs {
    3030    public string Action { get; private set; }
    31     public string EntityName { get; private set; }
    32     public PluginInfrastructureEventArgs(string action, string entityName) {
    33       Action = action;
    34       EntityName = entityName;
     31    public object Entity { get; private set; }
     32    public PluginInfrastructureEventArgs(string action, object entity) {
     33      this.Action = action;
     34      this.Entity = entity;
    3535    }
    3636  }
  • branches/PluginInfrastructure Refactoring/HeuristicLab.PluginInfrastructure.Manager/PluginManager.cs

    r2489 r2497  
    4343    private string pluginDir;
    4444
    45     // singleton pattern
    4645    public PluginManager(string pluginDir) {
    4746      this.pluginDir = pluginDir;
    4847    }
    4948
    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 
    8349    private List<PluginDescription> plugins;
    84     //public IEnumerable<PluginDescription> Plugins {
    85     //  get { return plugins; }
    86     //}
    8750
    8851    private List<ApplicationDescription> applications;
     
    9760    /// Determines installed plugins and checks if all plugins are loadable.
    9861    /// </summary>
    99     public void Initialize() {
    100       NotifyListeners("Initializing", "PluginInfrastructure");
     62    public void DiscoverAndCheckPlugins() {
     63      FireAction("Initializing", "PluginInfrastructure");
    10164      AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
    10265      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.PluginLoaded += delegate(object sender, PluginInfrastructureEventArgs args) { NotifyListeners(args.Action, args.EntityName); }; // forward all events from the remoteLoader to listeners
    107       remoteLoader.Init();
    108       NotifyListeners("Initialized", "PluginInfrastructure");
    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);
     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      }
    11581    }
    11682
    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     //}
    13583
    13684    /// <summary>
     
    14492      // and remotely tell it to start the application
    14593
    146       NotifyListeners("Starting application", appInfo.Name);
     94      FireAction("Starting application", appInfo.Name);
    14795      AppDomain applicationDomain = null;
    14896      try {
     
    152100        DefaultApplicationManager applicationManager =
    153101          (DefaultApplicationManager)applicationDomain.CreateInstanceAndUnwrap("HeuristicLab.PluginInfraStructure.Manager", "HeuristicLab.PluginInfrastructure.Manager.DefaultApplicationManager");
    154         applicationManager.PluginLoaded += delegate(object sender, PluginInfrastructureEventArgs args) { NotifyListeners(args.Action, args.EntityName); };
     102        applicationManager.PluginLoaded += applicationManager_PluginLoaded;
    155103        applicationManager.PrepareApplicationDomain(
    156104          new List<IApplicationDescription>(applications.Cast<IApplicationDescription>()),
    157105          new List<IPluginDescription>(plugins.Cast<IPluginDescription>()));
    158         NotifyListeners("Started application", appInfo.Name);
     106        FireAction("Started application", appInfo.Name);
    159107        applicationManager.Run(appInfo);
    160108      }
    161109      finally {
    162110        // make sure domain is unloaded in all cases
    163         if (applicationDomain != null) AppDomain.Unload(applicationDomain);
     111        UnloadAppDomain(applicationDomain);
    164112      }
    165113    }
    166114
    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");
     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    }
    175123
    176     //  AssemblyName assemblyName = assembly.GetName();
    177     //  Debug.Assert(assemblyName != null, "Could not get assembly name");
     124    private void UnloadAppDomain(AppDomain appDomain) {
     125      AppDomain.Unload(appDomain);
    178126
    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");
     127      // TODO: Update plugin descriptions in all active AppDomains
    183128
    184     //  StrongNamePublicKeyBlob keyBlob = new StrongNamePublicKeyBlob(publicKey);
     129      // unload all plugins
     130      foreach (var pluginDescription in plugins)
     131        pluginDescription.Unload();
     132    }
    185133
    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(string action, string entityName) {
     134    private void FireAction(string action, object entity) {
    262135      if (Action != null) {
    263         Action(this, new PluginInfrastructureEventArgs(action, entityName));
     136        Action(this, new PluginInfrastructureEventArgs(action, entity));
    264137      }
    265138    }
  • branches/PluginInfrastructure Refactoring/HeuristicLab/MainForm.cs

    r2495 r2497  
    5454      this.Enabled = false;
    5555
    56       pluginManager.Initialize();
     56      pluginManager.DiscoverAndCheckPlugins();
    5757
    5858      applicationsListView.Items.Clear();
  • branches/PluginInfrastructure Refactoring/HeuristicLab/SplashScreen.cs

    r2489 r2497  
    8989
    9090    public void managerActionEventHandler(object sender, PluginInfrastructureEventArgs e) {
    91       string info = e.Action + ": " + e.EntityName;
     91      string info = e.Action + ": " + e.Entity;
    9292      //if (e.Action == PluginManagerAction.Initializing) info = "Initializing ...";
    9393      //else if (e.Action == PluginManagerAction.PluginLoaded) info = "Loaded plugin " + e.Id + " ...";
Note: See TracChangeset for help on using the changeset viewer.