ObjectUploadListener: Add callback interface

The callback interface is invoked after object upload was
completed.

Change-Id: I705d8becaf4f35188caf098aa75cff8963d64a60
Signed-off-by: David Pursehouse <david.pursehouse@gmail.com>
diff --git a/org.eclipse.jgit.lfs.server/.settings/.api_filters b/org.eclipse.jgit.lfs.server/.settings/.api_filters
new file mode 100644
index 0000000..ad4b9fc
--- /dev/null
+++ b/org.eclipse.jgit.lfs.server/.settings/.api_filters
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<component id="org.eclipse.jgit.lfs.server" version="2">
+    <resource path="META-INF/MANIFEST.MF">
+        <filter id="924844039">
+            <message_arguments>
+                <message_argument value="5.1.7"/>
+                <message_argument value="5.1.0"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/jgit/lfs/server/fs/ObjectUploadListener.java" type="org.eclipse.jgit.lfs.server.fs.ObjectUploadListener">
+        <filter id="1142947843">
+            <message_arguments>
+                <message_argument value="5.1.7"/>
+                <message_argument value="setCallback(ObjectUploadListener.Callback)"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/jgit/lfs/server/fs/ObjectUploadListener.java" type="org.eclipse.jgit.lfs.server.fs.ObjectUploadListener$Callback">
+        <filter id="1142947843">
+            <message_arguments>
+                <message_argument value="5.1.7"/>
+                <message_argument value="Callback"/>
+            </message_arguments>
+        </filter>
+    </resource>
+</component>
diff --git a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/ObjectUploadListener.java b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/ObjectUploadListener.java
index c5b6a67..3bb2899 100644
--- a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/ObjectUploadListener.java
+++ b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/ObjectUploadListener.java
@@ -48,6 +48,7 @@
 import java.nio.channels.Channels;
 import java.nio.channels.ReadableByteChannel;
 import java.nio.channels.WritableByteChannel;
+import java.nio.file.Path;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -87,6 +88,29 @@ public class ObjectUploadListener implements ReadListener {
 
 	private final ByteBuffer buffer = ByteBuffer.allocateDirect(8192);
 
+	private final Path path;
+
+	private long uploaded;
+
+	private Callback callback;
+
+	/**
+	 * Callback invoked after object upload completed.
+	 *
+	 * @since 5.1.7
+	 */
+	public interface Callback {
+		/**
+		 * Notified after object upload completed.
+		 *
+		 * @param path
+		 *            path to the object on the backend
+		 * @param size
+		 *            uploaded size in bytes
+		 */
+		void uploadCompleted(String path, long size);
+	}
+
 	/**
 	 * Constructor for ObjectUploadListener.
 	 *
@@ -113,10 +137,25 @@ public ObjectUploadListener(FileLfsRepository repository,
 		this.inChannel = Channels.newChannel(in);
 		this.out = repository.getOutputStream(id);
 		this.channel = Channels.newChannel(out);
+		this.path = repository.getPath(id);
+		this.uploaded = 0L;
 		response.setContentType(Constants.CONTENT_TYPE_GIT_LFS_JSON);
 	}
 
 	/**
+	 * Set the callback to invoke after upload completed.
+	 *
+	 * @param callback
+	 *            the callback
+	 * @return {@code this}.
+	 * @since 5.1.7
+	 */
+	public ObjectUploadListener setCallback(Callback callback) {
+		this.callback = callback;
+		return this;
+	}
+
+	/**
 	 * {@inheritDoc}
 	 *
 	 * Writes all the received data to the output channel
@@ -126,12 +165,13 @@ public void onDataAvailable() throws IOException {
 		while (in.isReady()) {
 			if (inChannel.read(buffer) > 0) {
 				buffer.flip();
-				channel.write(buffer);
+				uploaded += Integer.valueOf(channel.write(buffer)).longValue();
 				buffer.compact();
 			} else {
 				buffer.flip();
 				while (buffer.hasRemaining()) {
-					channel.write(buffer);
+					uploaded += Integer.valueOf(channel.write(buffer))
+							.longValue();
 				}
 				close();
 				return;
@@ -159,6 +199,9 @@ protected void close() throws IOException {
 			if (!response.isCommitted()) {
 				response.setStatus(HttpServletResponse.SC_OK);
 			}
+			if (callback != null) {
+				callback.uploadCompleted(path.toString(), uploaded);
+			}
 		} finally {
 			context.complete();
 		}