7
// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
9
// Permission is hereby granted, free of charge, to any person obtaining
10
// a copy of this software and associated documentation files (the
11
// "Software"), to deal in the Software without restriction, including
12
// without limitation the rights to use, copy, modify, merge, publish,
13
// distribute, sublicense, and/or sell copies of the Software, and to
14
// permit persons to whom the Software is furnished to do so, subject to
15
// the following conditions:
17
// The above copyright notice and this permission notice shall be
18
// included in all copies or substantial portions of the Software.
20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33
using System.Collections;
34
using ICSharpCode.SharpZipLib.Zip;
35
using Mono.Addins.Description;
36
using Mono.Addins.Setup.ProgressMonitoring;
38
namespace Mono.Addins.Setup
40
public class SetupService
42
RepositoryRegistry repositories;
43
string applicationNamespace;
44
string installDirectory;
46
AddinSystemConfiguration config;
48
AddinRegistry registry;
50
public SetupService ()
52
if (AddinManager.IsInitialized)
53
registry = AddinManager.Registry;
55
registry = AddinRegistry.GetGlobalRegistry ();
57
repositories = new RepositoryRegistry (this);
58
store = new AddinStore (this);
61
public SetupService (AddinRegistry registry)
63
this.registry = registry;
64
repositories = new RepositoryRegistry (this);
65
store = new AddinStore (this);
68
public AddinRegistry Registry {
69
get { return registry; }
72
internal string RepositoryCachePath {
73
get { return Path.Combine (registry.RegistryPath, "repository-cache"); }
76
string RootConfigFile {
77
get { return Path.Combine (registry.RegistryPath, "addins-setup.config"); }
80
public string ApplicationNamespace {
81
get { return applicationNamespace; }
82
set { applicationNamespace = value; }
85
public string InstallDirectory {
87
if (installDirectory != null && installDirectory.Length > 0)
88
return installDirectory;
90
return registry.DefaultAddinsFolder;
92
set { installDirectory = value; }
95
public RepositoryRegistry Repositories {
96
get { return repositories; }
99
internal AddinStore Store {
100
get { return store; }
103
public bool ResolveDependencies (IProgressStatus statusMonitor, AddinRepositoryEntry[] addins, out PackageCollection resolved, out PackageCollection toUninstall, out DependencyCollection unresolved)
105
return store.ResolveDependencies (statusMonitor, addins, out resolved, out toUninstall, out unresolved);
108
public bool ResolveDependencies (IProgressStatus statusMonitor, PackageCollection packages, out PackageCollection toUninstall, out DependencyCollection unresolved)
110
return store.ResolveDependencies (statusMonitor, packages, out toUninstall, out unresolved);
113
public bool Install (IProgressStatus statusMonitor, params string[] files)
115
return store.Install (statusMonitor, files);
118
public bool Install (IProgressStatus statusMonitor, params AddinRepositoryEntry[] addins)
120
return store.Install (statusMonitor, addins);
123
public bool Install (IProgressStatus statusMonitor, PackageCollection packages)
125
return store.Install (statusMonitor, packages);
128
public void Uninstall (IProgressStatus statusMonitor, string id)
130
store.Uninstall (statusMonitor, id);
133
public static AddinHeader GetAddinHeader (Addin addin)
135
return AddinInfo.ReadFromDescription (addin.Description);
138
public Addin[] GetDependentAddins (string id, bool recursive)
140
return store.GetDependentAddins (id, recursive);
143
public void BuildPackage (IProgressStatus statusMonitor, string targetDirectory, params string[] filePaths)
145
foreach (string file in filePaths)
146
BuildPackageInternal (statusMonitor, targetDirectory, file);
149
void BuildPackageInternal (IProgressStatus monitor, string targetDirectory, string filePath)
151
AddinDescription conf = registry.GetAddinDescription (monitor, filePath);
153
monitor.ReportError ("Could not read add-in file: " + filePath, null);
157
string basePath = Path.GetDirectoryName (filePath);
159
if (targetDirectory == null)
160
targetDirectory = basePath;
162
// Generate the file name
165
if (conf.LocalId.Length == 0)
166
name = Path.GetFileNameWithoutExtension (filePath);
169
name = Addin.GetFullId (conf.Namespace, name, conf.Version);
170
name = name.Replace (',','_').Replace (".__", ".");
172
string outFilePath = Path.Combine (targetDirectory, name) + ".mpack";
174
ZipOutputStream s = new ZipOutputStream (File.Create (outFilePath));
177
// Generate a stripped down description of the add-in in a file, since the complete
178
// description may be declared as assembly attributes
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;
189
byte[] data = ms.ToArray ();
191
ZipEntry infoEntry = new ZipEntry ("addin.info");
192
s.PutNextEntry (infoEntry);
193
s.Write (data, 0, data.Length);
195
// Now add the add-in files
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) {
204
monitor.Log ("Creating package " + Path.GetFileName (outFilePath));
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);
212
ZipEntry entry = new ZipEntry (file);
213
s.PutNextEntry (entry);
214
s.Write (buffer, 0, buffer.Length);
222
void CleanDescription (XmlElement parent)
224
ArrayList todelete = new ArrayList ();
226
foreach (XmlNode nod in parent.ChildNodes) {
227
XmlElement elem = nod as XmlElement;
230
if (elem.LocalName == "Module")
231
CleanDescription (elem);
232
else if (elem.LocalName != "Dependencies" && elem.LocalName != "Runtime")
235
foreach (XmlElement e in todelete)
236
parent.RemoveChild (e);
239
public void BuildRepository (IProgressStatus statusMonitor, string path)
241
string mainPath = Path.Combine (path, "main.mrep");
242
ArrayList allAddins = new ArrayList ();
244
Repository rootrep = (Repository) AddinStore.ReadObject (mainPath, typeof(Repository));
245
if (rootrep == null) {
246
rootrep = new Repository ();
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");
256
void BuildRepository (IProgressMonitor monitor, Repository rootrep, string rootPath, string relFilePath, ArrayList allAddins)
258
DateTime lastModified = DateTime.MinValue;
260
string mainFile = Path.Combine (rootPath, relFilePath);
261
string mainPath = Path.GetDirectoryName (mainFile);
263
Repository mainrep = (Repository) AddinStore.ReadObject (mainFile, typeof(Repository));
264
if (mainrep == null) {
265
mainrep = new Repository ();
268
bool modified = false;
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);
275
entry = new PackageRepositoryEntry ();
276
AddinPackage p = (AddinPackage) Package.FromFile (file);
277
entry.Addin = (AddinInfo) p.Addin;
279
mainrep.AddEntry (entry);
281
monitor.Log.WriteLine ("Added addin: " + fname);
283
allAddins.Add (entry);
285
DateTime date = File.GetLastWriteTime (file);
286
if (date > lastModified)
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);
295
foreach (PackageRepositoryEntry entry in toRemove)
296
mainrep.RemoveEntry (entry);
298
if (modified || toRemove.Count > 0) {
299
AddinStore.WriteObject (mainFile, mainrep);
300
monitor.Log.WriteLine ("Updated " + relFilePath);
303
ReferenceRepositoryEntry repEntry = (ReferenceRepositoryEntry) rootrep.FindEntry (relFilePath);
304
if (repEntry != null) {
305
if (repEntry.LastModified < lastModified)
306
repEntry.LastModified = lastModified;
308
repEntry = new ReferenceRepositoryEntry ();
309
repEntry.LastModified = lastModified;
310
repEntry.Url = relFilePath;
311
rootrep.AddEntry (repEntry);
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);
320
void GenerateIndexPage (Repository rep, ArrayList addins, string basePath)
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>");
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>");
334
sw.WriteLine ("</table>");
335
sw.WriteLine ("</body></html>");
339
internal AddinSystemConfiguration Configuration {
341
if (config == null) {
342
config = (AddinSystemConfiguration) AddinStore.ReadObject (RootConfigFile, typeof(AddinSystemConfiguration));
344
config = new AddinSystemConfiguration ();
350
internal void SaveConfiguration ()
352
if (config != null) {
353
AddinStore.WriteObject (RootConfigFile, config);
357
internal void ResetConfiguration ()
359
if (File.Exists (RootConfigFile))
360
File.Delete (RootConfigFile);
364
internal void ResetAddinInfo ()
366
if (Directory.Exists (RepositoryCachePath))
367
Directory.Delete (RepositoryCachePath, true);