#7 - Treat non-text formats as binary; download them into a separate structure.
M src/main/java/com/ajtjp/geminiclient/GeminiClient.java +53 -9
@@ 54,20 54,64 @@ public class GeminiClient {
             return connect(doc.meta, 1965);
         }
         
-        StringBuilder sb = new StringBuilder();
-        byte[] buffer = new byte[2000];
-        
-        while (true) {
-            int bytesRead = is.read(buffer, 0, 2000);
-            if (bytesRead == -1) {
-                doc.lines = parseLines(sb.toString());
-                return doc;
+        if (doc.getMeta().startsWith("text/")) {
+            //TODO: Should this apply for text/xml; text/plain; etc. as well
+            //as text/gemini?  Quite possible not.  Leaving it for now as I
+            //haven't seen any issues with pretending text/plain; is
+            //text/gemini;, yet, and non-text; needs more support first.
+            StringBuilder sb = new StringBuilder();
+            byte[] buffer = new byte[2000];
+
+            while (true) {
+                int bytesRead = is.read(buffer, 0, 2000);
+                if (bytesRead == -1) {
+                    doc.lines = parseLines(sb.toString());
+                    return doc;
+                }
+                sb.append(new String(buffer, 0, bytesRead, "UTF-8"));
             }
-            sb.append(new String(buffer, 0, bytesRead, "UTF-8"));
+        }
+        else {
+            byte[] fileContents = new byte[4096];
+            byte[] buffer = new byte[2000];
+            int fileContentsIndex = 0;
+
+            while (true) {
+                int bytesRead = is.read(buffer, 0, 2000);
+                if (bytesRead == -1) {
+                    fileContents = trimBufferToSize(fileContents, fileContentsIndex);
+                    
+                    doc.setBinaryContents(fileContents);
+                    return doc;
+                }
+                
+                //expand and re-allocate wholeBuffer if need be
+                if (fileContentsIndex + bytesRead > fileContents.length) {
+                    fileContents = expandFileContents(fileContents, fileContentsIndex);
+                }
+                
+                System.arraycopy(buffer, 0, fileContents, fileContentsIndex, bytesRead);
+                fileContentsIndex += bytesRead;
+            }
         }
         
     }
 
+    private static byte[] trimBufferToSize(byte[] fileContents, int wholeBufferIndex) {
+        //trim to size
+        byte[] oldBuffer = fileContents;
+        fileContents = new byte[wholeBufferIndex];
+        System.arraycopy(oldBuffer, 0, fileContents, 0, wholeBufferIndex);
+        return fileContents;
+    }
+
+    private static byte[] expandFileContents(byte[] wholeBuffer, int wholeBufferIndex) {
+        byte[] oldBuffer = wholeBuffer;
+        wholeBuffer = new byte[wholeBuffer.length * 2];
+        System.arraycopy(oldBuffer, 0, wholeBuffer, 0, wholeBufferIndex);
+        return wholeBuffer;
+    }
+
     private static String extractHost(String url) {
         //        String hardcodedURL = "rawtext.club";
         

          
M src/main/java/com/ajtjp/geminiclient/GeminiDocument.java +21 -0
@@ 4,6 4,18 @@ import com.ajtjp.geminiclient.lines.Gemi
 import java.util.ArrayList;
 import java.util.List;
 
+/**
+ * This class really represents two things:
+ *  - A Gemini (the format) document
+ *  - A resource loaded via the Gemini protocol
+ * Initially, when the focus was entirely on loading Gemini format documents
+ * over the Gemini protocol, these were basically the same.
+ * However, now that support for loading things that aren't even text over the
+ * Gemini protocol is being added, these should probably be de-conflated at
+ * some point.  Leaving that as tech debt for now, to see if that looks like a
+ * concern once the non-Gemini (format) support is working.
+ * @author Andrew
+ */
 public class GeminiDocument {
     String documentURL;
     String headers; //eventually, will parse this out more semantically

          
@@ 11,6 23,7 @@ public class GeminiDocument {
     String meta;
     
     List<GeminiLine> lines;
+    private byte[] binaryContents;
     
     public GeminiDocument(String url) {
         this.documentURL = url;

          
@@ 47,4 60,12 @@ public class GeminiDocument {
     public String getMeta() {
         return meta;
     }
+
+    public byte[] getBinaryContents() {
+        return binaryContents;
+    }
+
+    public void setBinaryContents(byte[] binaryContents) {
+        this.binaryContents = binaryContents;
+    }
 }