Index: org/tigris/subversion/javahl/BlameCallbackImpl.java
===================================================================
--- org/tigris/subversion/javahl/BlameCallbackImpl.java	(revision 0)
+++ org/tigris/subversion/javahl/BlameCallbackImpl.java	(revision 0)
@@ -0,0 +1,223 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Copyright (c) 2007 CollabNet.  All rights reserved.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution.  The terms
+ * are also available at http://subversion.tigris.org/license-1.html.
+ * If newer versions of this license are posted there, you may use a
+ * newer version instead, at your option.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals.  For exact contribution history, see the revision
+ * history and logs, available at http://subversion.tigris.org/.
+ * ====================================================================
+ * @endcopyright
+ */
+package org.tigris.subversion.javahl;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Implementation of {@link BlameCallback} interface.
+ *  
+ */
+public class BlameCallbackImpl implements BlameCallback {
+	
+	/** list of annotation records (lines) */
+	private List lines = new ArrayList();
+
+	/* (non-Javadoc)
+	 * @see org.tigris.subversion.javahl.BlameCallback#singleLine(java.util.Date, long, java.lang.String, java.lang.String)
+	 */
+	public void singleLine(Date changed, long revision, String author, String line) {
+		addBlameLine(new BlameLine(revision, author, changed, line));
+		
+	}
+
+	protected BlameLine getBlameLine(int i) {
+		if (i >= this.lines.size()) {
+			return null;
+		}
+		return (BlameLine) this.lines.get(i);
+	}
+
+	/**
+	 * Append the given blame info to the list
+	 * @param blameLine
+	 */
+	protected void addBlameLine(BlameLine blameLine)
+	{
+		this.lines.add(blameLine);
+	}
+	
+	public long getRevision(int lineNumber) {
+		BlameLine blameLine = getBlameLine(lineNumber);
+		if (blameLine == null) {
+			return -1;
+		} else {
+			return blameLine.getRevision();
+		}
+	}
+
+	public String getAuthor(int lineNumber) {
+		BlameLine blameLine = getBlameLine(lineNumber);
+		if (blameLine == null) {
+			return null;
+		} else {
+			return blameLine.getAuthor();
+		}
+	}
+
+	public Date getChanged(int lineNumber) {
+		BlameLine blameLine = getBlameLine(lineNumber);
+		if (blameLine == null) {
+			return null;
+		} else {
+			return blameLine.getChanged();
+		}
+	}
+
+	public String getLine(int lineNumber) {
+		BlameLine blameLine = getBlameLine(lineNumber);
+		if (blameLine == null) {
+			return null;
+		} else {
+			return blameLine.getLine();
+		}
+	}
+
+	public String getFormattedBlameLine(int lineNumber) {
+		BlameLine blameLine = getBlameLine(lineNumber);
+		if (blameLine == null) {
+			return null;
+		} else {
+			return blameLine.toString();
+		}
+	}
+
+	public int numberOfLines() {
+		return this.lines.size();
+	}
+
+	/**
+	 * Class represeting one line of the lines, i.e. a blame record
+	 * 
+	 */
+	public static class BlameLine {
+
+		private long revision;
+
+		private String author;
+
+		private Date changed;
+
+		private String line;
+
+		/**
+		 * Constructor
+		 * 
+		 * @param revision
+		 * @param author
+		 * @param changed
+		 * @param line
+		 */
+		public BlameLine(long revision, String author, Date changed,
+				String line) {
+			super();
+			this.revision = revision;
+			this.author = author;
+			this.changed = changed;
+			this.line = line;
+		}
+
+		/**
+		 * @return Returns the author.
+		 */
+		public String getAuthor() {
+			return author;
+		}
+
+		/**
+		 * @return Returns the changed.
+		 */
+		public Date getChanged() {
+			return changed;
+		}
+
+		/**
+		 * @return Returns the line.
+		 */
+		public String getLine() {
+			return line;
+		}
+
+		/**
+		 * @param line The line to set.
+		 */
+		public void setLine(String line) {
+			this.line = line;
+		}
+
+		/**
+		 * @return Returns the revision.
+		 */
+		public long getRevision() {
+			return revision;
+		}
+
+		/* (non-Javadoc)
+		 * @see java.lang.Object#toString()
+		 */
+		public String toString() {
+			StringBuffer sb = new StringBuffer();
+			if (revision > 0)
+            {
+                pad(sb, Long.toString(revision), 6);
+                sb.append(' ');
+            }
+            else
+            {
+                sb.append("     - ");
+            }
+
+            if (author != null)
+            {
+                pad(sb, author, 10);
+                sb.append(" ");
+            }
+            else
+            {
+                sb.append("         - ");
+            }
+
+            sb.append(line);
+            
+            return sb.toString();
+		}
+
+        /**
+         * Left pad the input string to a given length, to simulate printf()-
+         * style output.  This method appends the output to the class sb
+         * member.
+         * @param sb        StringBuffer to append to
+         * @param val       the input string
+         * @param len       the minimum length to pad to
+         */
+        private void pad(StringBuffer sb, String val, int len)
+        {
+            int padding = len - val.length();
+
+            for (int i = 0; i < padding; i++)
+            {
+                sb.append(' ');
+            }
+
+            sb.append(val);
+        }
+		
+	}
+}

