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);


Reply via email to