diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/util/CastUtil.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/util/CastUtil.java new file mode 100644 index 0000000000..8dd4238551 --- /dev/null +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/util/CastUtil.java @@ -0,0 +1,18 @@ +package uk.ac.ic.wlgitbridge.bridge.util; + +import com.google.common.base.Preconditions; + +/** + * Created by winston on 01/07/2017. + */ +public class CastUtil { + + public static int assumeInt(long l) { + Preconditions.checkArgument( + l <= (long) Integer.MAX_VALUE + && l >= (long) Integer.MIN_VALUE, + l + " cannot fit inside an int"); + return (int) l; + } + +} diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/data/filestore/RepositoryFile.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/data/filestore/RepositoryFile.java index 465c23bfec..751c672d23 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/data/filestore/RepositoryFile.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/data/filestore/RepositoryFile.java @@ -1,7 +1,5 @@ package uk.ac.ic.wlgitbridge.data.filestore; -import java.util.Map.Entry; - /** * Created by Winston on 16/11/14. */ @@ -10,11 +8,6 @@ public class RepositoryFile extends RawFile { private final String path; private final byte[] contents; - public RepositoryFile(Entry fileContents) { - path = fileContents.getKey(); - contents = fileContents.getValue(); - } - public RepositoryFile(String path, byte[] contents) { this.path = path; this.contents = contents; diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/git/exception/SizeLimitExceededException.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/git/exception/SizeLimitExceededException.java index 46cf62c626..69c6bd014a 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/git/exception/SizeLimitExceededException.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/git/exception/SizeLimitExceededException.java @@ -4,14 +4,21 @@ import uk.ac.ic.wlgitbridge.util.Util; import java.util.Arrays; import java.util.List; +import java.util.Optional; public class SizeLimitExceededException extends GitUserException { - private final String path; + private final Optional path; - public SizeLimitExceededException(String path) { - super(); + private final long actualSize; + + private final long maxSize; + + public SizeLimitExceededException( + Optional path, long actualSize, long maxSize) { this.path = path; + this.actualSize = actualSize; + this.maxSize = maxSize; } @Override @@ -22,7 +29,7 @@ public class SizeLimitExceededException extends GitUserException { @Override public List getDescriptionLines() { String filename = - path != null ? "File '" + path + "' is" : "There's a file"; + path.isPresent() ? "File '" + path.get() + "' is" : "There's a file"; return Arrays.asList( filename + " too large to push to " + Util.getServiceName() + " via git", diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/git/util/RepositoryObjectTreeWalker.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/git/util/RepositoryObjectTreeWalker.java index 262cdd5d17..71bb8a1418 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/git/util/RepositoryObjectTreeWalker.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/git/util/RepositoryObjectTreeWalker.java @@ -1,19 +1,22 @@ package uk.ac.ic.wlgitbridge.git.util; -import org.eclipse.jgit.errors.LargeObjectException; import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ObjectLoader; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.treewalk.TreeWalk; +import uk.ac.ic.wlgitbridge.bridge.util.CastUtil; import uk.ac.ic.wlgitbridge.data.filestore.RawDirectory; import uk.ac.ic.wlgitbridge.data.filestore.RawFile; import uk.ac.ic.wlgitbridge.data.filestore.RepositoryFile; import uk.ac.ic.wlgitbridge.git.exception.InvalidGitRepository; import uk.ac.ic.wlgitbridge.git.exception.SizeLimitExceededException; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; +import java.util.Optional; /** * Created by Winston on 16/11/14. @@ -46,7 +49,14 @@ public class RepositoryObjectTreeWalker { public RawDirectory getDirectoryContents( ) throws IOException, SizeLimitExceededException, InvalidGitRepository { - return new RawDirectory(walkGitObjectTree()); + return getDirectoryContents(50 * 1024 * 1024); + } + + private RawDirectory getDirectoryContents(long maxFileSize) + throws IOException, + SizeLimitExceededException, + InvalidGitRepository { + return new RawDirectory(walkGitObjectTree(maxFileSize)); } private TreeWalk initTreeWalk( @@ -63,8 +73,10 @@ public class RepositoryObjectTreeWalker { return treeWalk; } - private Map walkGitObjectTree( - ) throws IOException, SizeLimitExceededException, InvalidGitRepository { + private Map walkGitObjectTree(long maxFileSize) + throws IOException, + SizeLimitExceededException, + InvalidGitRepository { Map fileContentsTable = new HashMap<>(); if (treeWalk == null) { return fileContentsTable; @@ -76,14 +88,18 @@ public class RepositoryObjectTreeWalker { if (!repository.hasObject(objectId)) { throw new InvalidGitRepository(); } - try { - byte[] content = repository.open( - objectId - ).getBytes(); - fileContentsTable.put(path, new RepositoryFile(path, content)); - } catch (LargeObjectException e) { - throw new SizeLimitExceededException(path); + ObjectLoader obj = repository.open(objectId); + long size = obj.getSize(); + if (size > maxFileSize) { + throw new SizeLimitExceededException( + Optional.ofNullable(path), size, maxFileSize); } + try (ByteArrayOutputStream o = new ByteArrayOutputStream( + CastUtil.assumeInt(size))) { + obj.copyTo(o); + fileContentsTable.put( + path, new RepositoryFile(path, o.toByteArray())); + }; } return fileContentsTable; }