~ubuntu-branches/ubuntu/karmic/mono-addins/karmic

« back to all changes in this revision

Viewing changes to Mono.Addins.Setup/Mono.Addins.Setup/SetupService.cs

  • Committer: Bazaar Package Importer
  • Author(s): Mirco Bauer
  • Date: 2007-07-14 12:07:48 UTC
  • Revision ID: james.westby@ubuntu.com-20070714120748-2elczfsjlrdsrpms
Tags: upstream-0.2
ImportĀ upstreamĀ versionĀ 0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// SetupService.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.Xml;
 
32
using System.IO;
 
33
using System.Collections;
 
34
using ICSharpCode.SharpZipLib.Zip;
 
35
using Mono.Addins.Description;
 
36
using Mono.Addins.Setup.ProgressMonitoring;
 
37
 
 
38
namespace Mono.Addins.Setup
 
39
{
 
40
        public class SetupService
 
41
        {
 
42
                RepositoryRegistry repositories;
 
43
                string applicationNamespace;
 
44
                string installDirectory;
 
45
                AddinStore store;
 
46
                AddinSystemConfiguration config;
 
47
                
 
48
                AddinRegistry registry;
 
49
                
 
50
                public SetupService ()
 
51
                {
 
52
                        if (AddinManager.IsInitialized)
 
53
                                registry = AddinManager.Registry;
 
54
                        else
 
55
                                registry = AddinRegistry.GetGlobalRegistry ();
 
56
                        
 
57
                        repositories = new RepositoryRegistry (this);
 
58
                        store = new AddinStore (this);
 
59
                }
 
60
                
 
61
                public SetupService (AddinRegistry registry)
 
62
                {
 
63
                        this.registry = registry;
 
64
                        repositories = new RepositoryRegistry (this);
 
65
                        store = new AddinStore (this);
 
66
                }
 
67
                
 
68
                public AddinRegistry Registry {
 
69
                        get { return registry; }
 
70
                }
 
71
                
 
72
                internal string RepositoryCachePath {
 
73
                        get { return Path.Combine (registry.RegistryPath, "repository-cache"); }
 
74
                }
 
75
                
 
76
                string RootConfigFile {
 
77
                        get { return Path.Combine (registry.RegistryPath, "addins-setup.config"); }
 
78
                }
 
79
                
 
80
                public string ApplicationNamespace {
 
81
                        get { return applicationNamespace; }
 
82
                        set { applicationNamespace = value; }
 
83
                }
 
84
                
 
85
                public string InstallDirectory {
 
86
                        get {
 
87
                                if (installDirectory != null && installDirectory.Length > 0)
 
88
                                        return installDirectory;
 
89
                                else
 
90
                                        return registry.DefaultAddinsFolder;
 
91
                        }
 
92
                        set { installDirectory = value; }
 
93
                }
 
94
                
 
95
                public RepositoryRegistry Repositories {
 
96
                        get { return repositories; }
 
97
                }
 
98
                
 
99
                internal AddinStore Store {
 
100
                        get { return store; }
 
101
                }
 
102
                
 
103
                public bool ResolveDependencies (IProgressStatus statusMonitor, AddinRepositoryEntry[] addins, out PackageCollection resolved, out PackageCollection toUninstall, out DependencyCollection unresolved)
 
104
                {
 
105
                        return store.ResolveDependencies (statusMonitor, addins, out resolved, out toUninstall, out unresolved);
 
106
                }
 
107
                
 
108
                public bool ResolveDependencies (IProgressStatus statusMonitor, PackageCollection packages, out PackageCollection toUninstall, out DependencyCollection unresolved)
 
109
                {
 
110
                        return store.ResolveDependencies (statusMonitor, packages, out toUninstall, out unresolved);
 
111
                }
 
112
                
 
113
                public bool Install (IProgressStatus statusMonitor, params string[] files)
 
114
                {
 
115
                        return store.Install (statusMonitor, files);
 
116
                }
 
117
                
 
118
                public bool Install (IProgressStatus statusMonitor, params AddinRepositoryEntry[] addins)
 
119
                {
 
120
                        return store.Install (statusMonitor, addins);
 
121
                }
 
122
                
 
123
                public bool Install (IProgressStatus statusMonitor, PackageCollection packages)
 
124
                {
 
125
                        return store.Install (statusMonitor, packages);
 
126
                }
 
127
                
 
128
                public void Uninstall (IProgressStatus statusMonitor, string id)
 
129
                {
 
130
                        store.Uninstall (statusMonitor, id);
 
131
                }
 
132
                
 
133
                public static AddinHeader GetAddinHeader (Addin addin)
 
134
                {
 
135
                        return AddinInfo.ReadFromDescription (addin.Description);
 
136
                }
 
137
                
 
138
                public Addin[] GetDependentAddins (string id, bool recursive)
 
139
                {
 
140
                        return store.GetDependentAddins (id, recursive);
 
141
                }
 
142
                
 
143
                public void BuildPackage (IProgressStatus statusMonitor, string targetDirectory, params string[] filePaths)
 
144
                {
 
145
                        foreach (string file in filePaths)
 
146
                                BuildPackageInternal (statusMonitor, targetDirectory, file);
 
147
                }
 
148
                
 
149
                void BuildPackageInternal (IProgressStatus monitor, string targetDirectory, string filePath)
 
150
                {
 
151
                        AddinDescription conf = registry.GetAddinDescription (monitor, filePath);
 
152
                        if (conf == null) {
 
153
                                monitor.ReportError ("Could not read add-in file: " + filePath, null);
 
154
                                return;
 
155
                        }
 
156
                        
 
157
                        string basePath = Path.GetDirectoryName (filePath);
 
158
                        
 
159
                        if (targetDirectory == null)
 
160
                                targetDirectory = basePath;
 
161
 
 
162
                        // Generate the file name
 
163
                        
 
164
                        string name;
 
165
                        if (conf.LocalId.Length == 0)
 
166
                                name = Path.GetFileNameWithoutExtension (filePath);
 
167
                        else
 
168
                                name = conf.LocalId;
 
169
                        name = Addin.GetFullId (conf.Namespace, name, conf.Version);
 
170
                        name = name.Replace (',','_').Replace (".__", ".");
 
171
                        
 
172
                        string outFilePath = Path.Combine (targetDirectory, name) + ".mpack";
 
173
                        
 
174
                        ZipOutputStream s = new ZipOutputStream (File.Create (outFilePath));
 
175
                        s.SetLevel(5);
 
176
                        
 
177
                        // Generate a stripped down description of the add-in in a file, since the complete
 
178
                        // description may be declared as assembly attributes
 
179
                        
 
180
                        XmlDocument doc = new XmlDocument ();
 
181
                        doc.PreserveWhitespace = false;
 
182
                        doc.LoadXml (conf.SaveToXml ().OuterXml);
 
183
                        CleanDescription (doc.DocumentElement);
 
184
                        MemoryStream ms = new MemoryStream ();
 
185
                        XmlTextWriter tw = new XmlTextWriter (ms, System.Text.Encoding.UTF8);
 
186
                        tw.Formatting = Formatting.Indented;
 
187
                        doc.WriteTo (tw);
 
188
                        tw.Flush ();
 
189
                        byte[] data = ms.ToArray ();
 
190
                        
 
191
                        ZipEntry infoEntry = new ZipEntry ("addin.info");
 
192
                        s.PutNextEntry (infoEntry);
 
193
                        s.Write (data, 0, data.Length);
 
194
                        
 
195
                        // Now add the add-in files
 
196
                        
 
197
                        ArrayList list = new ArrayList ();
 
198
                        if (!conf.AllFiles.Contains (Path.GetFileName (filePath)))
 
199
                                list.Add (Path.GetFileName (filePath));
 
200
                        foreach (string f in conf.AllFiles) {
 
201
                                list.Add (f);
 
202
                        }
 
203
                        
 
204
                        monitor.Log ("Creating package " + Path.GetFileName (outFilePath));
 
205
                        
 
206
                        foreach (string file in list) {
 
207
                                string fp = Path.Combine (basePath, file);
 
208
                                using (FileStream fs = File.OpenRead (fp)) {
 
209
                                        byte[] buffer = new byte [fs.Length];
 
210
                                        fs.Read (buffer, 0, buffer.Length);
 
211
                                        
 
212
                                        ZipEntry entry = new ZipEntry (file);
 
213
                                        s.PutNextEntry (entry);
 
214
                                        s.Write (buffer, 0, buffer.Length);
 
215
                                }
 
216
                        }
 
217
                        
 
218
                        s.Finish();
 
219
                        s.Close();                      
 
220
                }
 
221
                
 
222
                void CleanDescription (XmlElement parent)
 
223
                {
 
224
                        ArrayList todelete = new ArrayList ();
 
225
                        
 
226
                        foreach (XmlNode nod in parent.ChildNodes) {
 
227
                                XmlElement elem = nod as XmlElement;
 
228
                                if (elem == null)
 
229
                                        continue;
 
230
                                if (elem.LocalName == "Module")
 
231
                                        CleanDescription (elem);
 
232
                                else if (elem.LocalName != "Dependencies" && elem.LocalName != "Runtime")
 
233
                                        todelete.Add (elem);
 
234
                        }
 
235
                        foreach (XmlElement e in todelete)
 
236
                                parent.RemoveChild (e);
 
237
                }
 
238
                
 
239
                public void BuildRepository (IProgressStatus statusMonitor, string path)
 
240
                {
 
241
                        string mainPath = Path.Combine (path, "main.mrep");
 
242
                        ArrayList allAddins = new ArrayList ();
 
243
                        
 
244
                        Repository rootrep = (Repository) AddinStore.ReadObject (mainPath, typeof(Repository));
 
245
                        if (rootrep == null) {
 
246
                                rootrep = new Repository ();
 
247
                        }
 
248
                        
 
249
                        IProgressMonitor monitor = ProgressStatusMonitor.GetProgressMonitor (statusMonitor);
 
250
                        BuildRepository (monitor, rootrep, path, "root.mrep", allAddins);
 
251
                        AddinStore.WriteObject (mainPath, rootrep);
 
252
                        GenerateIndexPage (rootrep, allAddins, path);
 
253
                        monitor.Log.WriteLine ("Updated main.mrep");
 
254
                }
 
255
                
 
256
                void BuildRepository (IProgressMonitor monitor, Repository rootrep, string rootPath, string relFilePath, ArrayList allAddins)
 
257
                {
 
258
                        DateTime lastModified = DateTime.MinValue;
 
259
                        
 
260
                        string mainFile = Path.Combine (rootPath, relFilePath);
 
261
                        string mainPath = Path.GetDirectoryName (mainFile);
 
262
                        
 
263
                        Repository mainrep = (Repository) AddinStore.ReadObject (mainFile, typeof(Repository));
 
264
                        if (mainrep == null) {
 
265
                                mainrep = new Repository ();
 
266
                        }
 
267
                        
 
268
                        bool modified = false;
 
269
                        
 
270
                        monitor.Log.WriteLine ("Checking directory: " + mainPath);
 
271
                        foreach (string file in Directory.GetFiles (mainPath, "*.mpack")) {
 
272
                                string fname = Path.GetFileName (file);
 
273
                                PackageRepositoryEntry entry = (PackageRepositoryEntry) mainrep.FindEntry (fname);
 
274
                                if (entry == null) {
 
275
                                        entry = new PackageRepositoryEntry ();
 
276
                                        AddinPackage p = (AddinPackage) Package.FromFile (file);
 
277
                                        entry.Addin = (AddinInfo) p.Addin;
 
278
                                        entry.Url = fname;
 
279
                                        mainrep.AddEntry (entry);
 
280
                                        modified = true;
 
281
                                        monitor.Log.WriteLine ("Added addin: " + fname);
 
282
                                }
 
283
                                allAddins.Add (entry);
 
284
                                
 
285
                                DateTime date = File.GetLastWriteTime (file);
 
286
                                if (date > lastModified)
 
287
                                        lastModified = date;
 
288
                        }
 
289
                        
 
290
                        ArrayList toRemove = new ArrayList ();
 
291
                        foreach (PackageRepositoryEntry entry in mainrep.Addins)
 
292
                                if (!File.Exists (Path.Combine (mainPath, entry.Url)))
 
293
                                        toRemove.Add (entry);
 
294
                                        
 
295
                        foreach (PackageRepositoryEntry entry in toRemove)
 
296
                                mainrep.RemoveEntry (entry);
 
297
                        
 
298
                        if (modified || toRemove.Count > 0) {
 
299
                                AddinStore.WriteObject (mainFile, mainrep);
 
300
                                monitor.Log.WriteLine ("Updated " + relFilePath);
 
301
                        }
 
302
 
 
303
                        ReferenceRepositoryEntry repEntry = (ReferenceRepositoryEntry) rootrep.FindEntry (relFilePath);
 
304
                        if (repEntry != null) {
 
305
                                if (repEntry.LastModified < lastModified)
 
306
                                        repEntry.LastModified = lastModified;
 
307
                        } else {
 
308
                                repEntry = new ReferenceRepositoryEntry ();
 
309
                                repEntry.LastModified = lastModified;
 
310
                                repEntry.Url = relFilePath;
 
311
                                rootrep.AddEntry (repEntry);
 
312
                        }
 
313
                        
 
314
                        foreach (string dir in Directory.GetDirectories (mainPath)) {
 
315
                                string based = dir.Substring (rootPath.Length + 1);
 
316
                                BuildRepository (monitor, rootrep, rootPath, Path.Combine (based, "main.mrep"), allAddins);
 
317
                        }
 
318
                }
 
319
                
 
320
                void GenerateIndexPage (Repository rep, ArrayList addins, string basePath)
 
321
                {
 
322
                        StreamWriter sw = new StreamWriter (Path.Combine (basePath, "index.html"));
 
323
                        sw.WriteLine ("<html><body>");
 
324
                        sw.WriteLine ("<h1>Add-in Repository</h1>");
 
325
                        if (rep.Name != null && rep.Name != "")
 
326
                                sw.WriteLine ("<h2>" + rep.Name + "</h2>");
 
327
                        sw.WriteLine ("<p>This is a list of add-ins available in this repository.</p>");
 
328
                        sw.WriteLine ("<table border=1><thead><tr><th>Add-in</th><th>Version</th><th>Description</th></tr></thead>");
 
329
                        
 
330
                        foreach (PackageRepositoryEntry entry in addins) {
 
331
                                sw.WriteLine ("<tr><td>" + entry.Addin.Name + "</td><td>" + entry.Addin.Version + "</td><td>" + entry.Addin.Description + "</td></tr>");
 
332
                        }
 
333
                        
 
334
                        sw.WriteLine ("</table>");
 
335
                        sw.WriteLine ("</body></html>");
 
336
                        sw.Close ();
 
337
                }
 
338
                
 
339
                internal AddinSystemConfiguration Configuration {
 
340
                        get {
 
341
                                if (config == null) {
 
342
                                        config = (AddinSystemConfiguration) AddinStore.ReadObject (RootConfigFile, typeof(AddinSystemConfiguration));
 
343
                                        if (config == null)
 
344
                                                config = new AddinSystemConfiguration ();
 
345
                                }
 
346
                                return config;
 
347
                        }
 
348
                }
 
349
                
 
350
                internal void SaveConfiguration ()
 
351
                {
 
352
                        if (config != null) {
 
353
                                AddinStore.WriteObject (RootConfigFile, config); 
 
354
                        }
 
355
                }
 
356
 
 
357
                internal void ResetConfiguration ()
 
358
                {
 
359
                        if (File.Exists (RootConfigFile))
 
360
                                File.Delete (RootConfigFile);
 
361
                        ResetAddinInfo ();
 
362
                }
 
363
                                
 
364
                internal void ResetAddinInfo ()
 
365
                {
 
366
                        if (Directory.Exists (RepositoryCachePath))
 
367
                                Directory.Delete (RepositoryCachePath, true);
 
368
                }
 
369
        }
 
370
}