Browse Source

Improve LargeObjectException reporting

Use 3 different types of LargeObjectException for the 3 major ways
that we can fail to load an object.  For each of these use a unique
string translation which describes the root cause better than just
the ObjectId.name() does.

Change-Id: I810c98d5691b74af9fc6cbd46fc9879e35a7bdca
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
tags/v0.9.1
Shawn O. Pearce 13 years ago
parent
commit
e6bd689d2c

+ 11
- 3
org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/PackFileTest.java View File

@@ -47,9 +47,11 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.zip.Deflater;

import org.eclipse.jgit.JGitText;
import org.eclipse.jgit.errors.LargeObjectException;
import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
import org.eclipse.jgit.junit.TestRepository;
@@ -133,7 +135,9 @@ public class PackFileTest extends LocalDiskRepositoryTestCase {
ol.getCachedBytes();
fail("Should have thrown LargeObjectException");
} catch (LargeObjectException tooBig) {
assertEquals(id.name(), tooBig.getMessage());
assertEquals(MessageFormat.format(
JGitText.get().largeObjectException, id.name()), tooBig
.getMessage());
}

ObjectStream in = ol.openStream();
@@ -257,7 +261,9 @@ public class PackFileTest extends LocalDiskRepositoryTestCase {
ol.getCachedBytes();
fail("Should have thrown LargeObjectException");
} catch (LargeObjectException tooBig) {
assertEquals(id3.name(), tooBig.getMessage());
assertEquals(MessageFormat.format(
JGitText.get().largeObjectException, id3.name()), tooBig
.getMessage());
}

ObjectStream in = ol.openStream();
@@ -313,7 +319,9 @@ public class PackFileTest extends LocalDiskRepositoryTestCase {
ol.getCachedBytes();
fail("Should have thrown LargeObjectException");
} catch (LargeObjectException tooBig) {
assertEquals(id3.name(), tooBig.getMessage());
assertEquals(MessageFormat.format(
JGitText.get().largeObjectException, id3.name()), tooBig
.getMessage());
}

ObjectStream in = ol.openStream();

+ 6
- 2
org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/UnpackedObjectTest.java View File

@@ -135,7 +135,9 @@ public class UnpackedObjectTest extends LocalDiskRepositoryTestCase {
ol.getCachedBytes();
fail("Should have thrown LargeObjectException");
} catch (LargeObjectException tooBig) {
assertEquals(id.name(), tooBig.getMessage());
assertEquals(MessageFormat.format(
JGitText.get().largeObjectException, id.name()), tooBig
.getMessage());
}

ObjectStream in = ol.openStream();
@@ -416,7 +418,9 @@ public class UnpackedObjectTest extends LocalDiskRepositoryTestCase {
ol.getCachedBytes();
fail("Should have thrown LargeObjectException");
} catch (LargeObjectException tooBig) {
assertEquals(id.name(), tooBig.getMessage());
assertEquals(MessageFormat.format(
JGitText.get().largeObjectException, id.name()), tooBig
.getMessage());
}

ObjectStream in = ol.openStream();

+ 5
- 0
org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties View File

@@ -216,6 +216,10 @@ invalidWildcards=Invalid wildcards {0}
invalidWindowSize=Invalid window size
isAStaticFlagAndHasNorevWalkInstance={0} is a static flag and has no RevWalk instance
kNotInRange=k {0} not in {1} - {2}
largeObjectException={0} exceeds size limit
largeObjectOutOfMemory=Out of memory loading {0}
largeObjectExceedsByteArray=Object {0} exceeds 2 GiB byte array limit
largeObjectExceedsLimit=Object {0} exceeds {1} limit, actual size is {2}
lengthExceedsMaximumArraySize=Length exceeds maximum array size
listingAlternates=Listing alternates
localObjectsIncomplete=Local objects incomplete.
@@ -374,6 +378,7 @@ unexpectedReportLine=unexpected report line: {0}
unknownDIRCVersion=Unknown DIRC version {0}
unknownHost=unknown host
unknownIndexVersionOrCorruptIndex=Unknown index version (or corrupt index): {0}
unknownObject=unknown object
unknownObjectType=Unknown object type {0}.
unknownRepositoryFormat2=Unknown repository format "{0}"; expected "0".
unknownRepositoryFormat=Unknown repository format

+ 5
- 0
org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java View File

