Permalink
Browse files

Can now download individual large files.

  • Loading branch information...
1 parent 3c7a15e commit 30c2f072da184966329c74129bf29352b3b6f316 @pauldoo committed Mar 18, 2012
View
@@ -1,6 +1,7 @@
TODO:
* Remove all semicolons?!?!
* Remove all returns
+* Use Apache Commons VFS
* Ensure code is sensibly split between lib and gui.
* Do IO asynchronously to the UI.
* Write a lift gui?
@@ -0,0 +1,27 @@
+package arqbrowser.gui
+import arqbrowser.lib.ArqBucket
+import arqbrowser.lib.ArqFile
+import arqbrowser.lib.Hash
+import java.io.File
+import java.io.FileOutputStream
+
+class ArqTreeFileNode(
+ val arqBucket: ArqBucket,
+ val dataHashes: List[Tuple2[Hash, Boolean]],
+ val displayName: String) extends TreeNodeAdapter {
+
+ val arqFile: ArqFile = {
+ val sha1s: List[Hash] = dataHashes.map(_._1);
+ new ArqFile(sha1s)
+ }
+
+ override val toString = displayName;
+
+ override def isLeaf() = true;
+
+ def saveToDisk(destination: File) = {
+ val out = new FileOutputStream(destination);
+ arqFile.writeContentTo(arqBucket, out);
+ out.close();
+ }
+}
@@ -31,7 +31,10 @@ class ArqTreeTreeNode(
child._2.dataHashes(0)._1,
child._1);
} else {
- new DefaultMutableTreeNode(child._1);
+ new ArqTreeFileNode(
+ arqBucket,
+ child._2.dataHashes,
+ child._1);
}
}
}
@@ -13,6 +13,7 @@ import arqbrowser.lib.ArqStore
import com.amazonaws.services.s3.AmazonS3Client
import javax.swing.JTree
import javax.swing.JScrollPane
+import java.io.File
object Login {
@@ -37,8 +38,24 @@ object Login {
new String(awsPrivate.getPassword()));
val tree = new JTree(new S3BucketTreeNode(awsCred));
+ val button = new JButton("GO!");
+ button.addActionListener(new ActionListener {
+ def actionPerformed(e: ActionEvent): Unit = {
+ val obj = tree.getSelectionPath().getLastPathComponent();
+ System.out.println(obj);
+
+ obj match {
+ case file: ArqTreeFileNode => {
+ file.saveToDisk(new File("/tmp/" + file.toString));
+ }
+ }
+ }
+ });
+ val panel = new JPanel();
+ panel.add(new JScrollPane(tree));
+ panel.add(button);
val frame = new JFrame();
- frame.add(new JScrollPane(tree));
+ frame.add(panel);
frame.setSize(800, 600);
frame.show();
}
@@ -6,6 +6,7 @@ import com.amazonaws.services.s3.model.S3ObjectSummary
import com.amazonaws.services.s3.model.GetObjectRequest
import scala.actors.Futures
import scala.actors.Future
+import java.util.zip.GZIPInputStream
class ArqBucket(
val s3client: AmazonS3,
@@ -51,9 +52,12 @@ class ArqBucket(
return s3client.getObject(new GetObjectRequest(
s3bucket,
- computerUuid + "/objects/" + hash.toString.toLowerCase())).getObjectContent();
+ computerUuid + "/objects/" + hash.toBlockText().toLowerCase())).getObjectContent();
}
def getDecryptedStreamForObject(hash: Hash): InputStream =
decrypter.decrypt(getRawStreamForObject(hash));
+
+ def getDecompressedAndDecryptedStreamForObject(hash: Hash): InputStream =
+ new GZIPInputStream(getDecryptedStreamForObject(hash));
}
@@ -0,0 +1,11 @@
+package arqbrowser.lib
+import java.io.OutputStream
+
+class ArqFile(val dataHashes: List[Hash]) {
+ def writeContentTo(arqBucket: ArqBucket, outstream: OutputStream): Unit = {
+ for (hash <- dataHashes) {
+ Utils.withInputStream(arqBucket.getDecompressedAndDecryptedStreamForObject(hash))(Utils.copyAll(_, outstream));
+ }
+ }
+}
+
@@ -29,8 +29,12 @@ final class Hash(val value: Array[Byte]) extends Ordered[Hash] {
}
}
+ def toBlockText(): String = {
+ Utils.bytesToBlockHex(value);
+ }
+
override val toString: String =
- Utils.bytesToHex(value);
+ Utils.bytesToReadableHex(value);
}
object Hash {
@@ -5,6 +5,7 @@ import java.io.DataInput
import java.io.DataInputStream
import java.io.InputStream
import java.io.ByteArrayOutputStream
+import java.io.OutputStream
object Utils {
def iterated[T](
@@ -26,7 +27,10 @@ object Utils {
case Seq(keyNode, elementNode) => (keyNode.text, elementNode.text)
}.toMap;
- def bytesToHex(bytes: Array[Byte]): String =
+ def bytesToBlockHex(bytes: Array[Byte]): String =
+ bytes.map(toUnsigned).map("%02X".format(_)).reduce(_ + _);
+
+ def bytesToReadableHex(bytes: Array[Byte]): String =
bytes.map(toUnsigned).map("%02X".format(_)).grouped(4).map(_.reduce(_ + _)).reduce(_ + " " + _);
def toUnsigned(b: Byte): Int = {
@@ -107,18 +111,22 @@ object Utils {
}
}
- def readAll(is: InputStream): Array[Byte] = {
- val buffer = new ByteArrayOutputStream();
+ def copyAll(in: InputStream, out: OutputStream): Unit = {
val data = new Array[Byte](10240);
while (true) {
- val length = is.read(data);
+ val length = in.read(data);
if (length != -1) {
- buffer.write(data, 0, length);
+ out.write(data, 0, length);
} else {
- return buffer.toByteArray();
+ return
}
}
- throw new RuntimeException("Unreachable.");
+ }
+
+ def readAll(is: InputStream): Array[Byte] = {
+ val buffer = new ByteArrayOutputStream();
+ copyAll(is, buffer);
+ return buffer.toByteArray();
}
def readVersionBytes(stream: DataInput): Int = {

0 comments on commit 30c2f07

Please sign in to comment.