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.
30
using System.Collections;
33
using System.Xml.Serialization;
34
using System.Reflection;
35
using System.Diagnostics;
36
using System.Collections.Specialized;
39
using ICSharpCode.SharpZipLib.Zip;
41
using Mono.Addins.Description;
43
namespace Mono.Addins.Setup
45
internal class AddinPackage: Package
55
public AddinHeader Addin {
59
public override string Name {
60
get { return info.Name + " v" + info.Version; }
63
public static AddinPackage PackageFromRepository (AddinRepositoryEntry repAddin)
65
AddinPackage pack = new AddinPackage ();
66
pack.info = (AddinInfo) repAddin.Addin;
67
pack.url = new Uri (new Uri (repAddin.RepositoryUrl), repAddin.Url).ToString ();
71
public static AddinPackage PackageFromFile (string file)
73
AddinPackage pack = new AddinPackage ();
74
pack.info = ReadAddinInfo (file);
79
public static AddinPackage FromInstalledAddin (Addin sinfo)
81
AddinPackage pack = new AddinPackage ();
82
pack.info = AddinInfo.ReadFromDescription (sinfo.Description);
86
static AddinInfo ReadAddinInfo (string file)
88
ZipFile zfile = new ZipFile (file);
89
foreach (ZipEntry ze in zfile) {
90
if (ze.Name == "addin.info") {
91
using (Stream s = zfile.GetInputStream (ze)) {
92
return AddinInfo.ReadFromAddinFile (new StreamReader (s));
96
throw new InstallException ("Addin configuration file not found in package.");
99
internal override bool IsUpgradeOf (Package p)
101
AddinPackage ap = p as AddinPackage;
102
if (ap == null) return false;
103
return info.SupportsVersion (ap.info.Version);
106
public override bool Equals (object ob)
108
AddinPackage ap = ob as AddinPackage;
109
if (ap == null) return false;
110
return ap.info.Id == info.Id && ap.info.Version == info.Version;
113
public override int GetHashCode ()
115
return (info.Id + info.Version).GetHashCode ();
118
internal override void PrepareInstall (IProgressMonitor monitor, AddinStore service)
120
if (service.Registry.GetAddin (Mono.Addins.Addin.GetFullId (info.Namespace, info.Id, info.Version), true) != null)
121
throw new InstallException ("The addin " + info.Name + " v" + info.Version + " is already installed.");
124
packFile = service.DownloadFile (monitor, url);
126
tempFolder = CreateTempFolder ();
129
using (FileStream fs = new FileStream (packFile, FileMode.Open, FileAccess.Read)) {
130
ZipFile zip = new ZipFile (fs);
131
foreach (ZipEntry entry in zip) {
132
string path = Path.Combine (tempFolder, entry.Name);
133
string dir = Path.GetDirectoryName (path);
134
if (!Directory.Exists (dir))
135
Directory.CreateDirectory (dir);
137
byte[] buffer = new byte [8192];
139
Stream inStream = zip.GetInputStream (entry);
140
Stream outStream = null;
142
outStream = File.Create (path);
143
while ((n = inStream.Read (buffer, 0, buffer.Length)) > 0)
144
outStream.Write (buffer, 0, n);
147
if (outStream != null)
153
foreach (string s in Directory.GetFiles (tempFolder)) {
154
if (Path.GetFileName (s) == "addin.info") {
160
if (configFile == null)
161
throw new InstallException ("Add-in information file not found in package.");
164
internal override void CommitInstall (IProgressMonitor monitor, AddinStore service)
166
service.RegisterAddin (monitor, info, tempFolder);
170
internal override void RollbackInstall (IProgressMonitor monitor, AddinStore service)
173
iaddin = service.Registry.GetAddin (info.Id);
175
CommitUninstall (monitor, service);
179
internal override void EndInstall (IProgressMonitor monitor, AddinStore service)
181
if (url != null && packFile != null)
182
File.Delete (packFile);
183
if (tempFolder != null)
184
Directory.Delete (tempFolder, true);
187
internal override void Resolve (IProgressMonitor monitor, AddinStore service, PackageCollection toInstall, PackageCollection toUninstall, PackageCollection installedRequired, DependencyCollection unresolved)
189
Addin ia = service.Registry.GetAddin (Mono.Addins.Addin.GetIdName (info.Id));
192
Package p = AddinPackage.FromInstalledAddin (ia);
193
if (!toUninstall.Contains (p))
196
if (!info.SupportsVersion (ia.Version)) {
198
// This addin breaks the api of the currently installed one,
199
// it has to be removed, together with all dependencies
201
Addin[] ainfos = service.GetDependentAddins (info.Id, true);
202
foreach (Addin ainfo in ainfos) {
203
p = AddinPackage.FromInstalledAddin (ainfo);
204
if (!toUninstall.Contains (p))
210
foreach (Dependency dep in info.Dependencies) {
211
service.ResolveDependency (monitor, dep, this, toInstall, toUninstall, installedRequired, unresolved);
215
internal override void PrepareUninstall (IProgressMonitor monitor, AddinStore service)
217
iaddin = service.Registry.GetAddin (info.Id, true);
219
throw new InstallException (string.Format ("The add-in '{0}' is not installed.", info.Name));
221
AddinDescription conf = iaddin.Description;
222
string basePath = Path.GetDirectoryName (conf.AddinFile);
224
if (!File.Exists (iaddin.AddinFile)) {
225
monitor.ReportWarning (string.Format ("The add-in '{0}' is scheduled for uninstalling, but the add-in file could not be found.", info.Name));
229
if (!service.HasWriteAccess (iaddin.AddinFile))
230
throw new InstallException (AddinStore.GetUninstallErrorNoRoot (info));
232
foreach (string relPath in conf.AllFiles) {
233
string path = Path.Combine (basePath, relPath);
234
if (!File.Exists (path))
236
if (!service.HasWriteAccess (path))
237
throw new InstallException (AddinStore.GetUninstallErrorNoRoot (info));
240
tempFolder = CreateTempFolder ();
241
CopyAddinFiles (monitor, conf, iaddin.AddinFile, tempFolder);
244
internal override void CommitUninstall (IProgressMonitor monitor, AddinStore service)
246
if (tempFolder == null)
249
monitor.Log.WriteLine ("Uninstalling " + info.Name + " v" + info.Version);
251
AddinDescription conf = iaddin.Description;
252
string basePath = Path.GetDirectoryName (conf.AddinFile);
254
foreach (string relPath in conf.AllFiles) {
255
string path = Path.Combine (basePath, relPath);
256
if (!File.Exists (path))
261
File.Delete (iaddin.AddinFile);
263
if (Directory.GetFiles (basePath).Length == 0) {
265
Directory.Delete (basePath);
267
monitor.ReportWarning ("Directory " + basePath + " could not be deleted.");
271
monitor.Log.WriteLine ("Done");
274
internal override void RollbackUninstall (IProgressMonitor monitor, AddinStore service)
276
if (tempFolder != null) {
277
AddinDescription conf = iaddin.Description;
278
string configFile = Path.Combine (tempFolder, Path.GetFileName (iaddin.AddinFile));
280
string addinDir = Path.GetDirectoryName (iaddin.AddinFile);
281
CopyAddinFiles (monitor, conf, configFile, addinDir);
285
internal override void EndUninstall (IProgressMonitor monitor, AddinStore service)
287
if (tempFolder != null)
288
Directory.Delete (tempFolder, true);
292
void CopyAddinFiles (IProgressMonitor monitor, AddinDescription conf, string configFile, string destPath)
294
if (!Directory.Exists (destPath))
295
Directory.CreateDirectory (destPath);
297
string dfile = Path.Combine (destPath, Path.GetFileName (configFile));
298
if (File.Exists (dfile))
301
File.Copy (configFile, dfile);
303
string basePath = Path.GetDirectoryName (configFile);
305
foreach (string relPath in conf.AllFiles) {
306
string path = Path.Combine (basePath, relPath);
307
if (!File.Exists (path))
310
string destf = Path.Combine (destPath, Path.GetDirectoryName (relPath));
311
if (!Directory.Exists (destf))
312
Directory.CreateDirectory (destf);
314
dfile = Path.Combine (destPath, relPath);
315
if (File.Exists (dfile))
318
File.Copy (path, dfile);