Property changes on: org\tigris\subversion\javahl\BlameCallbackImpl.java
___________________________________________________________________
Name: svn:eol-style
   + native

Index: org/tigris/subversion/javahl/tests/BasicTests.java
===================================================================
--- org/tigris/subversion/javahl/tests/BasicTests.java	(revision 23940)
+++ org/tigris/subversion/javahl/tests/BasicTests.java	(working copy)
@@ -27,7 +27,6 @@
 import java.io.ByteArrayOutputStream;
 import java.util.Arrays;
 import java.util.HashMap;
-import java.util.Date;
 
 /**
  * Tests the basic functionality of javahl binding (inspired by the
@@ -53,80 +52,7 @@
         }
     }
 
-    private class BlameReceiver
-        implements BlameCallback
-    {
-        private StringBuffer sb = new StringBuffer();
-
-        private void pad(String val, int len)
-        {
-            int padding = len - val.length();
-
-            for (int i = 0; i < padding; i++)
-            {
-                sb.append(" ");
-            }
-
-            sb.append(val);
-        }
-
-        public void singleLine(Date changed, long revision, String author,
-               String line)
-        {
-            if (revision > 0)
-            {
-                pad(Long.toString(revision), 6);
-                sb.append(" ");
-            }
-            else
-            {
-                sb.append("     - ");
-            }
-
-            if (author != null)
-            {
-                pad(author, 10);
-                sb.append(" ");
-            }
-            else
-            {
-                sb.append("         - ");
-            }
-
-            sb.append(line);
-            sb.append("\n");
-        }
-
-        public String getResult()
-        {
-            return sb.toString();
-        }
-    }
-
     /**
-     * Test basic blame functionality.  This test marginally tests blame
-     * correctness, mainly just that the blame APIs link correctly.
-     * @throws Throwable
-     * @since 1.5
-     */
-    public void testBasicBlame()
-            throws Throwable
-    {
-        String expected = "     1    jrandom This is the file 'iota'.\n";
-        OneTest thisTest = new OneTest();
-
-        byte[] result = client.blame(thisTest.getWCPath() + "/iota",
-                Revision.getInstance(1), Revision.getInstance(1));
-        assertEquals(expected, new String(result));
-
-        BlameReceiver callback = new BlameReceiver();
-        client.blame(thisTest.getWCPath() + "/iota", 
-                Revision.getInstance(1), Revision.getInstance(1),
-                callback);
-        assertEquals(expected, callback.getResult());
-    }
-    
-    /**
      * Test SVNClient.getVersion().
      * @throws Throwable
      */
