From 675af5f9e12c24d33281c7c1d78a6a9e74f1f871 Mon Sep 17 00:00:00 2001 From: Steven Kirbach Date: Tue, 26 Mar 2019 17:14:11 -0700 Subject: [PATCH] ensuring that calling GetPart will call GetPartCore Package is an abstract class that others can derive from. Those derived classes can override GetPartsCore and potentially not return anything. Furthermore, it is not guaranteed that GetPartsCore will have been called if the package wasn't created using the Package.Open API, which only ensures that ZipPackage's internal data structures are filled in. Commit migrated from https://github.com/dotnet/corefx/commit/8f1d205116dd7dec996baa3276e73070c4f59ed5 --- .../src/System/IO/Packaging/Package.cs | 18 +++++- .../System.IO.Packaging/tests/Tests.cs | 59 +++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/Package.cs b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/Package.cs index a116814b8ee..be7e78fa08c 100644 --- a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/Package.cs +++ b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/Package.cs @@ -1135,7 +1135,23 @@ namespace System.IO.Packaging if (_partList.ContainsKey(validatePartUri)) return _partList[validatePartUri]; else - return null; + { + //Ideally we should decide whether we should query the underlying layer for the part based on the + //FileShare enum. But since we do not have that information, currently the design is to always + //ask the underlying layer, this allows for incremental access to the package. + //Note: + //Currently this incremental behavior for GetPart is not consistent with the GetParts method + //which just queries the underlying layer once. + PackagePart returnedPart = GetPartCore(validatePartUri); + + if (returnedPart != null) + { + // Add the part to the _partList if there is no prefix collision + AddIfNoPrefixCollisionDetected(validatePartUri, returnedPart); + } + + return returnedPart; + } } /// diff --git a/src/libraries/System.IO.Packaging/tests/Tests.cs b/src/libraries/System.IO.Packaging/tests/Tests.cs index 1ed3a6eb8db..d65c86f6462 100644 --- a/src/libraries/System.IO.Packaging/tests/Tests.cs +++ b/src/libraries/System.IO.Packaging/tests/Tests.cs @@ -3756,6 +3756,22 @@ namespace System.IO.Packaging.Tests } } + [Fact] + public void SupportNonPartEnumerableDerivedPackageTypes() + { + // Package is an abstract class that others can derive from. Those derived classes can override GetPartsCore and potentially not + // return anything. Furthermore, it is not guaranteed that GetPartsCore will have been called if the package wasn't created using + // the Package.Open API, which only ensures that ZipPackage's internal data structures are filled in. + var mockPackage = new NonEnumerablePackage(); + + var partUri = new Uri("/idontexist.xml", UriKind.Relative); + var part = mockPackage.GetPart(partUri); + + Assert.NotNull(part); + Assert.Equal(part.Uri, partUri); + Assert.IsType(typeof(MockPackagePart), part); + } + private const string DocumentRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"; } @@ -3772,4 +3788,47 @@ namespace System.IO.Packaging.Tests sb.Append(s); } } + + public class NonEnumerablePackage : Package + { + public NonEnumerablePackage() : base(FileAccess.Read) + { + } + + protected override PackagePart CreatePartCore(Uri partUri, string contentType, CompressionOption compressionOption) + { + throw new NotImplementedException(); + } + + protected override void DeletePartCore(Uri partUri) + { + throw new NotImplementedException(); + } + + protected override void FlushCore() + { + throw new NotImplementedException(); + } + + protected override PackagePart GetPartCore(Uri uri) + { + return new MockPackagePart(this, uri); + } + protected override PackagePart[] GetPartsCore() + { + throw new NotImplementedException(); + } + } + + public class MockPackagePart : PackagePart + { + public MockPackagePart(Package package, Uri uri) : base(package, uri) + { + } + + protected override Stream GetStreamCore(FileMode mode, FileAccess access) + { + throw new NotImplementedException(); + } + } } -- 2.34.1