]> source.dussan.org Git - jgit.git/commitdiff
Improve LargeObjectException reporting 60/1460/1
authorShawn O. Pearce <spearce@spearce.org>
Mon, 30 Aug 2010 18:53:25 +0000 (11:53 -0700)
committerShawn O. Pearce <spearce@spearce.org>
Mon, 30 Aug 2010 18:53:25 +0000 (11:53 -0700)
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>
org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/PackFileTest.java
org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/UnpackedObjectTest.java
org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties
org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java
org.eclipse.jgit/src/org/eclipse/jgit/errors/LargeObjectException.java
org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectLoader.java
org.eclipse.jgit/src/org/eclipse/jgit/storage/file/LargePackedDeltaObject.java
org.eclipse.jgit/src/org/eclipse/jgit/storage/file/LargePackedWholeObject.java
org.eclipse.jgit/src/org/eclipse/jgit/storage/file/UnpackedObject.java
org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/DeltaWindow.java

index f31bf558c86babfb194527a84e63c801d09080dd..9a4bc0b1abd0e9d694bfe3fc27deb330915fddf9 100644 (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();
index 25dfe4c2394e733312603afc904cf329aeaf7003..ab7445b17b46810da2b9b7038c24c75918180b6c 100644 (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();
index 0c3d0e5d87fada369c9e22b7da5352919b435be0..14c0ba0fc8c25bc917198a54b1ae2cc1f35f9501 100644 (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
index fc12e571350646a947ba309ebf66b9b834ad0c55..ea40fe8847405ac80f092499aaaa10df41bc8625 100644 (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;
index f77aecbb426da9eeb35787fa521f23b19efa0438..a1107dc35feb15657ba9bc9ca8187f454b384eaa 100644 (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);
+               }
        }
 }
index b7e58ea156a25408de6233fb2f4a5f669e422abd..0fc3bce65bd1a96718a019c38afdec1d08f05b0e 100644 (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);
index 02e218216d509bab79f0e646adaf062ac7c6edc5..2b98f107f814efe3c613d2057578d3f2ab8a60b8 100644 (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;
                }
        }
 
index 9f5b804ce424bf843ae2601d56adee59036a8133..9550be4e1d630edb38fd3342767ee4f3990a1c37 100644 (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;
                }
        }
 
index 78e7b10a7dc0eb440a5a37aff746f4c374dd3507..4065019dc5be1e1c919363bf8c80f9cd722e0464 100644 (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);
index d5296a03e34e8482363b7dc9c898a31cd156d570..6a71ad7dcf121304eaab8927e03b85ac65c7af1c 100644 (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)