From: David ‘Bombe’ Roden Date: Thu, 10 Apr 2008 10:39:21 +0000 (+0000) Subject: add ClientPut and PersistentPut X-Git-Url: https://git.pterodactylus.net/?a=commitdiff_plain;h=c866aafc3c75a2817358884cd1e08d240305528f;p=jSite2.git add ClientPut and PersistentPut git-svn-id: http://trooper/svn/projects/jSite/trunk@688 c3eda9e8-030b-0410-8277-bc7414b0a119 --- diff --git a/src/net/pterodactylus/util/fcp/ClientPut.java b/src/net/pterodactylus/util/fcp/ClientPut.java new file mode 100644 index 0000000..bfbe210 --- /dev/null +++ b/src/net/pterodactylus/util/fcp/ClientPut.java @@ -0,0 +1,222 @@ +/** + * © 2008 INA Service GmbH + */ +package net.pterodactylus.util.fcp; + +/** + * A “ClientPut” requests inserts a single file into freenet, either uploading + * it directly with this messge ({@link UploadFrom#direct}), uploading it from + * disk ({@link UploadFrom#disk}) or by creating a redirect to another URI ({@link UploadFrom#redirect}). + * + * @author David Roden + * @version $Id$ + */ +public class ClientPut extends FcpMessage { + + /** + * Creates a new “ClientPut” message that inserts a file to the given URI. + * The file data has to be supplied to this message using + * {@link #setPayloadInputStream(java.io.InputStream)}! + * + * Using this constructor is the same as using + * {@link #ClientPut(String, String, UploadFrom)} with + * {@link UploadFrom#direct} as third parameter. + * + * @param uri + * The URI to insert the file to + * @param identifier + * The identifier of the request + */ + public ClientPut(String uri, String identifier) { + this(uri, identifier, UploadFrom.direct); + } + + /** + * Creates a new “ClientPut” message that inserts a file to the given URI. + * Depending on uploadFrom the file data has to be supplied + * in different ways: + * + * If uploadFrom is {@link UploadFrom#direct}, use + * {@link #setPayloadInputStream(java.io.InputStream)} to supply the input + * data. + * + * If uploadFrom is {@link UploadFrom#disk}, use + * {@link #setFilename(String)} to supply the file to upload. You have to + * test your direct-disk access (see {@link TestDDARequest}, + * {@link TestDDAReply}, {@link TestDDAResponse}, {@link TestDDAComplete}) + * before using this option! + * + * If uploadFrom is {@link UploadFrom#redirect}, use + * {@link #setTargetURI(String)} to set the target URI of the redirect. + * + * @param uri + * The URI to insert to + * @param identifier + * The identifier of the insert + * @param uploadFrom + * The source of the upload + */ + public ClientPut(String uri, String identifier, UploadFrom uploadFrom) { + super("ClientPut"); + setField("URI", uri); + setField("Identifier", identifier); + setField("UploadFrom", String.valueOf(uploadFrom)); + } + + /** + * The MIME type of the content. + * + * @param metadataContentType + * The MIME type of the content + */ + public void setMetadataContentType(String metadataContentType) { + setField("Metadata.ContentType", metadataContentType); + } + + /** + * The verbosity of the request. Depending on this parameter you will + * received only the bare minimum of messages for the request (i.e. “it + * completed”) or a whole lot more. + * + * @see Verbosity + * @param verbosity + * The verbosity of the request + */ + public void setVerbosity(Verbosity verbosity) { + setField("Verbosity", String.valueOf(verbosity)); + } + + /** + * The number of retries for a request if the initial try failed. + * + * @param maxRetries + * The maximum number of retries after failure, or + * -1 to retry forever. + */ + public void setMaxRetries(int maxRetries) { + setField("MaxRetries", String.valueOf(maxRetries)); + } + + /** + * Sets the priority of the request. + * + * @param priority + * The priority of the request + */ + public void setPriority(Priority priority) { + setField("Priority", String.valueOf(priority)); + } + + /** + * Determines whether the node should really insert the data or generate the + * final CHK only. + * + * @param getCHKOnly + * true to generate the final CHK only, + * false to really insert the data + */ + public void setGetCHKOnly(boolean getCHKOnly) { + setField("GetCHKOnly", String.valueOf(getCHKOnly)); + } + + /** + * Determines whether this request appears on the global queue. + * + * @param global + * true to put the request on the global queue, + * false for the client-local queue. + */ + public void setGlobal(boolean global) { + setField("Global", String.valueOf(global)); + } + + /** + * Determines whether the node should skip compression because the file has + * already been compressed. + * + * @param dontCompress + * true to skip compression of the data in the + * node, false to allow compression + */ + public void setDontCompress(boolean dontCompress) { + setField("DontCompress", String.valueOf(dontCompress)); + } + + /** + * Sets an optional client token. This client token is mentioned in progress + * and other request-related messages and can be used to identify this + * request. + * + * @param clientToken + * The client token + */ + public void setClientToken(String clientToken) { + setField("ClientToken", clientToken); + } + + /** + * Sets the persistence of this request. + * + * @param persistence + * The persistence of this request + */ + public void setPersistence(Persistence persistence) { + setField("Persistence", String.valueOf(persistence)); + } + + /** + * Sets the target filename of the inserted file. This value is ignored for + * all inserts that do not have “CHK@” as a target. + * + * @param targetFilename + * The filename of the target + */ + public void setTargetFilename(String targetFilename) { + setField("TargetFilename", targetFilename); + } + + /** + * Determines whether to encode the complete file early in the life of the + * request. + * + * @param earlyEncode + * true to generate the final key long before the + * file is completely fetchable + */ + public void setEarlyEncode(boolean earlyEncode) { + setField("EarlyEncode", String.valueOf(earlyEncode)); + } + + /** + * Sets the length of the data that will be transferred after this message + * if uploadFrom is {@link UploadFrom#direct} is used. + * + * @param dataLength + * The length of the data + */ + public void setDataLength(long dataLength) { + setField("DataLength", String.valueOf(dataLength)); + } + + /** + * Sets the name of the file to upload the data from. + * + * @param filename + * The filename to upload + */ + public void setFilename(String filename) { + setField("Filename", filename); + } + + /** + * If uploadFrom is {@link UploadFrom#redirect}, use this + * method to determine that target of the redirect. + * + * @param targetURI + * The target URI to redirect to + */ + public void setTargetURI(String targetURI) { + setField("TargetURI", targetURI); + } + +} diff --git a/src/net/pterodactylus/util/fcp/FcpAdapter.java b/src/net/pterodactylus/util/fcp/FcpAdapter.java index 6ec19e3..a1bec35 100644 --- a/src/net/pterodactylus/util/fcp/FcpAdapter.java +++ b/src/net/pterodactylus/util/fcp/FcpAdapter.java @@ -104,6 +104,14 @@ public class FcpAdapter implements FcpListener { } /** + * @see net.pterodactylus.util.fcp.FcpListener#receivedPersistentPut(net.pterodactylus.util.fcp.FcpConnection, + * net.pterodactylus.util.fcp.PersistentPut) + */ + public void receivedPersistentPut(FcpConnection fcpConnection, PersistentPut persistentPut) { + /* empty. */ + } + + /** * @see net.pterodactylus.util.fcp.FcpListener#receivedProtocolError(net.pterodactylus.util.fcp.FcpConnection, * net.pterodactylus.util.fcp.ProtocolError) */ diff --git a/src/net/pterodactylus/util/fcp/FcpConnection.java b/src/net/pterodactylus/util/fcp/FcpConnection.java index dabb542..157093a 100644 --- a/src/net/pterodactylus/util/fcp/FcpConnection.java +++ b/src/net/pterodactylus/util/fcp/FcpConnection.java @@ -261,6 +261,7 @@ public class FcpConnection { /** * Notifies all listeners that a “TestDDAReply” message was received. * + * @see FcpListener#receivedTestDDAReply(FcpConnection, TestDDAReply) * @param testDDAReply * The “TestDDAReply” message */ @@ -273,6 +274,7 @@ public class FcpConnection { /** * Notifies all listeners that a “TestDDAComplete” message was received. * + * @see FcpListener#receivedTestDDAComplete(FcpConnection, TestDDAComplete) * @param testDDAComplete * The “TestDDAComplete” message */ @@ -283,6 +285,19 @@ public class FcpConnection { } /** + * Notifies all listeners that a “PersistentPut” message was received. + * + * @see FcpListener#receivedPersistentPut(FcpConnection, PersistentPut) + * @param persistentPut + * The “PersistentPut” message + */ + private void fireReceivedPersistentPut(PersistentPut persistentPut) { + for (FcpListener fcpListener: fcpListeners) { + fcpListener.receivedPersistentPut(this, persistentPut); + } + } + + /** * Notifies all listeners that a “ProtocolError” message was received. * * @param protocolError @@ -370,6 +385,8 @@ public class FcpConnection { String messageName = fcpMessage.getName(); if ("ProtocolError".equals(messageName)) { fireReceivedProtocolError(new ProtocolError(fcpMessage)); + } else if ("PersistentPut".equals(messageName)) { + fireReceivedPersistentPut(new PersistentPut(fcpMessage)); } else if ("Peer".equals(messageName)) { fireReceivedPeer(new Peer(fcpMessage)); } else if ("PeerNote".equals(messageName)) { diff --git a/src/net/pterodactylus/util/fcp/FcpListener.java b/src/net/pterodactylus/util/fcp/FcpListener.java index f17cdd3..928cdc9 100644 --- a/src/net/pterodactylus/util/fcp/FcpListener.java +++ b/src/net/pterodactylus/util/fcp/FcpListener.java @@ -141,6 +141,16 @@ public interface FcpListener extends EventListener { public void receivedTestDDAComplete(FcpConnection fcpConnection, TestDDAComplete testDDAComplete); /** + * Notifies a listener that a “PersistentPut” was received. + * + * @param fcpConnection + * The connection that received the message + * @param persistentPut + * The “PersistentPut” message + */ + public void receivedPersistentPut(FcpConnection fcpConnection, PersistentPut persistentPut); + + /** * Notifies a listener that a “ProtocolError” was received. * * @param fcpConnection diff --git a/src/net/pterodactylus/util/fcp/Persistence.java b/src/net/pterodactylus/util/fcp/Persistence.java new file mode 100644 index 0000000..5266ca2 --- /dev/null +++ b/src/net/pterodactylus/util/fcp/Persistence.java @@ -0,0 +1,29 @@ +/** + * © 2008 INA Service GmbH + */ +package net.pterodactylus.util.fcp; + +/** + * Convenience class for persistence values. + * + * @author David Roden + * @version $Id$ + */ +public enum Persistence { + + /** + * Connection persistence. A request with this persistence will die as soon + * as the connection goes down. + */ + connection, + + /** + * Reboot persistence. A request with this persistence will live until the + * node is restarted. + */ + reboot, + + /** Forever persistence. A request with this persistence will live forever. */ + forever; + +} diff --git a/src/net/pterodactylus/util/fcp/PersistentPut.java b/src/net/pterodactylus/util/fcp/PersistentPut.java new file mode 100644 index 0000000..4c7eb36 --- /dev/null +++ b/src/net/pterodactylus/util/fcp/PersistentPut.java @@ -0,0 +1,162 @@ +/** + * © 2008 INA Service GmbH + */ +package net.pterodactylus.util.fcp; + +/** + * A “PersistentPut” message notifies a client about a persistent + * {@link ClientPut} request. + * + * @author David Roden + * @version $Id$ + */ +public class PersistentPut extends BaseMessage { + + /** + * Creates a new “PersistentPut” message that wraps the received message. + * + * @param receivedMessage + * The received message + */ + public PersistentPut(FcpMessage receivedMessage) { + super(receivedMessage); + } + + /** + * Returns the client token of the request. + * + * @return The client token of the request + */ + public String getClientToken() { + return getField("ClientToken"); + } + + /** + * Returns the data length of the request. + * + * @return The data length of the request, or -1 if the + * length could not be parsed + */ + public long getDataLength() { + try { + return Long.valueOf(getField("DataLength")); + } catch (NumberFormatException nfe1) { + return -1; + } + } + + /** + * Returns whether the request is on the global queue. + * + * @return true if the request is on the global queue, + * false otherwise + */ + public boolean isGlobal() { + return Boolean.valueOf(getField("Global")); + } + + /** + * Returns the identifier of the request. + * + * @return The identifier of the request + */ + public String getIdentifier() { + return getField("Identifier"); + } + + /** + * Returns the maximum number of retries for failed blocks. When + * -1 is returned each block is tried forever. + * + * @return The maximum number of retries for failed blocks, or + * -1 for unlimited retries, or -2 if + * the number of retries could not be parsed + */ + public int getMaxRetries() { + try { + return Integer.valueOf(getField("MaxRetries")); + } catch (NumberFormatException nfe1) { + /* we need to return -2 here as -1 is also a valid value. */ + return -2; + } + } + + /** + * Returns the content type of the data. + * + * @return The content type + */ + public String getMetadataContentType() { + return getField("Metadata.ContentType"); + } + + /** + * Returns the persistence of the request. + * + * @return The persistence of the request + */ + public Persistence getPersistence() { + return Persistence.valueOf(getField("Persistence")); + } + + /** + * Returns the priority of the request. + * + * @return The priority of the request, or {@link Priority#unknown} if the + * priority could not be parsed + */ + public Priority getPriority() { + try { + return Priority.values()[Integer.valueOf(getField("Priority"))]; + } catch (NumberFormatException nfe1) { + return Priority.unknown; + } + } + + /** + * Returns whether this request has started. + * + * @return true if the request has started, + * false otherwise + */ + public boolean isStarted() { + return Boolean.valueOf(getField("Started")); + } + + /** + * Returns the target filename of the request. + * + * @return The target filename of the request + */ + public String getTargetFilename() { + return getField("TargetFilename"); + } + + /** + * Returns the upload source of the request. + * + * @return The upload source of the request + */ + public UploadFrom getUploadFrom() { + return UploadFrom.valueOf(getField("UploadFrom")); + } + + /** + * Returns the target URI of the request. + * + * @return The target URI of the request + */ + public String getURI() { + return getField("URI"); + } + + /** + * Returns the verbosity of the request. + * + * @return The verbosity of the request + */ + public Verbosity getVerbosity() { + return Verbosity.valueOf(getField("Verbosity")); + } + +} diff --git a/src/net/pterodactylus/util/fcp/Priority.java b/src/net/pterodactylus/util/fcp/Priority.java new file mode 100644 index 0000000..9e6a2ec --- /dev/null +++ b/src/net/pterodactylus/util/fcp/Priority.java @@ -0,0 +1,46 @@ +/** + * © 2008 INA Service GmbH + */ +package net.pterodactylus.util.fcp; + +/** + * The priority classes used by the Freenet node. + * + * @author David Roden + * @version $Id$ + */ +public enum Priority { + + /** Maximum priority. */ + maximum, + + /** Priority for interactive request, i.e. FProxy. */ + interactive, + + /** Priority for splitfile manifests. */ + immediateSplitfile, + + /** Priority for USK searches. */ + update, + + /** Priority for splitfile blocks. */ + bulkSplitfile, + + /** Priority for prefetching blocks. */ + prefetch, + + /** Minimum priority. */ + minimum, + + /** Unknown priority. */ + unknown; + + /** + * @see java.lang.Enum#toString() + */ + @Override + public String toString() { + return String.valueOf(ordinal()); + } + +} diff --git a/src/net/pterodactylus/util/fcp/UploadFrom.java b/src/net/pterodactylus/util/fcp/UploadFrom.java new file mode 100644 index 0000000..81736d5 --- /dev/null +++ b/src/net/pterodactylus/util/fcp/UploadFrom.java @@ -0,0 +1,24 @@ +/** + * © 2008 INA Service GmbH + */ +package net.pterodactylus.util.fcp; + +/** + * Enumeration for the different values for the “UploadFrom” field in + * {@link ClientPut} and {@link ClientGet} requests. + * + * @author David Roden + * @version $Id$ + */ +public enum UploadFrom { + + /** Request data follows the request. */ + direct, + + /** Request data is written to or read from disk. */ + disk, + + /** Request data is just a redirect. */ + redirect; + +} diff --git a/src/net/pterodactylus/util/fcp/Verbosity.java b/src/net/pterodactylus/util/fcp/Verbosity.java new file mode 100644 index 0000000..831a8cd --- /dev/null +++ b/src/net/pterodactylus/util/fcp/Verbosity.java @@ -0,0 +1,89 @@ +/** + * © 2008 INA Service GmbH + */ +package net.pterodactylus.util.fcp; + +/** + * Convenicence class for verbosity handling. This might come in handy with the + * {@link ClientPut} and {@link ClientGet} requests. + * + * The verbosity is a bit-mask that can be composed of several bits. + * {@link #PROGRESS} and {@link #COMPRESSION} are single bits in that mask and + * can be combined into a new verbosity using {@link #add(Verbosity)}. + * + * @author David Roden + * @version $Id$ + */ +public class Verbosity { + + /** Constant for no verbosity at all. */ + public static final Verbosity NONE = new Verbosity(0); + + /** Constant for progress message verbosity. */ + public static final Verbosity PROGRESS = new Verbosity(1); + + /** Constant for compression message verbosity. */ + public static final Verbosity COMPRESSION = new Verbosity(512); + + /** The verbosity level. */ + private final int level; + + /** + * Creates a new verbosity with the given level. + * + * @param level + * The verbosity level + */ + private Verbosity(int level) { + this.level = level; + } + + /** + * Adds the given verbosity to this verbosity and returns a verbosity with + * the new value. The value of this verbosity is not changed. + * + * @param verbosity + * The verbosity to add to this verbosity + * @return The verbosity with the new level. + */ + public Verbosity add(Verbosity verbosity) { + return new Verbosity(level | verbosity.level); + } + + /** + * Checks whether this Verbosity contains all bits of the given Verbosity. + * + * @param verbosity + * The verbosity to check for in this Verbosity + * @return true if and only if all set bits in the given + * Verbosity are also set in this Verbosity + */ + public boolean contains(Verbosity verbosity) { + return (level & verbosity.level) == verbosity.level; + } + + /** + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return String.valueOf(level); + } + + /** + * Parses the given string and creates a Verbosity with the given level. + * + * @param s + * The string to parse + * @return The parsed verbosity, or {@link #NONE} if the string could not be + * parsed + */ + public static Verbosity valueOf(String s) { + try { + return new Verbosity(Integer.valueOf(s)); + } catch (NumberFormatException nfe1) { + return NONE; + } + } + +}