@@ -2411,6 +2337,31 @@
     }
 
     /**
+     * Test basic blame functionality.  This test marginally tests blame
+     * correctness, mainly just that the blame APIs link correctly.
+     * @throws Throwable
+     * @since 1.5
+     */
+    public void testBasicBlame()
+            throws Throwable
+    {
+        String expected = "     1    jrandom This is the file 'iota'.\n";
+        OneTest thisTest = new OneTest();
+
+        byte[] result = client.blame(thisTest.getWCPath() + "/iota",
+                Revision.getInstance(1), Revision.getInstance(1));
+        assertEquals(expected, new String(result));
+
+        BlameCallbackImpl callback = new BlameCallbackImpl();
+        client.blame(thisTest.getWCPath() + "/iota", 
+                Revision.getInstance(1), Revision.getInstance(1),
+                callback);
+        assertEquals(1, callback.numberOfLines());
+        assertEquals(1, callback.getRevision(0));
+        assertEquals("jrandom", callback.getAuthor(0));
+    }
+
+    /**
      * A DiffSummaryReceiver implementation which collects all
      * DiffSummary notifications.
      */
Index: org/tigris/subversion/javahl/SVNClient.java
===================================================================
--- org/tigris/subversion/javahl/SVNClient.java	(revision 23940)
+++ org/tigris/subversion/javahl/SVNClient.java	(working copy)
@@ -20,7 +20,6 @@
 
 import java.io.File;
 import java.io.OutputStream;
-import java.util.Date;
 
 /**
  * This is the main interface class. All subversion commandline client svn &
@@ -1287,10 +1286,15 @@
     public byte[] blame(String path, Revision revisionStart,
                         Revision revisionEnd) throws ClientException
     {
-        BlameReceiver callback = new BlameReceiver();
+        BlameCallbackImpl callback = new BlameCallbackImpl();
         blame(path, revisionEnd, revisionStart, revisionEnd, callback);
-
-        return callback.getResult().getBytes();
+        
+        StringBuffer sb = new StringBuffer();
+        for (int i=0; i < callback.numberOfLines(); i++) {
+        	sb.append(callback.getFormattedBlameLine(i));
+        	sb.append("\n");
+        }
+        return sb.toString().getBytes();
     }
     /**
      * Retrieve the content together with the author, the revision and the date
@@ -1509,73 +1513,4 @@
      * NativeResources.loadNativeLibrary
      */
     static native void initNative();
-
-    /**
-     * A {@link #blame()} callback which receives and collects line
-     * information, formatting it for textual output.
-     */
-    private static class BlameReceiver
-        implements BlameCallback
-    {
-        private StringBuffer sb = new StringBuffer();
-
-        /**
-         * Left pad the input string to a given length, to simulate printf()-
-         * style output.  This method appends the output to the class sb
-         * member.
-         * @param val       the input string
-         * @param len       the minimum length to pad to
-         */
-        private void pad(String val, int len)
-        {
-            int padding = len - val.length();
-
-            for (int i = 0; i < padding; i++)
-            {
-                sb.append(' ');
-            }
-
-            sb.append(val);
-        }
-
-        /**
-         * Append the line information to the current text.  Called
-         * once for each line.
-         */
-        public void singleLine(Date changed, long revision, String author,
-                               String line)
-        {
-            if (revision > 0)
-            {
-                pad(Long.toString(revision), 6);
-                sb.append(' ');
-            }
-            else
-            {
-                sb.append("     - ");
-            }
-
-            if (author != null)
-            {
-                pad(author, 10);
-                sb.append(" ");
-            }
-            else
-            {
-                sb.append("         - ");
-            }
-
-            sb.append(line);
-            sb.append("\n");
-        }
-
-        /**
-         * Return the current blame output as formatted text.
-         * @return The blame output.
-         */
-        public String getResult()
-        {
-            return sb.toString();
-        }
-    }
 }
