7
// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
9
// Permission is hereby granted, free of charge, to any person obtaining
10
// a copy of this software and associated documentation files (the
11
// "Software"), to deal in the Software without restriction, including
12
// without limitation the rights to use, copy, modify, merge, publish,
13
// distribute, sublicense, and/or sell copies of the Software, and to
14
// permit persons to whom the Software is furnished to do so, subject to
15
// the following conditions:
17
// The above copyright notice and this permission notice shall be
18
// included in all copies or substantial portions of the Software.
20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32
using System.Collections;
33
using System.Reflection;
35
using Mono.Addins.Description;
36
using Mono.Addins.Database;
40
internal class AddinSessionService
42
bool checkAssemblyLoadConflicts;
43
Hashtable loadedAddins = new Hashtable ();
44
ExtensionContext defaultContext;
45
Hashtable nodeSets = new Hashtable ();
46
Hashtable autoExtensionTypes = new Hashtable ();
48
internal void Initialize ()
50
defaultContext = new ExtensionContext ();
52
AppDomain.CurrentDomain.AssemblyLoad += new AssemblyLoadEventHandler (OnAssemblyLoaded);
55
internal void Shutdown ()
57
AppDomain.CurrentDomain.AssemblyLoad -= new AssemblyLoadEventHandler (OnAssemblyLoaded);
58
defaultContext = null;
59
loadedAddins.Clear ();
60
defaultContext = null;
63
internal ExtensionContext DefaultContext {
64
get { return defaultContext; }
67
// Enables or disables conflict checking while loading assemblies.
68
// Disabling makes loading faster, but less safe.
69
public bool CheckAssemblyLoadConflicts {
70
get { return checkAssemblyLoadConflicts; }
71
set { checkAssemblyLoadConflicts = value; }
74
public bool IsAddinLoaded (string id)
76
return loadedAddins.Contains (Addin.GetIdName (id));
79
internal RuntimeAddin GetAddin (string id)
81
return (RuntimeAddin) loadedAddins [Addin.GetIdName (id)];
84
internal void ActivateAddin (string id)
86
defaultContext.ActivateAddinExtensions (id);
89
internal void UnloadAddin (string id)
91
defaultContext.RemoveAddinExtensions (id);
93
RuntimeAddin addin = GetAddin (id);
95
addin.UnloadExtensions ();
96
loadedAddins.Remove (Addin.GetIdName (id));
97
AddinManager.ReportAddinUnload (id);
101
internal bool LoadAddin (IProgressStatus statusMonitor, string id, bool throwExceptions)
104
if (IsAddinLoaded (id))
107
if (!AddinManager.Registry.IsAddinEnabled (id)) {
108
string msg = GettextCatalog.GetString ("Disabled add-ins can't be loaded.");
109
AddinManager.ReportError (msg, id, null, false);
111
throw new InvalidOperationException (msg);
115
ArrayList addins = new ArrayList ();
116
Stack depCheck = new Stack ();
117
ResolveLoadDependencies (addins, depCheck, id, false);
120
if (statusMonitor != null)
121
statusMonitor.SetMessage ("Loading Addins");
123
for (int n=0; n<addins.Count; n++) {
125
if (statusMonitor != null)
126
statusMonitor.SetProgress ((double) n / (double)addins.Count);
128
Addin iad = (Addin) addins [n];
129
if (IsAddinLoaded (iad.Id))
132
if (statusMonitor != null)
133
statusMonitor.SetMessage (string.Format(GettextCatalog.GetString("Loading {0} add-in"), iad.Id));
135
if (!InsertAddin (statusMonitor, iad))
140
catch (Exception ex) {
141
AddinManager.ReportError ("Add-in could not be loaded: " + ex.Message, id, ex, false);
142
if (statusMonitor != null)
143
statusMonitor.ReportError ("Add-in '" + id + "' could not be loaded.", ex);
150
bool InsertAddin (IProgressStatus statusMonitor, Addin iad)
153
RuntimeAddin p = new RuntimeAddin ();
155
// Read the config file and load the add-in assemblies
156
AddinDescription description = p.Load (iad);
158
// Register the add-in
159
loadedAddins [Addin.GetIdName (p.Id)] = p;
161
if (!AddinDatabase.RunningSetupProcess) {
162
// Load the extension points and other addin data
164
foreach (ExtensionNodeSet rel in description.ExtensionNodeSets) {
165
RegisterNodeSet (rel);
168
foreach (ConditionTypeDescription cond in description.ConditionTypes) {
169
Type ctype = p.GetType (cond.TypeName, true);
170
defaultContext.RegisterCondition (cond.Id, ctype);
174
foreach (ExtensionPoint ep in description.ExtensionPoints)
175
InsertExtensionPoint (p, ep);
178
defaultContext.NotifyAddinLoaded (p);
179
AddinManager.ReportAddinLoad (p.Id);
182
catch (Exception ex) {
183
AddinManager.ReportError ("Add-in could not be loaded", iad.Id, ex, false);
184
if (statusMonitor != null)
185
statusMonitor.ReportError ("Add-in '" + iad.Id + "' could not be loaded.", ex);
190
internal void InsertExtensionPoint (RuntimeAddin addin, ExtensionPoint ep)
192
defaultContext.CreateExtensionPoint (ep);
193
foreach (ExtensionNodeType nt in ep.NodeSet.NodeTypes) {
194
if (nt.ObjectTypeName.Length > 0) {
195
Type ntype = addin.GetType (nt.ObjectTypeName, true);
196
RegisterAutoTypeExtensionPoint (ntype, ep.Path);
201
bool ResolveLoadDependencies (ArrayList addins, Stack depCheck, string id, bool optional)
203
if (IsAddinLoaded (id))
206
if (depCheck.Contains (id))
207
throw new InvalidOperationException ("A cyclic addin dependency has been detected.");
211
Addin iad = AddinManager.Registry.GetAddin (id);
212
if (iad == null || !iad.Enabled) {
215
else if (iad != null && !iad.Enabled)
216
throw new MissingDependencyException (GettextCatalog.GetString ("The required addin '{0}' is disabled.", id));
218
throw new MissingDependencyException (GettextCatalog.GetString ("The required addin '{0}' is not installed.", id));
221
// If this addin has already been requested, bring it to the head
222
// of the list, so it is loaded earlier than before.
226
foreach (Dependency dep in iad.AddinInfo.Dependencies) {
227
AddinDependency adep = dep as AddinDependency;
230
string adepid = Addin.GetFullId (iad.AddinInfo.Namespace, adep.AddinId, adep.Version);
231
ResolveLoadDependencies (addins, depCheck, adepid, false);
232
} catch (MissingDependencyException) {
241
if (iad.AddinInfo.OptionalDependencies != null) {
242
foreach (Dependency dep in iad.AddinInfo.OptionalDependencies) {
243
AddinDependency adep = dep as AddinDependency;
245
string adepid = Addin.GetFullId (iad.Namespace, adep.AddinId, adep.Version);
246
if (!ResolveLoadDependencies (addins, depCheck, adepid, true))
256
public void RegisterNodeSet (ExtensionNodeSet nset)
258
nodeSets [nset.Id] = nset;
261
public void UnregisterNodeSet (ExtensionNodeSet nset)
263
nodeSets.Remove (nset.Id);
266
public string GetNodeTypeAddin (ExtensionNodeSet nset, string type, string callingAddinId)
268
ExtensionNodeType nt = FindType (nset, type, callingAddinId);
275
internal ExtensionNodeType FindType (ExtensionNodeSet nset, string name, string callingAddinId)
280
foreach (ExtensionNodeType nt in nset.NodeTypes) {
285
foreach (string ns in nset.NodeSets) {
286
ExtensionNodeSet regSet = (ExtensionNodeSet) nodeSets [ns];
287
if (regSet == null) {
288
AddinManager.ReportError ("Unknown node set: " + ns, callingAddinId, null, false);
291
ExtensionNodeType nt = FindType (regSet, name, callingAddinId);
298
public void RegisterAutoTypeExtensionPoint (Type type, string path)
300
autoExtensionTypes [type] = path;
303
public void UnregisterAutoTypeExtensionPoint (Type type, string path)
305
autoExtensionTypes.Remove (type);
308
public string GetAutoTypeExtensionPoint (Type type)
310
return autoExtensionTypes [type] as string;
313
void OnAssemblyLoaded (object s, AssemblyLoadEventArgs a)
315
CheckHostAssembly (a.LoadedAssembly);
318
internal void ActivateRoots ()
320
foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies ())
321
CheckHostAssembly (asm);
324
void CheckHostAssembly (Assembly asm)
326
if (AddinDatabase.RunningSetupProcess || asm is System.Reflection.Emit.AssemblyBuilder)
328
string asmFile = new Uri (asm.CodeBase).LocalPath;
329
Addin ainfo = AddinManager.Registry.GetAddinForHostAssembly (asmFile);
330
if (ainfo != null && !IsAddinLoaded (ainfo.Id))
331
InsertAddin (null, ainfo);