diff options
author | Lluis Sanchez Gual <lluis@novell.com> | 2011-02-04 05:37:46 +0300 |
---|---|---|
committer | Lluis Sanchez Gual <lluis@novell.com> | 2011-02-04 05:37:46 +0300 |
commit | 1cae03732c53614872e29ec42e39fa7315d3538b (patch) | |
tree | 30667e711a726f9c85ee57b4003a39d85bdd57e9 /Mono.Addins.Setup | |
parent | 5341950e897ffa0d13d15b245f240cae1018bcb4 (diff) |
Added support for downloable support files, to be used for package
icons, screenshots, etc.
Diffstat (limited to 'Mono.Addins.Setup')
4 files changed, 211 insertions, 7 deletions
diff --git a/Mono.Addins.Setup/Mono.Addins.Setup/AddinRepositoryEntry.cs b/Mono.Addins.Setup/Mono.Addins.Setup/AddinRepositoryEntry.cs index da784cc..4efa747 100644 --- a/Mono.Addins.Setup/Mono.Addins.Setup/AddinRepositoryEntry.cs +++ b/Mono.Addins.Setup/Mono.Addins.Setup/AddinRepositoryEntry.cs @@ -27,6 +27,10 @@ // using System; +using System.Net; +using System.Collections.Generic; +using System.IO; +using System.Threading; namespace Mono.Addins.Setup { @@ -61,6 +65,16 @@ namespace Mono.Addins.Setup else return Mono.Addins.Addin.CompareVersions (rep.Addin.Version, Addin.Version); } + + public IAsyncResult BeginDownloadSupportFile (string name, AsyncCallback cb, object state) + { + return Repository.BeginDownloadSupportFile (name, cb, state); + } + + public Stream EndDownloadSupportFile (IAsyncResult ares) + { + return Repository.EndDownloadSupportFile (ares); + } } /// <summary> @@ -95,5 +109,9 @@ namespace Mono.Addins.Setup string RepositoryName { get; } + + IAsyncResult BeginDownloadSupportFile (string name, AsyncCallback cb, object state); + + Stream EndDownloadSupportFile (IAsyncResult ares); } } diff --git a/Mono.Addins.Setup/Mono.Addins.Setup/Repository.cs b/Mono.Addins.Setup/Mono.Addins.Setup/Repository.cs index c4de1ae..b168dbe 100644 --- a/Mono.Addins.Setup/Mono.Addins.Setup/Repository.cs +++ b/Mono.Addins.Setup/Mono.Addins.Setup/Repository.cs @@ -30,6 +30,9 @@ using System; using System.Collections; using System.Xml; using System.Xml.Serialization; +using System.IO; +using System.Net; +using System.Threading; namespace Mono.Addins.Setup { @@ -49,6 +52,8 @@ namespace Mono.Addins.Setup get { return url; } set { url = value; } } + + internal string CachedFilesDir { get; set; } [XmlElement ("Repository", Type = typeof(ReferenceRepositoryEntry))] public RepositoryEntryCollection Repositories { @@ -98,5 +103,107 @@ namespace Mono.Addins.Setup else Repositories.Remove (entry); } + + public IAsyncResult BeginDownloadSupportFile (string name, AsyncCallback cb, object state) + { + FileAsyncResult res = new FileAsyncResult (); + res.AsyncState = state; + res.Callback = cb; + + string cachedFile = Path.Combine (CachedFilesDir, Path.GetFileName (name)); + if (File.Exists (cachedFile)) { + res.FilePath = cachedFile; + res.CompletedSynchronously = true; + res.SetDone (); + return res; + } + + Uri u = new Uri (new Uri (Url), name); + if (u.Scheme == "file") { + res.FilePath = u.AbsolutePath; + res.CompletedSynchronously = true; + res.SetDone (); + return res; + } + else { + HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create (u); + res.FilePath = cachedFile; + res.Request = req; + req.BeginGetResponse (OnGotResponse, res); + } + return res; + } + + void OnGotResponse (IAsyncResult ares) + { + FileAsyncResult res = (FileAsyncResult) ares.AsyncState; + try { + WebResponse resp = res.Request.EndGetResponse (ares); + string dir = Path.GetDirectoryName (res.FilePath); + lock (this) { + if (!Directory.Exists (dir)) + Directory.CreateDirectory (dir); + } + byte[] buffer = new byte [8092]; + using (var s = resp.GetResponseStream ()) { + using (var f = File.OpenWrite (res.FilePath)) { + int nr = 0; + while ((nr = s.Read (buffer, 0, buffer.Length)) > 0) + f.Write (buffer, 0, nr); + } + } + } catch (Exception ex) { + res.Error = ex; + } + res.SetDone (); + } + + public Stream EndDownloadSupportFile (IAsyncResult ares) + { + FileAsyncResult res = ares as FileAsyncResult; + if (res == null) + throw new InvalidOperationException ("Invalid IAsyncResult instance"); + if (res.Error != null) + throw res.Error; + return File.OpenRead (res.FilePath); + } + } + + class FileAsyncResult: IAsyncResult + { + ManualResetEvent done; + + public string FilePath; + public HttpWebRequest Request; + public AsyncCallback Callback; + public Exception Error; + + public void SetDone () + { + lock (this) { + IsCompleted = true; + if (done != null) + done.Set (); + } + if (Callback != null) + Callback (this); + } + + public object AsyncState { get; set; } + + public WaitHandle AsyncWaitHandle { + get { + lock (this) { + if (done == null) + done = new ManualResetEvent (IsCompleted); + } + return done; + } + } + + public bool CompletedSynchronously { get; set; } + + public bool IsCompleted { get; set; } } + } diff --git a/Mono.Addins.Setup/Mono.Addins.Setup/RepositoryRecord.cs b/Mono.Addins.Setup/Mono.Addins.Setup/RepositoryRecord.cs index 35c12af..70ba2a9 100644 --- a/Mono.Addins.Setup/Mono.Addins.Setup/RepositoryRecord.cs +++ b/Mono.Addins.Setup/Mono.Addins.Setup/RepositoryRecord.cs @@ -60,6 +60,12 @@ namespace Mono.Addins.Setup set { file = value; } } + public string CachedFilesDir { + get { + return Path.Combine (Path.GetDirectoryName (File), Path.GetFileNameWithoutExtension (File) + "_files"); + } + } + public string Url { get { return url; } set { url = value; } @@ -81,13 +87,18 @@ namespace Mono.Addins.Setup public Repository GetCachedRepository () { - return (Repository) AddinStore.ReadObject (File, typeof(Repository)); + Repository repo = (Repository) AddinStore.ReadObject (File, typeof(Repository)); + if (repo != null) + repo.CachedFilesDir = CachedFilesDir; + return repo; } public void ClearCachedRepository () { if (System.IO.File.Exists (File)) System.IO.File.Delete (File); + if (Directory.Exists (CachedFilesDir)) + Directory.Delete (CachedFilesDir, true); } internal void UpdateCachedRepository (Repository newRep) @@ -98,6 +109,7 @@ namespace Mono.Addins.Setup AddinStore.WriteObject (File, newRep); if (name == null) name = newRep.Name; + newRep.CachedFilesDir = CachedFilesDir; } } diff --git a/Mono.Addins.Setup/Mono.Addins.Setup/SetupService.cs b/Mono.Addins.Setup/Mono.Addins.Setup/SetupService.cs index 5bfa8cc..2be981a 100644 --- a/Mono.Addins.Setup/Mono.Addins.Setup/SetupService.cs +++ b/Mono.Addins.Setup/Mono.Addins.Setup/SetupService.cs @@ -56,6 +56,7 @@ namespace Mono.Addins.Setup string installDirectory; AddinStore store; AddinSystemConfiguration config; + const string addinFilesDir = "_addin_files"; AddinRegistry registry; @@ -387,6 +388,15 @@ namespace Mono.Addins.Setup list.Add (f); } + foreach (var prop in conf.Properties) { + try { + if (File.Exists (Path.Combine (basePath, prop.Value))) + list.Add (prop.Value); + } catch { + // Ignore errors + } + } + monitor.Log ("Creating package " + Path.GetFileName (outFilePath)); foreach (string file in list) { @@ -461,32 +471,45 @@ namespace Mono.Addins.Setup string mainFile = Path.Combine (rootPath, relFilePath); string mainPath = Path.GetDirectoryName (mainFile); + string supportFileDir = Path.Combine (mainPath, addinFilesDir); Repository mainrep = (Repository) AddinStore.ReadObject (mainFile, typeof(Repository)); if (mainrep == null) { mainrep = new Repository (); } + ReferenceRepositoryEntry repEntry = (ReferenceRepositoryEntry) rootrep.FindEntry (relFilePath); + DateTime rootLastModified = repEntry != null ? repEntry.LastModified : DateTime.MinValue; + bool modified = false; monitor.Log.WriteLine ("Checking directory: " + mainPath); foreach (string file in Directory.GetFiles (mainPath, "*.mpack")) { + + DateTime date = File.GetLastWriteTime (file); + if (date > lastModified) + lastModified = date; + string fname = Path.GetFileName (file); PackageRepositoryEntry entry = (PackageRepositoryEntry) mainrep.FindEntry (fname); + if (date > rootLastModified) { + if (entry != null) { + mainrep.RemoveEntry (entry); + DeleteSupportFiles (supportFileDir, entry.Addin); + entry = null; + } + } if (entry == null) { entry = new PackageRepositoryEntry (); AddinPackage p = (AddinPackage) Package.FromFile (file); entry.Addin = (AddinInfo) p.Addin; entry.Url = fname; + ExtractSupportFiles (supportFileDir, file, entry.Addin); mainrep.AddEntry (entry); modified = true; monitor.Log.WriteLine ("Added addin: " + fname); } allAddins.Add (entry); - - DateTime date = File.GetLastWriteTime (file); - if (date > lastModified) - lastModified = date; } ArrayList toRemove = new ArrayList (); @@ -494,15 +517,16 @@ namespace Mono.Addins.Setup if (!File.Exists (Path.Combine (mainPath, entry.Url))) toRemove.Add (entry); - foreach (PackageRepositoryEntry entry in toRemove) + foreach (PackageRepositoryEntry entry in toRemove) { + DeleteSupportFiles (supportFileDir, entry.Addin); mainrep.RemoveEntry (entry); + } if (modified || toRemove.Count > 0) { AddinStore.WriteObject (mainFile, mainrep); monitor.Log.WriteLine ("Updated " + relFilePath); } - ReferenceRepositoryEntry repEntry = (ReferenceRepositoryEntry) rootrep.FindEntry (relFilePath); if (repEntry != null) { if (repEntry.LastModified < lastModified) repEntry.LastModified = lastModified; @@ -514,11 +538,54 @@ namespace Mono.Addins.Setup } foreach (string dir in Directory.GetDirectories (mainPath)) { + if (Path.GetFileName (dir) == addinFilesDir) + continue; string based = dir.Substring (rootPath.Length + 1); BuildRepository (monitor, rootrep, rootPath, Path.Combine (based, "main.mrep"), allAddins); } } + void DeleteSupportFiles (string targetDir, AddinInfo ainfo) + { + foreach (var prop in ainfo.Properties) { + if (prop.Value.StartsWith (addinFilesDir + Path.DirectorySeparatorChar)) { + string file = Path.Combine (targetDir, Path.GetFileName (prop.Value)); + if (File.Exists (file)) + File.Delete (file); + } + } + if (Directory.Exists (targetDir) && Directory.GetFileSystemEntries (targetDir).Length == 0) + Directory.Delete (targetDir, true); + } + + void ExtractSupportFiles (string targetDir, string file, AddinInfo ainfo) + { + Random r = new Random (); + ZipFile zfile = new ZipFile (file); + foreach (var prop in ainfo.Properties) { + ZipEntry ze = zfile.GetEntry (prop.Value); + if (ze != null) { + string fname; + do { + fname = Path.Combine (targetDir, r.Next().ToString ("x") + Path.GetExtension (prop.Value)); + } while (File.Exists (fname)); + + if (!Directory.Exists (targetDir)) + Directory.CreateDirectory (targetDir); + + using (var f = File.OpenWrite (fname)) { + using (Stream s = zfile.GetInputStream (ze)) { + byte[] buffer = new byte [8092]; + int nr = 0; + while ((nr = s.Read (buffer, 0, buffer.Length)) > 0) + f.Write (buffer, 0, nr); + } + } + prop.Value = Path.Combine (addinFilesDir, Path.GetFileName (fname)); + } + } + } + void GenerateIndexPage (Repository rep, ArrayList addins, string basePath) { StreamWriter sw = new StreamWriter (Path.Combine (basePath, "index.html")); |