/// <summary>Copy this object to the output stream.</summary> /// <remarks> /// Copy this object to the output stream. /// <p> /// For some object store implementations, this method may be more efficient /// than reading from /// <see cref="OpenStream()">OpenStream()</see> /// into a temporary byte array, then /// writing to the destination stream. /// <p> /// The default implementation of this method is to copy with a temporary /// byte array for large objects, or to pass through the cached byte array /// for small objects. /// </remarks> /// <param name="out"> /// stream to receive the complete copy of this object's data. /// Caller is responsible for flushing or closing this stream /// after this method returns. /// </param> /// <exception cref="NGit.Errors.MissingObjectException">the object no longer exists. /// </exception> /// <exception cref="System.IO.IOException"> /// the object store cannot be accessed, or the stream cannot be /// written to. /// </exception> public virtual void CopyTo(OutputStream @out) { if (IsLarge()) { ObjectStream @in = OpenStream(); try { long sz = @in.GetSize(); byte[] tmp = new byte[8192]; long copied = 0; while (copied < sz) { int n = @in.Read(tmp); if (n < 0) { throw new EOFException(); } @out.Write(tmp, 0, n); copied += n; } if (0 <= @in.Read()) { throw new EOFException(); } } finally { @in.Close(); } } else { @out.Write(GetCachedBytes()); } }
public virtual void TestLargeObjectLoader() { byte[] act = GetRng().NextBytes(512); ObjectLoader ldr = new _ObjectLoader_122(act); NUnit.Framework.Assert.AreEqual(Constants.OBJ_BLOB, ldr.GetType()); NUnit.Framework.Assert.AreEqual(act.Length, ldr.GetSize()); NUnit.Framework.Assert.IsTrue(ldr.IsLarge(), "is large"); try { ldr.GetCachedBytes(); NUnit.Framework.Assert.Fail("did not throw on getCachedBytes()"); } catch (LargeObjectException) { } // expected try { ldr.GetBytes(); NUnit.Framework.Assert.Fail("did not throw on getBytes()"); } catch (LargeObjectException) { } // expected try { ldr.GetCachedBytes(64); NUnit.Framework.Assert.Fail("did not throw on getCachedBytes(64)"); } catch (LargeObjectException) { } // expected byte[] copy = ldr.GetCachedBytes(1024); NUnit.Framework.Assert.AreNotSame(act, copy); NUnit.Framework.Assert.IsTrue(Arrays.Equals(act, copy), "same content"); ObjectStream @in = ldr.OpenStream(); NUnit.Framework.Assert.IsNotNull(@in, "has stream"); NUnit.Framework.Assert.AreEqual(Constants.OBJ_BLOB, @in.GetType()); NUnit.Framework.Assert.AreEqual(act.Length, @in.GetSize()); NUnit.Framework.Assert.AreEqual(act.Length, @in.Available()); NUnit.Framework.Assert.IsTrue(@in.MarkSupported(), "mark supported"); copy = new byte[act.Length]; NUnit.Framework.Assert.AreEqual(act.Length, @in.Read(copy)); NUnit.Framework.Assert.AreEqual(0, @in.Available()); NUnit.Framework.Assert.AreEqual(-1, @in.Read()); NUnit.Framework.Assert.IsTrue(Arrays.Equals(act, copy), "same content"); ByteArrayOutputStream tmp = new ByteArrayOutputStream(); ldr.CopyTo(tmp); NUnit.Framework.Assert.IsTrue(Arrays.Equals(act, tmp.ToByteArray()), "same content" ); }
public virtual void TestSmallObjectLoader() { byte[] act = GetRng().NextBytes(512); ObjectLoader ldr = new ObjectLoader.SmallObject(Constants.OBJ_BLOB, act); NUnit.Framework.Assert.AreEqual(Constants.OBJ_BLOB, ldr.GetType()); NUnit.Framework.Assert.AreEqual(act.Length, ldr.GetSize()); NUnit.Framework.Assert.IsFalse(ldr.IsLarge(), "not is large"); NUnit.Framework.Assert.AreSame(act, ldr.GetCachedBytes()); NUnit.Framework.Assert.AreSame(act, ldr.GetCachedBytes(1)); NUnit.Framework.Assert.AreSame(act, ldr.GetCachedBytes(int.MaxValue)); byte[] copy = ldr.GetBytes(); NUnit.Framework.Assert.AreNotSame(act, copy); NUnit.Framework.Assert.IsTrue(Arrays.Equals(act, copy), "same content"); copy = ldr.GetBytes(1); NUnit.Framework.Assert.AreNotSame(act, copy); NUnit.Framework.Assert.IsTrue(Arrays.Equals(act, copy), "same content"); copy = ldr.GetBytes(int.MaxValue); NUnit.Framework.Assert.AreNotSame(act, copy); NUnit.Framework.Assert.IsTrue(Arrays.Equals(act, copy), "same content"); ObjectStream @in = ldr.OpenStream(); NUnit.Framework.Assert.IsNotNull(@in, "has stream"); NUnit.Framework.Assert.IsTrue(@in is ObjectStream.SmallStream, "is small stream"); NUnit.Framework.Assert.AreEqual(Constants.OBJ_BLOB, @in.GetType()); NUnit.Framework.Assert.AreEqual(act.Length, @in.GetSize()); NUnit.Framework.Assert.AreEqual(act.Length, @in.Available()); NUnit.Framework.Assert.IsTrue(@in.MarkSupported(), "mark supported"); copy = new byte[act.Length]; NUnit.Framework.Assert.AreEqual(act.Length, @in.Read(copy)); NUnit.Framework.Assert.AreEqual(0, @in.Available()); NUnit.Framework.Assert.AreEqual(-1, @in.Read()); NUnit.Framework.Assert.IsTrue(Arrays.Equals(act, copy), "same content"); ByteArrayOutputStream tmp = new ByteArrayOutputStream(); ldr.CopyTo(tmp); NUnit.Framework.Assert.IsTrue(Arrays.Equals(act, tmp.ToByteArray()), "same content" ); }
/// <summary>Obtain a reference to the (possibly cached) bytes of this object.</summary> /// <remarks> /// Obtain a reference to the (possibly cached) bytes of this object. /// If the object size is less than or equal to /// <code>sizeLimit</code> /// this method /// will provide it as a byte array, even if /// <see cref="IsLarge()">IsLarge()</see> /// is true. This /// utility is useful for application code that absolutely must have the /// object as a single contiguous byte array in memory. /// This method offers direct access to the internal caches, potentially /// saving on data copies between the internal cache and higher level code. /// Callers who receive this reference <b>must not</b> modify its contents. /// Changes (if made) will affect the cache but not the repository itself. /// </remarks> /// <param name="sizeLimit"> /// maximum number of bytes to return. If the object size is /// larger than this limit and /// <see cref="IsLarge()">IsLarge()</see> /// is true, /// <see cref="NGit.Errors.LargeObjectException">NGit.Errors.LargeObjectException</see> /// will be thrown. /// </param> /// <returns>the cached bytes of this object. Do not modify it.</returns> /// <exception cref="NGit.Errors.LargeObjectException"> /// if the object is bigger than /// <code>sizeLimit</code> /// , or if /// <see cref="System.OutOfMemoryException">System.OutOfMemoryException</see> /// occurs during allocation of the /// result array. Callers should use /// <see cref="OpenStream()">OpenStream()</see> /// instead to access the contents. /// </exception> /// <exception cref="NGit.Errors.MissingObjectException">the object is large, and it no longer exists. /// </exception> /// <exception cref="System.IO.IOException">the object store cannot be accessed.</exception> public virtual byte[] GetCachedBytes(int sizeLimit) { if (!IsLarge()) { return(GetCachedBytes()); } ObjectStream @in = OpenStream(); try { long sz = @in.GetSize(); if (sizeLimit < sz) { throw new LargeObjectException.ExceedsLimit(sizeLimit, sz); } if (int.MaxValue < sz) { throw new LargeObjectException.ExceedsByteArrayLimit(); } byte[] buf; try { buf = new byte[(int)sz]; } catch (OutOfMemoryException notEnoughHeap) { throw new LargeObjectException.OutOfMemory(notEnoughHeap); } IOUtil.ReadFully(@in, buf, 0, buf.Length); return(buf); } finally { @in.Close(); } }