internal void Rebind(Stream newOriginal) { if (newOriginal == null) { throw new ArgumentNullException("newOriginal"); } // close this as we will open a new one _originalPackage.Value.Close(); _trashCan.Add(_originalPackage.Value); _isDirty = false; Package newPackage = Package.Open(newOriginal, FileMode.Open, FileAccess.Read); // remap parts for people who keep references around after we rebind foreach (PackagePart part in newPackage.GetParts()) { Uri normalizedPartUri = PackUriHelper.GetNormalizedPartUri(part.Uri); if (_activeParts.ContainsKey(normalizedPartUri)) { _activeParts[normalizedPartUri].Target = newPackage.GetPart(part.Uri); } } _originalPackage.Value = newPackage; }
//------------------------------------------------------------------------- // Protected Methods - Package Overrides //------------------------------------------------------------------------- /// <summary> /// Creates a new PackagePart. /// </summary> /// <remarks> /// When creating a new PackagePart we must: /// a) ensure the part does not exist in package /// b) ensure there is a writable package /// c) create a temp part /// d) update active part reference to the temp part /// /// What if a PackagePart with the same Uri already exists? /// Package.CreatePart checks for this. /// /// Do we need to worry about updating relationships and other parts? /// Relationships are a part and are thus intrinsically handled. /// </remarks> /// <param name="partUri">Uri for the part to create.</param> /// <param name="contentType">Content type string.</param> /// <param name="compressionOption">Compression options.</param> /// <returns>A new PackagePart.</returns> protected override PackagePart CreatePartCore( Uri partUri, string contentType, CompressionOption compressionOption) { // Skipping parameter validation as it is done by CreatePart. EnsureTempPackage(); // the underlying temp package does all the physical work PackagePart result = _tempPackage.Value.CreatePart( partUri, contentType, compressionOption); Uri normalizedPartUri = PackUriHelper.GetNormalizedPartUri(partUri); result = new WriteableOnDemandPackagePart( this, result, TempPackagePartFactory); _activeParts.Add(normalizedPartUri, (WriteableOnDemandPackagePart)result); Trace.SafeWrite( Trace.Packaging, "New part {0}({1})#{2} created.", result.Uri, result.ContentType, result.GetHashCode()); return(result); }
/// <summary> /// Deletes a PackagePart. /// </summary> /// <remarks> /// When deleting a PackagePart we must: /// a) ensure there is a writable package /// b) remove the temp part /// /// What if the part was already deleted? /// What if delete is the first operation? /// Then a relationship part in the temorary package would be active; /// and the case(s) would be handled by Package.DeletePart. /// /// What if delete is called after a part is created / edited? /// No different then the other cases. /// /// What if we call DeletePart on temp Package? /// Unsure why relationships are not updated twice; once by base /// accessing relationship part, then a second when the underlying /// implementor does for Package.DeletePart. /// /// Note: We should explore only cleaning up the stream; as the rest is /// likely handed by base interacting with the relationship parts. /// </remarks> /// <param name="partUri">Uri for the part to delete.</param> protected override void DeletePartCore(Uri partUri) { // Skipping parameter validation as it is done by CreatePart. if (_tempPackage.Value.PartExists(partUri)) { _tempPackage.Value.DeletePart(partUri); Trace.SafeWrite(Trace.Packaging, "Part {0} deleted.", partUri); } Uri normalizedPartUri = PackUriHelper.GetNormalizedPartUri(partUri); if (_activeParts.ContainsKey(normalizedPartUri)) { _activeParts.Remove(normalizedPartUri); } }
/// <summary> /// Returns an existing PackagePart. /// </summary> /// <remarks> /// When getting an existing PackagePart we must: /// a) Create a proxy (WriteableOnDemandPackagePart) if there is not /// already one; if there is we just return it. /// b) We must return the same instance of the proxy for any request /// for that part, as new instances will not have any way of /// knowing which internal part is 'active' (original/temp) within /// the proxy. /// /// What if the part does not exist? /// What if the part has been deleted? /// These cases are handled by Package.GetPart. /// /// What if the part ends up being edited? /// That is the reason for the proxy, on edit the internal reference /// will be updated to the temp object and it will service the call. /// /// What if a part has already been edited? /// That is why we must return the active part. /// </remarks> /// <param name="partUri">The Uri of the part to return.</param> /// <returns>An existing PackagePart.</returns> protected override PackagePart GetPartCore(Uri partUri) { // Skipping parameter validation as it is done by CreatePart. PackagePart result = null; Uri normalizedPartUri = PackUriHelper.GetNormalizedPartUri(partUri); #if DEBUG if (_activeParts.ContainsKey(normalizedPartUri)) { Trace.SafeWrite( Trace.Packaging, "WARNING: GetPartCore called multiple times for {0}.", partUri); } #endif // We can get the part from three places, which we check in this order: // 1) Our saved list of active parts. It's important to get it from // here if possible because all references should point to a single // instance of our WriteableOnDemandPackagePart class. // 2) The temp package. If there is a change to a part it will be here, // and we want to return the user's changes. // 3) The original package. // Even if the part exists in our list of active parts, as part of our // contract with the Packaging team we still must use PartExists to // check if the part is actually present in either the temporary or the // original package. If the part does not exist in either the original // or the temporary package, this method will return null. bool canGetFromTempPackage = (_tempPackage.Value != null) && (_tempPackage.Value.PartExists(partUri)); bool canGetFromOriginalPackage = canGetFromTempPackage ? false : _originalPackage.Value.PartExists(partUri); if (_activeParts.ContainsKey(normalizedPartUri) && (canGetFromTempPackage || canGetFromOriginalPackage)) { result = _activeParts[normalizedPartUri]; } else if (canGetFromTempPackage) { result = _tempPackage.Value.GetPart(partUri); result = new WriteableOnDemandPackagePart( this, result, TempPackagePartFactory); _activeParts.Add(normalizedPartUri, (WriteableOnDemandPackagePart)result); Trace.SafeWrite( Trace.Packaging, "GetPartCore returned {0}({1})#{2} a temp part.", partUri, result.ContentType, result.GetHashCode()); } else if (canGetFromOriginalPackage) { PackagePart original = _originalPackage.Value.GetPart(partUri); result = new WriteableOnDemandPackagePart( this, original, TempPackagePartFactory); _activeParts.Add(normalizedPartUri, (WriteableOnDemandPackagePart)result); Trace.SafeWrite( Trace.Packaging, "GetPartCore returned {0}({1})#{2} a new proxy.", partUri, result.ContentType, result.GetHashCode()); } return(result); }
public void ReserveUri(string contentType, Uri partUri) { GetNextSequenceNumber(contentType); AddToReserveUri(PackUriHelper.GetNormalizedPartUri(partUri)); }
public void GetNormalizedPartUriTest3() { Assert.AreEqual(new Uri(a.ToString().ToUpperInvariant(), UriKind.Relative), PackUriHelper.GetNormalizedPartUri(a)); }
public void GetNormalizedPartUriTest2() { PackUriHelper.GetNormalizedPartUri(null); }
public void GetNormalisedPartUritest4() { PackUriHelper.GetNormalizedPartUri(part1); }
public void GetNormalizedPartUriTest() { Uri uri = new Uri("/test.com".ToUpperInvariant(), UriKind.Relative); Assert.IsTrue(uri == PackUriHelper.GetNormalizedPartUri(uri)); }