~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/mono-addins/Mono.Addins/Mono.Addins.Description/AddinDescription.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// AddinDescription.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
using System;
 
30
using System.Collections;
 
31
using System.Collections.Generic;
 
32
using System.IO;
 
33
using System.Xml;
 
34
using System.Xml.Serialization;
 
35
using System.Collections.Specialized;
 
36
using Mono.Addins.Serialization;
 
37
using Mono.Addins.Database;
 
38
using System.Text;
 
39
 
 
40
namespace Mono.Addins.Description
 
41
{
 
42
        /// <summary>
 
43
        /// An add-in description
 
44
        /// </summary>
 
45
        /// <remarks>
 
46
        /// This class represent an add-in manifest. It has properties for getting
 
47
        /// all information, and methods for loading and saving files.
 
48
        ///     </remarks>
 
49
        public class AddinDescription: IBinaryXmlElement
 
50
        {
 
51
                XmlDocument configDoc;
 
52
                string configFile;
 
53
                AddinDatabase ownerDatabase;
 
54
                
 
55
                string id;
 
56
                string name;
 
57
                string ns;
 
58
                string version;
 
59
                string compatVersion;
 
60
                string author;
 
61
                string url;
 
62
                string copyright;
 
63
                string description;
 
64
                string category;
 
65
                string basePath;
 
66
                string sourceAddinFile;
 
67
                bool isroot;
 
68
                bool hasUserId;
 
69
                bool canWrite = true;
 
70
                bool defaultEnabled = true;
 
71
                AddinFlags flags = AddinFlags.None;
 
72
                string domain;
 
73
                                
 
74
                ModuleDescription mainModule;
 
75
                ModuleCollection optionalModules;
 
76
                ExtensionNodeSetCollection nodeSets;
 
77
                ConditionTypeDescriptionCollection conditionTypes;
 
78
                ExtensionPointCollection extensionPoints;
 
79
                ExtensionNodeDescription localizer;
 
80
                object[] fileInfo;
 
81
                
 
82
                AddinPropertyCollectionImpl properties;
 
83
                Dictionary<string,string> variables;
 
84
                
 
85
                internal static BinaryXmlTypeMap typeMap;
 
86
                
 
87
                static AddinDescription ()
 
88
                {
 
89
                        typeMap = new BinaryXmlTypeMap ();
 
90
                        typeMap.RegisterType (typeof(AddinDescription), "AddinDescription");
 
91
                        typeMap.RegisterType (typeof(Extension), "Extension");
 
92
                        typeMap.RegisterType (typeof(ExtensionNodeDescription), "Node");
 
93
                        typeMap.RegisterType (typeof(ExtensionNodeSet), "NodeSet");
 
94
                        typeMap.RegisterType (typeof(ExtensionNodeType), "NodeType");
 
95
                        typeMap.RegisterType (typeof(ExtensionPoint), "ExtensionPoint");
 
96
                        typeMap.RegisterType (typeof(ModuleDescription), "ModuleDescription");
 
97
                        typeMap.RegisterType (typeof(ConditionTypeDescription), "ConditionType");
 
98
                        typeMap.RegisterType (typeof(Condition), "Condition");
 
99
                        typeMap.RegisterType (typeof(AddinDependency), "AddinDependency");
 
100
                        typeMap.RegisterType (typeof(AssemblyDependency), "AssemblyDependency");
 
101
                        typeMap.RegisterType (typeof(NodeTypeAttribute), "NodeTypeAttribute");
 
102
                        typeMap.RegisterType (typeof(AddinFileInfo), "FileInfo");
 
103
                        typeMap.RegisterType (typeof(AddinProperty), "Property");
 
104
                }
 
105
                
 
106
                internal AddinDatabase OwnerDatabase {
 
107
                        get { return ownerDatabase; }
 
108
                        set { ownerDatabase = value; }
 
109
                }
 
110
                
 
111
                /// <summary>
 
112
                /// Gets or sets the path to the main addin file.
 
113
                /// </summary>
 
114
                /// <value>
 
115
                /// The addin file.
 
116
                /// </value>
 
117
                /// <remarks>
 
118
                /// The add-in file can be either the main assembly of an add-in or an xml manifest.
 
119
                /// </remarks>
 
120
                public string AddinFile {
 
121
                        get { return sourceAddinFile; }
 
122
                        set { sourceAddinFile = value; }
 
123
                }
 
124
                
 
125
                /// <summary>
 
126
                /// Gets the addin identifier.
 
127
                /// </summary>
 
128
                /// <value>
 
129
                /// The addin identifier.
 
130
                /// </value>
 
131
                public string AddinId {
 
132
                        get { return Addin.GetFullId (Namespace, LocalId, Version); }
 
133
                }
 
134
                
 
135
                /// <summary>
 
136
                /// Gets or sets the local identifier.
 
137
                /// </summary>
 
138
                /// <value>
 
139
                /// The local identifier.
 
140
                /// </value>
 
141
                public string LocalId {
 
142
                        get { return id != null ? ParseString (id) : string.Empty; }
 
143
                        set { id = value; hasUserId = true; }
 
144
                }
 
145
 
 
146
                /// <summary>
 
147
                /// Gets or sets the namespace.
 
148
                /// </summary>
 
149
                /// <value>
 
150
                /// The namespace.
 
151
                /// </value>
 
152
                public string Namespace {
 
153
                        get { return ns != null ? ParseString (ns) : string.Empty; }
 
154
                        set { ns = value; }
 
155
                }
 
156
 
 
157
                /// <summary>
 
158
                /// Gets or sets the display name of the add-in.
 
159
                /// </summary>
 
160
                /// <value>
 
161
                /// The name.
 
162
                /// </value>
 
163
                public string Name {
 
164
                        get {
 
165
                                string val = Properties.GetPropertyValue ("Name");
 
166
                                if (val.Length > 0)
 
167
                                        return val;
 
168
                                if (name != null && name.Length > 0)
 
169
                                        return ParseString (name);
 
170
                                if (HasUserId)
 
171
                                        return AddinId;
 
172
                                else if (sourceAddinFile != null)
 
173
                                        return Path.GetFileNameWithoutExtension (sourceAddinFile);
 
174
                                else
 
175
                                        return string.Empty;
 
176
                        }
 
177
                        set { name = value; }
 
178
                }
 
179
                
 
180
                /// <summary>
 
181
                /// Gets or sets the version.
 
182
                /// </summary>
 
183
                /// <value>
 
184
                /// The version.
 
185
                /// </value>
 
186
                public string Version {
 
187
                        get { return version != null ? ParseString (version) : string.Empty; }
 
188
                        set { version = value; }
 
189
                }
 
190
 
 
191
                /// <summary>
 
192
                /// Gets or sets the version of the add-in with which this add-in is backwards compatible.
 
193
                /// </summary>
 
194
                /// <value>
 
195
                /// The compat version.
 
196
                /// </value>
 
197
                public string CompatVersion {
 
198
                        get { return compatVersion != null ? ParseString (compatVersion) : string.Empty; }
 
199
                        set { compatVersion = value; }
 
200
                }
 
201
 
 
202
                /// <summary>
 
203
                /// Gets or sets the author.
 
204
                /// </summary>
 
205
                /// <value>
 
206
                /// The author.
 
207
                /// </value>
 
208
                public string Author {
 
209
                        get {
 
210
                                string val = Properties.GetPropertyValue ("Author");
 
211
                                if (val.Length > 0)
 
212
                                        return val;
 
213
                                return ParseString (author) ?? string.Empty; 
 
214
                        }
 
215
                        set { author = value; }
 
216
                }
 
217
 
 
218
                /// <summary>
 
219
                /// Gets or sets the Url where more information about the add-in can be found.
 
220
                /// </summary>
 
221
                /// <value>
 
222
                /// The URL.
 
223
                /// </value>
 
224
                public string Url {
 
225
                        get {
 
226
                                string val = Properties.GetPropertyValue ("Url");
 
227
                                if (val.Length > 0)
 
228
                                        return val;
 
229
                                return ParseString (url) ?? string.Empty;
 
230
                        }
 
231
                        set { url = value; }
 
232
                }
 
233
 
 
234
                /// <summary>
 
235
                /// Gets or sets the copyright.
 
236
                /// </summary>
 
237
                /// <value>
 
238
                /// The copyright.
 
239
                /// </value>
 
240
                public string Copyright {
 
241
                        get {
 
242
                                string val = Properties.GetPropertyValue ("Copyright");
 
243
                                if (val.Length > 0)
 
244
                                        return val;
 
245
                                return ParseString (copyright) ?? string.Empty; 
 
246
                        }
 
247
                        set { copyright = value; }
 
248
                }
 
249
 
 
250
                /// <summary>
 
251
                /// Gets or sets the description of the add-in.
 
252
                /// </summary>
 
253
                /// <value>
 
254
                /// The description.
 
255
                /// </value>
 
256
                public string Description {
 
257
                        get {
 
258
                                string val = Properties.GetPropertyValue ("Description");
 
259
                                if (val.Length > 0)
 
260
                                        return val;
 
261
                                return ParseString (description) ?? string.Empty;
 
262
                        }
 
263
                        set { description = value; }
 
264
                }
 
265
 
 
266
                /// <summary>
 
267
                /// Gets or sets the category of the add-in.
 
268
                /// </summary>
 
269
                /// <value>
 
270
                /// The category.
 
271
                /// </value>
 
272
                public string Category {
 
273
                        get {
 
274
                                string val = Properties.GetPropertyValue ("Category");
 
275
                                if (val.Length > 0)
 
276
                                        return val;
 
277
                                return ParseString (category) ?? string.Empty;
 
278
                        }
 
279
                        set { category = value; }
 
280
                }
 
281
                
 
282
                /// <summary>
 
283
                /// Gets the base path for locating external files relative to the add-in.
 
284
                /// </summary>
 
285
                /// <value>
 
286
                /// The base path.
 
287
                /// </value>
 
288
                public string BasePath {
 
289
                        get { return basePath != null ? basePath : string.Empty; }
 
290
                }
 
291
                
 
292
                internal void SetBasePath (string path)
 
293
                {
 
294
                        basePath = path;
 
295
                }
 
296
                
 
297
                /// <summary>
 
298
                /// Gets or sets a value indicating whether this instance is an add-in root.
 
299
                /// </summary>
 
300
                /// <value>
 
301
                /// <c>true</c> if this instance is an add-in root; otherwise, <c>false</c>.
 
302
                /// </value>
 
303
                public bool IsRoot {
 
304
                        get { return isroot; }
 
305
                        set { isroot = value; }
 
306
                }
 
307
                
 
308
                /// <summary>
 
309
                /// Gets or sets a value indicating whether this add-in is enabled by default.
 
310
                /// </summary>
 
311
                /// <value>
 
312
                /// <c>true</c> if enabled by default; otherwise, <c>false</c>.
 
313
                /// </value>
 
314
                public bool EnabledByDefault {
 
315
                        get { return defaultEnabled; }
 
316
                        set { defaultEnabled = value; }
 
317
                }
 
318
                
 
319
                /// <summary>
 
320
                /// Gets or sets the add-in flags.
 
321
                /// </summary>
 
322
                /// <value>
 
323
                /// The flags.
 
324
                /// </value>
 
325
                public AddinFlags Flags {
 
326
                        get { return flags; }
 
327
                        set { flags = value; }
 
328
                }
 
329
                
 
330
                internal bool HasUserId {
 
331
                        get { return hasUserId; }
 
332
                        set { hasUserId = value; }
 
333
                }
 
334
                
 
335
                /// <summary>
 
336
                /// Gets a value indicating whether this add-in can be disabled.
 
337
                /// </summary>
 
338
                /// <value>
 
339
                /// <c>true</c> if this add-in can be disabled; otherwise, <c>false</c>.
 
340
                /// </value>
 
341
                public bool CanDisable {
 
342
                        get { return (flags & AddinFlags.CantDisable) == 0 && !IsHidden; }
 
343
                }
 
344
                
 
345
                /// <summary>
 
346
                /// Gets a value indicating whether this add-in can be uninstalled.
 
347
                /// </summary>
 
348
                /// <value>
 
349
                /// <c>true</c> if this instance can be uninstalled; otherwise, <c>false</c>.
 
350
                /// </value>
 
351
                public bool CanUninstall {
 
352
                        get { return (flags & AddinFlags.CantUninstall) == 0 && !IsHidden; }
 
353
                }
 
354
                
 
355
                /// <summary>
 
356
                /// Gets a value indicating whether this add-in is hidden.
 
357
                /// </summary>
 
358
                /// <value>
 
359
                /// <c>true</c> if this add-in is hidden; otherwise, <c>false</c>.
 
360
                /// </value>
 
361
                public bool IsHidden {
 
362
                        get { return (flags & AddinFlags.Hidden) != 0; }
 
363
                }
 
364
                
 
365
                internal bool SupportsVersion (string ver)
 
366
                {
 
367
                        return Addin.CompareVersions (ver, Version) >= 0 &&
 
368
                                   (CompatVersion.Length == 0 || Addin.CompareVersions (ver, CompatVersion) <= 0);
 
369
                }
 
370
                
 
371
                /// <summary>
 
372
                /// Gets all external files
 
373
                /// </summary>
 
374
                /// <value>
 
375
                /// All files.
 
376
                /// </value>
 
377
                /// <remarks>
 
378
                /// External files are data files and assemblies explicitly referenced in the Runtime section of the add-in manifest.
 
379
                /// </remarks>
 
380
                public StringCollection AllFiles {
 
381
                        get {
 
382
                                StringCollection col = new StringCollection ();
 
383
                                foreach (string s in MainModule.AllFiles)
 
384
                                        col.Add (s);
 
385
 
 
386
                                foreach (ModuleDescription mod in OptionalModules) {
 
387
                                        foreach (string s in mod.AllFiles)
 
388
                                                col.Add (s);
 
389
                                }
 
390
                                return col;
 
391
                        }
 
392
                }
 
393
                
 
394
                /// <summary>
 
395
                /// Gets all paths to be ignored by the add-in scanner.
 
396
                /// </summary>
 
397
                /// <value>
 
398
                /// All paths to be ignored.
 
399
                /// </value>
 
400
                public StringCollection AllIgnorePaths {
 
401
                        get {
 
402
                                StringCollection col = new StringCollection ();
 
403
                                foreach (string s in MainModule.IgnorePaths)
 
404
                                        col.Add (s);
 
405
 
 
406
                                foreach (ModuleDescription mod in OptionalModules) {
 
407
                                        foreach (string s in mod.IgnorePaths)
 
408
                                                col.Add (s);
 
409
                                }
 
410
                                return col;
 
411
                        }
 
412
                }
 
413
                
 
414
                /// <summary>
 
415
                /// Gets the main module.
 
416
                /// </summary>
 
417
                /// <value>
 
418
                /// The main module.
 
419
                /// </value>
 
420
                public ModuleDescription MainModule {
 
421
                        get {
 
422
                                if (mainModule == null) {
 
423
                                        if (RootElement == null)
 
424
                                                mainModule = new ModuleDescription ();
 
425
                                        else
 
426
                                                mainModule = new ModuleDescription (RootElement);
 
427
                                        mainModule.SetParent (this);
 
428
                                }
 
429
                                return mainModule;
 
430
                        }
 
431
                }
 
432
                
 
433
                /// <summary>
 
434
                /// Gets the optional modules.
 
435
                /// </summary>
 
436
                /// <value>
 
437
                /// The optional modules.
 
438
                /// </value>
 
439
                /// <remarks>
 
440
                /// Optional modules can be used to declare extensions which will be registered only if some specified
 
441
                /// add-in dependencies can be satisfied. Dependencies specified in optional modules are 'soft dependencies',
 
442
                /// which means that they don't need to be satisfied in order to load the add-in.
 
443
                /// </remarks>
 
444
                public ModuleCollection OptionalModules {
 
445
                        get {
 
446
                                if (optionalModules == null) {
 
447
                                        optionalModules = new ModuleCollection (this);
 
448
                                        if (RootElement != null) {
 
449
                                                foreach (XmlElement mod in RootElement.SelectNodes ("Module"))
 
450
                                                        optionalModules.Add (new ModuleDescription (mod));
 
451
                                        }
 
452
                                }
 
453
                                return optionalModules;
 
454
                        }
 
455
                }
 
456
                
 
457
                /// <summary>
 
458
                /// Gets all modules (including the main module and all optional modules)
 
459
                /// </summary>
 
460
                /// <value>
 
461
                /// All modules.
 
462
                /// </value>
 
463
                public ModuleCollection AllModules {
 
464
                        get {
 
465
                                ModuleCollection col = new ModuleCollection (this);
 
466
                                col.Add (MainModule);
 
467
                                foreach (ModuleDescription mod in OptionalModules)
 
468
                                        col.Add (mod);
 
469
                                return col;
 
470
                        }
 
471
                }
 
472
                
 
473
                /// <summary>
 
474
                /// Gets the extension node sets.
 
475
                /// </summary>
 
476
                /// <value>
 
477
                /// The extension node sets.
 
478
                /// </value>
 
479
                public ExtensionNodeSetCollection ExtensionNodeSets {
 
480
                        get {
 
481
                                if (nodeSets == null) {
 
482
                                        nodeSets = new ExtensionNodeSetCollection (this);
 
483
                                        if (RootElement != null) {
 
484
                                                foreach (XmlElement elem in RootElement.SelectNodes ("ExtensionNodeSet"))
 
485
                                                        nodeSets.Add (new ExtensionNodeSet (elem));
 
486
                                        }
 
487
                                }
 
488
                                return nodeSets;
 
489
                        }
 
490
                }
 
491
                
 
492
                /// <summary>
 
493
                /// Gets the extension points.
 
494
                /// </summary>
 
495
                /// <value>
 
496
                /// The extension points.
 
497
                /// </value>
 
498
                public ExtensionPointCollection ExtensionPoints {
 
499
                        get {
 
500
                                if (extensionPoints == null) {
 
501
                                        extensionPoints = new ExtensionPointCollection (this);
 
502
                                        if (RootElement != null) {
 
503
                                                foreach (XmlElement elem in RootElement.SelectNodes ("ExtensionPoint"))
 
504
                                                        extensionPoints.Add (new ExtensionPoint (elem));
 
505
                                        }
 
506
                                }
 
507
                                return extensionPoints;
 
508
                        }
 
509
                }
 
510
                
 
511
                /// <summary>
 
512
                /// Gets the condition types.
 
513
                /// </summary>
 
514
                /// <value>
 
515
                /// The condition types.
 
516
                /// </value>
 
517
                public ConditionTypeDescriptionCollection ConditionTypes {
 
518
                        get {
 
519
                                if (conditionTypes == null) {
 
520
                                        conditionTypes = new ConditionTypeDescriptionCollection (this);
 
521
                                        if (RootElement != null) {
 
522
                                                foreach (XmlElement elem in RootElement.SelectNodes ("ConditionType"))
 
523
                                                        conditionTypes.Add (new ConditionTypeDescription (elem));
 
524
                                        }
 
525
                                }
 
526
                                return conditionTypes;
 
527
                        }
 
528
                }
 
529
                
 
530
                /// <summary>
 
531
                /// Gets or sets the add-in localizer.
 
532
                /// </summary>
 
533
                /// <value>
 
534
                /// The description of the add-in localizer for this add-in.
 
535
                /// </value>
 
536
                public ExtensionNodeDescription Localizer {
 
537
                        get { return localizer; }
 
538
                        set { localizer = value; }
 
539
                }
 
540
                
 
541
                /// <summary>
 
542
                /// Custom properties specified in the add-in header
 
543
                /// </summary>
 
544
                public AddinPropertyCollection Properties {
 
545
                        get {
 
546
                                if (properties == null)
 
547
                                        properties = new AddinPropertyCollectionImpl (this);
 
548
                                return properties;
 
549
                        }
 
550
                }
 
551
                
 
552
                /// <summary>
 
553
                /// Adds an extension point.
 
554
                /// </summary>
 
555
                /// <returns>
 
556
                /// The extension point.
 
557
                /// </returns>
 
558
                /// <param name='path'>
 
559
                /// Path that identifies the new extension point.
 
560
                /// </param>
 
561
                public ExtensionPoint AddExtensionPoint (string path)
 
562
                {
 
563
                        ExtensionPoint ep = new ExtensionPoint ();
 
564
                        ep.Path = path;
 
565
                        ExtensionPoints.Add (ep);
 
566
                        return ep;
 
567
                }
 
568
                
 
569
                internal ExtensionNodeDescription FindExtensionNode (string path, bool lookInDeps)
 
570
                {
 
571
                        // Look in the extensions of this add-in
 
572
                        
 
573
                        foreach (Extension ext in MainModule.Extensions) {
 
574
                                if (path.StartsWith (ext.Path + "/")) {
 
575
                                        string subp = path.Substring (ext.Path.Length).Trim ('/');
 
576
                                        ExtensionNodeDescriptionCollection nodes = ext.ExtensionNodes;
 
577
                                        ExtensionNodeDescription node = null;
 
578
                                        foreach (string p in subp.Split ('/')) {
 
579
                                                if (p.Length == 0) continue;
 
580
                                                node = nodes [p];
 
581
                                                if (node == null)
 
582
                                                        break;
 
583
                                                nodes = node.ChildNodes;
 
584
                                        }
 
585
                                        if (node != null)
 
586
                                                return node;
 
587
                                }
 
588
                        }
 
589
                        
 
590
                        if (!lookInDeps || OwnerDatabase == null)
 
591
                                return null;
 
592
                        
 
593
                        // Look in dependencies
 
594
                        
 
595
                        foreach (Dependency dep in MainModule.Dependencies) {
 
596
                                AddinDependency adep = dep as AddinDependency;
 
597
                                if (adep == null) continue;
 
598
                                Addin ad = OwnerDatabase.GetInstalledAddin (Domain, adep.FullAddinId);
 
599
                                if (ad != null && ad.Description != null) {
 
600
                                        ExtensionNodeDescription node = ad.Description.FindExtensionNode (path, false);
 
601
                                        if (node != null)
 
602
                                                return node;
 
603
                                }
 
604
                        }
 
605
                        return null;
 
606
                }
 
607
                
 
608
                XmlElement RootElement {
 
609
                        get {
 
610
                                if (configDoc != null)
 
611
                                        return configDoc.DocumentElement;
 
612
                                else
 
613
                                        return null;
 
614
                        }
 
615
                }
 
616
                
 
617
                /// <summary>
 
618
                /// Gets or sets file where this description is stored
 
619
                /// </summary>
 
620
                /// <value>
 
621
                /// The file path.
 
622
                /// </value>
 
623
                public string FileName {
 
624
                        get { return configFile; }
 
625
                        set { configFile = value; }
 
626
                }
 
627
                
 
628
                internal string Domain {
 
629
                        get { return domain; }
 
630
                        set { domain = value; }
 
631
                }
 
632
                
 
633
                internal void StoreFileInfo ()
 
634
                {
 
635
                        ArrayList list = new ArrayList ();
 
636
                        foreach (string f in AllFiles) {
 
637
                                string file = Path.Combine (this.BasePath, f);
 
638
                                AddinFileInfo fi = new AddinFileInfo ();
 
639
                                fi.FileName = f;
 
640
                                fi.Timestamp = File.GetLastWriteTime (file);
 
641
                                list.Add (fi);
 
642
                        }
 
643
                        fileInfo = list.ToArray ();
 
644
                }
 
645
                
 
646
                internal bool FilesChanged ()
 
647
                {
 
648
                        // Checks if the files of the add-in have changed.
 
649
                        if (fileInfo == null)
 
650
                                return true;
 
651
                        
 
652
                        foreach (AddinFileInfo f in fileInfo) {
 
653
                                string file = Path.Combine (this.BasePath, f.FileName);
 
654
                                if (!File.Exists (file))
 
655
                                        return true;
 
656
                                if (f.Timestamp != File.GetLastWriteTime (file))
 
657
                                        return true;
 
658
                        }
 
659
                        
 
660
                        return false;
 
661
                }
 
662
                
 
663
                void TransferCoreProperties (bool removeProperties)
 
664
                {
 
665
                        if (properties == null)
 
666
                                return;
 
667
                        
 
668
                        string val = properties.ExtractCoreProperty ("Id", removeProperties);
 
669
                        if (val != null)
 
670
                                id = val;
 
671
                        
 
672
                        val = properties.ExtractCoreProperty ("Namespace", removeProperties);
 
673
                        if (val != null)
 
674
                                ns = val;
 
675
                        
 
676
                        val = properties.ExtractCoreProperty ("Version", removeProperties);
 
677
                        if (val != null)
 
678
                                version = val;
 
679
                        
 
680
                        val = properties.ExtractCoreProperty ("CompatVersion", removeProperties);
 
681
                        if (val != null)
 
682
                                compatVersion = val;
 
683
                        
 
684
                        val = properties.ExtractCoreProperty ("DefaultEnabled", removeProperties);
 
685
                        if (val != null)
 
686
                                defaultEnabled = GetBool (val, true);
 
687
                        
 
688
                        val = properties.ExtractCoreProperty ("IsRoot", removeProperties);
 
689
                        if (val != null)
 
690
                                isroot = GetBool (val, true);
 
691
                        
 
692
                        val = properties.ExtractCoreProperty ("Flags", removeProperties);
 
693
                        if (val != null)
 
694
                                flags = (AddinFlags) Enum.Parse (typeof(AddinFlags), val);
 
695
                }
 
696
                
 
697
                /// <summary>
 
698
                /// Saves the add-in description.
 
699
                /// </summary>
 
700
                /// <param name='fileName'>
 
701
                /// File name where to save this instance
 
702
                /// </param>
 
703
                /// <remarks>
 
704
                /// Saves the add-in description to the specified file and sets the FileName property.
 
705
                /// </remarks>
 
706
                public void Save (string fileName)
 
707
                {
 
708
                        configFile = fileName;
 
709
                        Save ();
 
710
                }
 
711
                
 
712
                /// <summary>
 
713
                /// Saves the add-in description.
 
714
                /// </summary>
 
715
                /// <exception cref='InvalidOperationException'>
 
716
                /// It is thrown if FileName is not set
 
717
                /// </exception>
 
718
                /// <remarks>
 
719
                /// The description is saved to the file specified in the FileName property.
 
720
                /// </remarks>
 
721
                public void Save ()
 
722
                {
 
723
                        if (configFile == null)
 
724
                                throw new InvalidOperationException ("File name not specified.");
 
725
                        
 
726
                        SaveXml ();
 
727
 
 
728
                        using (StreamWriter sw = new StreamWriter (configFile)) {
 
729
                                XmlTextWriter tw = new XmlTextWriter (sw);
 
730
                                tw.Formatting = Formatting.Indented;
 
731
                                configDoc.Save (tw);
 
732
                        }
 
733
                }
 
734
                
 
735
                /// <summary>
 
736
                /// Generates an XML representation of the add-in description
 
737
                /// </summary>
 
738
                /// <returns>
 
739
                /// An XML manifest.
 
740
                /// </returns>
 
741
                public XmlDocument SaveToXml ()
 
742
                {
 
743
                        SaveXml ();
 
744
                        return configDoc;
 
745
                }
 
746
                
 
747
                void SaveXml ()
 
748
                {
 
749
                        if (!canWrite)
 
750
                                throw new InvalidOperationException ("Can't write incomplete description.");
 
751
                        
 
752
                        XmlElement elem;
 
753
                        
 
754
                        if (configDoc == null) {
 
755
                                configDoc = new XmlDocument ();
 
756
                                configDoc.AppendChild (configDoc.CreateElement ("Addin"));
 
757
                        }
 
758
                        
 
759
                        elem = configDoc.DocumentElement;
 
760
 
 
761
                        SaveCoreProperty (elem, HasUserId ? id : null, "id", "Id");
 
762
                        SaveCoreProperty (elem, version, "version", "Version");
 
763
                        SaveCoreProperty (elem, ns, "namespace", "Namespace");
 
764
                        SaveCoreProperty (elem, isroot ? "true" : null, "isroot", "IsRoot");
 
765
                        
 
766
                        // Name will return the file name when HasUserId=false
 
767
                        if (!string.IsNullOrEmpty (name))
 
768
                                elem.SetAttribute ("name", name);
 
769
                        else
 
770
                                elem.RemoveAttribute ("name");
 
771
                                
 
772
                        SaveCoreProperty (elem, compatVersion, "compatVersion", "CompatVersion");
 
773
                        SaveCoreProperty (elem, defaultEnabled ? null : "false", "defaultEnabled", "DefaultEnabled");
 
774
                        SaveCoreProperty (elem, flags != AddinFlags.None ? flags.ToString () : null, "flags", "Flags");
 
775
                        
 
776
                        if (author != null && author.Length > 0)
 
777
                                elem.SetAttribute ("author", author);
 
778
                        else
 
779
                                elem.RemoveAttribute ("author");
 
780
                                
 
781
                        if (url != null && url.Length > 0)
 
782
                                elem.SetAttribute ("url", url);
 
783
                        else
 
784
                                elem.RemoveAttribute ("url");
 
785
                                
 
786
                        if (copyright != null && copyright.Length > 0)
 
787
                                elem.SetAttribute ("copyright", copyright);
 
788
                        else
 
789
                                elem.RemoveAttribute ("copyright");
 
790
                                
 
791
                        if (description != null && description.Length > 0)
 
792
                                elem.SetAttribute ("description", description);
 
793
                        else
 
794
                                elem.RemoveAttribute ("description");
 
795
                                
 
796
                        if (category != null && category.Length > 0)
 
797
                                elem.SetAttribute ("category", category);
 
798
                        else
 
799
                                elem.RemoveAttribute ("category");
 
800
                        
 
801
                        if (localizer == null || localizer.Element == null) {
 
802
                                // Remove old element if it exists
 
803
                                XmlElement oldLoc = (XmlElement) elem.SelectSingleNode ("Localizer");
 
804
                                if (oldLoc != null)
 
805
                                        elem.RemoveChild (oldLoc);
 
806
                        }
 
807
                        if (localizer != null)
 
808
                                localizer.SaveXml (elem);
 
809
                        
 
810
                        if (mainModule != null) {
 
811
                                mainModule.Element = elem;
 
812
                                mainModule.SaveXml (elem);
 
813
                        }
 
814
                                
 
815
                        if (optionalModules != null)
 
816
                                optionalModules.SaveXml (elem);
 
817
                                
 
818
                        if (nodeSets != null)
 
819
                                nodeSets.SaveXml (elem);
 
820
                                
 
821
                        if (extensionPoints != null)
 
822
                                extensionPoints.SaveXml (elem);
 
823
                        
 
824
                        XmlElement oldHeader = (XmlElement) elem.SelectSingleNode ("Header");
 
825
                        if (properties == null || properties.Count == 0) {
 
826
                                if (oldHeader != null)
 
827
                                        elem.RemoveChild (oldHeader);
 
828
                        } else {
 
829
                                if (oldHeader == null) {
 
830
                                        oldHeader = elem.OwnerDocument.CreateElement ("Header");
 
831
                                        if (elem.FirstChild != null)
 
832
                                                elem.InsertBefore (oldHeader, elem.FirstChild);
 
833
                                        else
 
834
                                                elem.AppendChild (oldHeader);
 
835
                                }
 
836
                                else
 
837
                                        oldHeader.RemoveAll ();
 
838
                                foreach (var prop in properties) {
 
839
                                        XmlElement propElem = elem.OwnerDocument.CreateElement (prop.Name);
 
840
                                        if (!string.IsNullOrEmpty (prop.Locale))
 
841
                                                propElem.SetAttribute ("locale", prop.Locale);
 
842
                                        propElem.InnerText = prop.Value ?? string.Empty;
 
843
                                        oldHeader.AppendChild (propElem);
 
844
                                }
 
845
                        }
 
846
                        
 
847
                        XmlElement oldVars = (XmlElement) elem.SelectSingleNode ("Variables");
 
848
                        if (variables == null || variables.Count == 0) {
 
849
                                if (oldVars != null)
 
850
                                        elem.RemoveChild (oldVars);
 
851
                        } else {
 
852
                                if (oldVars == null) {
 
853
                                        oldVars = elem.OwnerDocument.CreateElement ("Variables");
 
854
                                        if (elem.FirstChild != null)
 
855
                                                elem.InsertBefore (oldVars, elem.FirstChild);
 
856
                                        else
 
857
                                                elem.AppendChild (oldVars);
 
858
                                }
 
859
                                else
 
860
                                        oldVars.RemoveAll ();
 
861
                                foreach (var prop in variables) {
 
862
                                        XmlElement propElem = elem.OwnerDocument.CreateElement (prop.Key);
 
863
                                        propElem.InnerText = prop.Value ?? string.Empty;
 
864
                                        oldVars.AppendChild (propElem);
 
865
                                }
 
866
                        }
 
867
                }
 
868
                
 
869
                void SaveCoreProperty (XmlElement elem, string val, string attr, string prop)
 
870
                {
 
871
                        if (properties != null && properties.HasProperty (prop)) {
 
872
                                elem.RemoveAttribute (attr);
 
873
                                if (!string.IsNullOrEmpty (val))
 
874
                                        properties.SetPropertyValue (prop, val);
 
875
                                else
 
876
                                        properties.RemoveProperty (prop);
 
877
                        }
 
878
                        else if (string.IsNullOrEmpty (val))
 
879
                                elem.RemoveAttribute (attr);
 
880
                        else
 
881
                                elem.SetAttribute (attr, val);
 
882
                }
 
883
                
 
884
 
 
885
                /// <summary>
 
886
                /// Load an add-in description from a file
 
887
                /// </summary>
 
888
                /// <param name='configFile'>
 
889
                /// The file.
 
890
                /// </param>
 
891
                public static AddinDescription Read (string configFile)
 
892
                {
 
893
                        AddinDescription config;
 
894
                        using (Stream s = File.OpenRead (configFile)) {
 
895
                                config = Read (s, Path.GetDirectoryName (configFile));
 
896
                        }
 
897
                        config.configFile = configFile;
 
898
                        return config;
 
899
                }
 
900
                
 
901
                /// <summary>
 
902
                /// Load an add-in description from a stream
 
903
                /// </summary>
 
904
                /// <param name='stream'>
 
905
                /// The stream
 
906
                /// </param>
 
907
                /// <param name='basePath'>
 
908
                /// The path to be used to resolve relative file paths.
 
909
                /// </param>
 
910
                public static AddinDescription Read (Stream stream, string basePath)
 
911
                {
 
912
                        return Read (new StreamReader (stream), basePath);
 
913
                }
 
914
                
 
915
                /// <summary>
 
916
                /// Load an add-in description from a text reader
 
917
                /// </summary>
 
918
                /// <param name='reader'>
 
919
                /// The text reader
 
920
                /// </param>
 
921
                /// <param name='basePath'>
 
922
                /// The path to be used to resolve relative file paths.
 
923
                /// </param>
 
924
                public static AddinDescription Read (TextReader reader, string basePath)
 
925
                {
 
926
                        AddinDescription config = new AddinDescription ();
 
927
                        
 
928
                        try {
 
929
                                config.configDoc = new XmlDocument ();
 
930
                                config.configDoc.Load (reader);
 
931
                        } catch (Exception ex) {
 
932
                                throw new InvalidOperationException ("The add-in configuration file is invalid: " + ex.Message, ex);
 
933
                        }
 
934
 
 
935
                        XmlElement elem = config.configDoc.DocumentElement;
 
936
                        if (elem.LocalName == "ExtensionModel")
 
937
                                return config;
 
938
                        
 
939
                        XmlElement varsElem = (XmlElement) elem.SelectSingleNode ("Variables");
 
940
                        if (varsElem != null) {
 
941
                                foreach (XmlNode node in varsElem.ChildNodes) {
 
942
                                        XmlElement prop = node as XmlElement;
 
943
                                        if (prop == null)
 
944
                                                continue;
 
945
                                        if (config.variables == null)
 
946
                                                config.variables = new Dictionary<string, string> ();
 
947
                                        config.variables [prop.LocalName] = prop.InnerText;
 
948
                                }
 
949
                        }
 
950
 
 
951
                        config.id = elem.GetAttribute ("id");
 
952
                        config.ns = elem.GetAttribute ("namespace");
 
953
                        config.name = elem.GetAttribute ("name");
 
954
                        config.version = elem.GetAttribute ("version");
 
955
                        config.compatVersion = elem.GetAttribute ("compatVersion");
 
956
                        config.author = elem.GetAttribute ("author");
 
957
                        config.url = elem.GetAttribute ("url");
 
958
                        config.copyright = elem.GetAttribute ("copyright");
 
959
                        config.description = elem.GetAttribute ("description");
 
960
                        config.category = elem.GetAttribute ("category");
 
961
                        config.basePath = elem.GetAttribute ("basePath");
 
962
                        config.domain = "global";
 
963
                        
 
964
                        string s = elem.GetAttribute ("isRoot");
 
965
                        if (s.Length == 0) s = elem.GetAttribute ("isroot");
 
966
                        config.isroot = GetBool (s, false);
 
967
                        
 
968
                        config.defaultEnabled = GetBool (elem.GetAttribute ("defaultEnabled"), true);
 
969
                        
 
970
                        string prot = elem.GetAttribute ("flags");
 
971
                        if (prot.Length == 0)
 
972
                                config.flags = AddinFlags.None;
 
973
                        else
 
974
                                config.flags = (AddinFlags) Enum.Parse (typeof(AddinFlags), prot);
 
975
                        
 
976
                        XmlElement localizerElem = (XmlElement) elem.SelectSingleNode ("Localizer");
 
977
                        if (localizerElem != null)
 
978
                                config.localizer = new ExtensionNodeDescription (localizerElem);
 
979
                        
 
980
                        XmlElement headerElem = (XmlElement) elem.SelectSingleNode ("Header");
 
981
                        if (headerElem != null) {
 
982
                                foreach (XmlNode node in headerElem.ChildNodes) {
 
983
                                        XmlElement prop = node as XmlElement;
 
984
                                        if (prop == null)
 
985
                                                continue;
 
986
                                                config.Properties.SetPropertyValue (prop.LocalName, prop.InnerText, prop.GetAttribute ("locale"));
 
987
                                }
 
988
                        }
 
989
                        
 
990
                        config.TransferCoreProperties (false);
 
991
                        
 
992
                        if (config.id.Length > 0)
 
993
                                config.hasUserId = true;
 
994
                        
 
995
                        return config;
 
996
                }
 
997
 
 
998
                internal string ParseString (string input)
 
999
                {
 
1000
                        if (input == null || input.Length < 4 || variables == null || variables.Count == 0)
 
1001
                                return input;
 
1002
 
 
1003
                        int i = input.IndexOf ("$(");
 
1004
                        if (i == -1)
 
1005
                                return input;
 
1006
 
 
1007
                        StringBuilder result = new StringBuilder (input.Substring (0, i), input.Length);
 
1008
 
 
1009
                        while (i < input.Length) {
 
1010
                                if (input [i] == '$') {
 
1011
                                        i++;
 
1012
                                        
 
1013
                                        if (i >= input.Length || input[i] != '(') {
 
1014
                                                result.Append ('$');
 
1015
                                                continue;
 
1016
                                        }
 
1017
                                        
 
1018
                                        i++;
 
1019
                                        int start = i;
 
1020
                                        while (i < input.Length && input [i] != ')')
 
1021
                                                i++;
 
1022
                                        
 
1023
                                        string tag = input.Substring (start, i - start);
 
1024
 
 
1025
                                        string tagValue;
 
1026
                                        if (variables.TryGetValue (tag, out tagValue))
 
1027
                                                result.Append (tagValue);
 
1028
                                        else {
 
1029
                                                result.Append ('$');
 
1030
                                                i = start - 1;
 
1031
                                        }
 
1032
                                } else {
 
1033
                                        result.Append (input [i]);
 
1034
                                }
 
1035
                                i++;
 
1036
                        }
 
1037
                        return result.ToString ();
 
1038
                }
 
1039
                
 
1040
                static bool GetBool (string s, bool defval)
 
1041
                {
 
1042
                        if (s.Length == 0)
 
1043
                                return defval;
 
1044
                        else
 
1045
                                return s == "true" || s == "yes";
 
1046
                }
 
1047
                
 
1048
                internal static AddinDescription ReadBinary (FileDatabase fdb, string configFile)
 
1049
                {
 
1050
                        AddinDescription description = (AddinDescription) fdb.ReadSharedObject (configFile, typeMap);
 
1051
                        if (description != null) {
 
1052
                                description.FileName = configFile;
 
1053
                                description.canWrite = !fdb.IgnoreDescriptionData;
 
1054
                        }
 
1055
                        return description;
 
1056
                }
 
1057
                
 
1058
                internal void SaveBinary (FileDatabase fdb, string file)
 
1059
                {
 
1060
                        configFile = file;
 
1061
                        SaveBinary (fdb);
 
1062
                }
 
1063
                
 
1064
                internal void SaveBinary (FileDatabase fdb)
 
1065
                {
 
1066
                        if (!canWrite)
 
1067
                                throw new InvalidOperationException ("Can't write incomplete description.");
 
1068
                        fdb.WriteSharedObject (AddinFile, FileName, typeMap, this);
 
1069
//                      BinaryXmlReader.DumpFile (configFile);
 
1070
                }
 
1071
                
 
1072
                /// <summary>
 
1073
                /// Verify this instance.
 
1074
                /// </summary>
 
1075
                /// <remarks>
 
1076
                /// This method checks all the definitions in the description and returns a list of errors.
 
1077
                /// If the returned list is empty, it means that the description is valid.
 
1078
                /// </remarks>
 
1079
                public StringCollection Verify ()
 
1080
                {
 
1081
                        return Verify (new AddinFileSystemExtension ());
 
1082
                }
 
1083
                
 
1084
                internal StringCollection Verify (AddinFileSystemExtension fs)
 
1085
                {
 
1086
                        StringCollection errors = new StringCollection ();
 
1087
                        
 
1088
                        if (IsRoot) {
 
1089
                                if (OptionalModules.Count > 0)
 
1090
                                        errors.Add ("Root add-in hosts can't have optional modules.");
 
1091
                        }
 
1092
                        
 
1093
                        if (AddinId.Length == 0 || Version.Length == 0) {
 
1094
                                if (ExtensionPoints.Count > 0)
 
1095
                                        errors.Add ("Add-ins which define new extension points must have an Id and Version.");
 
1096
                        }
 
1097
 
 
1098
                        MainModule.Verify ("", errors);
 
1099
                        OptionalModules.Verify ("", errors);
 
1100
                        ExtensionNodeSets.Verify ("", errors);
 
1101
                        ExtensionPoints.Verify ("", errors);
 
1102
                        ConditionTypes.Verify ("", errors);
 
1103
                        
 
1104
                        foreach (ExtensionNodeSet nset in ExtensionNodeSets) {
 
1105
                                if (nset.Id.Length == 0)
 
1106
                                        errors.Add ("Attribute 'id' can't be empty for global node sets.");
 
1107
                        }
 
1108
                        
 
1109
                        string bp = null;
 
1110
                        if (BasePath.Length > 0)
 
1111
                                bp = BasePath;
 
1112
                        else if (sourceAddinFile != null && sourceAddinFile.Length > 0)
 
1113
                                bp = Path.GetDirectoryName (AddinFile);
 
1114
                        else if (configFile != null && configFile.Length > 0)
 
1115
                                bp = Path.GetDirectoryName (configFile);
 
1116
                                
 
1117
                        if (bp != null) {
 
1118
                                foreach (string file in AllFiles) {
 
1119
                                        string asmFile = Path.Combine (bp, file);
 
1120
                                        if (!fs.FileExists (asmFile))
 
1121
                                                errors.Add ("The file '" + asmFile + "' referenced in the manifest could not be found.");
 
1122
                                }
 
1123
                        }
 
1124
                        
 
1125
                        if (localizer != null && localizer.GetAttribute ("type").Length == 0) {
 
1126
                                errors.Add ("The attribute 'type' in the Location element is required.");
 
1127
                        }
 
1128
                        
 
1129
                        // Ensure that there are no duplicated properties
 
1130
                        
 
1131
                        if (properties != null) {
 
1132
                                HashSet<string> props = new HashSet<string> ();
 
1133
                                foreach (var prop in properties) {
 
1134
                                        if (!props.Add (prop.Name + " " + prop.Locale))
 
1135
                                                errors.Add (string.Format ("Property {0} specified more than once", prop.Name + (prop.Locale != null ? " (" + prop.Locale + ")" : "")));
 
1136
                                }
 
1137
                        }
 
1138
                        
 
1139
                        return errors;
 
1140
                }
 
1141
                
 
1142
                internal void SetExtensionsAddinId (string addinId)
 
1143
                {
 
1144
                        foreach (ExtensionPoint ep in ExtensionPoints)
 
1145
                                ep.SetExtensionsAddinId (addinId);
 
1146
                                
 
1147
                        foreach (ExtensionNodeSet ns in ExtensionNodeSets)
 
1148
                                ns.SetExtensionsAddinId (addinId);
 
1149
                }
 
1150
                
 
1151
                internal void UnmergeExternalData (Hashtable addins)
 
1152
                {
 
1153
                        // Removes extension types and extension sets coming from other add-ins.
 
1154
                        foreach (ExtensionPoint ep in ExtensionPoints)
 
1155
                                ep.UnmergeExternalData (AddinId, addins);
 
1156
                                
 
1157
                        foreach (ExtensionNodeSet ns in ExtensionNodeSets)
 
1158
                                ns.UnmergeExternalData (AddinId, addins);
 
1159
                }
 
1160
                
 
1161
                internal void MergeExternalData (AddinDescription other)
 
1162
                {
 
1163
                        // Removes extension types and extension sets coming from other add-ins.
 
1164
                        foreach (ExtensionPoint ep in other.ExtensionPoints) {
 
1165
                                ExtensionPoint tep = ExtensionPoints [ep.Path];
 
1166
                                if (tep != null)
 
1167
                                        tep.MergeWith (AddinId, ep);
 
1168
                        }
 
1169
                                
 
1170
                        foreach (ExtensionNodeSet ns in other.ExtensionNodeSets) {
 
1171
                                ExtensionNodeSet tns = ExtensionNodeSets [ns.Id];
 
1172
                                if (tns != null)
 
1173
                                        tns.MergeWith (AddinId, ns);
 
1174
                        }
 
1175
                }
 
1176
                
 
1177
                internal bool IsExtensionModel {
 
1178
                        get { return RootElement.LocalName == "ExtensionModel"; }
 
1179
                }
 
1180
                
 
1181
                internal static AddinDescription Merge (AddinDescription desc1, AddinDescription desc2)
 
1182
                {
 
1183
                        if (!desc2.IsExtensionModel) {
 
1184
                                AddinDescription tmp = desc1;
 
1185
                                desc1 = desc2; desc2 = tmp;
 
1186
                        }
 
1187
                        ((AddinPropertyCollectionImpl)desc1.Properties).AddRange (desc2.Properties);
 
1188
                        desc1.ExtensionPoints.AddRange (desc2.ExtensionPoints);
 
1189
                        desc1.ExtensionNodeSets.AddRange (desc2.ExtensionNodeSets);
 
1190
                        desc1.ConditionTypes.AddRange (desc2.ConditionTypes);
 
1191
                        desc1.OptionalModules.AddRange (desc2.OptionalModules);
 
1192
                        foreach (string s in desc2.MainModule.Assemblies)
 
1193
                                desc1.MainModule.Assemblies.Add (s);
 
1194
                        foreach (string s in desc2.MainModule.DataFiles)
 
1195
                                desc1.MainModule.DataFiles.Add (s);
 
1196
                        desc1.MainModule.Dependencies.AddRange (desc2.MainModule.Dependencies);
 
1197
                        desc1.MainModule.Extensions.AddRange (desc2.MainModule.Extensions);
 
1198
                        return desc1;
 
1199
                }
 
1200
                
 
1201
                void IBinaryXmlElement.Write (BinaryXmlWriter writer)
 
1202
                {
 
1203
                        TransferCoreProperties (true);
 
1204
                        writer.WriteValue ("id", ParseString (id));
 
1205
                        writer.WriteValue ("ns", ParseString (ns));
 
1206
                        writer.WriteValue ("isroot", isroot);
 
1207
                        writer.WriteValue ("name", ParseString (name));
 
1208
                        writer.WriteValue ("version", ParseString (version));
 
1209
                        writer.WriteValue ("compatVersion", ParseString (compatVersion));
 
1210
                        writer.WriteValue ("hasUserId", hasUserId);
 
1211
                        writer.WriteValue ("author", ParseString (author));
 
1212
                        writer.WriteValue ("url", ParseString (url));
 
1213
                        writer.WriteValue ("copyright", ParseString (copyright));
 
1214
                        writer.WriteValue ("description", ParseString (description));
 
1215
                        writer.WriteValue ("category", ParseString (category));
 
1216
                        writer.WriteValue ("basePath", basePath);
 
1217
                        writer.WriteValue ("sourceAddinFile", sourceAddinFile);
 
1218
                        writer.WriteValue ("defaultEnabled", defaultEnabled);
 
1219
                        writer.WriteValue ("domain", domain);
 
1220
                        writer.WriteValue ("MainModule", MainModule);
 
1221
                        writer.WriteValue ("OptionalModules", OptionalModules);
 
1222
                        writer.WriteValue ("NodeSets", ExtensionNodeSets);
 
1223
                        writer.WriteValue ("ExtensionPoints", ExtensionPoints);
 
1224
                        writer.WriteValue ("ConditionTypes", ConditionTypes);
 
1225
                        writer.WriteValue ("FilesInfo", fileInfo);
 
1226
                        writer.WriteValue ("Localizer", localizer);
 
1227
                        writer.WriteValue ("flags", (int)flags);
 
1228
                        writer.WriteValue ("Properties", properties);
 
1229
                }
 
1230
                
 
1231
                void IBinaryXmlElement.Read (BinaryXmlReader reader)
 
1232
                {
 
1233
                        id = reader.ReadStringValue ("id");
 
1234
                        ns = reader.ReadStringValue ("ns");
 
1235
                        isroot = reader.ReadBooleanValue ("isroot");
 
1236
                        name = reader.ReadStringValue ("name");
 
1237
                        version = reader.ReadStringValue ("version");
 
1238
                        compatVersion = reader.ReadStringValue ("compatVersion");
 
1239
                        hasUserId = reader.ReadBooleanValue ("hasUserId");
 
1240
                        author = reader.ReadStringValue ("author");
 
1241
                        url = reader.ReadStringValue ("url");
 
1242
                        copyright = reader.ReadStringValue ("copyright");
 
1243
                        description = reader.ReadStringValue ("description");
 
1244
                        category = reader.ReadStringValue ("category");
 
1245
                        basePath = reader.ReadStringValue ("basePath");
 
1246
                        sourceAddinFile = reader.ReadStringValue ("sourceAddinFile");
 
1247
                        defaultEnabled = reader.ReadBooleanValue ("defaultEnabled");
 
1248
                        domain = reader.ReadStringValue ("domain");
 
1249
                        mainModule = (ModuleDescription) reader.ReadValue ("MainModule");
 
1250
                        optionalModules = (ModuleCollection) reader.ReadValue ("OptionalModules", new ModuleCollection (this));
 
1251
                        nodeSets = (ExtensionNodeSetCollection) reader.ReadValue ("NodeSets", new ExtensionNodeSetCollection (this));
 
1252
                        extensionPoints = (ExtensionPointCollection) reader.ReadValue ("ExtensionPoints", new ExtensionPointCollection (this));
 
1253
                        conditionTypes = (ConditionTypeDescriptionCollection) reader.ReadValue ("ConditionTypes", new ConditionTypeDescriptionCollection (this));
 
1254
                        fileInfo = (object[]) reader.ReadValue ("FilesInfo", null);
 
1255
                        localizer = (ExtensionNodeDescription) reader.ReadValue ("Localizer");
 
1256
                        flags = (AddinFlags) reader.ReadInt32Value ("flags");
 
1257
                        properties = (AddinPropertyCollectionImpl) reader.ReadValue ("Properties", new AddinPropertyCollectionImpl (this));
 
1258
                        
 
1259
                        if (mainModule != null)
 
1260
                                mainModule.SetParent (this);
 
1261
                }
 
1262
        }
 
1263
        
 
1264
        class AddinFileInfo: IBinaryXmlElement
 
1265
        {
 
1266
                string fileName;
 
1267
                DateTime timestamp;
 
1268
                
 
1269
                public string FileName {
 
1270
                        get {
 
1271
                                return fileName;
 
1272
                        }
 
1273
                        set {
 
1274
                                fileName = value;
 
1275
                        }
 
1276
                }
 
1277
 
 
1278
                public System.DateTime Timestamp {
 
1279
                        get {
 
1280
                                return timestamp;
 
1281
                        }
 
1282
                        set {
 
1283
                                timestamp = value;
 
1284
                        }
 
1285
                }
 
1286
                
 
1287
                public void Read (BinaryXmlReader reader)
 
1288
                {
 
1289
                        fileName = reader.ReadStringValue ("fileName");
 
1290
                        timestamp = reader.ReadDateTimeValue ("timestamp");
 
1291
                }
 
1292
 
 
1293
                public void Write (BinaryXmlWriter writer)
 
1294
                {
 
1295
                        writer.WriteValue ("fileName", fileName);
 
1296
                        writer.WriteValue ("timestamp", timestamp);
 
1297
                }
 
1298
        }
 
1299
}