@@ -276,6 +276,10 @@ public class JGitText extends TranslationBundle {
/***/ public String invalidWindowSize;
/***/ public String isAStaticFlagAndHasNorevWalkInstance;
/***/ public String kNotInRange;
/***/ public String largeObjectException;
/***/ public String largeObjectOutOfMemory;
/***/ public String largeObjectExceedsByteArray;
/***/ public String largeObjectExceedsLimit;
/***/ public String lengthExceedsMaximumArraySize;
/***/ public String listingAlternates;
/***/ public String localObjectsIncomplete;
@@ -433,6 +437,7 @@ public class JGitText extends TranslationBundle {
/***/ public String unknownDIRCVersion;
/***/ public String unknownHost;
/***/ public String unknownIndexVersionOrCorruptIndex;
/***/ public String unknownObject;
/***/ public String unknownObjectType;
/***/ public String unknownRepositoryFormat2;
/***/ public String unknownRepositoryFormat;

+ 73
- 1
org.eclipse.jgit/src/org/eclipse/jgit/errors/LargeObjectException.java View File

@@ -43,6 +43,9 @@

package org.eclipse.jgit.errors;

import java.text.MessageFormat;

import org.eclipse.jgit.JGitText;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.ObjectId;

@@ -73,6 +76,13 @@ public class LargeObjectException extends RuntimeException {
return objectId;
}

/** @return either the hex encoded name of the object, or 'unknown object'. */
protected String getObjectName() {
if (getObjectId() != null)
return getObjectId().name();
return JGitText.get().unknownObject;
}

/**
* Set the identity of the object, if its not already set.
*
@@ -86,6 +96,68 @@ public class LargeObjectException extends RuntimeException {

@Override
public String getMessage() {
return objectId != null ? objectId.name() : getClass().getSimpleName();
return MessageFormat.format(JGitText.get().largeObjectException,
getObjectName());
}

/** An error caused by the JVM being out of heap space. */
public static class OutOfMemory extends LargeObjectException {
private static final long serialVersionUID = 1L;

/**
* Construct a wrapper around the original OutOfMemoryError.
*
* @param cause
* the original root cause.
*/
public OutOfMemory(OutOfMemoryError cause) {
initCause(cause);
}

@Override
public String getMessage() {
return MessageFormat.format(JGitText.get().largeObjectOutOfMemory,
getObjectName());
}
}

/** Object size exceeds JVM limit of 2 GiB per byte array. */
public static class ExceedsByteArrayLimit extends LargeObjectException {
private static final long serialVersionUID = 1L;

@Override
public String getMessage() {
return MessageFormat
.format(JGitText.get().largeObjectExceedsByteArray,
getObjectName());
}
}

/** Object size exceeds the caller's upper limit. */
public static class ExceedsLimit extends LargeObjectException {
private static final long serialVersionUID = 1L;

private final long limit;

private final long size;

/**
* Construct an exception for a particular size being exceeded.
*
* @param limit
* the limit the caller imposed on the object.
* @param size
* the actual size of the object.
*/
public ExceedsLimit(long limit, long size) {
this.limit = limit;
this.size = size;
}

@Override
public String getMessage() {
return MessageFormat.format(JGitText.get().largeObjectExceedsLimit,
getObjectName(), limit, size);
}
}
}

+ 7
- 4
org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectLoader.java View File

@@ -139,7 +139,7 @@ public abstract class ObjectLoader {
try {
return cloneArray(cached);
} catch (OutOfMemoryError tooBig) {
throw new LargeObjectException();
throw new LargeObjectException.OutOfMemory(tooBig);
}
}

@@ -195,14 +195,17 @@ public abstract class ObjectLoader {
ObjectStream in = openStream();
try {
long sz = in.getSize();
if (sizeLimit < sz || Integer.MAX_VALUE < sz)
throw new LargeObjectException();
if (sizeLimit < sz)
throw new LargeObjectException.ExceedsLimit(sizeLimit, sz);

if (Integer.MAX_VALUE < sz)
throw new LargeObjectException.ExceedsByteArrayLimit();

byte[] buf;
try {
buf = new byte[(int) sz];
} catch (OutOfMemoryError notEnoughHeap) {
throw new LargeObjectException();
throw new LargeObjectException.OutOfMemory(notEnoughHeap);
}

IO.readFully(in, buf, 0, buf.length);

+ 3
- 1
org.eclipse.jgit/src/org/eclipse/jgit/storage/file/LargePackedDeltaObject.java View File

@@ -157,7 +157,9 @@ class LargePackedDeltaObject extends ObjectLoader {
try {
throw new LargeObjectException(getObjectId());
} catch (IOException cannotObtainId) {
throw new LargeObjectException();
LargeObjectException err = new LargeObjectException();
err.initCause(cannotObtainId);
throw err;
}
}


+ 3
- 1
org.eclipse.jgit/src/org/eclipse/jgit/storage/file/LargePackedWholeObject.java View File

@@ -97,7 +97,9 @@ class LargePackedWholeObject extends ObjectLoader {
try {
throw new LargeObjectException(getObjectId());
} catch (IOException cannotObtainId) {
throw new LargeObjectException();
LargeObjectException err = new LargeObjectException();
err.initCause(cannotObtainId);
throw err;
}
}


+ 12
- 4
org.eclipse.jgit/src/org/eclipse/jgit/storage/file/UnpackedObject.java View File

@@ -125,8 +125,12 @@ public class UnpackedObject {
if (hdr[p.value++] != 0)
throw new CorruptObjectException(id,
JGitText.get().corruptObjectGarbageAfterSize);
if (path == null && Integer.MAX_VALUE < size)
throw new LargeObjectException(id.copy());
if (path == null && Integer.MAX_VALUE < size) {
LargeObjectException.ExceedsByteArrayLimit e;
e = new LargeObjectException.ExceedsByteArrayLimit();
e.setObjectId(id);
throw e;
}
if (size < wc.getStreamFileThreshold() || path == null) {
byte[] data = new byte[(int) size];
int n = avail - p.value;
@@ -163,8 +167,12 @@ public class UnpackedObject {
JGitText.get().corruptObjectInvalidType);
}

if (path == null && Integer.MAX_VALUE < size)
throw new LargeObjectException(id.copy());
if (path == null && Integer.MAX_VALUE < size) {
LargeObjectException.ExceedsByteArrayLimit e;
e = new LargeObjectException.ExceedsByteArrayLimit();
e.setObjectId(id);
throw e;
}
if (size < wc.getStreamFileThreshold() || path == null) {
in.reset();
IO.skipFully(in, p);

+ 3
- 2
org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/DeltaWindow.java View File

@@ -424,8 +424,9 @@ class DeltaWindow {
try {
idx = new DeltaIndex(buffer(ent));
} catch (OutOfMemoryError noMemory) {
LargeObjectException e = new LargeObjectException(ent.object);
e.initCause(noMemory);
LargeObjectException.OutOfMemory e;
e = new LargeObjectException.OutOfMemory(noMemory);
e.setObjectId(ent.object);
throw e;
}
if (0 < maxMemory)

Loading…
Cancel
Save