~do-win/do/test-paths

« back to all changes in this revision

Viewing changes to Mono.Addins/Mono.Addins.Database/AddinUpdateData.cs

  • Committer: Chris S.
  • Date: 2009-06-21 03:37:34 UTC
  • Revision ID: chris@szikszoy.com-20090621033734-ud2jdcd5pq9r3ue9
initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// AddinUpdateData.cs
 
3
//
 
4
// Author:
 
5
//   Lluis Sanchez Gual
 
6
//
 
7
// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
 
8
//
 
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:
 
16
// 
 
17
// The above copyright notice and this permission notice shall be
 
18
// included in all copies or substantial portions of the Software.
 
19
// 
 
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.
 
27
//
 
28
 
 
29
 
 
30
using System;
 
31
using System.Collections;
 
32
using Mono.Addins.Description;
 
33
 
 
34
namespace Mono.Addins.Database
 
35
{
 
36
        class AddinUpdateData
 
37
        {
 
38
                // This table collects information about extensions. For each path (key)
 
39
                // has a ExtensionInfo object with information about the addin that
 
40
                // defines the extension point and the addins which extend it
 
41
                Hashtable pathHash = new Hashtable ();
 
42
                
 
43
                // Collects globally defined node sets. Key is node set name. Value is
 
44
                // a ExtensionInfo
 
45
                Hashtable nodeSetHash = new Hashtable ();
 
46
                
 
47
                Hashtable objectTypeExtensions = new Hashtable ();
 
48
                
 
49
                internal int RelExtensionPoints;
 
50
                internal int RelExtensions;
 
51
                internal int RelNodeSetTypes;
 
52
                internal int RelExtensionNodes;
 
53
                
 
54
                class RootExtensionPoint
 
55
                {
 
56
                        public AddinDescription Description;
 
57
                        public ExtensionPoint ExtensionPoint;
 
58
                }
 
59
                
 
60
                IProgressStatus monitor;
 
61
                
 
62
                public AddinUpdateData (AddinDatabase database, IProgressStatus monitor)
 
63
                {
 
64
                        this.monitor = monitor;
 
65
                }
 
66
                
 
67
                public void RegisterNodeSet (AddinDescription description, ExtensionNodeSet nset)
 
68
                {
 
69
                        ArrayList extensions = (ArrayList) nodeSetHash [nset.Id];
 
70
                        if (extensions != null) {
 
71
                                // Extension point already registered
 
72
                                ArrayList compatExtensions = GetCompatibleExtensionPoints (nset.Id, description, description.MainModule, extensions);
 
73
                                if (compatExtensions.Count > 0) {
 
74
                                        foreach (ExtensionPoint einfo in compatExtensions)
 
75
                                                einfo.NodeSet.MergeWith (null, nset);
 
76
                                        return;
 
77
                                }
 
78
                        }
 
79
                        // Create a new extension set
 
80
                        RootExtensionPoint rep = new RootExtensionPoint ();
 
81
                        rep.ExtensionPoint = new ExtensionPoint ();
 
82
                        rep.ExtensionPoint.SetNodeSet (nset);
 
83
                        rep.ExtensionPoint.RootAddin = description.AddinId;
 
84
                        rep.ExtensionPoint.Path = nset.Id;
 
85
                        rep.Description = description;
 
86
                        if (extensions == null) {
 
87
                                extensions = new ArrayList ();
 
88
                                nodeSetHash [nset.Id] = extensions;
 
89
                        }
 
90
                        extensions.Add (rep);
 
91
                }
 
92
                
 
93
                public void RegisterExtensionPoint (AddinDescription description, ExtensionPoint ep)
 
94
                {
 
95
                        ArrayList extensions = (ArrayList) pathHash [ep.Path];
 
96
                        if (extensions != null) {
 
97
                                // Extension point already registered
 
98
                                ArrayList compatExtensions = GetCompatibleExtensionPoints (ep.Path, description, description.MainModule, extensions);
 
99
                                if (compatExtensions.Count > 0) {
 
100
                                        foreach (ExtensionPoint einfo in compatExtensions)
 
101
                                                einfo.MergeWith (null, ep);
 
102
                                        RegisterObjectTypes (ep);
 
103
                                        return;
 
104
                                }
 
105
                        }
 
106
                        // Create a new extension
 
107
                        RootExtensionPoint rep = new RootExtensionPoint ();
 
108
                        rep.ExtensionPoint = ep;
 
109
                        rep.ExtensionPoint.RootAddin = description.AddinId;
 
110
                        rep.Description = description;
 
111
                        if (extensions == null) {
 
112
                                extensions = new ArrayList ();
 
113
                                pathHash [ep.Path] = extensions;
 
114
                        }
 
115
                        extensions.Add (rep);
 
116
                        RegisterObjectTypes (ep);
 
117
                }
 
118
                        
 
119
                void RegisterObjectTypes (ExtensionPoint ep)
 
120
                {
 
121
                        // Register extension points bound to a node type
 
122
                        
 
123
                        foreach (ExtensionNodeType nt in ep.NodeSet.NodeTypes) {
 
124
                                if (nt.ObjectTypeName.Length > 0) {
 
125
                                        ArrayList list = (ArrayList) objectTypeExtensions [nt.ObjectTypeName];
 
126
                                        if (list == null) {
 
127
                                                list = new ArrayList ();
 
128
                                                objectTypeExtensions [nt.ObjectTypeName] = list;
 
129
                                        }
 
130
                                        list.Add (ep);
 
131
                                }
 
132
                        }
 
133
                }
 
134
 
 
135
                public void RegisterExtension (AddinDescription description, ModuleDescription module, Extension extension)
 
136
                {
 
137
                        if (extension.Path.StartsWith ("$")) {
 
138
                                string[] objectTypes = extension.Path.Substring (1).Split (',');
 
139
                                bool found = false;
 
140
                                foreach (string s in objectTypes) {
 
141
                                        ArrayList list = (ArrayList) objectTypeExtensions [s];
 
142
                                        if (list != null) {
 
143
                                                found = true;
 
144
                                                foreach (ExtensionPoint ep in list) {
 
145
                                                        if (IsAddinCompatible (ep.ParentAddinDescription, description, module)) {
 
146
                                                                extension.Path = ep.Path;
 
147
                                                                RegisterExtension (description, module, ep.Path);
 
148
                                                        }
 
149
                                                }
 
150
                                        }
 
151
                                }
 
152
                                if (!found)
 
153
                                        monitor.ReportWarning ("The add-in '" + description.AddinId + "' is trying to register the class '" + extension.Path.Substring (1) + "', but there isn't any add-in defining a suitable extension point");
 
154
                        }
 
155
                }
 
156
                
 
157
                public void RegisterExtension (AddinDescription description, ModuleDescription module, string path)
 
158
                {
 
159
                        ArrayList extensions = (ArrayList) pathHash [path];
 
160
                        if (extensions == null) {
 
161
                                // Root add-in extension points are registered before any other kind of extension,
 
162
                                // so we should find it now.
 
163
                                extensions = GetParentExtensionInfo (path);
 
164
                        }
 
165
                        if (extensions == null) {
 
166
                                monitor.ReportWarning ("The add-in '" + description.AddinId + "' is trying to extend '" + path + "', but there isn't any add-in defining this extension point");
 
167
                                return;
 
168
                        }
 
169
                        
 
170
                        bool found = false;
 
171
                        foreach (RootExtensionPoint einfo in extensions) {
 
172
                                if (IsAddinCompatible (einfo.Description, description, module)) {
 
173
                                        if (!einfo.ExtensionPoint.Addins.Contains (description.AddinId))
 
174
                                                einfo.ExtensionPoint.Addins.Add (description.AddinId);
 
175
                                        found = true;
 
176
                                }
 
177
                        }
 
178
                        if (!found)
 
179
                                monitor.ReportWarning ("The add-in '" + description.AddinId + "' is trying to extend '" + path + "', but there isn't any compatible add-in defining this extension point");
 
180
                }
 
181
                
 
182
                ArrayList GetCompatibleExtensionPoints (string path, AddinDescription description, ModuleDescription module, ArrayList rootExtensionPoints)
 
183
                {
 
184
                        ArrayList list = new ArrayList ();
 
185
                        foreach (RootExtensionPoint rep in rootExtensionPoints) {
 
186
                                
 
187
                                // Find an extension point defined in a root add-in which is compatible with the version of the extender dependency
 
188
                                if (IsAddinCompatible (rep.Description, description, module))
 
189
                                        list.Add (rep.ExtensionPoint);
 
190
                        }
 
191
                        return list;
 
192
                }
 
193
                
 
194
                ArrayList GetParentExtensionInfo (string path)
 
195
                {
 
196
                        int i = path.LastIndexOf ('/');
 
197
                        if (i == -1)
 
198
                                return null;
 
199
                        string np = path.Substring (0, i);
 
200
                        ArrayList ep = (ArrayList) pathHash [np];
 
201
                        if (ep != null)
 
202
                                return ep;
 
203
                        else
 
204
                                return GetParentExtensionInfo (np);
 
205
                }
 
206
                
 
207
                bool IsAddinCompatible (AddinDescription installedDescription, AddinDescription description, ModuleDescription module)
 
208
                {
 
209
                        if (installedDescription == description)
 
210
                                return true;
 
211
                        if (installedDescription.Domain != AddinDatabase.GlobalDomain) {
 
212
                                if (description.Domain != AddinDatabase.GlobalDomain && description.Domain != installedDescription.Domain)
 
213
                                        return false;
 
214
                        } else if (description.Domain != AddinDatabase.GlobalDomain)
 
215
                                return false;
 
216
                                
 
217
                        string addinId = Addin.GetFullId (installedDescription.Namespace, installedDescription.LocalId, null);
 
218
                        string requiredVersion = null;
 
219
                        
 
220
                        for (int n = module.Dependencies.Count - 1; n >= 0; n--) {
 
221
                                AddinDependency adep = module.Dependencies [n] as AddinDependency;
 
222
                                if (adep != null && Addin.GetFullId (description.Namespace, adep.AddinId, null) == addinId) {
 
223
                                        requiredVersion = adep.Version;
 
224
                                        break;
 
225
                                }
 
226
                        }
 
227
                        if (requiredVersion == null)
 
228
                                return false;
 
229
 
 
230
                        // Check if the required version is between rep.Description.CompatVersion and rep.Description.Version
 
231
                        if (Addin.CompareVersions (installedDescription.Version, requiredVersion) > 0)
 
232
                                return false;
 
233
                        if (installedDescription.CompatVersion.Length > 0 && Addin.CompareVersions (installedDescription.CompatVersion, requiredVersion) < 0)
 
234
                                return false;
 
235
                        
 
236
                        return true;
 
237
                }
 
238
        }
 
239
}