Author: toad
Date: 2006-03-11 00:11:20 +0000 (Sat, 11 Mar 2006)
New Revision: 8222
Added:
trunk/freenet/src/freenet/node/fcp/BaseDataCarryingMessage.java
trunk/freenet/src/freenet/node/fcp/ClientPutComplexDirMessage.java
trunk/freenet/src/freenet/node/fcp/DirPutFile.java
trunk/freenet/src/freenet/node/fcp/DirectDirPutFile.java
trunk/freenet/src/freenet/node/fcp/DiskDirPutFile.java
Modified:
trunk/freenet/src/freenet/node/Version.java
trunk/freenet/src/freenet/node/fcp/ClientPutDirMessage.java
trunk/freenet/src/freenet/node/fcp/ClientPutDiskDirMessage.java
trunk/freenet/src/freenet/node/fcp/DataCarryingMessage.java
trunk/freenet/src/freenet/node/fcp/FCPConnectionInputHandler.java
trunk/freenet/src/freenet/node/fcp/FCPMessage.java
Log:
523: 80% of ClientPutComplexDir support. The rest will follow soon.
Still no persistence support for putdir's.
Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2006-03-10 22:35:51 UTC (rev
8221)
+++ trunk/freenet/src/freenet/node/Version.java 2006-03-11 00:11:20 UTC (rev
8222)
@@ -20,7 +20,7 @@
public static final String protocolVersion = "1.0";
/** The build number of the current revision */
- private static final int buildNumber = 522;
+ private static final int buildNumber = 523;
/** Oldest build of Fred we will talk to */
private static final int lastGoodBuild = 507;
Added: trunk/freenet/src/freenet/node/fcp/BaseDataCarryingMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/BaseDataCarryingMessage.java
2006-03-10 22:35:51 UTC (rev 8221)
+++ trunk/freenet/src/freenet/node/fcp/BaseDataCarryingMessage.java
2006-03-11 00:11:20 UTC (rev 8222)
@@ -0,0 +1,25 @@
+package freenet.node.fcp;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import freenet.node.Node;
+import freenet.support.Bucket;
+import freenet.support.BucketFactory;
+import freenet.support.SimpleFieldSet;
+
+public abstract class BaseDataCarryingMessage extends FCPMessage {
+
+ abstract long dataLength();
+
+ public abstract void readFrom(InputStream is, BucketFactory bf,
FCPServer server) throws IOException, MessageInvalidException;
+
+ public void send(OutputStream os) throws IOException {
+ super.send(os);
+ writeData(os);
+ }
+
+ protected abstract void writeData(OutputStream os) throws IOException;
+
+}
Added: trunk/freenet/src/freenet/node/fcp/ClientPutComplexDirMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPutComplexDirMessage.java
2006-03-10 22:35:51 UTC (rev 8221)
+++ trunk/freenet/src/freenet/node/fcp/ClientPutComplexDirMessage.java
2006-03-11 00:11:20 UTC (rev 8222)
@@ -0,0 +1,128 @@
+package freenet.node.fcp;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+
+import freenet.node.Node;
+import freenet.support.BucketFactory;
+import freenet.support.SimpleFieldSet;
+
+/**
+ * ClientPutComplexDir
+ * < ... standard ClientPutDir headers ... >
+ * Files.1.Name=hello.txt
+ * Files.1.UploadFrom=direct
+ * Files.1.Metadata.ContentType=text/plain
+ * Files.1.DataLength=6
+ * ( upload the 6 bytes following this message as hello.txt, type plain text)
+ * Files.2.Name=something.pdf
+ * Files.2.UploadFrom=disk
+ * Files.2.Filename=something.pdf
+ * ( upload something.pdf, guess the mime type from the filename )
+ * Files.AnythingNotIncludingADotInIt.Name=toad.jpeg
+ * Files.AnythingNotIncludingADotInIt.UploadFrom=redirect
+ * Files.AnythingNotIncludingADotInIt.TargetURI=CHK at ...,...,...
+ * Files.AnythingNotIncludingADotInIt.Metadata.ContentType=image/jpeg
+ * ( not yet supported, but would be really useful! FIXME ! )
+ * ...
+ */
+public class ClientPutComplexDirMessage extends ClientPutDirMessage {
+
+ /** The files attached to this message, in a directory hierarchy */
+ private final HashMap filesByName;
+ /** Any files we want to read data from */
+ private final LinkedList filesToRead;
+ /** Total number of bytes of attached data */
+ private final long attachedBytes;
+
+ public ClientPutComplexDirMessage(SimpleFieldSet fs, BucketFactory
bfTemp, BucketFactory bfPersistent) throws MessageInvalidException {
+ // Parse the standard ClientPutDir headers - URI, etc.
+ super(fs);
+
+ filesByName = new HashMap();
+ filesToRead = new LinkedList();
+ long totalBytes = 0;
+ // Now parse the meat
+ SimpleFieldSet files = fs.subset("Files");
+ if(files == null)
+ throw new
MessageInvalidException(ProtocolErrorMessage.MISSING_FIELD, "Missing Files
section", identifier);
+ Iterator i = files.directSubsetNameIterator();
+ while(i.hasNext()) {
+ String name = (String) i.next();
+ SimpleFieldSet subset = files.subset(name);
+ DirPutFile f = DirPutFile.create(subset, identifier,
(persistenceType == ClientRequest.PERSIST_FOREVER) ? bfPersistent : bfTemp);
+ addFile(f);
+ if(f instanceof DirectDirPutFile) {
+ totalBytes +=
((DirectDirPutFile)f).bytesToRead();
+ }
+ }
+ attachedBytes = totalBytes;
+ }
+
+ /**
+ * Add a file to the filesByName.
+ * @throws MessageInvalidException
+ */
+ private void addFile(DirPutFile f) throws MessageInvalidException {
+ addFile(filesByName, f.getName(), f);
+ }
+
+ private void addFile(HashMap byName, String name, DirPutFile f) throws
MessageInvalidException {
+ int idx = name.indexOf('/');
+ if(idx == -1) {
+ byName.put(name, f);
+ } else {
+ String before = name.substring(0, idx);
+ String after = name.substring(idx+1);
+ Object o = byName.get(before);
+ if(o != null) {
+ if(o instanceof HashMap) {
+ addFile((HashMap)o, after, f);
+ return;
+ } else {
+ throw new
MessageInvalidException(ProtocolErrorMessage.INVALID_MESSAGE, "Cannot be both a
file and a directory: "+before, identifier);
+ }
+ }
+ }
+ }
+
+ static final String name = "ClientPutComplexDir";
+
+ public String getName() {
+ return name;
+ }
+
+ long dataLength() {
+ return attachedBytes;
+ }
+
+ String getIdentifier() {
+ return identifier;
+ }
+
+ public void readFrom(InputStream is, BucketFactory bf, FCPServer
server) throws IOException, MessageInvalidException {
+ Iterator i = filesToRead.iterator();
+ while(i.hasNext()) {
+ DirectDirPutFile f = (DirectDirPutFile) i.next();
+ f.read(is);
+ }
+ }
+
+ protected void writeData(OutputStream os) throws IOException {
+ Iterator i = filesToRead.iterator();
+ while(i.hasNext()) {
+ DirectDirPutFile f = (DirectDirPutFile) i.next();
+ f.write(os);
+ }
+ }
+
+ public void run(FCPConnectionHandler handler, Node node) throws
MessageInvalidException {
+ // TODO Auto-generated method stub
+
+ }
+
+}
Modified: trunk/freenet/src/freenet/node/fcp/ClientPutDirMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPutDirMessage.java 2006-03-10
22:35:51 UTC (rev 8221)
+++ trunk/freenet/src/freenet/node/fcp/ClientPutDirMessage.java 2006-03-11
00:11:20 UTC (rev 8222)
@@ -25,7 +25,8 @@
* Persistence=<Persistence as ClientPut>
* Global=<Global as ClientPut>
*/
-public abstract class ClientPutDirMessage extends FCPMessage {
+public abstract class ClientPutDirMessage extends BaseDataCarryingMessage {
+ // Some subtypes of this (ClientPutComplexDirMessage) may carry a
payload.
final String identifier;
final FreenetURI uri;
Modified: trunk/freenet/src/freenet/node/fcp/ClientPutDiskDirMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPutDiskDirMessage.java
2006-03-10 22:35:51 UTC (rev 8221)
+++ trunk/freenet/src/freenet/node/fcp/ClientPutDiskDirMessage.java
2006-03-11 00:11:20 UTC (rev 8222)
@@ -1,10 +1,14 @@
package freenet.node.fcp;
import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.util.HashMap;
import freenet.client.async.ManifestElement;
import freenet.node.Node;
+import freenet.support.BucketFactory;
import freenet.support.Fields;
import freenet.support.Logger;
import freenet.support.SimpleFieldSet;
@@ -84,4 +88,20 @@
return ret;
}
+ long dataLength() {
+ return 0;
+ }
+
+ String getIdentifier() {
+ return identifier;
+ }
+
+ public void readFrom(InputStream is, BucketFactory bf, FCPServer
server) throws IOException, MessageInvalidException {
+ // Do nothing
+ }
+
+ protected void writeData(OutputStream os) throws IOException {
+ // Do nothing
+ }
+
}
Modified: trunk/freenet/src/freenet/node/fcp/DataCarryingMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/DataCarryingMessage.java 2006-03-10
22:35:51 UTC (rev 8221)
+++ trunk/freenet/src/freenet/node/fcp/DataCarryingMessage.java 2006-03-11
00:11:20 UTC (rev 8222)
@@ -10,12 +10,10 @@
import freenet.support.Logger;
-public abstract class DataCarryingMessage extends FCPMessage {
+public abstract class DataCarryingMessage extends BaseDataCarryingMessage {
protected Bucket bucket;
- abstract long dataLength();
-
Bucket createBucket(BucketFactory bf, long length, FCPServer server)
throws IOException {
return bf.makeBucket(length);
}
@@ -44,12 +42,11 @@
this.bucket = bucket;
}
- public void send(OutputStream os) throws IOException {
- super.send(os);
+ protected void writeData(OutputStream os) throws IOException {
BucketTools.copyTo(bucket, os, dataLength());
if(freeOnSent) bucket.free();
}
-
+
String getEndString() {
return "Data";
}
Added: trunk/freenet/src/freenet/node/fcp/DirPutFile.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/DirPutFile.java 2006-03-10 22:35:51 UTC
(rev 8221)
+++ trunk/freenet/src/freenet/node/fcp/DirPutFile.java 2006-03-11 00:11:20 UTC
(rev 8222)
@@ -0,0 +1,52 @@
+package freenet.node.fcp;
+
+import freenet.client.ClientMetadata;
+import freenet.client.DefaultMIMETypes;
+import freenet.support.BucketFactory;
+import freenet.support.SimpleFieldSet;
+
+/**
+ * A request to upload a file to a manifest.
+ * A ClientPutComplexDir will contain many of these.
+ */
+abstract class DirPutFile {
+
+ final String name;
+ final ClientMetadata meta;
+
+ public DirPutFile(SimpleFieldSet subset, String identifier) throws
MessageInvalidException {
+ this.name = subset.get("Name");
+ if(name == null)
+ throw new
MessageInvalidException(ProtocolErrorMessage.MISSING_FIELD, "Missing field
Name", identifier);
+ String contentTypeOverride = subset.get("Metadata.ContentType");
+ if(contentTypeOverride != null) {
+ meta = new ClientMetadata(contentTypeOverride);
+ } else {
+ meta = new ClientMetadata(guessMIME());
+ }
+ }
+
+ protected String guessMIME() {
+ // Guess it just from the name
+ return DefaultMIMETypes.guessMIMEType(name);
+ }
+
+ /**
+ * Create a DirPutFile from a SimpleFieldSet.
+ */
+ public static DirPutFile create(SimpleFieldSet subset, String
identifier, BucketFactory bf) throws MessageInvalidException {
+ String type = subset.get("UploadFrom");
+ if(type == null || type.equalsIgnoreCase("direct")) {
+ return new DirectDirPutFile(subset, identifier, bf);
+ } else if(type.equalsIgnoreCase("disk")) {
+ return new DiskDirPutFile(subset, identifier);
+ } else {
+ throw new
MessageInvalidException(ProtocolErrorMessage.INVALID_FIELD, "Unsupported or
unknown UploadFrom: "+type, identifier);
+ }
+ }
+
+ public String getName() {
+ return name;
+ }
+
+}
Added: trunk/freenet/src/freenet/node/fcp/DirectDirPutFile.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/DirectDirPutFile.java 2006-03-10
22:35:51 UTC (rev 8221)
+++ trunk/freenet/src/freenet/node/fcp/DirectDirPutFile.java 2006-03-11
00:11:20 UTC (rev 8222)
@@ -0,0 +1,49 @@
+package freenet.node.fcp;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import freenet.support.Bucket;
+import freenet.support.BucketFactory;
+import freenet.support.BucketTools;
+import freenet.support.SimpleFieldSet;
+
+/**
+ * Specialized DirPutFile for direct uploads.
+ */
+public class DirectDirPutFile extends DirPutFile {
+
+ private final Bucket data;
+ private final long length;
+
+ public DirectDirPutFile(SimpleFieldSet subset, String identifier,
BucketFactory bf) throws MessageInvalidException {
+ super(subset, identifier);
+ String s = subset.get("DataLength");
+ if(s == null)
+ throw new
MessageInvalidException(ProtocolErrorMessage.MISSING_FIELD, "UploadFrom=direct
requires a DataLength for "+name, identifier);
+ try {
+ length = Long.parseLong(s);
+ } catch (NumberFormatException e) {
+ throw new
MessageInvalidException(ProtocolErrorMessage.ERROR_PARSING_NUMBER, "Could not
parse DataLength: "+e.toString(), identifier);
+ }
+ try {
+ data = bf.makeBucket(length);
+ } catch (IOException e) {
+ throw new
MessageInvalidException(ProtocolErrorMessage.INTERNAL_ERROR, "Internal error:
could not allocate temp bucket: "+e.toString(), identifier);
+ }
+ }
+
+ public long bytesToRead() {
+ return length;
+ }
+
+ public void read(InputStream is) throws IOException {
+ BucketTools.copyFrom(data, is, length);
+ }
+
+ public void write(OutputStream os) throws IOException {
+ BucketTools.copyTo(data, os, length);
+ }
+
+}
Added: trunk/freenet/src/freenet/node/fcp/DiskDirPutFile.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/DiskDirPutFile.java 2006-03-10
22:35:51 UTC (rev 8221)
+++ trunk/freenet/src/freenet/node/fcp/DiskDirPutFile.java 2006-03-11
00:11:20 UTC (rev 8222)
@@ -0,0 +1,28 @@
+package freenet.node.fcp;
+
+import java.io.File;
+
+import freenet.client.DefaultMIMETypes;
+import freenet.support.SimpleFieldSet;
+
+public class DiskDirPutFile extends DirPutFile {
+
+ final File file;
+
+ public DiskDirPutFile(SimpleFieldSet subset, String identifier) throws
MessageInvalidException {
+ super(subset, identifier);
+ String s = subset.get("Filename");
+ if(s == null)
+ throw new
MessageInvalidException(ProtocolErrorMessage.MISSING_FIELD, "Missing field:
Filename on "+name, identifier);
+ file = new File(s);
+ }
+
+ protected String guessMIME() {
+ String mime = super.guessMIME();
+ if(mime == null) {
+ mime = DefaultMIMETypes.guessMIMEType(file.getName());
+ }
+ return mime;
+ }
+
+}
Modified: trunk/freenet/src/freenet/node/fcp/FCPConnectionInputHandler.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/FCPConnectionInputHandler.java
2006-03-10 22:35:51 UTC (rev 8221)
+++ trunk/freenet/src/freenet/node/fcp/FCPConnectionInputHandler.java
2006-03-11 00:11:20 UTC (rev 8222)
@@ -52,7 +52,7 @@
fs = new SimpleFieldSet(lis, 4096, 128, false, false);
FCPMessage msg;
try {
- msg = FCPMessage.create(messageType, fs);
+ msg = FCPMessage.create(messageType, fs,
handler.bf, handler.server.node.persistentTempBucketFactory);
if(msg == null) continue;
} catch (MessageInvalidException e) {
FCPMessage err = new
ProtocolErrorMessage(e.protocolCode, false, e.getMessage(), e.ident);
@@ -65,10 +65,10 @@
handler.close();
continue;
}
- if(msg instanceof DataCarryingMessage) {
+ if(msg instanceof BaseDataCarryingMessage) {
// FIXME tidy up - coalesce with above and
below try { } catch (MIE) {}'s?
try {
-
((DataCarryingMessage)msg).readFrom(lis, handler.bf, handler.server);
+
((BaseDataCarryingMessage)msg).readFrom(lis, handler.bf, handler.server);
} catch (MessageInvalidException e) {
FCPMessage err = new
ProtocolErrorMessage(e.protocolCode, false, e.getMessage(), e.ident);
handler.outputHandler.queue(err);
Modified: trunk/freenet/src/freenet/node/fcp/FCPMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/FCPMessage.java 2006-03-10 22:35:51 UTC
(rev 8221)
+++ trunk/freenet/src/freenet/node/fcp/FCPMessage.java 2006-03-11 00:11:20 UTC
(rev 8222)
@@ -4,6 +4,7 @@
import java.io.OutputStream;
import freenet.node.Node;
+import freenet.support.BucketFactory;
import freenet.support.SimpleFieldSet;
public abstract class FCPMessage {
@@ -24,7 +25,10 @@
public abstract String getName();
- public static FCPMessage create(String name, SimpleFieldSet fs) throws
MessageInvalidException {
+ /**
+ * Create a message from a SimpleFieldSet, and the message's name, if
possible.
+ */
+ public static FCPMessage create(String name, SimpleFieldSet fs,
BucketFactory bfTemp, BucketFactory bfPersistent) throws
MessageInvalidException {
if(name.equals(ClientHelloMessage.name))
return new ClientHelloMessage(fs);
if(name.equals(ClientGetMessage.name))
@@ -43,6 +47,8 @@
return new ModifyPersistentRequest(fs);
if(name.equals(ClientPutDiskDirMessage.name))
return new ClientPutDiskDirMessage(fs);
+ if(name.equals(ClientPutComplexDirMessage.name))
+ return new ClientPutComplexDirMessage(fs, bfTemp,
bfPersistent);
if(name.equals("Void"))
return null;
throw new
MessageInvalidException(ProtocolErrorMessage.INVALID_MESSAGE, "Unknown message
name "+name, null);