00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 using System;
00013 using System.Collections.Generic;
00014 using System.IO;
00015 using System.Net;
00016 using System.Xml;
00017 using ICSharpCode.SharpZipLib.Zip;
00018 using Mcs.Epm.MicrosoftProject.mpFx.Client.Shared.Properties;
00019
00020 namespace Mcs.Epm.MicrosoftProject.mpFx.Client.Shared
00021 {
00022 public class PluginGallery : IDisposable
00023 {
00024 bool _Disposed;
00025 private string _GalleryCatalogPath;
00026 private readonly PluginHost _Parent;
00027 private string _Location;
00028
00029 public Dictionary<Guid, PluginDescriptor> Plugins { get; private set; }
00030
00031 public string Location
00032 {
00033 get
00034 {
00035 if (string.IsNullOrEmpty(_Location))
00036 {
00037 return string.Empty;
00038 }
00039
00040 if (!_Location.EndsWith("/"))
00041 {
00042 _Location = _Location + "/";
00043
00044 }
00045
00046 return _Location;
00047 }
00048 set
00049 {
00050 _Location = value;
00051 }
00052 }
00053
00054 public string UserName { get; set; }
00055
00056 public string Password { get; set; }
00057
00058 public PluginGallery(PluginHost parent)
00059 {
00060 Plugins = new Dictionary<Guid, PluginDescriptor>();
00061 _Parent = parent;
00062 }
00063
00064 public void Load()
00065 {
00066 if (!string.IsNullOrEmpty(_GalleryCatalogPath) && File.Exists(_GalleryCatalogPath))
00067 {
00068 File.Delete(_GalleryCatalogPath);
00069 }
00070
00071 Plugins.Clear();
00072
00073 _GalleryCatalogPath = Path.GetTempFileName();
00074
00075 Tools.HttpDownload(Settings.Default.PluginGalleryLocation, _GalleryCatalogPath);
00076
00077 XmlDocument galleryDocument = new XmlDocument();
00078
00079 galleryDocument.Load(_GalleryCatalogPath);
00080 XmlNode pluginsNode = galleryDocument.SelectSingleNode("/plugins");
00081
00082 foreach (XmlNode pluginNode in pluginsNode.ChildNodes)
00083 {
00084 PluginDescriptor pluginDescriptor = new PluginDescriptor();
00085
00086 pluginDescriptor.Name = pluginNode.Attributes["name"].Value;
00087 pluginDescriptor.Description = pluginNode.Attributes["description"].Value;
00088 pluginDescriptor.Author = pluginNode.Attributes["author"].Value;
00089 pluginDescriptor.Version = new Version(pluginNode.Attributes["version"].Value);
00090 pluginDescriptor.Preview = pluginNode.Attributes["preview"].Value;
00091 pluginDescriptor.Tag = pluginNode.Attributes["tag"].Value;
00092 pluginDescriptor.Guid = new Guid(pluginNode.Attributes["guid"].Value);
00093 pluginDescriptor.Zip = pluginNode.Attributes["zip"].Value;
00094
00095 if (!Plugins.ContainsKey(pluginDescriptor.Guid))
00096 {
00097 Plugins.Add(pluginDescriptor.Guid, pluginDescriptor);
00098 }
00099
00100 }
00101 }
00102
00103 #region IDisposable members
00104
00105 ~PluginGallery()
00106 {
00107 Dispose(false);
00108 }
00109
00110 public void Dispose()
00111 {
00112 Dispose(true);
00113 GC.SuppressFinalize(this);
00114 }
00115
00116 private void Dispose(bool disposing)
00117 {
00118 if (!_Disposed)
00119 {
00120 if (disposing)
00121 {
00122 try
00123 {
00124 if (!string.IsNullOrEmpty(_GalleryCatalogPath) && File.Exists(_GalleryCatalogPath))
00125 {
00126 File.Delete(_GalleryCatalogPath);
00127 }
00128 }
00129 catch (Exception)
00130 {}
00131 }
00132
00133 _Disposed = true;
00134 }
00135 }
00136
00137 #endregion
00138
00139 public void AddPlugin(PluginDescriptor descriptor, List<string> files, bool update)
00140 {
00141 string tempLocalFile = string.Empty;
00142 string tempDirectory = string.Empty;
00143 string zipPath = string.Empty;
00144 string catalogFileXml = string.Empty;
00145
00146 try
00147 {
00148 string ftpLocation = Location.Replace("http://", "ftp://");
00149 ftpLocation = ftpLocation.Replace("www.", "ftp.");
00150
00151 string pluginSubDirectory = descriptor.Name.Replace(" ", "");
00152 string pluginLocation = ftpLocation + pluginSubDirectory;
00153
00154 _Parent.DoOnStatusChanged(new OnStatusChangedArgs(string.Format("Connecting to {0}", pluginLocation)));
00155
00156 if (Tools.FtpDirectoryExists(pluginLocation, UserName, Password))
00157 {
00158 _Parent.DoOnStatusChanged(new OnStatusChangedArgs(string.Format("Removing {0}", pluginLocation)));
00159 Tools.FtpRemoveDirectory(pluginLocation, UserName, Password);
00160 }
00161
00162 try
00163 {
00164 zipPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), descriptor.Name.Replace(" ", "") + ".zip");
00165
00166 _Parent.DoOnStatusChanged(new OnStatusChangedArgs("Zipping files."));
00167
00168 tempDirectory = Tools.CreateTempDirectory();
00169
00170 foreach (string file in files)
00171 {
00172 File.Copy(file, Path.Combine(tempDirectory, Path.GetFileName(file)));
00173 }
00174
00175 Tools.ZipFiles(tempDirectory, zipPath);
00176
00177 string fullPath = pluginLocation;
00178
00179 Tools.FtpCreateDirectory(pluginLocation, UserName, Password);
00180
00181 if (!fullPath.EndsWith("/"))
00182 {
00183 fullPath = fullPath + '/';
00184 }
00185
00186 string targetFile = fullPath + Path.GetFileName(zipPath);
00187
00188 _Parent.DoOnStatusChanged(new OnStatusChangedArgs(string.Format("Uploading {0}", Path.GetFileName(zipPath))));
00189
00190 Tools.FtpUploadFile(targetFile, zipPath, UserName, Password);
00191
00192 string catalogFile = CreateCatalog(descriptor, update);
00193
00194 catalogFileXml = Path.ChangeExtension(catalogFile, "xml");
00195
00196 catalogFileXml = catalogFileXml.Replace(Path.GetFileNameWithoutExtension(catalogFileXml), "catalog");
00197
00198 Tools.DeleteFile(catalogFileXml);
00199
00200 File.Move(catalogFile, catalogFileXml);
00201
00202 string targetCatalogPath = ftpLocation + "catalog.xml";
00203
00204 _Parent.DoOnStatusChanged(new OnStatusChangedArgs(string.Format("Uploading {0}", Path.GetFileName(catalogFileXml))));
00205
00206 Tools.FtpUploadFile(targetCatalogPath, catalogFileXml, UserName, Password);
00207 }
00208 catch (WebException)
00209 {
00210 try
00211 {
00212 Tools.FtpRemoveDirectory(pluginLocation, UserName, Password);
00213 }
00214 catch (Exception) { }
00215
00216 throw;
00217 }
00218 }
00219 finally
00220 {
00221 Tools.DeleteFile(tempLocalFile);
00222 Tools.DeleteFile(zipPath);
00223 Tools.DeleteFile(catalogFileXml);
00224 Tools.DeleteDirectory(tempDirectory, true);
00225 _Parent.DoOnStatusChanged(new OnStatusChangedArgs(string.Empty));
00226 }
00227 }
00228
00229 private string CreateCatalog(PluginDescriptor newdescriptor, bool update)
00230 {
00231 string catalogPath = Path.GetTempFileName();
00232
00233 XmlDocument catalogDocument = new XmlDocument();
00234
00235 XmlNode rootNode = catalogDocument.CreateNode(XmlNodeType.Element,
00236 "plugins",
00237 string.Empty);
00238
00239 foreach (KeyValuePair<Guid, PluginDescriptor> pluginPair in _Parent.Gallery.Plugins)
00240 {
00241 PluginDescriptor existingPlugin = pluginPair.Value;
00242
00243 XmlNode pluginNode = CreatePluginNodeFromPluginDescriptor(catalogDocument, existingPlugin);
00244
00245 rootNode.AppendChild(pluginNode);
00246 }
00247
00248 if (!update)
00249 {
00250 XmlNode descriptorNode = CreatePluginNodeFromPluginDescriptor(catalogDocument, newdescriptor);
00251 rootNode.AppendChild(descriptorNode);
00252 }
00253
00254 catalogDocument.AppendChild(rootNode);
00255
00256 catalogDocument.Save(catalogPath);
00257
00258 return catalogPath;
00259 }
00260
00261 private static XmlNode CreatePluginNodeFromPluginDescriptor(XmlDocument catalogDocument, PluginDescriptor plugin)
00262 {
00263 XmlNode pluginNode = catalogDocument.CreateNode(XmlNodeType.Element, "plugin", string.Empty);
00264
00265 XmlAttribute guidAttribute = catalogDocument.CreateAttribute("guid");
00266 guidAttribute.Value = plugin.Guid.ToString();
00267 pluginNode.Attributes.Append(guidAttribute);
00268
00269 XmlAttribute nameAttribute = catalogDocument.CreateAttribute("name");
00270 nameAttribute.Value = plugin.Name;
00271 pluginNode.Attributes.Append(nameAttribute);
00272
00273 XmlAttribute desciptionAttribute = catalogDocument.CreateAttribute("description");
00274 desciptionAttribute.Value = plugin.Description;
00275 pluginNode.Attributes.Append(desciptionAttribute);
00276
00277 XmlAttribute authorAttribute = catalogDocument.CreateAttribute("author");
00278 authorAttribute.Value = plugin.Author;
00279 pluginNode.Attributes.Append(authorAttribute);
00280
00281 XmlAttribute versionAttribute = catalogDocument.CreateAttribute("version");
00282 versionAttribute.Value = plugin.Version.ToString();
00283 pluginNode.Attributes.Append(versionAttribute);
00284
00285 XmlAttribute previewAttribute = catalogDocument.CreateAttribute("preview");
00286 previewAttribute.Value = plugin.Preview;
00287 pluginNode.Attributes.Append(previewAttribute);
00288
00289 XmlAttribute tagAttribute = catalogDocument.CreateAttribute("tag");
00290 tagAttribute.Value = plugin.Tag;
00291 pluginNode.Attributes.Append(tagAttribute);
00292
00293 XmlAttribute zipAttribute = catalogDocument.CreateAttribute("zip");
00294 zipAttribute.Value = plugin.Name.Replace(" ", "") + ".zip";
00295 pluginNode.Attributes.Append(zipAttribute);
00296 return pluginNode;
00297 }
00298
00299 private static XmlNode CreatePluginNodeFromPlugin(XmlDocument catalogDocument, IMpFxClientPlugin plugin)
00300 {
00301 XmlNode pluginNode = catalogDocument.CreateNode(XmlNodeType.Element, "plugin", string.Empty);
00302
00303 XmlAttribute guidAttribute = catalogDocument.CreateAttribute("guid");
00304 guidAttribute.Value = plugin.Guid.ToString();
00305 pluginNode.Attributes.Append(guidAttribute);
00306
00307 XmlAttribute nameAttribute = catalogDocument.CreateAttribute("name");
00308 nameAttribute.Value = plugin.Name;
00309 pluginNode.Attributes.Append(nameAttribute);
00310
00311 XmlAttribute desciptionAttribute = catalogDocument.CreateAttribute("description");
00312 desciptionAttribute.Value = plugin.Description;
00313 pluginNode.Attributes.Append(desciptionAttribute);
00314
00315 XmlAttribute authorAttribute = catalogDocument.CreateAttribute("author");
00316 authorAttribute.Value = plugin.Author;
00317 pluginNode.Attributes.Append(authorAttribute);
00318
00319 XmlAttribute versionAttribute = catalogDocument.CreateAttribute("version");
00320 versionAttribute.Value = plugin.Version.ToString();
00321 pluginNode.Attributes.Append(versionAttribute);
00322
00323 XmlAttribute previewAttribute = catalogDocument.CreateAttribute("preview");
00324 previewAttribute.Value = plugin.Preview.ToString();
00325 pluginNode.Attributes.Append(previewAttribute);
00326
00327 XmlAttribute tagAttribute = catalogDocument.CreateAttribute("tag");
00328 tagAttribute.Value = plugin.Tag;
00329 pluginNode.Attributes.Append(tagAttribute);
00330
00331 XmlAttribute zipAttribute = catalogDocument.CreateAttribute("zip");
00332 zipAttribute.Value = string.Format("{0}.zip", plugin.Name.Replace(" ", ""));
00333 pluginNode.Attributes.Append(zipAttribute);
00334
00335 return pluginNode;
00336 }
00337
00338 public PluginDescriptor GetPluginInformation(string path)
00339 {
00340 IMpFxClientPlugin plugin = null;
00341 try
00342 {
00343 AppDomain testDomain = AppDomain.CreateDomain(Resources.AppTitle);
00344
00345 IInterfaceInspector interfaceInspector = InterfaceInspector.Get(testDomain, Resources.Inspector);
00346
00347 plugin = _Parent.LoadPlugin(interfaceInspector, path, false);
00348
00349 if (plugin != null)
00350 {
00351 PluginDescriptor plugDescriptor = new PluginDescriptor();
00352
00353 plugDescriptor.Guid = plugin.Guid;
00354 plugDescriptor.Name = plugin.Name;
00355 plugDescriptor.Version = plugin.Version;
00356 plugDescriptor.Description = plugin.Description;
00357 plugDescriptor.Author = plugin.Author;
00358 plugDescriptor.Preview = plugin.Preview.ToString();
00359 plugDescriptor.Tag = plugin.Tag;
00360
00361 return plugDescriptor;
00362 }
00363 }
00364 finally
00365 {
00366 if (plugin != null)
00367 {
00368 plugin.Dispose();
00369 }
00370 }
00371
00372 return null;
00373 }
00374
00375 public void InstallLocal(Guid guid)
00376 {
00377 string tempFile = Path.GetTempFileName();
00378 string tempDir = Path.Combine(Path.GetDirectoryName(tempFile), Path.GetFileNameWithoutExtension(tempFile));
00379 string zipPath = Settings.Default.PluginGalleryLocation;
00380
00381 try
00382 {
00383
00384 Tools.DeleteDirectory(tempDir, true);
00385 Directory.CreateDirectory(tempDir);
00386
00387 zipPath = zipPath.Replace("catalog.xml", "");
00388
00389 if (!zipPath.EndsWith("/"))
00390 {
00391 zipPath = zipPath + "/";
00392 }
00393
00394 zipPath = zipPath + Plugins[guid].Name.Replace(" ", "") + "/" + Plugins[guid].Zip;
00395
00396 _Parent.DoOnStatusChanged(new OnStatusChangedArgs(string.Format("Downloading {0}", zipPath)));
00397 Tools.HttpDownload(zipPath, tempFile);
00398
00399 FastZip fastZip = new FastZip();
00400
00401 fastZip.ExtractZip(tempFile, tempDir, string.Empty);
00402
00403 string pluginFile = string.Empty;
00404
00405 AppDomain testDomain = AppDomain.CreateDomain(Resources.AppTitle);
00406 IInterfaceInspector interfaceInspector = InterfaceInspector.Get(testDomain, Resources.Inspector);
00407
00408 string[] files = Directory.GetFiles(tempDir, "*.dll");
00409
00410 foreach (string file in files)
00411 {
00412 _Parent.DoOnStatusChanged(new OnStatusChangedArgs(string.Format("Inspecting {0}", file)));
00413
00414 IMpFxClientPlugin plugin = _Parent.LoadPlugin(interfaceInspector, file, false);
00415
00416 if (plugin != null)
00417 {
00418 pluginFile = plugin.Implementation;
00419 break;
00420 }
00421 }
00422
00423 if (string.IsNullOrEmpty(pluginFile))
00424 {
00425 throw new FileNotFoundException("Plugin not found.");
00426 }
00427
00428 _Parent.DoOnStatusChanged(new OnStatusChangedArgs(string.Format("Installing {0}", Path.GetFileName(pluginFile))));
00429
00430 pluginFile = _Parent.AddPluginToLocalGallery(Plugins[guid], pluginFile);
00431 _Parent.LoadPlugin(interfaceInspector, pluginFile, true);
00432
00433 }
00434 finally
00435 {
00436 Tools.DeleteFile(tempFile);
00437 Tools.DeleteDirectory(tempDir, true);
00438 _Parent.DoOnStatusChanged(new OnStatusChangedArgs(string.Empty));
00439 }
00440 }
00441 }
00442 }