|
From: <mcu...@us...> - 2009-09-24 18:47:32
|
Revision: 1411
http://orm.svn.sourceforge.net/orm/?rev=1411&view=rev
Author: mcurland
Date: 2009-09-24 18:47:24 +0000 (Thu, 24 Sep 2009)
Log Message:
-----------
* Handle extension load failure by removing unsupported extension, revert to previous state if the extension manager fails to load the new extension. refs #398
* Fix error with dynamic changes not producing an ObjectifyingInstanceRequiredError. Switching from an internal identifier to an external supertype identifier does not create an error present on reload. refs #374
Modified Paths:
--------------
trunk/ORMModel/ObjectModel/SamplePopulation.cs
trunk/ORMModel/Resources/ResourceStringsGenerator.cs
trunk/ORMModel/Resources/ResourceStringsGenerator.xml
trunk/ORMModel/ShapeModel/ORMDiagram.resx
trunk/ORMModel/Shell/ExtensionManager.cs
trunk/ORMModel/Shell/ORMDocData.cs
trunk/ORMModel/Shell/ORMPackage.cs
Modified: trunk/ORMModel/ObjectModel/SamplePopulation.cs
===================================================================
--- trunk/ORMModel/ObjectModel/SamplePopulation.cs 2009-09-16 07:45:45 UTC (rev 1410)
+++ trunk/ORMModel/ObjectModel/SamplePopulation.cs 2009-09-24 18:47:24 UTC (rev 1411)
@@ -1670,7 +1670,8 @@
Role unaryRole = null;
ObjectifiedUnaryRole objectifiedUnaryRole = null;
if (!deletedLink &&
- null != (pid = entityType.PreferredIdentifier) &&
+ null != (pid = entityType.ResolvedPreferredIdentifier) &&
+ pid.PreferredIdentifierFor == entityType &&
pid.IsInternal &&
1 == (pidFactTypes = pid.FactTypeCollection).Count &&
((identifierFactType = pidFactTypes[0]) == factType ||
Modified: trunk/ORMModel/Resources/ResourceStringsGenerator.cs
===================================================================
--- trunk/ORMModel/Resources/ResourceStringsGenerator.cs 2009-09-16 07:45:45 UTC (rev 1410)
+++ trunk/ORMModel/Resources/ResourceStringsGenerator.cs 2009-09-24 18:47:24 UTC (rev 1411)
@@ -2660,6 +2660,22 @@
return ResourceStrings.GetString(ResourceManagers.Diagram, "MessageBox.FileFormatUpgrade.Message");
}
}
+ /// <summary>The message shown when extensions are automatically removed from a file. Replacements: {0}=file name, {1}=list of unrecognized extensions.</summary>
+ public static string UnrecognizedExtensionsStrippedMessage
+ {
+ get
+ {
+ return ResourceStrings.GetString(ResourceManagers.Diagram, "MessageBox.UnrecognizedExtensionsStripped.Message");
+ }
+ }
+ /// <summary>The header for the message displayed if a set of extensions fails to correctly reload.</summary>
+ public static string RevertExtensionsMessage
+ {
+ get
+ {
+ return ResourceStrings.GetString(ResourceManagers.Diagram, "MessageBox.RevertExtensions.Message");
+ }
+ }
/// <summary>The name of the transaction that auto-fixes implied and duplicate internal constraints.</summary>
public static string RemoveImpliedInternalUniquenessConstraintsTransactionName
{
Modified: trunk/ORMModel/Resources/ResourceStringsGenerator.xml
===================================================================
--- trunk/ORMModel/Resources/ResourceStringsGenerator.xml 2009-09-16 07:45:45 UTC (rev 1410)
+++ trunk/ORMModel/Resources/ResourceStringsGenerator.xml 2009-09-24 18:47:24 UTC (rev 1411)
@@ -382,6 +382,8 @@
<ResourceString name="ImpliedInternalConstraintFixMessage" model="Diagram" resourceName="MessageBox.ImpliedInternalUniquenessConstraint.Message"/>
<ResourceString name="FinalShapeDeletionMessage" model="Diagram" resourceName="MessageBox.FinalShapeDeletion.Message"/>
<ResourceString name="FileFormatUpgradeMessage" model="Diagram" resourceName="MessageBox.FileFormatUpgrade.Message"/>
+ <ResourceString name="UnrecognizedExtensionsStrippedMessage" model="Diagram" resourceName="MessageBox.UnrecognizedExtensionsStripped.Message"/>
+ <ResourceString name="RevertExtensionsMessage" model="Diagram" resourceName="MessageBox.RevertExtensions.Message"/>
<ResourceString name="RemoveImpliedInternalUniquenessConstraintsTransactionName" model="Model" resourceName="FactType.RemoveImpliedInternalUniquenessConstraints.TransactionName"/>
<ResourceString name="AlignShapesTransactionName" model="Diagram" resourceName="AlignShapes.TransactionName"/>
<ResourceString name="AutoLayoutTransactionName" model="Diagram" resourceName="AutoLayout.TransactionName"/>
Modified: trunk/ORMModel/ShapeModel/ORMDiagram.resx
===================================================================
--- trunk/ORMModel/ShapeModel/ORMDiagram.resx 2009-09-16 07:45:45 UTC (rev 1410)
+++ trunk/ORMModel/ShapeModel/ORMDiagram.resx 2009-09-24 18:47:24 UTC (rev 1411)
@@ -515,6 +515,10 @@
<value xml:space="preserve">Interpret Fact Editor Line</value>
<comment xml:space="preserve">The transaction name used for changes made in response to committing a modified line in the fact editor. The text appears in the undo dropdown in the VS IDE.</comment>
</data>
+ <data name="MessageBox.RevertExtensions.Message">
+ <value xml:space="preserve">Restoring previous model state, loading new extensions faileds with exception:
</value>
+ <comment xml:space="preserve">The header for the message displayed if a set of extensions fails to correctly reload.</comment>
+ </data>
<data name="MessageBox.ImpliedInternalUniquenessConstraint.Message">
<value xml:space="preserve">One or more of the internal uniqueness constraints are implied by other internal uniqueness constraints. Do you wish to remove the implied constraints?</value>
<comment xml:space="preserve">The message for the auto-fix implied internal uniqueness constraint message box.</comment>
@@ -527,7 +531,11 @@
<value xml:space="preserve">The final shape corresponding to this element is being deleted. Delete the underlying '{0}' element '{1}' as well?</value>
<comment xml:space="preserve">The message for the prompt to delete an element from the model when the final shape representing it is delete. Replacement field 0 gets the class name and 1 the component name.</comment>
</data>
- <data name="ModelErrorDisplayFilterChange.TransactionName">
+ <data name="MessageBox.UnrecognizedExtensionsStripped.Message">
+ <value xml:space="preserve">The file format of '{0}' contains unsupported extensions.
Data associated with extension(s) '{1}' has been removed.
Should the 'Save' command be disabled to preserve the original file contents? The 'Save As' command will remain enabled.</value>
+ <comment xml:space="preserve">The message shown when extensions are automatically removed from a file. Replacements: {0}=file name, {1}=list of unrecognized extensions.</comment>
+ </data>
+ <data name="ModelErrorDisplayFilterChange.TransactionName">
<value xml:space="preserve">Change Error Display</value>
<comment xml:space="preserve">The transaction name used by the model error display filter dialog when a filter is changed. The text appears in the undo dropdown in the VS IDE.</comment>
</data>
Modified: trunk/ORMModel/Shell/ExtensionManager.cs
===================================================================
--- trunk/ORMModel/Shell/ExtensionManager.cs 2009-09-16 07:45:45 UTC (rev 1410)
+++ trunk/ORMModel/Shell/ExtensionManager.cs 2009-09-24 18:47:24 UTC (rev 1411)
@@ -3,7 +3,7 @@
* Natural Object-Role Modeling Architect for Visual Studio *
* *
* Copyright \xA9 Neumont University. All rights reserved. *
-* Copyright \xA9 ORM Solutions, LLC. All rights reserved. *
+* Copyright \xA9 ORM Solutions, LLC. All rights reserved. *
* *
* The use and distribution terms for this software are covered by the *
* Common Public License 1.0 (http://opensource.org/licenses/cpl) which *
@@ -70,7 +70,8 @@
public static void ShowDialog(IServiceProvider serviceProvider, ORMDesignerDocData docData)
{
ExtensionManager extensionManager = new ExtensionManager(docData.Store);
- if (extensionManager.ShowDialog(Utility.GetDialogOwnerWindow(serviceProvider)) == DialogResult.OK)
+ IWin32Window dialogOwner = Utility.GetDialogOwnerWindow(serviceProvider);
+ if (extensionManager.ShowDialog(dialogOwner) == DialogResult.OK)
{
// TODO: Prompt the user to make sure they really want us to start deleting stuff...
@@ -87,24 +88,29 @@
// secondary extensions back on.
ORMDesignerPackage.VerifyRequiredExtensions(ref checkedTypes);
- Stream stream = null;
+ Stream currentStream = null;
+ Stream newStream = null;
try
{
Object streamObj;
(docData as EnvDTE.IExtensibleObject).GetAutomationObject("ORMXmlStream", null, out streamObj);
- stream = streamObj as Stream;
+ currentStream = streamObj as Stream;
- Debug.Assert(stream != null);
+ Debug.Assert(currentStream != null);
- stream = CleanupStream(stream, ORMDesignerPackage.StandardDomainModels, checkedTypes.Values);
- docData.ReloadFromStream(stream);
+ newStream = CleanupStream(currentStream, ORMDesignerPackage.StandardDomainModels, checkedTypes.Values, null);
+ docData.ReloadFromStream(newStream, currentStream);
}
finally
{
- if (stream != null)
+ if (currentStream != null)
{
- stream.Dispose();
+ currentStream.Dispose();
}
+ if (newStream != null)
+ {
+ newStream.Dispose();
+ }
}
}
}
@@ -124,11 +130,11 @@
/// <summary>
/// Default Constructor for the <see cref="ExtensionManagerUtility"/>.
/// </summary>
- /// <param name="namespaces">An array of available namespaces.</param>
- public ExtensionManagerUtility(string[] namespaces)
+ /// <param name="sortedNamespaces">An array of available namespaces. The array should be sorted with the
+ /// default string sort.</param>
+ public ExtensionManagerUtility(string[] sortedNamespaces)
{
- myNamespaces = namespaces;
- Array.Sort<string>(namespaces);
+ myNamespaces = sortedNamespaces;
myLastIdRemovalPhase = -1;
}
/// <summary>
@@ -243,8 +249,12 @@
/// <param name="stream">The file stream that contains the ORM file.</param>
/// <param name="standardTypes">The standard models that are not loaded as extensions</param>
/// <param name="extensionTypes">A collection of extension types.</param>
+ /// <param name="unrecognizedNamespaces">An editable list of unrecognized namespaces. If this is set,
+ /// the namespaces will be verified after secondary namespaces from the extension types are validated.
+ /// If no remaining unrecognized namespaces are left after validation, then the method will return null.
+ /// Recognized namespaces will be removed from the list.</param>
/// <returns>The cleaned stream.</returns>
- public static Stream CleanupStream(Stream stream, ICollection<Type> standardTypes, ICollection<ORMExtensionType> extensionTypes)
+ public static Stream CleanupStream(Stream stream, ICollection<Type> standardTypes, ICollection<ORMExtensionType> extensionTypes, IList<string> unrecognizedNamespaces)
{
MemoryStream outputStream = new MemoryStream((int)stream.Length);
XsltArgumentList argList = new XsltArgumentList();
@@ -295,6 +305,21 @@
namespaces[++namespaceIndex] = currentAttribute[j];
}
}
+ Array.Sort<string>(namespaces);
+ if (unrecognizedNamespaces != null)
+ {
+ for (int i = unrecognizedNamespaces.Count - 1; i >= 0; --i)
+ {
+ if (Array.BinarySearch<string>(namespaces, unrecognizedNamespaces[i]) >= 0)
+ {
+ unrecognizedNamespaces.RemoveAt(i);
+ }
+ }
+ if (unrecognizedNamespaces.Count == 0)
+ {
+ return null;
+ }
+ }
argList.AddExtensionObject("urn:schemas-neumont-edu:ORM:ExtensionManagerUtility", new ExtensionManagerUtility(namespaces));
XslCompiledTransform transform = GetExtensionStripperTransform();
Modified: trunk/ORMModel/Shell/ORMDocData.cs
===================================================================
--- trunk/ORMModel/Shell/ORMDocData.cs 2009-09-16 07:45:45 UTC (rev 1410)
+++ trunk/ORMModel/Shell/ORMDocData.cs 2009-09-24 18:47:24 UTC (rev 1411)
@@ -3,7 +3,7 @@
* Natural Object-Role Modeling Architect for Visual Studio *
* *
* Copyright \xA9 Neumont University. All rights reserved. *
-* Copyright \xA9 ORM Solutions, LLC. All rights reserved. *
+* Copyright \xA9 ORM Solutions, LLC. All rights reserved. *
* *
* The use and distribution terms for this software are covered by the *
* Common Public License 1.0 (http://opensource.org/licenses/cpl) which *
@@ -18,27 +18,28 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Windows.Forms;
using System.Xml;
+using System.Xml.Schema;
+using EnvDTE;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Shell;
using Microsoft.VisualStudio.Modeling.Diagrams;
+using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
-using ORMSolutions.ORMArchitect.Framework.Shell;
using ORMSolutions.ORMArchitect.Core.ObjectModel;
using ORMSolutions.ORMArchitect.Core.ShapeModel;
using ORMSolutions.ORMArchitect.Framework;
-using EnvDTE;
-using System.Xml.Schema;
-using System.Collections.ObjectModel;
+using ORMSolutions.ORMArchitect.Framework.Shell;
using ORMSolutions.ORMArchitect.Framework.Shell.DynamicSurveyTreeGrid;
-using System.Runtime.InteropServices;
-using Microsoft.VisualStudio.Shell;
-using System.Windows.Forms;
namespace ORMSolutions.ORMArchitect.Core.Shell
{
@@ -60,6 +61,8 @@
SaveDisabled = 8,
ErrorDisplayModified = 0x10,
UndoStackRemoved = 0x20,
+ RethrowLoadDocDataException = 0x40,
+ IgnoreDocumentReloading = 0x80,
// Other flags here, add instead of lots of bool variables
}
private PrivateFlags myFlags;
@@ -160,16 +163,66 @@
/// <summary>
/// Reload this document from a <see cref="Stream"/> instead of from a file.
/// </summary>
- /// <param name="stream">The <see cref="Stream"/> to load</param>
- public void ReloadFromStream(Stream stream)
+ /// <param name="newStream">The <see cref="Stream"/> to load</param>
+ /// <param name="fallbackStream">If <paramref name="newStream"/> fails to load, then
+ /// reload this stream instead.</param>
+ public void ReloadFromStream(Stream newStream, Stream fallbackStream)
{
- myFileStream = stream;
+ myFileStream = newStream;
// This calls into LoadDocData(string, bool) after doing necessary cleanup
- ReloadDocData((uint)_VSRELOADDOCDATA.RDD_RemoveUndoStack);
+ IServiceProvider serviceProvider;
+ if (fallbackStream == null)
+ {
+ ReloadDocData((uint)_VSRELOADDOCDATA.RDD_RemoveUndoStack);
+ }
+ else
+ {
+ SetFlag(PrivateFlags.RethrowLoadDocDataException, true);
+ try
+ {
+ ReloadDocData((uint)_VSRELOADDOCDATA.RDD_RemoveUndoStack);
+ }
+ catch (Exception ex)
+ {
+ SetFlag(PrivateFlags.RethrowLoadDocDataException, false);
+ SetFlag(PrivateFlags.IgnoreDocumentReloading, true);
+ fallbackStream.Position = 0;
+ myFileStream = fallbackStream;
+ ReloadDocData((uint)_VSRELOADDOCDATA.RDD_RemoveUndoStack);
+ if (null != (serviceProvider = ServiceProvider))
+ {
+ StringBuilder builder = new StringBuilder(ResourceStrings.RevertExtensionsMessage);
+ const string offset = "\r\n";
+ Exception messageException = ex;
+ while (messageException != null)
+ {
+ string message = messageException.Message;
+ if (!string.IsNullOrEmpty(message))
+ {
+ builder.Append(offset);
+ builder.Append(message);
+ }
+ messageException = messageException.InnerException;
+ }
- // The document now has no undo stack, but we need it to display as dirty
+ VsShellUtilities.ShowMessageBox(
+ serviceProvider,
+ builder.ToString(),
+ ResourceStrings.PackageOfficialName,
+ OLEMSGICON.OLEMSGICON_INFO,
+ OLEMSGBUTTON.OLEMSGBUTTON_OK,
+ OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
+ }
+ }
+ finally
+ {
+ SetFlag(PrivateFlags.RethrowLoadDocDataException, false);
+ SetFlag(PrivateFlags.IgnoreDocumentReloading, false);
+ }
+ }
+
+ // The document now has no undo stack, but we need it to display it as dirty
SetFlag(PrivateFlags.UndoStackRemoved, true);
- IServiceProvider serviceProvider;
uint cookie;
IVsUIShell shell;
if (null != (serviceProvider = base.ServiceProvider) &&
@@ -180,6 +233,29 @@
}
}
/// <summary>
+ /// Enable reloading of the original stream during a failed attempt
+ /// to modify extensions.
+ /// </summary>
+ protected override void OnDocumentReloading(EventArgs e)
+ {
+ if (!GetFlag(PrivateFlags.IgnoreDocumentReloading))
+ {
+ base.OnDocumentReloading(e);
+ }
+ }
+ /// <summary>
+ /// Enable reloading of the original stream during a failed attempt
+ /// to modify extensions.
+ /// </summary>
+ protected override void HandleLoadDocDataException(string fileName, Exception exception, bool isReload)
+ {
+ if (GetFlag(PrivateFlags.RethrowLoadDocDataException))
+ {
+ throw exception;
+ }
+ base.HandleLoadDocDataException(fileName, exception, isReload);
+ }
+ /// <summary>
/// See the <see cref="LoadDocData"/> method.
/// </summary>
/// <param name="fileName">The file name that we pass to <see cref="ModelingDocData.LoadDocData"/>.</param>
@@ -236,12 +312,14 @@
// Convert early so we can accurately check extension elements
int retVal = 0;
bool dontSave = false;
+ List<string> unrecognizedNamespaces = null;
ORMDesignerSettings settings = ORMDesignerPackage.DesignerSettings;
using (Stream convertedStream = settings.ConvertStream(inputStream, ServiceProvider))
{
dontSave = convertedStream != null;
Stream stream = dontSave ? convertedStream : inputStream;
myFileStream = stream;
+ Stream namespaceStrippedStream = null;
try
{
XmlReaderSettings readerSettings = new XmlReaderSettings();
@@ -272,6 +350,10 @@
}
documentExtensions[URI] = extensionType.Value;
}
+ else
+ {
+ (unrecognizedNamespaces ?? (unrecognizedNamespaces = new List<string>())).Add(URI);
+ }
}
}
} while (reader.MoveToNextAttribute());
@@ -279,11 +361,74 @@
}
}
ORMDesignerPackage.VerifyRequiredExtensions(ref documentExtensions);
+ Stream unstrippedNamespaceStream = stream;
+ if (unrecognizedNamespaces != null)
+ {
+ stream.Position = 0;
+ namespaceStrippedStream = ExtensionManager.CleanupStream(stream, ORMDesignerPackage.StandardDomainModels, documentExtensions.Values, unrecognizedNamespaces);
+ if (namespaceStrippedStream != null)
+ {
+ dontSave = true;
+ stream = namespaceStrippedStream;
+ myFileStream = namespaceStrippedStream;
+ }
+ else
+ {
+ unrecognizedNamespaces = null;
+ }
+ }
myExtensionDomainModels = documentExtensions;
stream.Position = 0;
-
- retVal = base.LoadDocData(fileName, isReload);
+ try
+ {
+ retVal = base.LoadDocData(fileName, isReload);
+ }
+ catch (TypeInitializationException ex)
+ {
+ // If the type that failed to load is an extensions, then remove it from
+ // the list of available extensions and try again.
+ if (documentExtensions != null)
+ {
+ string typeName = ex.TypeName;
+ foreach (KeyValuePair<string, ORMExtensionType> pair in documentExtensions)
+ {
+ Type testType = pair.Value.Type;
+ if (testType.FullName == typeName)
+ {
+ if (ORMDesignerPackage.CustomExtensionUnavailable(testType))
+ {
+ // If the unloadable type is a registered extensions, then
+ // we now have an additional namespace element that will not
+ // load correctly. Recurse on this function with the stream
+ // before any extensions namespace were stripped so that we can
+ // see all stripped namespaces in the final message. Obviously,
+ // this repeats some processing we've already done, but this is
+ // very much an exception case, and the additional minor performance
+ // hit is minimal compared with the user annoyance at potentially
+ // seeing multiple error displays.
+ Exception innerException = ex.InnerException;
+ string message;
+ if (innerException != null &&
+ !string.IsNullOrEmpty(message = innerException.Message))
+ {
+ VsShellUtilities.ShowMessageBox(
+ ServiceProvider,
+ message,
+ ResourceStrings.PackageOfficialName,
+ OLEMSGICON.OLEMSGICON_INFO,
+ OLEMSGBUTTON.OLEMSGBUTTON_OK,
+ OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
+ }
+ unstrippedNamespaceStream.Position = 0;
+ return LoadDocDataFromStream(fileName, true, unstrippedNamespaceStream);
+ }
+ break;
+ }
+ }
+ }
+ throw;
+ }
// HACK: After the file is loaded and the load transaction has committed, commit a new transaction.
// For some reason this seems to fix various line routing issues (including the lines not showing up).
@@ -300,6 +445,10 @@
finally
{
myFileStream = null;
+ if (namespaceStrippedStream != null)
+ {
+ namespaceStrippedStream.Dispose();
+ }
}
}
if (dontSave)
@@ -317,10 +466,35 @@
}
if (dontSave)
{
+ string message;
+ CultureInfo culture = CultureInfo.CurrentCulture;
+ int unrecognizedCount;
+ if (unrecognizedNamespaces != null &&
+ 0 != (unrecognizedCount = unrecognizedNamespaces.Count))
+ {
+ string namespaceReplacement = unrecognizedNamespaces[0];
+ if (unrecognizedCount > 1)
+ {
+ string separator = culture.TextInfo.ListSeparator;
+ if (!char.IsWhiteSpace(separator, separator.Length - 1))
+ {
+ separator += " ";
+ }
+ for (int i = 1; i < unrecognizedCount; ++i)
+ {
+ namespaceReplacement += separator + unrecognizedNamespaces[i];
+ }
+ }
+ message = string.Format(culture, ResourceStrings.UnrecognizedExtensionsStrippedMessage, fileName, namespaceReplacement);
+ }
+ else
+ {
+ message = string.Format(culture, ResourceStrings.FileFormatUpgradeMessage, fileName);
+ }
// The disabled save is leading to data loss, prompt the user
dontSave = (int)DialogResult.Yes == VsShellUtilities.ShowMessageBox(
ServiceProvider,
- string.Format(CultureInfo.CurrentCulture, ResourceStrings.FileFormatUpgradeMessage, fileName),
+ message,
ResourceStrings.PackageOfficialName,
OLEMSGICON.OLEMSGICON_QUERY,
OLEMSGBUTTON.OLEMSGBUTTON_YESNO,
@@ -883,19 +1057,34 @@
}
Object streamObj;
(myDocData as EnvDTE.IExtensibleObject).GetAutomationObject("ORMXmlStream", null, out streamObj);
- Stream stream = streamObj as Stream;
+ Stream currentStream = streamObj as Stream;
+ Stream newStream = null;
- Debug.Assert(stream != null);
+ Debug.Assert(currentStream != null);
- ORMDesignerPackage.VerifyRequiredExtensions(ref requestedExtensions);
- ICollection<ORMExtensionType> allExtensions = requestedExtensions.Values;
- if (nonRequestedLoadedExtensions != null)
+ try
{
- nonRequestedLoadedExtensions.AddRange(allExtensions);
- allExtensions = nonRequestedLoadedExtensions;
+ ORMDesignerPackage.VerifyRequiredExtensions(ref requestedExtensions);
+ ICollection<ORMExtensionType> allExtensions = requestedExtensions.Values;
+ if (nonRequestedLoadedExtensions != null)
+ {
+ nonRequestedLoadedExtensions.AddRange(allExtensions);
+ allExtensions = nonRequestedLoadedExtensions;
+ }
+ newStream = ExtensionManager.CleanupStream(currentStream, ORMDesignerPackage.StandardDomainModels, allExtensions, null);
+ myDocData.ReloadFromStream(newStream, currentStream);
}
- stream = ExtensionManager.CleanupStream(stream, ORMDesignerPackage.StandardDomainModels, allExtensions);
- myDocData.ReloadFromStream(stream);
+ finally
+ {
+ if (currentStream != null)
+ {
+ currentStream.Dispose();
+ }
+ if (newStream != null)
+ {
+ newStream.Dispose();
+ }
+ }
}
}
}
Modified: trunk/ORMModel/Shell/ORMPackage.cs
===================================================================
--- trunk/ORMModel/Shell/ORMPackage.cs 2009-09-16 07:45:45 UTC (rev 1410)
+++ trunk/ORMModel/Shell/ORMPackage.cs 2009-09-24 18:47:24 UTC (rev 1411)
@@ -1074,6 +1074,57 @@
return retVal;
}
/// <summary>
+ /// A custom extension has failed to load. Remove the extension from the list
+ /// of available extensions.
+ /// </summary>
+ /// <param name="unvailableExtensionType">The extension <see cref="Type"/>The
+ /// extension that has failed to load.</param>
+ /// <returns><see langword="true"/> if the extension was successfully removed.</returns>
+ public static bool CustomExtensionUnavailable(Type unvailableExtensionType)
+ {
+ IDictionary<string, ORMExtensionType> customExtensions = GetAvailableCustomExtensions();
+ if (customExtensions != null)
+ {
+ foreach (KeyValuePair<string, ORMExtensionType> pair in customExtensions)
+ {
+ ORMExtensionType extensionType = pair.Value;
+ if (extensionType.Type == unvailableExtensionType)
+ {
+ customExtensions.Remove(pair.Key);
+ ORMDesignerPackage package = mySingleton; // Note that we must have a singleton, or we would have no custom extensions
+ IDictionary<Guid, string> extensionIdMap = package.myExtensionIdToExtensionNameMap;
+ if (extensionIdMap != null && extensionIdMap.ContainsKey(extensionType.DomainModelId))
+ {
+ extensionIdMap.Remove(extensionType.DomainModelId);
+ }
+ string[] autoloadExtensions = package.myAutoLoadExtensions;
+ int autoloadExtensionLength;
+ int removeExtensionIndex;
+ if (autoloadExtensions != null &&
+ 0 != (autoloadExtensionLength = autoloadExtensions.Length) &&
+ -1 != (removeExtensionIndex = Array.IndexOf<string>(autoloadExtensions, extensionType.NamespaceUri)))
+ {
+ string[] newExtensions = new string[autoloadExtensionLength - 1];
+ if (autoloadExtensionLength > 1)
+ {
+ for (int i = 0; i < removeExtensionIndex; ++i)
+ {
+ newExtensions[i] = autoloadExtensions[i];
+ }
+ for (int i = removeExtensionIndex + 1; i < autoloadExtensionLength; ++i)
+ {
+ newExtensions[i - 1] = autoloadExtensions[i];
+ }
+ }
+ package.myAutoLoadExtensions = newExtensions;
+ }
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ /// <summary>
/// Helper method for <see cref="GetAvailableCustomExtensions"/>
/// </summary>
private static void LoadAvailableCustomExtensions(RegistryKey rootKey, IDictionary<string, ORMExtensionType> extensionMap)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|