diff options
author | Lluis Sanchez <lluis@novell.com> | 2007-08-07 23:46:04 +0400 |
---|---|---|
committer | Lluis Sanchez <lluis@novell.com> | 2007-08-07 23:46:04 +0400 |
commit | 2586e2e67943c70a586478333d151d4759062d5d (patch) | |
tree | 6e4ec77c8aeebb15137ba073358f5225f81e9ac8 | |
parent | b2667b7c3ce6884d6d333e533ccbd1e32ccea1aa (diff) |
* Mono.Addins.Database/AddinDatabase.cs,
Mono.Addins.Database/AddinHostIndex.cs,
Mono.Addins.Database/AddinScanFolderInfo.cs,
Mono.Addins.Database/AddinScanner.cs,
Mono.Addins.Database/AddinUpdateData.cs,
Mono.Addins.Database/FileDatabase.cs,
Mono.Addins.Description/AddinDescription.cs,
Mono.Addins.Description/Extension.cs,
Mono.Addins.Description/ExtensionNodeSet.cs, Mono.Addins.mdp,
Mono.Addins/Addin.cs, Mono.Addins/AddinManager.cs,
Mono.Addins/AddinRegistry.cs, Mono.Addins/AddinSessionService.cs:
Implemented support for non-shared add-in folders. Add-ins located
in such folders won't be visible from other non-shared folders.
Folders containing add-in hosts are non-shared by default, wihch
means that different installations of the same application won't
interfere each other anymore.
Add-in roots now can have depencencies on other add-in roots
lacated in the same folder.
The add-in database format has changed.
svn path=/trunk/mono-addins/; revision=83612
-rw-r--r-- | Mono.Addins/ChangeLog | 24 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins.Database/AddinDatabase.cs | 570 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins.Database/AddinHostIndex.cs | 15 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins.Database/AddinScanFolderInfo.cs | 82 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins.Database/AddinScanner.cs | 132 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins.Database/AddinUpdateData.cs | 277 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins.Database/FileDatabase.cs | 24 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins.Description/AddinDescription.cs | 41 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins.Description/Extension.cs | 2 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins.Description/ExtensionNodeSet.cs | 2 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins.mdp | 1 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins/Addin.cs | 30 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins/AddinManager.cs | 10 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins/AddinRegistry.cs | 37 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins/AddinSessionService.cs | 2 |
15 files changed, 725 insertions, 524 deletions
diff --git a/Mono.Addins/ChangeLog b/Mono.Addins/ChangeLog index 62d9251..b8927bf 100644 --- a/Mono.Addins/ChangeLog +++ b/Mono.Addins/ChangeLog @@ -1,5 +1,29 @@ 2007-08-07 Lluis Sanchez Gual <lluis@novell.com> + * Mono.Addins.Database/AddinDatabase.cs, + Mono.Addins.Database/AddinHostIndex.cs, + Mono.Addins.Database/AddinScanFolderInfo.cs, + Mono.Addins.Database/AddinScanner.cs, + Mono.Addins.Database/AddinUpdateData.cs, + Mono.Addins.Database/FileDatabase.cs, + Mono.Addins.Description/AddinDescription.cs, + Mono.Addins.Description/Extension.cs, + Mono.Addins.Description/ExtensionNodeSet.cs, Mono.Addins.mdp, + Mono.Addins/Addin.cs, Mono.Addins/AddinManager.cs, + Mono.Addins/AddinRegistry.cs, Mono.Addins/AddinSessionService.cs: + Implemented support for non-shared add-in folders. Add-ins located in + such folders won't be visible from other non-shared folders. Folders + containing add-in hosts are non-shared by default, wihch means that + different installations of the same application won't interfere each + other anymore. + + Add-in roots now can have depencencies on other add-in roots lacated in + the same folder. + + The add-in database format has changed. + +2007-08-07 Lluis Sanchez Gual <lluis@novell.com> + * Mono.Addins/RuntimeAddin.cs: Added missing null check. 2007-07-27 Lluis Sanchez Gual <lluis@novell.com> diff --git a/Mono.Addins/Mono.Addins.Database/AddinDatabase.cs b/Mono.Addins/Mono.Addins.Database/AddinDatabase.cs index f02edcb..7a41492 100644 --- a/Mono.Addins/Mono.Addins.Database/AddinDatabase.cs +++ b/Mono.Addins/Mono.Addins.Database/AddinDatabase.cs @@ -40,9 +40,13 @@ namespace Mono.Addins.Database { class AddinDatabase { + public const string GlobalDomain = "global"; + const string VersionTag = "000"; + ArrayList allSetupInfos; ArrayList addinSetupInfos; + ArrayList rootSetupInfos; internal static bool RunningSetupProcess; bool fatalDatabseError; Hashtable cachedAddinSetupInfos = new Hashtable (); @@ -52,6 +56,7 @@ namespace Mono.Addins.Database string addinDbDir; DatabaseConfiguration config = null; AddinRegistry registry; + int lastDomainId; public AddinDatabase (AddinRegistry registry) { @@ -98,27 +103,19 @@ namespace Mono.Addins.Database Directory.Delete (AddinFolderCachePath, true); } - public ExtensionNodeSet FindNodeSet (string addinId, string id) + public ExtensionNodeSet FindNodeSet (string domain, string addinId, string id) { - return FindNodeSet (addinId, id, new Hashtable ()); + return FindNodeSet (domain, addinId, id, new Hashtable ()); } - ExtensionNodeSet FindNodeSet (string addinId, string id, Hashtable visited) + ExtensionNodeSet FindNodeSet (string domain, string addinId, string id, Hashtable visited) { if (visited.Contains (addinId)) return null; visited.Add (addinId, addinId); - Addin addin = GetInstalledAddin (addinId, true, false); - if (addin == null) { - foreach (Addin root in GetAddinRoots ()) { - if (root.Id == addinId) { - addin = root; - break; - } - } - if (addin == null) - return null; - } + Addin addin = GetInstalledAddin (domain, addinId, true, false); + if (addin == null) + return null; AddinDescription desc = addin.Description; if (desc == null) return null; @@ -133,78 +130,128 @@ namespace Mono.Addins.Database if (adep == null) continue; string aid = Addin.GetFullId (desc.Namespace, adep.AddinId, adep.Version); - ExtensionNodeSet nset = FindNodeSet (aid, id, visited); + ExtensionNodeSet nset = FindNodeSet (domain, aid, id, visited); if (nset != null) return nset; } return null; } - public AddinDescription GetDescription (string id) + public ArrayList GetInstalledAddins (string domain, AddinType type) { - InternalCheck (); - IDisposable dblock = fileDatabase.LockRead (); - try { - string path = GetDescriptionPath (id); - AddinDescription desc = AddinDescription.ReadBinary (fileDatabase, path); - if (desc != null) - desc.OwnerDatabase = this; - return desc; + if (type == AddinType.All) { + if (allSetupInfos != null) + return allSetupInfos; } - catch (FileNotFoundException) { - throw new InvalidOperationException ("Add-in not found: " + id); - } finally { - dblock.Dispose (); + else if (type == AddinType.Addin) { + if (addinSetupInfos != null) + return addinSetupInfos; + } + else { + if (rootSetupInfos != null) + return rootSetupInfos; } - } - public ArrayList GetInstalledAddins () - { - if (addinSetupInfos != null) - return addinSetupInfos; + InternalCheck (domain); - InternalCheck (); using (fileDatabase.LockRead ()) { - return InternalGetInstalledAddins (); + return InternalGetInstalledAddins (domain, null, type); } } - public ArrayList GetAddinRoots () + ArrayList InternalGetInstalledAddins (string domain, AddinType type) { - ArrayList list = new ArrayList (); - foreach (string file in fileDatabase.GetDirectoryFiles (AddinCachePath, "*.mroot")) { - list.Add (new Addin (this, file)); + return InternalGetInstalledAddins (domain, null, type); + } + + ArrayList InternalGetInstalledAddins (string domain, string idFilter, AddinType type) + { + if (allSetupInfos == null) { + ArrayList alist = new ArrayList (); + + // Global add-ins are valid for any private domain + if (domain != AddinDatabase.GlobalDomain) + FindInstalledAddins (alist, AddinDatabase.GlobalDomain, idFilter); + + FindInstalledAddins (alist, domain, idFilter); + if (idFilter != null) + return alist; + allSetupInfos = alist; + } + if (type == AddinType.All) + return FilterById (allSetupInfos, idFilter); + + if (type == AddinType.Addin) { + if (addinSetupInfos == null) { + addinSetupInfos = new ArrayList (); + foreach (Addin adn in allSetupInfos) + if (!adn.Description.IsRoot) + addinSetupInfos.Add (adn); + } + return FilterById (addinSetupInfos, idFilter); + } + else { + if (rootSetupInfos == null) { + rootSetupInfos = new ArrayList (); + foreach (Addin adn in allSetupInfos) + if (!adn.Description.IsRoot) + rootSetupInfos.Add (adn); + } + return FilterById (rootSetupInfos, idFilter); } - return list; } - ArrayList InternalGetInstalledAddins () + ArrayList FilterById (ArrayList addins, string id) { - if (addinSetupInfos != null) - return addinSetupInfos; + if (id == null) + return addins; + ArrayList list = new ArrayList (); + foreach (Addin adn in addins) { + if (Addin.GetIdName (adn.Id) == id) + list.Add (adn); + } + return list; + } - addinSetupInfos = new ArrayList (); - - foreach (string file in fileDatabase.GetDirectoryFiles (AddinCachePath, "*.maddin")) { - addinSetupInfos.Add (new Addin (this, file)); + void FindInstalledAddins (ArrayList result, string domain, string idFilter) + { + if (idFilter == null) idFilter = "*"; + string dir = Path.Combine (AddinCachePath, domain); + if (Directory.Exists (dir)) { + foreach (string file in fileDatabase.GetDirectoryFiles (dir, idFilter + ".maddin")) { + string id = Path.GetFileNameWithoutExtension (file); + result.Add (GetInstalledDomainAddin (domain, id, true, false, false)); + } } - return addinSetupInfos; + } + + public Addin GetInstalledAddin (string domain, string id) + { + return GetInstalledAddin (domain, id, false, false); } - public Addin GetInstalledAddin (string id) + public Addin GetInstalledAddin (string domain, string id, bool exactVersionMatch) { - return GetInstalledAddin (id, false, false); + return GetInstalledAddin (domain, id, exactVersionMatch, false); } - public Addin GetInstalledAddin (string id, bool exactVersionMatch) + public Addin GetInstalledAddin (string domain, string id, bool exactVersionMatch, bool enabledOnly) { - return GetInstalledAddin (id, exactVersionMatch, false); + // Try the given domain, and if not found, try the shared domain + Addin ad = GetInstalledDomainAddin (domain, id, exactVersionMatch, enabledOnly, true); + if (ad != null) + return ad; + if (domain != AddinDatabase.GlobalDomain) + return GetInstalledDomainAddin (AddinDatabase.GlobalDomain, id, exactVersionMatch, enabledOnly, true); + else + return null; } - public Addin GetInstalledAddin (string id, bool exactVersionMatch, bool enabledOnly) + Addin GetInstalledDomainAddin (string domain, string id, bool exactVersionMatch, bool enabledOnly, bool dbLockCheck) { Addin sinfo = null; - object ob = cachedAddinSetupInfos [id]; + string idd = id + " " + domain; + object ob = cachedAddinSetupInfos [idd]; if (ob != null) { sinfo = ob as Addin; if (sinfo != null) { @@ -218,19 +265,20 @@ namespace Mono.Addins.Database return null; } - InternalCheck (); + if (dbLockCheck) + InternalCheck (domain); - using (fileDatabase.LockRead ()) + using (dbLockCheck ? fileDatabase.LockRead () : null) { - string path = GetDescriptionPath (id); + string path = GetDescriptionPath (domain, id); if (sinfo == null && fileDatabase.Exists (path)) { sinfo = new Addin (this, path); - cachedAddinSetupInfos [id] = sinfo; + cachedAddinSetupInfos [idd] = sinfo; if (!enabledOnly || sinfo.Enabled) return sinfo; if (exactVersionMatch) { // Cache lookups with negative result - cachedAddinSetupInfos [id] = this; + cachedAddinSetupInfos [idd] = this; return null; } } @@ -241,11 +289,9 @@ namespace Mono.Addins.Database string version, name, bestVersion = null; Addin.GetIdParts (id, out name, out version); - // FIXME: Not very efficient, will load all descriptions - foreach (Addin ia in InternalGetInstalledAddins ()) + foreach (Addin ia in InternalGetInstalledAddins (domain, name, AddinType.All)) { - if (Addin.GetIdName (ia.Id) == name && - (!enabledOnly || ia.Enabled) && + if ((!enabledOnly || ia.Enabled) && (version.Length == 0 || ia.SupportsVersion (version)) && (bestVersion == null || Addin.CompareVersions (bestVersion, ia.Version) > 0)) { @@ -254,7 +300,7 @@ namespace Mono.Addins.Database } } if (sinfo != null) { - cachedAddinSetupInfos [id] = sinfo; + cachedAddinSetupInfos [idd] = sinfo; return sinfo; } } @@ -262,82 +308,81 @@ namespace Mono.Addins.Database // Cache lookups with negative result // Ignore the 'not installed' flag when disabled add-ins are allowed if (enabledOnly) - cachedAddinSetupInfos [id] = this; + cachedAddinSetupInfos [idd] = this; return null; } } - public Addin GetInstalledAddin (string id, string version) +/* public Addin GetInstalledAddin (string domain, string id, string version) { - foreach (Addin ia in GetInstalledAddins ()) { + foreach (Addin ia in GetInstalledAddins (domain)) { if ((id == null || ia.Id == id) && (version == null || ia.Version == version)) return ia; } return null; } - +*/ public void Shutdown () { - addinSetupInfos = null; + ResetCachedData (); } - public Addin GetAddinForHostAssembly (string assemblyLocation) + public Addin GetAddinForHostAssembly (string domain, string assemblyLocation) { - InternalCheck (); + InternalCheck (domain); Addin ainfo = null; object ob = cachedAddinSetupInfos [assemblyLocation]; - if (ob != null) { - ainfo = ob as Addin; - if (ainfo != null) - return ainfo; - else - return null; - } + if (ob != null) + return ob as Addin; // Don't use a cast here is ob may not be an Addin. AddinHostIndex index = GetAddinHostIndex (); - string addin, addinFile; - if (index.GetAddinForAssembly (assemblyLocation, out addin, out addinFile)) { - ainfo = new Addin (this, addin, addinFile); + string addin, addinFile, rdomain; + if (index.GetAddinForAssembly (assemblyLocation, out addin, out addinFile, out rdomain)) { + string sid = addin + " " + rdomain; + ainfo = cachedAddinSetupInfos [sid] as Addin; + if (ainfo == null) + ainfo = new Addin (this, GetDescriptionPath (rdomain, addin)); cachedAddinSetupInfos [assemblyLocation] = ainfo; + cachedAddinSetupInfos [addin + " " + rdomain] = ainfo; } return ainfo; } - public bool IsAddinEnabled (string id) + public bool IsAddinEnabled (string domain, string id) { - Addin ainfo = GetInstalledAddin (id); + Addin ainfo = GetInstalledAddin (domain, id); if (ainfo != null) return ainfo.Enabled; else return false; } - internal bool IsAddinEnabled (string id, bool exactVersionMatch) + internal bool IsAddinEnabled (string domain, string id, bool exactVersionMatch) { if (!exactVersionMatch) - return IsAddinEnabled (id); - Addin ainfo = GetInstalledAddin (id, exactVersionMatch, false); + return IsAddinEnabled (domain, id); + Addin ainfo = GetInstalledAddin (domain, id, exactVersionMatch, false); if (ainfo == null) return false; return Configuration.IsEnabled (id, ainfo.AddinInfo.EnabledByDefault); } - public void EnableAddin (string id) + public void EnableAddin (string domain, string id) { - EnableAddin (id, true); + EnableAddin (domain, id, true); } - internal void EnableAddin (string id, bool exactVersionMatch) + internal void EnableAddin (string domain, string id, bool exactVersionMatch) { - Addin ainfo = GetInstalledAddin (id, exactVersionMatch, false); + Addin ainfo = GetInstalledAddin (domain, id, exactVersionMatch, false); if (ainfo == null) // It may be an add-in root return; - if (IsAddinEnabled (id)) + if (IsAddinEnabled (domain, id)) return; // Enable required add-ins @@ -346,7 +391,7 @@ namespace Mono.Addins.Database if (dep is AddinDependency) { AddinDependency adep = dep as AddinDependency; string adepid = Addin.GetFullId (ainfo.AddinInfo.Namespace, adep.AddinId, adep.Version); - EnableAddin (adepid, false); + EnableAddin (domain, adepid, false); } } @@ -357,13 +402,13 @@ namespace Mono.Addins.Database AddinManager.SessionService.ActivateAddin (id); } - public void DisableAddin (string id) + public void DisableAddin (string domain, string id) { - Addin ai = GetInstalledAddin (id, true); + Addin ai = GetInstalledAddin (domain, id, true); if (ai == null) throw new InvalidOperationException ("Add-in '" + id + "' not installed."); - if (!IsAddinEnabled (id)) + if (!IsAddinEnabled (domain, id)) return; Configuration.SetStatus (id, false, ai.AddinInfo.EnabledByDefault); @@ -374,7 +419,7 @@ namespace Mono.Addins.Database try { string idName = Addin.GetIdName (id); - foreach (Addin ainfo in GetInstalledAddins ()) { + foreach (Addin ainfo in GetInstalledAddins (domain, AddinType.Addin)) { foreach (Dependency dep in ainfo.AddinInfo.Dependencies) { AddinDependency adep = dep as AddinDependency; if (adep == null) @@ -388,10 +433,10 @@ namespace Mono.Addins.Database // if there is an older version available. Check it now. adepid = Addin.GetFullId (ainfo.AddinInfo.Namespace, adep.AddinId, adep.Version); - Addin adepinfo = GetInstalledAddin (adepid, false, true); + Addin adepinfo = GetInstalledAddin (domain, adepid, false, true); if (adepinfo == null) { - DisableAddin (ainfo.Id); + DisableAddin (domain, ainfo.Id); break; } } @@ -408,12 +453,12 @@ namespace Mono.Addins.Database AddinManager.SessionService.UnloadAddin (id); } - internal string GetDescriptionPath (string id) + internal string GetDescriptionPath (string domain, string id) { - return Path.Combine (AddinCachePath, id + ".maddin"); + return Path.Combine (Path.Combine (AddinCachePath, domain), id + ".maddin"); } - void InternalCheck () + void InternalCheck (string domain) { // If the database is broken, don't try to regenerate it at every check. if (fatalDatabseError) @@ -426,19 +471,19 @@ namespace Mono.Addins.Database } } if (update) - Update (null); + Update (null, domain); } void GenerateAddinExtensionMapsInternal (IProgressStatus monitor, ArrayList addinsToUpdate, ArrayList removedAddins) { - AddinUpdateData updateData = new AddinUpdateData (this); + AddinUpdateData updateData = new AddinUpdateData (this, monitor); // Clear cached data cachedAddinSetupInfos.Clear (); // Collect all information - Hashtable addinHash = new Hashtable (); + AddinIndex addinHash = new AddinIndex (); if (monitor.LogLevel > 1) monitor.Log ("Generating add-in extension maps"); @@ -448,6 +493,7 @@ namespace Mono.Addins.Database ArrayList files = new ArrayList (); bool partialGeneration = addinsToUpdate != null; + string[] domains = GetDomains (); // Get the files to be updated @@ -455,18 +501,21 @@ namespace Mono.Addins.Database changedAddins = new Hashtable (); foreach (string s in addinsToUpdate) { changedAddins [s] = s; - string mp = GetDescriptionPath (s); - if (fileDatabase.Exists (mp)) - files.Add (mp); - else - files.AddRange (fileDatabase.GetObjectSharedFiles (this.AddinCachePath, s, ".mroot")); + + // Look for the add-in in any of the existing folders + foreach (string domain in domains) { + string mp = GetDescriptionPath (domain, s); + if (fileDatabase.Exists (mp)) { + files.Add (mp); + } + } } foreach (string s in removedAddins) changedAddins [s] = s; } else { - files.AddRange (fileDatabase.GetDirectoryFiles (AddinCachePath, "*.maddin")); - files.AddRange (fileDatabase.GetDirectoryFiles (AddinCachePath, "*.mroot")); + foreach (string dom in domains) + files.AddRange (fileDatabase.GetDirectoryFiles (Path.Combine (AddinCachePath, dom), "*.maddin")); } // Load the descriptions. @@ -490,40 +539,20 @@ namespace Mono.Addins.Database conf.UnmergeExternalData (changedAddins); descriptionsToSave.Add (conf); - // Register extension points and node sets from root add-ins - if (conf.IsRoot) { - foreach (ExtensionPoint ep in conf.ExtensionPoints) - updateData.RegisterAddinRootExtensionPoint (conf, ep); - foreach (ExtensionNodeSet ns in conf.ExtensionNodeSets) - updateData.RegisterAddinRootNodeSet (conf, ns); - } - else - addinHash [conf.AddinId] = conf; + addinHash.Add (conf); } + + // Sort the add-ins, to make sure add-ins are processed before + // all their dependencies + ArrayList sorted = addinHash.GetSortedAddins (); + + // Register extension points and node sets + foreach (AddinDescription conf in sorted) + CollectExtensionPointData (conf, updateData); - foreach (AddinDescription conf in addinHash.Values) { + // Register extensions + foreach (AddinDescription conf in sorted) CollectExtensionData (conf, updateData); - } - - updateData.ResolveExtensions (monitor, addinHash); - - // Update the extension points defined by this add-in - foreach (ExtensionPoint ep in updateData.GetUnresolvedExtensionPoints ()) { - AddinDescription am = (AddinDescription) addinHash [ep.RootAddin]; - ExtensionPoint amep = am.ExtensionPoints [ep.Path]; - if (amep != null) { - amep.MergeWith (am.AddinId, ep); - amep.RootAddin = ep.RootAddin; - } - } - - // Now update the node sets - foreach (ExtensionPoint ep in updateData.GetUnresolvedExtensionSets ()) { - AddinDescription am = (AddinDescription) addinHash [ep.RootAddin]; - ExtensionNodeSet nset = am.ExtensionNodeSets [ep.Path]; - if (nset != null) - nset.MergeWith (am.AddinId, ep.NodeSet); - } // Save the maps foreach (AddinDescription conf in descriptionsToSave) @@ -542,7 +571,7 @@ namespace Mono.Addins.Database // Collects extension data in a hash table. The key is the path, the value is a list // of add-ins ids that extend that path - void CollectExtensionData (AddinDescription conf, AddinUpdateData updateData) + void CollectExtensionPointData (AddinDescription conf, AddinUpdateData updateData) { foreach (ExtensionNodeSet nset in conf.ExtensionNodeSets) { try { @@ -561,7 +590,10 @@ namespace Mono.Addins.Database throw new InvalidOperationException ("Error reading extension point: " + ep.Path, ex); } } - + } + + void CollectExtensionData (AddinDescription conf, AddinUpdateData updateData) + { foreach (ModuleDescription module in conf.AllModules) { foreach (Extension ext in module.Extensions) { updateData.RelExtensions++; @@ -586,18 +618,50 @@ namespace Mono.Addins.Database AddChildExtensions (conf, module, updateData, path + "/" + id, node.ChildNodes, node.NodeName == "Condition"); } } + + string[] GetDomains () + { + string[] dirs = fileDatabase.GetDirectories (AddinCachePath); + string[] ids = new string [dirs.Length]; + for (int n=0; n<dirs.Length; n++) + ids [n] = Path.GetFileName (dirs [n]); + return ids; + } + public string GetUniqueDomainId () + { + if (lastDomainId != 0) { + lastDomainId++; + return lastDomainId.ToString (); + } + lastDomainId = 1; + foreach (string s in fileDatabase.GetDirectories (AddinCachePath)) { + string dn = Path.GetFileName (s); + if (dn == GlobalDomain) + continue; + try { + int n = int.Parse (dn); + if (n >= lastDomainId) + lastDomainId = n + 1; + } catch { + } + } + return lastDomainId.ToString (); + } + internal void ResetCachedData () { + allSetupInfos = null; addinSetupInfos = null; + rootSetupInfos = null; hostIndex = null; cachedAddinSetupInfos.Clear (); } - public bool AddinDependsOn (string id1, string id2) + public bool AddinDependsOn (string domain, string id1, string id2) { - Addin addin1 = GetInstalledAddin (id1, false); + Addin addin1 = GetInstalledAddin (domain, id1, false); // We can assumbe that if the add-in is not returned here, it may be a root addin. if (addin1 == null) @@ -611,13 +675,13 @@ namespace Mono.Addins.Database string depid = Addin.GetFullId (addin1.AddinInfo.Namespace, adep.AddinId, null); if (depid == id2) return true; - else if (AddinDependsOn (depid, id2)) + else if (AddinDependsOn (domain, depid, id2)) return true; } return false; } - public void Repair (IProgressStatus monitor) + public void Repair (IProgressStatus monitor, string domain) { using (fileDatabase.LockWrite ()) { try { @@ -632,10 +696,10 @@ namespace Mono.Addins.Database monitor.ReportError ("The add-in registry could not be rebuilt. It may be due to lack of write permissions to the directory: " + AddinDbDir, ex); } } - Update (monitor); + Update (monitor, domain); } - public void Update (IProgressStatus monitor) + public void Update (IProgressStatus monitor, string domain) { if (monitor == null) monitor = new ConsoleProgressStatus (false); @@ -660,9 +724,11 @@ namespace Mono.Addins.Database // Something has changed, the add-ins need to be re-scanned, but it has // to be done in an external process - using (fileDatabase.LockRead ()) { - foreach (Addin ainfo in InternalGetInstalledAddins ()) { - installed [ainfo.Id] = ainfo.Id; + if (domain != null) { + using (fileDatabase.LockRead ()) { + foreach (Addin ainfo in InternalGetInstalledAddins (domain, AddinType.Addin)) { + installed [ainfo.Id] = ainfo.Id; + } } } @@ -675,9 +741,9 @@ namespace Mono.Addins.Database monitor.ReportError ("The add-in database could not be updated. It may be due to file corruption. Try running the setup repair utility", null); // Update the currently loaded add-ins - if (changesFound && AddinManager.IsInitialized && AddinManager.Registry.RegistryPath == registry.RegistryPath) { + if (changesFound && domain != null && AddinManager.IsInitialized && AddinManager.Registry.RegistryPath == registry.RegistryPath) { Hashtable newInstalled = new Hashtable (); - foreach (Addin ainfo in GetInstalledAddins ()) { + foreach (Addin ainfo in GetInstalledAddins (domain, AddinType.Addin)) { newInstalled [ainfo.Id] = ainfo.Id; } @@ -894,9 +960,9 @@ namespace Mono.Addins.Database foreach (string dir in registry.AddinDirectories) { if (dir == registry.DefaultAddinsFolder) - scanner.ScanFolderRec (monitor, dir, scanResult); + scanner.ScanFolderRec (monitor, dir, GlobalDomain, scanResult); else - scanner.ScanFolder (monitor, dir, scanResult); + scanner.ScanFolder (monitor, dir, GlobalDomain, scanResult); if (scanResult.CheckOnly) { if (scanResult.ChangesFound || monitor.IsCanceled) return; @@ -961,12 +1027,9 @@ namespace Mono.Addins.Database AddinScanFolderInfo finfo; if (GetFolderInfoForPath (progressStatus, Path.GetDirectoryName (file), out finfo) && finfo != null) { AddinFileInfo afi = finfo.GetAddinFileInfo (file); - if (afi != null && afi.AddinId != null) { + if (afi != null && afi.IsAddin) { AddinDescription adesc; - if (afi.IsRoot) - GetHostDescription (progressStatus, afi.AddinId, file, out adesc); - else - GetAddinDescription (progressStatus, afi.AddinId, out adesc); + GetAddinDescription (progressStatus, afi.Domain, afi.AddinId, out adesc); if (adesc != null) adesc.Save (outFile); return; @@ -996,6 +1059,15 @@ namespace Mono.Addins.Database } } + public string GetFolderDomain (IProgressStatus progressStatus, string path) + { + AddinScanFolderInfo folderInfo; + if (GetFolderInfoForPath (progressStatus, path, out folderInfo) && folderInfo != null && !folderInfo.SharedFolder) + return folderInfo.Domain; + else + return GlobalDomain; + } + Assembly OnResolveAddinAssembly (object s, ResolveEventArgs args) { string file = currentScanResult.GetAssemblyLocation (args.Name); @@ -1019,23 +1091,13 @@ namespace Mono.Addins.Database return Path.Combine (AddinFolderCachePath, s + ".data"); } - internal void UninstallAddin (IProgressStatus monitor, string addinId, AddinScanResult scanResult) + internal void UninstallAddin (IProgressStatus monitor, string domain, string addinId, AddinScanResult scanResult) { scanResult.AddRemovedAddin (addinId); - string file = GetDescriptionPath (addinId); - DeleteAddin (monitor, file, scanResult); - } - - internal void UninstallRootAddin (IProgressStatus monitor, string addinId, string addinFile, AddinScanResult scanResult) - { - string file = fileDatabase.GetSharedObjectFile (AddinCachePath, addinId, ".mroot", addinFile); - DeleteAddin (monitor, file, scanResult); - } - - void DeleteAddin (IProgressStatus monitor, string file, AddinScanResult scanResult) - { - if (!fileDatabase.Exists (file)) + string file = GetDescriptionPath (domain, addinId); + if (!fileDatabase.Exists (file)) { return; + } // Add-in already existed. The dependencies of the old add-in need to be re-analized @@ -1049,29 +1111,15 @@ namespace Mono.Addins.Database scanResult.RegenerateRelationData = true; SafeDelete (monitor, file); + string dir = Path.GetDirectoryName (file); + if (fileDatabase.DirectoryIsEmpty (dir)) + SafeDeleteDir (monitor, dir); SafeDeleteDir (monitor, Path.Combine (AddinPrivateDataPath, Path.GetFileNameWithoutExtension (file))); } - public bool GetHostDescription (IProgressStatus monitor, string addinId, string fileName, out AddinDescription description) - { - try { - description = AddinDescription.ReadHostBinary (fileDatabase, AddinCachePath, addinId, fileName); - if (description != null) - description.OwnerDatabase = this; - return true; - } - catch (Exception ex) { - if (monitor == null) - throw; - description = null; - monitor.ReportError ("Could not read folder info file", ex); - return false; - } - } - - public bool GetAddinDescription (IProgressStatus monitor, string addinId, out AddinDescription description) + public bool GetAddinDescription (IProgressStatus monitor, string domain, string addinId, out AddinDescription description) { - string file = GetDescriptionPath (addinId); + string file = GetDescriptionPath (domain, addinId); return ReadAddinDescription (monitor, file, out description); } @@ -1097,10 +1145,13 @@ namespace Mono.Addins.Database try { if (replaceFileName != null) desc.SaveBinary (fileDatabase, replaceFileName); - else if (desc.IsRoot) - desc.SaveHostBinary (fileDatabase, AddinCachePath); - else - desc.SaveBinary (fileDatabase, GetDescriptionPath (desc.AddinId)); + else { + string file = GetDescriptionPath (desc.Domain, desc.AddinId); + string dir = Path.GetDirectoryName (file); + if (!fileDatabase.DirExists (dir)) + fileDatabase.CreateDir (dir); + desc.SaveBinary (fileDatabase, file); + } return true; } catch (Exception ex) { @@ -1109,14 +1160,10 @@ namespace Mono.Addins.Database } } - public bool AddinDescriptionExists (string addinId) - { - return fileDatabase.Exists (GetDescriptionPath (addinId)); - } - - public bool HostDescriptionExists (string addinId, string sourceFile) + public bool AddinDescriptionExists (string domain, string addinId) { - return fileDatabase.SharedObjectExists (AddinCachePath, addinId, ".mroot", sourceFile); + string file = GetDescriptionPath (domain, addinId); + return fileDatabase.Exists (file); } public bool ReadFolderInfo (IProgressStatus monitor, string file, out AddinScanFolderInfo folderInfo) @@ -1140,7 +1187,8 @@ namespace Mono.Addins.Database } catch (Exception ex) { folderInfo = null; - monitor.ReportError ("Could not read folder info file", ex); + if (monitor != null) + monitor.ReportError ("Could not read folder info file", ex); return false; } } @@ -1227,7 +1275,7 @@ namespace Mono.Addins.Database return name; int n = 1; - while (fileDatabase.Exists (GetDescriptionPath (id))) { + while (AddinIdExists (id)) { name = baseId + "_" + n; id = Addin.GetFullId (ns, name, version); n++; @@ -1235,6 +1283,15 @@ namespace Mono.Addins.Database return name; } + bool AddinIdExists (string id) + { + foreach (string d in fileDatabase.GetDirectories (AddinCachePath)) { + if (fileDatabase.Exists (Path.Combine (d, id + ".addin"))) + return true; + } + return false; + } + public void ResetConfiguration () { if (File.Exists (ConfigFile)) @@ -1286,7 +1343,7 @@ namespace Mono.Addins.Database scanResult.LocateAssembliesOnly = true; foreach (string dir in registry.AddinDirectories) - scanner.ScanFolder (progressStatus, dir, scanResult); + scanner.ScanFolder (progressStatus, dir, AddinDatabase.GlobalDomain, scanResult); } string afile = scanResult.GetAssemblyLocation (args.Name); @@ -1296,6 +1353,101 @@ namespace Mono.Addins.Database return null; } } + + class AddinIndex + { + Hashtable addins = new Hashtable (); + + public void Add (AddinDescription desc) + { + string id = Addin.GetFullId (desc.Namespace, desc.LocalId, null); + ArrayList list = (ArrayList) addins [id]; + if (list == null) { + list = new ArrayList (); + addins [id] = list; + } + list.Add (desc); + } + + ArrayList FindDescriptions (string domain, string fullid) + { + // Returns all registered add-ins which are compatible with the provided + // fullid. Compatible means that the id is the same and the version is within + // the range of compatible versions of the add-in. + + ArrayList res = new ArrayList (); + string id = Addin.GetIdName (fullid); + ArrayList list = (ArrayList) addins [id]; + if (list == null) + return res; + string version = Addin.GetIdVersion (fullid); + foreach (AddinDescription desc in list) { + if ((desc.Domain == domain || domain == AddinDatabase.GlobalDomain) && desc.SupportsVersion (version)) + res.Add (desc); + } + return res; + } + + public ArrayList GetSortedAddins () + { + Hashtable inserted = new Hashtable (); + Hashtable lists = new Hashtable (); + + foreach (ArrayList dlist in addins.Values) { + foreach (AddinDescription desc in dlist) + InsertSortedAddin (inserted, lists, desc); + } + + // Merge all domain lists into a single list. + // Make sure the global domain is inserted the last + + ArrayList global = (ArrayList) lists [AddinDatabase.GlobalDomain]; + lists.Remove (AddinDatabase.GlobalDomain); + + ArrayList list = new ArrayList (); + foreach (ArrayList dl in lists.Values) { + list.AddRange (dl); + } + if (global != null) + list.AddRange (global); + return list; + } + + void InsertSortedAddin (Hashtable inserted, Hashtable lists, AddinDescription desc) + { + string sid = desc.AddinId + " " + desc.Domain; + if (inserted.ContainsKey (sid)) + return; + inserted [sid] = desc; + foreach (ModuleDescription mod in desc.AllModules) { + foreach (Dependency dep in mod.Dependencies) { + AddinDependency adep = dep as AddinDependency; + if (adep == null) + continue; + ArrayList descs = FindDescriptions (desc.Domain, adep.FullAddinId); + if (descs.Count > 0) { + foreach (AddinDescription sd in descs) + InsertSortedAddin (inserted, lists, sd); + } else + Console.WriteLine ("NOT FOUND: " + adep.FullAddinId + " " + desc.Domain); + } + } + ArrayList list = (ArrayList) lists [desc.Domain]; + if (list == null) { + list = new ArrayList (); + lists [desc.Domain] = list; + } + + list.Add (desc); + } + } + + enum AddinType + { + Addin, + Root, + All + } } diff --git a/Mono.Addins/Mono.Addins.Database/AddinHostIndex.cs b/Mono.Addins/Mono.Addins.Database/AddinHostIndex.cs index 1fea8de..d7b5174 100644 --- a/Mono.Addins/Mono.Addins.Database/AddinHostIndex.cs +++ b/Mono.Addins/Mono.Addins.Database/AddinHostIndex.cs @@ -39,35 +39,38 @@ namespace Mono.Addins.Database Hashtable index = new Hashtable (); - public void RegisterAssembly (string assemblyLocation, string addinId, string addinLocation) + public void RegisterAssembly (string assemblyLocation, string addinId, string addinLocation, string domain) { assemblyLocation = NormalizeFileName (assemblyLocation); - index [Util.GetFullPath (assemblyLocation)] = addinId + " " + addinLocation; + index [Util.GetFullPath (assemblyLocation)] = addinId + " " + addinLocation + " " + domain; } - public bool GetAddinForAssembly (string assemblyLocation, out string addinId, out string addinLocation) + public bool GetAddinForAssembly (string assemblyLocation, out string addinId, out string addinLocation, out string domain) { assemblyLocation = NormalizeFileName (assemblyLocation); string s = index [Util.GetFullPath (assemblyLocation)] as string; if (s == null) { addinId = null; addinLocation = null; + domain = null; return false; } else { int i = s.IndexOf (' '); + int j = s.LastIndexOf (' '); addinId = s.Substring (0, i); - addinLocation = s.Substring (i+1); + addinLocation = s.Substring (i+1, j-i-1); + domain = s.Substring (j+1); return true; } } public void RemoveHostData (string addinId, string addinLocation) { - string loc = addinId + " " + Util.GetFullPath (addinLocation); + string loc = addinId + " " + Util.GetFullPath (addinLocation) + " "; ArrayList todelete = new ArrayList (); foreach (DictionaryEntry e in index) { - if (((string)e.Value) == loc) + if (((string)e.Value).StartsWith (loc)) todelete.Add (e.Key); } foreach (string s in todelete) diff --git a/Mono.Addins/Mono.Addins.Database/AddinScanFolderInfo.cs b/Mono.Addins/Mono.Addins.Database/AddinScanFolderInfo.cs index e6f4af5..cac7d66 100644 --- a/Mono.Addins/Mono.Addins.Database/AddinScanFolderInfo.cs +++ b/Mono.Addins/Mono.Addins.Database/AddinScanFolderInfo.cs @@ -39,6 +39,8 @@ namespace Mono.Addins.Database Hashtable files = new Hashtable (); string folder; string fileName; + string domain; + bool sharedFolder = true; static BinaryXmlTypeMap typeMap = new BinaryXmlTypeMap ( typeof(AddinScanFolderInfo), @@ -69,13 +71,13 @@ namespace Mono.Addins.Database public static AddinScanFolderInfo Read (FileDatabase filedb, string basePath, string folderPath) { string fileName; - AddinScanFolderInfo finfo = (AddinScanFolderInfo) filedb.ReadSharedObject (basePath, GetFolderId (folderPath), ".data", Util.GetFullPath (folderPath), typeMap, out fileName); + AddinScanFolderInfo finfo = (AddinScanFolderInfo) filedb.ReadSharedObject (basePath, GetDomain (folderPath), ".data", Util.GetFullPath (folderPath), typeMap, out fileName); if (finfo != null) finfo.fileName = fileName; return finfo; } - static string GetFolderId (string path) + static string GetDomain (string path) { path = Util.GetFullPath (path); string s = path.Replace (Path.DirectorySeparatorChar, '_'); @@ -89,12 +91,60 @@ namespace Mono.Addins.Database public void Write (FileDatabase filedb, string basePath) { - filedb.WriteSharedObject (basePath, GetFolderId (folder), ".data", Util.GetFullPath (folder), fileName, typeMap, this); + filedb.WriteSharedObject (basePath, GetDomain (folder), ".data", Util.GetFullPath (folder), fileName, typeMap, this); + } + + public string GetExistingLocalDomain () + { + foreach (AddinFileInfo info in files.Values) { + if (info.Domain != null && info.Domain != AddinDatabase.GlobalDomain) + return info.Domain; + } + return AddinDatabase.GlobalDomain; } public string Folder { get { return folder; } } + + public string Domain { + get { + if (sharedFolder) + return AddinDatabase.GlobalDomain; + else + return domain; + } + set { + domain = value; + sharedFolder = true; + } + } + + public string RootsDomain { + get { + return domain; + } + set { + domain = value; + } + } + + public string GetDomain (bool isRoot) + { + if (isRoot) + return RootsDomain; + else + return Domain; + } + + public bool SharedFolder { + get { + return sharedFolder; + } + set { + sharedFolder = value; + } + } public DateTime GetLastScanTime (string file) { @@ -122,6 +172,10 @@ namespace Mono.Addins.Database info.AddinId = addinId; info.IsRoot = isRoot; info.ScanError = scanError; + if (addinId != null) + info.Domain = GetDomain (isRoot); + else + info.Domain = null; } public ArrayList GetMissingAddins () @@ -131,7 +185,7 @@ namespace Mono.Addins.Database if (!Directory.Exists (folder)) { // All deleted foreach (AddinFileInfo info in files.Values) { - if (info.AddinId != null && info.AddinId.Length > 0) + if (info.IsAddin) missing.Add (info); } files.Clear (); @@ -140,10 +194,13 @@ namespace Mono.Addins.Database ArrayList toDelete = new ArrayList (); foreach (AddinFileInfo info in files.Values) { if (!File.Exists (info.File)) { - if (info.AddinId != null && info.AddinId.Length > 0) + if (info.IsAddin) missing.Add (info); toDelete.Add (info.File); } + else if (info.IsAddin && info.Domain != GetDomain (info.IsRoot)) { + missing.Add (info); + } } foreach (string file in toDelete) files.Remove (file); @@ -153,14 +210,22 @@ namespace Mono.Addins.Database void IBinaryXmlElement.Write (BinaryXmlWriter writer) { + if (files.Count == 0) { + domain = null; + sharedFolder = true; + } writer.WriteValue ("folder", folder); writer.WriteValue ("files", files); + writer.WriteValue ("domain", domain); + writer.WriteValue ("sharedFolder", sharedFolder); } void IBinaryXmlElement.Read (BinaryXmlReader reader) { folder = reader.ReadStringValue ("folder"); reader.ReadValue ("files", files); + domain = reader.ReadStringValue ("domain"); + sharedFolder = reader.ReadBooleanValue ("sharedFolder"); } } @@ -172,6 +237,11 @@ namespace Mono.Addins.Database public string AddinId; public bool IsRoot; public bool ScanError; + public string Domain; + + public bool IsAddin { + get { return AddinId != null && AddinId.Length != 0; } + } void IBinaryXmlElement.Write (BinaryXmlWriter writer) { @@ -180,6 +250,7 @@ namespace Mono.Addins.Database writer.WriteValue ("AddinId", AddinId); writer.WriteValue ("IsRoot", IsRoot); writer.WriteValue ("ScanError", ScanError); + writer.WriteValue ("Domain", Domain); } void IBinaryXmlElement.Read (BinaryXmlReader reader) @@ -189,6 +260,7 @@ namespace Mono.Addins.Database AddinId = reader.ReadStringValue ("AddinId"); IsRoot = reader.ReadBooleanValue ("IsRoot"); ScanError = reader.ReadBooleanValue ("ScanError"); + Domain = reader.ReadStringValue ("Domain"); } } } diff --git a/Mono.Addins/Mono.Addins.Database/AddinScanner.cs b/Mono.Addins/Mono.Addins.Database/AddinScanner.cs index 9614155..42fe59d 100644 --- a/Mono.Addins/Mono.Addins.Database/AddinScanner.cs +++ b/Mono.Addins/Mono.Addins.Database/AddinScanner.cs @@ -49,7 +49,7 @@ namespace Mono.Addins.Database this.database = database; } - public void ScanFolder (IProgressStatus monitor, string path, AddinScanResult scanResult) + public void ScanFolder (IProgressStatus monitor, string path, string domain, AddinScanResult scanResult) { path = Util.GetFullPath (path); @@ -71,9 +71,32 @@ namespace Mono.Addins.Database return; } + // if domain is null it means that a new domain has to be created. + + bool sharedFolder = domain == AddinDatabase.GlobalDomain; + if (folderInfo == null) folderInfo = new AddinScanFolderInfo (path); + if (!sharedFolder && (folderInfo.SharedFolder || folderInfo.Domain != domain)) { + // If the folder already has a domain, reuse it + if (domain == null && folderInfo.RootsDomain != null && folderInfo.RootsDomain != AddinDatabase.GlobalDomain) + domain = folderInfo.RootsDomain; + else if (domain == null) { + folderInfo.Domain = domain = database.GetUniqueDomainId (); + scanResult.RegenerateRelationData = true; + } + else { + folderInfo.Domain = domain; + scanResult.RegenerateRelationData = true; + } + } + else if (!folderInfo.SharedFolder && sharedFolder) { + scanResult.RegenerateRelationData = true; + } + + folderInfo.SharedFolder = sharedFolder; + if (Directory.Exists (path)) { string[] files = Directory.GetFiles (path); @@ -95,7 +118,7 @@ namespace Mono.Addins.Database scanResult.AddAssemblyLocation (file); break; case ".addins": - ScanAddinsFile (monitor, file, scanResult); + ScanAddinsFile (monitor, file, domain, scanResult); break; } } @@ -128,10 +151,7 @@ namespace Mono.Addins.Database return; foreach (AddinFileInfo info in missing) { - if (info.IsRoot) - database.UninstallRootAddin (monitor, info.AddinId, info.File, scanResult); - else - database.UninstallAddin (monitor, info.AddinId, scanResult); + database.UninstallAddin (monitor, info.Domain, info.AddinId, scanResult); } } } @@ -144,7 +164,7 @@ namespace Mono.Addins.Database AddinFileInfo finfo = folderInfo.GetAddinFileInfo (file); bool added = false; - if (finfo != null && File.GetLastWriteTime (file) == finfo.LastScan && !scanResult.RegenerateAllData) { + if (finfo != null && (!finfo.IsAddin || finfo.Domain == folderInfo.GetDomain (finfo.IsRoot)) && File.GetLastWriteTime (file) == finfo.LastScan && !scanResult.RegenerateAllData) { if (finfo.ScanError) { // Always schedule the file for scan if there was an error in a previous scan. // However, don't set ChangesFound=true, in this way if there isn't any other @@ -153,15 +173,10 @@ namespace Mono.Addins.Database added = true; } - if (finfo.AddinId == null || finfo.AddinId.Length == 0) + if (!finfo.IsAddin) + return; + if (database.AddinDescriptionExists (finfo.Domain, finfo.AddinId)) return; - if (!finfo.IsRoot) { - if (database.AddinDescriptionExists (finfo.AddinId)) - return; - } else { - if (database.HostDescriptionExists (finfo.AddinId, file)) - return; - } } scanResult.ChangesFound = true; @@ -239,12 +254,7 @@ namespace Mono.Addins.Database // Also, the dependencies of the old add-in need to be re-analized AddinDescription existingDescription = null; - bool res; - - if (config.IsRoot) - res = database.GetHostDescription (monitor, config.AddinId, config.AddinFile, out existingDescription); - else - res = database.GetAddinDescription (monitor, config.AddinId, out existingDescription); + bool res = database.GetAddinDescription (monitor, folderInfo.Domain, config.AddinId, out existingDescription); // If we can't get information about the old assembly, just regenerate all relation data if (!res) @@ -261,11 +271,8 @@ namespace Mono.Addins.Database // If the scanned file results in an add-in version different from the one obtained from // previous scans, the old add-in needs to be uninstalled. - if (fi != null && fi.AddinId != null && fi.AddinId != config.AddinId) { - if (fi.IsRoot) - database.UninstallRootAddin (monitor, fi.AddinId, file, scanResult); - else - database.UninstallAddin (monitor, fi.AddinId, scanResult); + if (fi != null && fi.IsAddin && fi.AddinId != config.AddinId) { + database.UninstallAddin (monitor, folderInfo.Domain, fi.AddinId, scanResult); // If the add-in version has changed, regenerate everything again since old data can't be reused if (Addin.GetIdName (fi.AddinId) == Addin.GetIdName (config.AddinId)) @@ -274,6 +281,23 @@ namespace Mono.Addins.Database // If a description could be generated, save it now (if the scan was successful) if (scanSuccessful) { + + // Assign the domain + if (config.IsRoot) { + if (folderInfo.RootsDomain == null) + folderInfo.RootsDomain = database.GetUniqueDomainId (); + config.Domain = folderInfo.RootsDomain; + } else + config.Domain = folderInfo.Domain; + + if (config.IsRoot && scanResult.HostIndex != null) { + // If the add-in is a root, register its assemblies + foreach (string f in config.MainModule.Assemblies) { + string asmFile = Path.Combine (config.BasePath, f); + scanResult.HostIndex.RegisterAssembly (asmFile, config.AddinId, config.AddinFile, config.Domain); + } + } + if (database.SaveDescription (monitor, config, replaceFileName)) { // The new dependencies also have to be updated Util.AddDependencies (config, scanResult); @@ -331,11 +355,11 @@ namespace Mono.Addins.Database return config; } - public void ScanAddinsFile (IProgressStatus monitor, string file, AddinScanResult scanResult) + public void ScanAddinsFile (IProgressStatus monitor, string file, string domain, AddinScanResult scanResult) { XmlTextReader r = null; - StringCollection directories = new StringCollection (); - StringCollection directoriesWithSubdirs = new StringCollection (); + ArrayList directories = new ArrayList (); + ArrayList directoriesWithSubdirs = new ArrayList (); try { r = new XmlTextReader (new StreamReader (file)); r.MoveToContent (); @@ -346,20 +370,31 @@ namespace Mono.Addins.Database while (r.NodeType != XmlNodeType.EndElement) { if (r.NodeType == XmlNodeType.Element && r.LocalName == "Directory") { string subs = r.GetAttribute ("include-subdirs"); + string sdom; + string share = r.GetAttribute ("shared"); + if (share == "true") + sdom = AddinDatabase.GlobalDomain; + else if (share == "false") + sdom = null; + else + sdom = domain; // Inherit the domain + string path = r.ReadElementString ().Trim (); if (path.Length > 0) { if (subs == "true") - directoriesWithSubdirs.Add (path); + directoriesWithSubdirs.Add (new string[] {path, sdom}); else - directories.Add (path); + directories.Add (new string[] {path, sdom}); } } else if (r.NodeType == XmlNodeType.Element && r.LocalName == "GacAssembly") { string aname = r.ReadElementString ().Trim (); if (aname.Length > 0) { aname = Util.GetGacPath (aname); - if (aname != null) - directories.Add (aname); + if (aname != null) { + // Gac assemblies always use the global domain + directories.Add (new string[] {aname, AddinDatabase.GlobalDomain}); + } } } else @@ -373,29 +408,29 @@ namespace Mono.Addins.Database if (r != null) r.Close (); } - foreach (string d in directories) { - string dir = d; + foreach (string[] d in directories) { + string dir = d[0]; if (!Path.IsPathRooted (dir)) dir = Path.Combine (Path.GetDirectoryName (file), dir); - ScanFolder (monitor, dir, scanResult); + ScanFolder (monitor, dir, d[1], scanResult); } - foreach (string d in directoriesWithSubdirs) { - string dir = d; + foreach (string[] d in directoriesWithSubdirs) { + string dir = d[0]; if (!Path.IsPathRooted (dir)) dir = Path.Combine (Path.GetDirectoryName (file), dir); - ScanFolderRec (monitor, dir, scanResult); + ScanFolderRec (monitor, dir, d[1], scanResult); } } - public void ScanFolderRec (IProgressStatus monitor, string dir, AddinScanResult scanResult) + public void ScanFolderRec (IProgressStatus monitor, string dir, string domain, AddinScanResult scanResult) { - ScanFolder (monitor, dir, scanResult); + ScanFolder (monitor, dir, domain, scanResult); if (!Directory.Exists (dir)) return; foreach (string sd in Directory.GetDirectories (dir)) - ScanFolderRec (monitor, sd, scanResult); + ScanFolderRec (monitor, sd, domain, scanResult); } bool ScanConfigAssemblies (IProgressStatus monitor, string filePath, AddinScanResult scanResult, out AddinDescription config) @@ -503,12 +538,6 @@ namespace Mono.Addins.Database foreach (Assembly asm in assemblies) ScanAssemblyContents (config, asm, hostExtensionClasses, scanResult); - if (config.IsRoot && scanResult.HostIndex != null) { - // If the add-in is a root, register its assemblies - foreach (string asmFile in asmFiles) - scanResult.HostIndex.RegisterAssembly (asmFile, config.AddinId, config.AddinFile); - } - } catch (Exception ex) { ReportReflectionException (monitor, ex, config, scanResult); return false; @@ -545,12 +574,6 @@ namespace Mono.Addins.Database } foreach (Assembly asm in assemblies) ScanAssemblyContents (config, asm, null, scanResult); - - if (config.IsRoot && scanResult.HostIndex != null) { - // If the add-in is a root, register its assemblies - foreach (string asmFile in asmFiles) - scanResult.HostIndex.RegisterAssembly (asmFile, config.AddinId, config.AddinFile); - } } catch (Exception ex) { ReportReflectionException (monitor, ex, config, scanResult); @@ -572,7 +595,6 @@ namespace Mono.Addins.Database ReflectionTypeLoadException rex = ex as ReflectionTypeLoadException; if (rex != null) { - Console.WriteLine ("pp e: " + ex.InnerException); foreach (Exception e in rex.LoaderExceptions) monitor.Log ("Load exception: " + e); } diff --git a/Mono.Addins/Mono.Addins.Database/AddinUpdateData.cs b/Mono.Addins/Mono.Addins.Database/AddinUpdateData.cs index ebcfc99..e0b0eb2 100644 --- a/Mono.Addins/Mono.Addins.Database/AddinUpdateData.cs +++ b/Mono.Addins/Mono.Addins.Database/AddinUpdateData.cs @@ -57,213 +57,129 @@ namespace Mono.Addins.Database public ExtensionPoint ExtensionPoint; } - AddinDatabase database; + IProgressStatus monitor; - public AddinUpdateData (AddinDatabase database) + public AddinUpdateData (AddinDatabase database, IProgressStatus monitor) { - this.database = database; + this.monitor = monitor; } - public void RegisterAddinRootExtensionPoint (AddinDescription description, ExtensionPoint ep) + public void RegisterNodeSet (AddinDescription description, ExtensionNodeSet nset) { - RelExtensionPoints++; - ArrayList list = (ArrayList) pathHash [ep.Path]; - if (list == null) { - list = new ArrayList (); - pathHash [ep.Path] = list; + ArrayList extensions = (ArrayList) nodeSetHash [nset.Id]; + if (extensions != null) { + // Extension point already registered + ArrayList compatExtensions = GetCompatibleExtensionPoints (nset.Id, description, description.MainModule, extensions); + if (compatExtensions.Count > 0) { + foreach (ExtensionPoint einfo in compatExtensions) + einfo.NodeSet.MergeWith (null, nset); + return; + } } - + // Create a new extension set RootExtensionPoint rep = new RootExtensionPoint (); + rep.ExtensionPoint = new ExtensionPoint (); + rep.ExtensionPoint.SetNodeSet (nset); + rep.ExtensionPoint.RootAddin = description.AddinId; + rep.ExtensionPoint.Path = nset.Id; rep.Description = description; - rep.ExtensionPoint = ep; - ep.RootAddin = description.AddinId; - list.Add (rep); + if (extensions == null) { + extensions = new ArrayList (); + nodeSetHash [nset.Id] = extensions; + } + extensions.Add (rep); } - - public void RegisterAddinRootNodeSet (AddinDescription description, ExtensionNodeSet nodeSet) + + public void RegisterExtensionPoint (AddinDescription description, ExtensionPoint ep) { - ArrayList list = (ArrayList) nodeSetHash [nodeSet.Id]; - if (list == null) { - list = new ArrayList (); - nodeSetHash [nodeSet.Id] = list; + ArrayList extensions = (ArrayList) pathHash [ep.Path]; + if (extensions != null) { + // Extension point already registered + ArrayList compatExtensions = GetCompatibleExtensionPoints (ep.Path, description, description.MainModule, extensions); + if (compatExtensions.Count > 0) { + foreach (ExtensionPoint einfo in compatExtensions) + einfo.MergeWith (null, ep); + RegisterObjectTypes (ep); + return; + } } - + // Create a new extension RootExtensionPoint rep = new RootExtensionPoint (); - rep.Description = description; - ExtensionPoint ep = new ExtensionPoint (); - ep.RootAddin = description.AddinId; - ep.SetNodeSet (nodeSet); rep.ExtensionPoint = ep; - list.Add (rep); - } - - public void RegisterNodeSet (AddinDescription description, ExtensionNodeSet nset) - { - string id = Addin.GetFullId (description.Namespace, nset.Id, description.Version); - foreach (ExtensionPoint einfo in GetExtensionInfo (nodeSetHash, id, description, description.MainModule, false)) { - if (einfo.RootAddin == null || database.AddinDependsOn (einfo.RootAddin, description.AddinId)) - einfo.RootAddin = description.AddinId; - einfo.NodeSet.MergeWith (null, nset); + rep.ExtensionPoint.RootAddin = description.AddinId; + rep.Description = description; + if (extensions == null) { + extensions = new ArrayList (); + pathHash [ep.Path] = extensions; } + extensions.Add (rep); + RegisterObjectTypes (ep); } - - public void RegisterExtensionPoint (AddinDescription description, ExtensionPoint ep) + + void RegisterObjectTypes (ExtensionPoint ep) { - foreach (ExtensionPoint einfo in GetExtensionInfo (pathHash, ep.Path, description, description.MainModule, false)) { - if (einfo.RootAddin == null || database.AddinDependsOn (einfo.RootAddin, description.AddinId)) - einfo.RootAddin = description.AddinId; - einfo.MergeWith (null, ep); + // Register extension points bound to a node type + + foreach (ExtensionNodeType nt in ep.NodeSet.NodeTypes) { + if (nt.ObjectTypeName.Length > 0) { + ArrayList list = (ArrayList) objectTypeExtensions [nt.ObjectTypeName]; + if (list == null) { + list = new ArrayList (); + objectTypeExtensions [nt.ObjectTypeName] = list; + } + list.Add (ep); + } } } public void RegisterExtension (AddinDescription description, ModuleDescription module, Extension extension) { if (extension.Path.StartsWith ("$")) { - UnresolvedObjectTypeExtension extData = new UnresolvedObjectTypeExtension (); - extData.Description = description; - extData.ModuleDescription = module; - extData.Extension = extension; string[] objectTypes = extension.Path.Substring (1).Split (','); + bool found = false; foreach (string s in objectTypes) { ArrayList list = (ArrayList) objectTypeExtensions [s]; - if (list == null) { - list = new ArrayList (); - objectTypeExtensions [s] = list; - } - list.Add (extData); - } - } - } - - void CollectObjectTypeExtensions (AddinDescription desc, ExtensionPoint ep, string objectTypeName) - { - ArrayList list = (ArrayList) objectTypeExtensions [objectTypeName]; - if (list == null) - return; - - foreach (UnresolvedObjectTypeExtension data in list) { - if (IsAddinCompatible (desc, data.Description, data.ModuleDescription)) { - data.Extension.Path = ep.Path; - RegisterExtension (data.Description, data.ModuleDescription, ep.Path); - data.FoundExtensionPoint = true; - } - } - } - - public void RegisterExtension (AddinDescription description, ModuleDescription module, string path) - { - foreach (ExtensionPoint einfo in GetExtensionInfo (pathHash, path, description, module, true)) { - if (!einfo.Addins.Contains (description.AddinId)) - einfo.Addins.Add (description.AddinId); - } - } - - public IEnumerable GetUnresolvedExtensionPoints () - { - ArrayList list = new ArrayList (); - foreach (object ob in pathHash.Values) - if (ob is ExtensionPoint) - list.Add (ob); - return list; - } - - public IEnumerable GetUnresolvedExtensionSets () - { - ArrayList list = new ArrayList (); - foreach (object ob in nodeSetHash.Values) - if (ob is ExtensionPoint) - list.Add (ob); - return list; - } - - public void ResolveExtensions (IProgressStatus monitor, Hashtable descriptions) - { - // Make a copy of the extensions found, sice the hash may change while being scanned - object[] extensionPointsFound = new object [pathHash.Count]; - pathHash.Values.CopyTo (extensionPointsFound, 0); - - foreach (object ob in extensionPointsFound) { - ExtensionPoint ep = ob as ExtensionPoint; - - if (ep == null) { - // It is a list of extension from a root add-in - ArrayList rootExtensionPoints = (ArrayList) ob; - foreach (RootExtensionPoint rep in rootExtensionPoints) { - foreach (ExtensionNodeType nt in rep.ExtensionPoint.NodeSet.NodeTypes) { - if (nt.ObjectTypeName.Length > 0) - CollectObjectTypeExtensions (rep.Description, rep.ExtensionPoint, nt.ObjectTypeName); - } - } - continue; - } - - if (ep.RootAddin == null) { - // Ignore class extensions - if (!ep.Path.StartsWith ("$")) { - // No add-in has defined this extension point, but some add-in - // is trying to extend it. A parent extension may exist. Check it now. - ExtensionPoint pep = GetParentExtensionPoint (ep.Path); - if (pep != null) { - foreach (string a in ep.Addins) - if (!pep.Addins.Contains (a)) - pep.Addins.Add (a); - } else { - foreach (string s in ep.Addins) - monitor.ReportWarning ("The add-in '" + s + "' is trying to extend '" + ep.Path + "', but there isn't any add-in defining this extension point"); + if (list != null) { + found = true; + foreach (ExtensionPoint ep in list) { + if (IsAddinCompatible (ep.ParentAddinDescription, description, module)) { + extension.Path = ep.Path; + RegisterExtension (description, module, ep.Path); + } } } - pathHash.Remove (ep.Path); - } - else { - foreach (ExtensionNodeType nt in ep.NodeSet.NodeTypes) { - if (nt.ObjectTypeName.Length > 0) { - AddinDescription desc = (AddinDescription) descriptions [ep.RootAddin]; - CollectObjectTypeExtensions (desc, ep, nt.ObjectTypeName); - } - } - } - } - - foreach (ArrayList list in objectTypeExtensions.Values) { - foreach (UnresolvedObjectTypeExtension data in list) { - if (!data.FoundExtensionPoint) { - monitor.ReportWarning ("The add-in '" + data.Description.AddinId + "' is trying to register the class '" + data.Extension.Path + "', but there isn't any add-in defining a suitable extension point"); - // The type extensions may be registered using different base classes. - // Make sure the warning is shown only once - data.FoundExtensionPoint = true; - } } + if (!found) + monitor.ReportWarning ("The add-in '" + description.AddinId + "' is trying to register the class '" + extension.Path.Substring (1) + "', but there isn't any add-in defining a suitable extension point"); } } - IEnumerable GetExtensionInfo (Hashtable hash, string path, AddinDescription description, ModuleDescription module, bool lookInParents) + public void RegisterExtension (AddinDescription description, ModuleDescription module, string path) { - ArrayList list = new ArrayList (); - - object data = hash [path]; - if (data == null && lookInParents) { + ArrayList extensions = (ArrayList) pathHash [path]; + if (extensions == null) { // Root add-in extension points are registered before any other kind of extension, // so we should find it now. - data = GetParentExtensionInfo (path); + extensions = GetParentExtensionInfo (path); } - - if (data is ArrayList) { - // Extension point which belongs to a root assembly. - list.AddRange (GetRootExtensionInfo (hash, path, description, module, (ArrayList) data)); + if (extensions == null) { + monitor.ReportWarning ("The add-in '" + description.AddinId + "' is trying to extend '" + path + "', but there isn't any add-in defining this extension point"); + return; } - else { - ExtensionPoint info = (ExtensionPoint) data; - if (info == null) { - info = new ExtensionPoint (); - info.Path = path; - hash [path] = info; + + bool found = false; + foreach (RootExtensionPoint einfo in extensions) { + if (IsAddinCompatible (einfo.Description, description, module)) { + if (!einfo.ExtensionPoint.Addins.Contains (description.AddinId)) + einfo.ExtensionPoint.Addins.Add (description.AddinId); + found = true; } - list.Add (info); } - return list; + if (!found) + monitor.ReportWarning ("The add-in '" + description.AddinId + "' is trying to extend '" + path + "', but there isn't any compatible add-in defining this extension point"); } - - ArrayList GetRootExtensionInfo (Hashtable hash, string path, AddinDescription description, ModuleDescription module, ArrayList rootExtensionPoints) + + ArrayList GetCompatibleExtensionPoints (string path, AddinDescription description, ModuleDescription module, ArrayList rootExtensionPoints) { ArrayList list = new ArrayList (); foreach (RootExtensionPoint rep in rootExtensionPoints) { @@ -275,18 +191,13 @@ namespace Mono.Addins.Database return list; } - ExtensionPoint GetParentExtensionPoint (string path) - { - return GetParentExtensionInfo (path) as ExtensionPoint; - } - - object GetParentExtensionInfo (string path) + ArrayList GetParentExtensionInfo (string path) { int i = path.LastIndexOf ('/'); if (i == -1) return null; string np = path.Substring (0, i); - object ep = pathHash [np]; + ArrayList ep = (ArrayList) pathHash [np]; if (ep != null) return ep; else @@ -295,6 +206,14 @@ namespace Mono.Addins.Database bool IsAddinCompatible (AddinDescription installedDescription, AddinDescription description, ModuleDescription module) { + if (installedDescription == description) + return true; + if (installedDescription.Domain != AddinDatabase.GlobalDomain) { + if (description.Domain != AddinDatabase.GlobalDomain && description.Domain != installedDescription.Domain) + return false; + } else if (description.Domain != AddinDatabase.GlobalDomain) + return false; + string addinId = Addin.GetFullId (installedDescription.Namespace, installedDescription.LocalId, null); string requiredVersion = null; @@ -317,12 +236,4 @@ namespace Mono.Addins.Database return true; } } - - class UnresolvedObjectTypeExtension - { - public AddinDescription Description; - public ModuleDescription ModuleDescription; - public Extension Extension; - public bool FoundExtensionPoint; - } } diff --git a/Mono.Addins/Mono.Addins.Database/FileDatabase.cs b/Mono.Addins/Mono.Addins.Database/FileDatabase.cs index 798ffd3..1f78f2b 100644 --- a/Mono.Addins/Mono.Addins.Database/FileDatabase.cs +++ b/Mono.Addins/Mono.Addins.Database/FileDatabase.cs @@ -205,6 +205,30 @@ namespace Mono.Addins.Database return File.Exists (fileName); } + public bool DirExists (string dir) + { + return Directory.Exists (dir); + } + + public void CreateDir (string dir) + { + Directory.CreateDirectory (dir); + } + + public string[] GetDirectories (string dir) + { + return Directory.GetDirectories (dir); + } + + public bool DirectoryIsEmpty (string dir) + { + foreach (string f in Directory.GetFiles (dir)) { + if (!inTransaction || !deletedFiles.Contains (f)) + return false; + } + return true; + } + public string[] GetDirectoryFiles (string dir, string pattern) { if (pattern == null || pattern.Length == 0 || pattern.EndsWith ("*")) diff --git a/Mono.Addins/Mono.Addins.Description/AddinDescription.cs b/Mono.Addins/Mono.Addins.Description/AddinDescription.cs index bab72d0..984cc55 100644 --- a/Mono.Addins/Mono.Addins.Description/AddinDescription.cs +++ b/Mono.Addins/Mono.Addins.Description/AddinDescription.cs @@ -43,7 +43,6 @@ namespace Mono.Addins.Description { XmlDocument configDoc; string configFile; - bool fromBinaryFile; AddinDatabase ownerDatabase; string id; @@ -62,6 +61,7 @@ namespace Mono.Addins.Description bool hasUserId; bool canWrite = true; bool defaultEnabled = true; + string domain; ModuleDescription mainModule; ModuleCollection optionalModules; @@ -183,6 +183,12 @@ namespace Mono.Addins.Description set { hasUserId = value; } } + internal bool SupportsVersion (string ver) + { + return Addin.CompareVersions (ver, Version) >= 0 && + (CompatVersion.Length == 0 || Addin.CompareVersions (ver, CompatVersion) <= 0); + } + public StringCollection AllFiles { get { StringCollection col = new StringCollection (); @@ -309,7 +315,7 @@ namespace Mono.Addins.Description foreach (Dependency dep in MainModule.Dependencies) { AddinDependency adep = dep as AddinDependency; if (adep == null) continue; - Addin ad = OwnerDatabase.GetInstalledAddin (adep.FullAddinId); + Addin ad = OwnerDatabase.GetInstalledAddin (Domain, adep.FullAddinId); if (ad != null && ad.Description != null) { ExtensionNodeDescription node = ad.Description.FindExtensionNode (path, false); if (node != null) @@ -333,6 +339,11 @@ namespace Mono.Addins.Description set { configFile = value; } } + internal string Domain { + get { return domain; } + set { domain = value; } + } + internal void StoreFileInfo () { ArrayList list = new ArrayList (); @@ -525,19 +536,6 @@ namespace Mono.Addins.Description AddinDescription description = (AddinDescription) fdb.ReadSharedObject (configFile, typeMap); if (description != null) { description.FileName = configFile; - description.fromBinaryFile = true; - description.canWrite = !fdb.IgnoreDescriptionData; - } - return description; - } - - internal static AddinDescription ReadHostBinary (FileDatabase fdb, string basePath, string addinId, string addinFile) - { - string fileName; - AddinDescription description = (AddinDescription) fdb.ReadSharedObject (basePath, addinId, ".mroot", Util.GetFullPath (addinFile), typeMap, out fileName); - if (description != null) { - description.FileName = fileName; - description.fromBinaryFile = true; description.canWrite = !fdb.IgnoreDescriptionData; } return description; @@ -557,15 +555,6 @@ namespace Mono.Addins.Description // BinaryXmlReader.DumpFile (configFile); } - internal void SaveHostBinary (FileDatabase fdb, string basePath) - { - if (!canWrite) - throw new InvalidOperationException ("Can't write incomplete description."); - if (!fromBinaryFile) - FileName = null; - FileName = fdb.WriteSharedObject (basePath, AddinId, ".mroot", AddinFile, FileName, typeMap, this); - } - public StringCollection Verify () { StringCollection errors = new StringCollection (); @@ -573,8 +562,6 @@ namespace Mono.Addins.Description if (IsRoot) { if (OptionalModules.Count > 0) errors.Add ("Root add-in hosts can't have optional modules."); - if (MainModule.Dependencies.Count > 0) - errors.Add ("Root add-in hosts can't have dependencies."); } if (AddinId.Length == 0 || Version.Length == 0) { @@ -664,6 +651,7 @@ namespace Mono.Addins.Description writer.WriteValue ("basePath", basePath); writer.WriteValue ("sourceAddinFile", sourceAddinFile); writer.WriteValue ("defaultEnabled", defaultEnabled); + writer.WriteValue ("domain", domain); writer.WriteValue ("MainModule", MainModule); writer.WriteValue ("OptionalModules", OptionalModules); writer.WriteValue ("NodeSets", ExtensionNodeSets); @@ -689,6 +677,7 @@ namespace Mono.Addins.Description basePath = reader.ReadStringValue ("basePath"); sourceAddinFile = reader.ReadStringValue ("sourceAddinFile"); defaultEnabled = reader.ReadBooleanValue ("defaultEnabled"); + domain = reader.ReadStringValue ("domain"); mainModule = (ModuleDescription) reader.ReadValue ("MainModule"); optionalModules = (ModuleCollection) reader.ReadValue ("OptionalModules", new ModuleCollection (this)); nodeSets = (ExtensionNodeSetCollection) reader.ReadValue ("NodeSets", new ExtensionNodeSetCollection (this)); diff --git a/Mono.Addins/Mono.Addins.Description/Extension.cs b/Mono.Addins/Mono.Addins.Description/Extension.cs index eeeb1ac..b145a18 100644 --- a/Mono.Addins/Mono.Addins.Description/Extension.cs +++ b/Mono.Addins/Mono.Addins.Description/Extension.cs @@ -60,7 +60,7 @@ namespace Mono.Addins.Description foreach (Dependency dep in desc.MainModule.Dependencies) { AddinDependency adep = dep as AddinDependency; if (adep == null) continue; - Addin ad = desc.OwnerDatabase.GetInstalledAddin (adep.FullAddinId); + Addin ad = desc.OwnerDatabase.GetInstalledAddin (ParentAddinDescription.Domain, adep.FullAddinId); if (ad != null && ad.Description != null) { ep = FindExtensionPoint (ad.Description, path); if (ep != null) diff --git a/Mono.Addins/Mono.Addins.Description/ExtensionNodeSet.cs b/Mono.Addins/Mono.Addins.Description/ExtensionNodeSet.cs index a6fc315..2d85188 100644 --- a/Mono.Addins/Mono.Addins.Description/ExtensionNodeSet.cs +++ b/Mono.Addins/Mono.Addins.Description/ExtensionNodeSet.cs @@ -161,7 +161,7 @@ namespace Mono.Addins.Description string startAddin = ns [1]; if (startAddin == null || startAddin.Length == 0) startAddin = desc.AddinId; - ExtensionNodeSet nset = desc.OwnerDatabase.FindNodeSet (startAddin, ns[0]); + ExtensionNodeSet nset = desc.OwnerDatabase.FindNodeSet (ParentAddinDescription.Domain, startAddin, ns[0]); if (nset != null) nset.GetAllowedNodeTypes (visitedSets, col); } diff --git a/Mono.Addins/Mono.Addins.mdp b/Mono.Addins/Mono.Addins.mdp index ca863bb..f79d80d 100644 --- a/Mono.Addins/Mono.Addins.mdp +++ b/Mono.Addins/Mono.Addins.mdp @@ -96,5 +96,4 @@ <AsmRefVar Sync="True" Name="DLL_REFERENCES" /> <ProjectRefVar Sync="True" Name="PROJECT_REFERENCES" /> </MonoDevelop.Autotools.MakefileInfo> - <Deployment.LinuxDeployData scriptName="mono.addins" /> </Project>
\ No newline at end of file diff --git a/Mono.Addins/Mono.Addins/Addin.cs b/Mono.Addins/Mono.Addins/Addin.cs index 0c0d6e9..2706988 100644 --- a/Mono.Addins/Mono.Addins/Addin.cs +++ b/Mono.Addins/Mono.Addins/Addin.cs @@ -42,7 +42,6 @@ namespace Mono.Addins AddinInfo addin; string configFile; string sourceFile; - string hostId; WeakReference desc; AddinDatabase database; @@ -52,15 +51,12 @@ namespace Mono.Addins configFile = file; } - internal Addin (AddinDatabase database, string hostId, string hostSourceFile) - { - this.database = database; - this.hostId = hostId; - this.sourceFile = hostSourceFile; - } - public string Id { - get { return this.AddinInfo.Id; } + get { + if (configFile != null) + return Path.GetFileNameWithoutExtension (configFile); + return this.AddinInfo.Id; + } } public string Namespace { @@ -102,12 +98,12 @@ namespace Mono.Addins } public bool Enabled { - get { return AddinInfo.IsRoot ? true : database.IsAddinEnabled (AddinInfo.Id, true); } + get { return AddinInfo.IsRoot ? true : database.IsAddinEnabled (Description.Domain, AddinInfo.Id, true); } set { if (value) - database.EnableAddin (AddinInfo.Id, true); + database.EnableAddin (Description.Domain, AddinInfo.Id, true); else - database.DisableAddin (AddinInfo.Id); + database.DisableAddin (Description.Domain, AddinInfo.Id); } } @@ -143,13 +139,9 @@ namespace Mono.Addins if (d != null) return d; } - + AddinDescription m; - - if (hostId != null) - database.GetHostDescription (null, hostId, sourceFile, out m); - else - database.ReadAddinDescription (null, configFile, out m); + database.ReadAddinDescription (null, configFile, out m); if (m == null) throw new InvalidOperationException ("Could not read add-in description"); @@ -162,7 +154,7 @@ namespace Mono.Addins } } - + // returns -1 if v1 > v2 public static int CompareVersions (string v1, string v2) { string[] a1 = v1.Split ('.'); diff --git a/Mono.Addins/Mono.Addins/AddinManager.cs b/Mono.Addins/Mono.Addins/AddinManager.cs index a6c0261..4f7ae4b 100644 --- a/Mono.Addins/Mono.Addins/AddinManager.cs +++ b/Mono.Addins/Mono.Addins/AddinManager.cs @@ -62,8 +62,11 @@ namespace Mono.Addins if (initialized) return; - startupDirectory = new Uri (Assembly.GetCallingAssembly ().CodeBase).LocalPath; - startupDirectory = Path.GetDirectoryName (startupDirectory); + Assembly asm = Assembly.GetEntryAssembly (); + if (asm == null) asm = Assembly.GetCallingAssembly (); + string asmFile = new Uri (asm.CodeBase).LocalPath; + + startupDirectory = Path.GetDirectoryName (asmFile); string customDir = Environment.GetEnvironmentVariable ("MONO_ADDINS_REGISTRY"); if (customDir != null && customDir.Length > 0) @@ -74,9 +77,6 @@ namespace Mono.Addins else registry = new AddinRegistry (configDir, startupDirectory); - Assembly asm = Assembly.GetEntryAssembly (); - if (asm == null) asm = Assembly.GetCallingAssembly (); - string asmFile = new Uri (asm.CodeBase).LocalPath; if (registry.CreateHostAddinsFile (asmFile)) registry.Update (new ConsoleProgressStatus (false)); diff --git a/Mono.Addins/Mono.Addins/AddinRegistry.cs b/Mono.Addins/Mono.Addins/AddinRegistry.cs index 363587b..11a6d9f 100644 --- a/Mono.Addins/Mono.Addins/AddinRegistry.cs +++ b/Mono.Addins/Mono.Addins/AddinRegistry.cs @@ -42,6 +42,8 @@ namespace Mono.Addins AddinDatabase database; StringCollection addinDirs; string basePath; + string currentDomain; + string startupDirectory; public AddinRegistry (string registryPath): this (registryPath, null) { @@ -53,6 +55,11 @@ namespace Mono.Addins database = new AddinDatabase (this); addinDirs = new StringCollection (); addinDirs.Add (Path.Combine (basePath, "addins")); + if (startupDirectory != null) { + currentDomain = database.GetFolderDomain (null, startupDirectory); + this.startupDirectory = startupDirectory; + } else + currentDomain = AddinDatabase.GlobalDomain; } public static AddinRegistry GetGlobalRegistry () @@ -96,23 +103,23 @@ namespace Mono.Addins public Addin GetAddin (string id) { - return database.GetInstalledAddin (id); + return database.GetInstalledAddin (currentDomain, id); } public Addin GetAddin (string id, bool exactVersionMatch) { - return database.GetInstalledAddin (id, exactVersionMatch); + return database.GetInstalledAddin (currentDomain, id, exactVersionMatch); } public Addin[] GetAddins () { - ArrayList list = database.GetInstalledAddins (); + ArrayList list = database.GetInstalledAddins (currentDomain, AddinType.Addin); return (Addin[]) list.ToArray (typeof(Addin)); } public Addin[] GetAddinRoots () { - ArrayList list = database.GetAddinRoots (); + ArrayList list = database.GetInstalledAddins (currentDomain, AddinType.Root); return (Addin[]) list.ToArray (typeof(Addin)); } @@ -153,17 +160,17 @@ namespace Mono.Addins public bool IsAddinEnabled (string id) { - return database.IsAddinEnabled (id); + return database.IsAddinEnabled (currentDomain, id); } public void EnableAddin (string id) { - database.EnableAddin (id, true); + database.EnableAddin (currentDomain, id, true); } public void DisableAddin (string id) { - database.DisableAddin (id); + database.DisableAddin (currentDomain, id); } public void DumpFile (string file) @@ -178,22 +185,26 @@ namespace Mono.Addins public void Update (IProgressStatus monitor) { - database.Update (monitor); + database.Update (monitor, currentDomain); + if (startupDirectory != null) + currentDomain = database.GetFolderDomain (null, startupDirectory); } public void Rebuild (IProgressStatus monitor) { - database.Repair (monitor); + database.Repair (monitor, currentDomain); + if (startupDirectory != null) + currentDomain = database.GetFolderDomain (null, startupDirectory); } internal Addin GetAddinForHostAssembly (string filePath) { - return database.GetAddinForHostAssembly (filePath); + return database.GetAddinForHostAssembly (currentDomain, filePath); } internal bool AddinDependsOn (string id1, string id2) { - return database.AddinDependsOn (id1, id2); + return database.AddinDependsOn (currentDomain, id1, id2); } internal void ScanFolders (IProgressStatus monitor, string folderToScan, StringCollection filesToIgnore) @@ -248,7 +259,9 @@ namespace Mono.Addins tw.Formatting = Formatting.Indented; tw.WriteStartElement ("Addins"); tw.WriteAttributeString ("host-reference", hostFile); - tw.WriteElementString ("Directory", Path.GetDirectoryName (hostFile)); + tw.WriteStartElement ("Directory"); + tw.WriteAttributeString ("shared", "false"); + tw.WriteString (Path.GetDirectoryName (hostFile)); tw.WriteEndElement (); tw.Close (); } diff --git a/Mono.Addins/Mono.Addins/AddinSessionService.cs b/Mono.Addins/Mono.Addins/AddinSessionService.cs index 6711537..6aec5c2 100644 --- a/Mono.Addins/Mono.Addins/AddinSessionService.cs +++ b/Mono.Addins/Mono.Addins/AddinSessionService.cs @@ -337,7 +337,7 @@ namespace Mono.Addins if (ainfo == null) return; } - InsertAddin (null, ainfo); + LoadAddin (null, ainfo.Id, false); } } } |