Author: jflesch
Date: 2006-07-06 17:38:01 +0000 (Thu, 06 Jul 2006)
New Revision: 9478
Added:
trunk/apps/Thaw/src/thaw/core/WarningWindow.java
trunk/apps/Thaw/src/thaw/fcp/
trunk/apps/Thaw/src/thaw/fcp/FCPClientHello.java
trunk/apps/Thaw/src/thaw/fcp/FCPConnection.java
trunk/apps/Thaw/src/thaw/fcp/FCPMessage.java
trunk/apps/Thaw/src/thaw/fcp/FCPQuery.java
trunk/apps/Thaw/src/thaw/fcp/FCPQueryManager.java
trunk/apps/Thaw/src/thaw/fcp/FCPQueueManager.java
Removed:
trunk/apps/Thaw/src/thaw/queue/
Modified:
trunk/apps/Thaw/src/thaw/core/Config.java
trunk/apps/Thaw/src/thaw/core/Core.java
trunk/apps/Thaw/src/thaw/core/Logger.java
trunk/apps/Thaw/src/thaw/core/MainWindow.java
trunk/apps/Thaw/src/thaw/core/NodeConfigPanel.java
trunk/apps/Thaw/src/thaw/i18n/thaw.properties
Log:
Starting FCP implementation (ClientHello and NodeHello implemented)
Modified: trunk/apps/Thaw/src/thaw/core/Config.java
===================================================================
--- trunk/apps/Thaw/src/thaw/core/Config.java 2006-07-06 16:08:28 UTC (rev
9477)
+++ trunk/apps/Thaw/src/thaw/core/Config.java 2006-07-06 17:38:01 UTC (rev
9478)
@@ -5,6 +5,7 @@
import java.io.File;
import java.util.Set;
import java.util.Iterator;
+import java.util.Random;
/* XML */
import org.w3c.dom.Document;
@@ -296,6 +297,7 @@
setValue("nodePort", "9481");
setValue("maxSimultaneousDownloads", "5");
setValue("maxSimultaneousInsertions", "2");
+ setValue("thawId", "thaw-"+(new Integer((new
Random()).nextInt(1000))).toString());
}
}
Modified: trunk/apps/Thaw/src/thaw/core/Core.java
===================================================================
--- trunk/apps/Thaw/src/thaw/core/Core.java 2006-07-06 16:08:28 UTC (rev
9477)
+++ trunk/apps/Thaw/src/thaw/core/Core.java 2006-07-06 17:38:01 UTC (rev
9478)
@@ -1,20 +1,29 @@
package thaw.core;
+import java.util.Observer;
+import java.util.Observable;
import thaw.i18n.I18n;
+import thaw.fcp.*;
/**
* A "core" contains references to all the main parts of Thaw.
*
*/
-public class Core {
+public class Core implements Observer {
private MainWindow mainWindow = null;
private Config config = null;
private PluginManager pluginManager = null;
private ConfigWindow configWindow = null;
+ private FCPConnection connection = null;
+ private FCPQueryManager queryManager = null;
+ private FCPQueueManager queueManager = null;
+ private FCPClientHello clientHello = null;
+
+
/**
* Creates a core, but do nothing else (no initialization).
*/
@@ -64,6 +73,9 @@
if(!initConfig())
return false;
+ if(!initNodeConnection())
+ return false;
+
if(!initGraphics())
return false;
@@ -101,8 +113,84 @@
return true;
}
+
+ /**
+ * Init the connection to the node.
+ * If a connection is already established, it will disconnect, so this
function could be call safely later.
+ */
+ public boolean initNodeConnection() {
+ if(getMainWindow() != null)
+
getMainWindow().setStatus(I18n.getMessage("thaw.statusBar.connecting"));
+ try {
+
+ if(connection != null && connection.isConnected())
+ connection.disconnect();
+
+ connection = new
FCPConnection(config.getValue("nodeAddress"),
+ (new
Integer(config.getValue("nodePort"))).intValue());
+
+ if(!connection.connect()) {
+ new WarningWindow(this, "Unable to connect to
"+config.getValue("nodeAddress")+":"+
+ config.getValue("nodePort"));
+
+ /* Not returning false,
+ else it will break the loading */
+ }
+
+ queryManager = new FCPQueryManager(connection);
+ queueManager = new FCPQueueManager(queryManager,
+ (new
Integer(config.getValue("maxSimultaneousDownloads"))).intValue(),
+ (new
Integer(config.getValue("maxSimultaneousInsertions"))).intValue());
+ if(connection.isConnected()) {
+ queryManager.startListening();
+
+ clientHello = new
FCPClientHello(config.getValue("thawId"));
+
+ if(!clientHello.start(queryManager)) {
+ new WarningWindow(this,
I18n.getMessage("thaw.error.idAlreadyUsed"));
+ } else {
+ Logger.debug(this, "Hello successful");
+ Logger.debug(this, "Node name :
"+clientHello.getNodeName());
+ Logger.debug(this, "FCP version :
"+clientHello.getNodeFCPVersion());
+ Logger.debug(this, "Node version :
"+clientHello.getNodeVersion());
+ }
+
+ }
+
+ } catch(Exception e) { /* A little bit not ... "nice" ... */
+ Logger.warning(this, "Exception while connecting :
"+e.toString()+" ; "+e.getMessage() + " ; "+e.getCause());
+ e.printStackTrace();
+ new WarningWindow(this, "Unable to connect to the node.
Please check your configuration.");
+ }
+
+ if(connection.isConnected())
+ connection.addObserver(this);
+
+ if(getMainWindow() != null)
+
getMainWindow().setStatus(I18n.getMessage("thaw.statusBar.ready"));
+
+ return true;
+ }
+
+
+ public FCPConnection getConnectionManager() {
+ return connection;
+ }
+
+ public FCPQueueManager getQueueManger() {
+ return queueManager;
+ }
+
/**
+ * FCPClientHello object contains all the information given by the node
when the connection
+ * was initiated.
+ */
+ public FCPClientHello getClientHello() {
+ return clientHello;
+ }
+
+ /**
* Init graphics.
*/
public boolean initGraphics() {
@@ -148,4 +236,13 @@
+ public void update(Observable o, Object target) {
+ Logger.debug(this, "Move on the connection (?)");
+
+ if(o == connection && !connection.isConnected()) {
+ new WarningWindow(this, "We have been disconnected");
+ connection.deleteObserver(this);
+ }
+ }
+
}
Modified: trunk/apps/Thaw/src/thaw/core/Logger.java
===================================================================
--- trunk/apps/Thaw/src/thaw/core/Logger.java 2006-07-06 16:08:28 UTC (rev
9477)
+++ trunk/apps/Thaw/src/thaw/core/Logger.java 2006-07-06 17:38:01 UTC (rev
9478)
@@ -19,16 +19,14 @@
* 3 or more is recommanded.
* 5 is never logged in a file, only on stdout.
*/
- private final static int LOG_LEVEL = 3;
+ private final static int LOG_LEVEL = 5;
protected static void displayErr(String msg) {
- // TODO : Log to a file
System.err.println(msg);
}
protected static void display(String msg) {
- // TODO : Log to a file
System.out.println(msg);
}
@@ -82,6 +80,14 @@
*/
public static void verbose(Object o, String msg) {
if(LOG_LEVEL >= 5)
- System.out.println(o.getClass().getName()+": "+msg);
+ System.out.println("[VERBOSE] "+
o.getClass().getName()+": "+msg);
}
+
+ /**
+ * As it. Similar to verbose()
+ */
+ public static void asIt(Object o, String msg) {
+ if(LOG_LEVEL >= 5)
+ System.out.println(msg);
+ }
}
Modified: trunk/apps/Thaw/src/thaw/core/MainWindow.java
===================================================================
--- trunk/apps/Thaw/src/thaw/core/MainWindow.java 2006-07-06 16:08:28 UTC
(rev 9477)
+++ trunk/apps/Thaw/src/thaw/core/MainWindow.java 2006-07-06 17:38:01 UTC
(rev 9478)
@@ -97,10 +97,15 @@
mainWindow.setVisible(v);
}
+
+ public JFrame getMainFrame() {
+ return mainWindow;
+ }
+
/**
* Should not be used.
- * @see #addTab(String, JPanel)
+ * @see #addTab(String, java.awt.Component)
* @return In the future, it's possible that it will sometimes return
null.
*/
public JTabbedPane getTabbedPane() {
@@ -109,6 +114,7 @@
/**
* Used to add a tab in the main window.
+ * In the future, even if the interface, this function should remain
available.
*/
public boolean addTab(String tabName, java.awt.Component panel) {
tabbedPane.addTab(tabName, panel);
Modified: trunk/apps/Thaw/src/thaw/core/NodeConfigPanel.java
===================================================================
--- trunk/apps/Thaw/src/thaw/core/NodeConfigPanel.java 2006-07-06 16:08:28 UTC
(rev 9477)
+++ trunk/apps/Thaw/src/thaw/core/NodeConfigPanel.java 2006-07-06 17:38:01 UTC
(rev 9478)
@@ -28,14 +28,16 @@
I18n.getMessage("thaw.config.nodeAddress"),
I18n.getMessage("thaw.config.nodePort"),
I18n.getMessage("thaw.config.maxSimultaneousDownloads"),
- I18n.getMessage("thaw.config.maxSimultaneousInsertions")
+ I18n.getMessage("thaw.config.maxSimultaneousInsertions"),
+ I18n.getMessage("thaw.config.thawId")
};
private final static String[] configNames = {
"nodeAddress",
"nodePort",
"maxSimultaneousDownloads",
- "maxSimultaneousInsertions"
+ "maxSimultaneousInsertions",
+ "thawId"
};
private JLabel[] paramLabels = new JLabel[paramNames.length];
@@ -75,6 +77,9 @@
for(int i=0;i < paramNames.length;i++) {
core.getConfig().setValue(configNames[i],
paramFields[i].getText());
}
+
+ /* should reinit the whole connection correctly */
+ core.initNodeConnection();
}
Added: trunk/apps/Thaw/src/thaw/core/WarningWindow.java
===================================================================
--- trunk/apps/Thaw/src/thaw/core/WarningWindow.java 2006-07-06 16:08:28 UTC
(rev 9477)
+++ trunk/apps/Thaw/src/thaw/core/WarningWindow.java 2006-07-06 17:38:01 UTC
(rev 9478)
@@ -0,0 +1,30 @@
+package thaw.core;
+
+import javax.swing.JOptionPane;
+
+
+/**
+ * Use to create a warning popup.
+ * Currently this popup is simple as possible, but
+ * in the future, it may become more complex, showing,
+ * for example, last log messages.
+ */
+public class WarningWindow {
+
+
+ public WarningWindow(Core core,
+ String warning)
+ {
+ if(core.getMainWindow() != null) {
+
JOptionPane.showMessageDialog(core.getMainWindow().getMainFrame(),
+ warning,
+ "Warning",
+
JOptionPane.WARNING_MESSAGE);
+ } else {
+ JOptionPane.showMessageDialog(null,
+ warning,
+ "Warning",
+
JOptionPane.WARNING_MESSAGE);
+ }
+ }
+}
Copied: trunk/apps/Thaw/src/thaw/fcp (from rev 9412,
trunk/apps/Thaw/src/thaw/queue)
Added: trunk/apps/Thaw/src/thaw/fcp/FCPClientHello.java
===================================================================
--- trunk/apps/Thaw/src/thaw/queue/FCPClientHello.java 2006-06-30 20:35:07 UTC
(rev 9412)
+++ trunk/apps/Thaw/src/thaw/fcp/FCPClientHello.java 2006-07-06 17:38:01 UTC
(rev 9478)
@@ -0,0 +1,148 @@
+package thaw.fcp;
+
+import java.util.Observer;
+import java.util.Observable;
+
+import thaw.core.Logger;
+
+/**
+ * http://wiki.freenetproject.org/FreenetFCPSpec2Point0
+ * See "ClientHello" and "NodeHello".
+ * Note: This query disconnect you if node answer
CloseConnectionDuplicateClientName
+ * and start() returns false.
+ */
+public class FCPClientHello implements FCPQuery, Observer {
+
+ private final static String FCP_EXPECTED_VERSION = "2.0";
+ private String id = null;
+
+ private String nodeFCPVersion = null;
+ private String nodeVersion = null;
+ private String nodeName = null;
+ private boolean testnet = false; /* Hmm, in fact, we shouldn't have to
bother about this one */
+ private int nmbCompressionCodecs = -1;
+
+ private boolean receiveAnswer = false;
+
+ private FCPQueryManager queryManager = null;
+
+
+ /**
+ * Need to know the id of the application (see FCP specs).
+ */
+ public FCPClientHello(String id) {
+ setID(id);
+ }
+
+
+ public void setID(String id) {
+ this.id = id;
+ }
+
+ public int getThawPriority() {
+ return -1;
+ }
+
+ public String getNodeFCPVersion() {
+ return nodeFCPVersion;
+ }
+
+ public String getNodeVersion() {
+ return nodeVersion;
+ }
+
+ public String getNodeName() {
+ return nodeName;
+ }
+
+ public boolean isOnTestnet() {
+ return testnet;
+ }
+
+ public int getNmbCompressionCodecs() {
+ return nmbCompressionCodecs;
+ }
+
+
+ /**
+ * Warning: This query is blocking (only this one) !
+ */
+ public boolean start(FCPQueryManager queryManager) {
+ this.queryManager = queryManager;
+
+ FCPMessage message = new FCPMessage();
+
+ message.setMessageName("ClientHello");
+ message.setValue("Name", id);
+ message.setValue("ExpectedVersion", FCP_EXPECTED_VERSION);
+
+ queryManager.addObserver(this);
+
+ if(!queryManager.writeMessage(message)) {
+ Logger.warning(this, "Unable to say hello ... ;(");
+ return false;
+ }
+
+ while(!receiveAnswer) {
+ try {
+ Thread.sleep(500);
+ } catch(java.lang.InterruptedException e) {
+ /* Dodo j'ai dis ! */
+ }
+ }
+
+ if(nodeName != null) {
+ Logger.info(this, "Hello "+nodeName+", I'm Thaw :)");
+ } else {
+ Logger.warning(this, "Unable to connect, ID is probably
already taken");
+ return false;
+ }
+
+ return true;
+ }
+
+
+ public void update(Observable o, Object arg) {
+ if(arg == null)
+ return;
+
+ FCPMessage answer = (FCPMessage)arg;
+
+ if(o == queryManager) {
+
+ if(answer.getMessageName().equals("NodeHello")) {
+ Logger.info(this, "Received a nodeHello");
+
+ nodeFCPVersion = answer.getValue("FCPVersion");
+ nodeVersion = answer.getValue("Version");
+ nodeName = answer.getValue("Node");
+ testnet = (new
Boolean(answer.getValue("Testnet"))).booleanValue();
+ nmbCompressionCodecs = (new
Integer(answer.getValue("CompressionCodecs"))).intValue();
+
+ queryManager.deleteObserver(this);
+
+ receiveAnswer = true;
+ }
+
+
if(answer.getMessageName().equals("CloseConnectionDuplicateClientName")) {
+ /* Damn ... ! */
+ Logger.warning(this, "According to the node,
Thaw ID is already used. Please change it in the configuration");
+ queryManager.deleteObserver(this);
+ queryManager.getConnection().disconnect();
+ receiveAnswer = true;
+ }
+ }
+
+ if(!receiveAnswer) {
+ Logger.warning(this, "This message wasn't for us ?! :
"+answer.getMessageName());
+ }
+ }
+
+ /**
+ * Not used.
+ */
+ public boolean stop(FCPQueryManager queryManager) {
+ return false;
+ }
+
+}
Added: trunk/apps/Thaw/src/thaw/fcp/FCPConnection.java
===================================================================
--- trunk/apps/Thaw/src/thaw/queue/FCPConnection.java 2006-06-30 20:35:07 UTC
(rev 9412)
+++ trunk/apps/Thaw/src/thaw/fcp/FCPConnection.java 2006-07-06 17:38:01 UTC
(rev 9478)
@@ -0,0 +1,207 @@
+package thaw.fcp;
+
+import java.net.Socket;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.util.Observable;
+
+/* Should be the only real dep of the FCP package */
+import thaw.core.Logger;
+
+
+/**
+ * This object manages directly the socket attached to the node.
+ * After being instanciated, you should commit it to the FCPQueryManager, and
then
+ * commit the FCPQueryManager to the FCPQueueManager.
+ * Call observer when connected / disconnected.
+ */
+public class FCPConnection extends Observable {
+
+ private String nodeAddress = null;
+ private int port = 0;
+
+ private Socket socket = null;
+ private InputStream in = null;
+ private OutputStream out = null;
+
+ private BufferedReader reader = null;
+
+ /** If == 1, then will print on stdout
+ * all fcp input / output.
+ */
+ private final static int DEBUG_MODE = 1;
+
+ /**
+ * Don't connect. Call connect() for that.
+ */
+ public FCPConnection(String nodeAddress,
+ int port)
+ {
+ if(DEBUG_MODE == 1) {
+ Logger.notice(this, "DEBUG_MODE ACTIVATED");
+ }
+
+ setNodeAddress(nodeAddress);
+ setNodePort(port);
+ }
+
+
+ /**
+ * You will probably have to use resetQueue() from the FCPQueueManager
after using this function.
+ */
+ public void setNodeAddress(String nodeAddress) {
+ this.nodeAddress = nodeAddress;
+ }
+
+ /**
+ * You will probably have to use resetQueue() from the FCPQueueManager
after using this function.
+ */
+ public void setNodePort(int port) {
+ this.port = port;
+ }
+
+
+ public void disconnect() {
+ try {
+ socket.close();
+ } catch(java.io.IOException e) {
+ Logger.warning(this, "Unable to close cleanly the
connection : "+e.toString());
+ }
+
+ socket = null;
+ in = null;
+ out = null;
+
+ setChanged();
+ notifyObservers();
+ }
+
+
+ /**
+ * If already connected, disconnect before connecting.
+ * @return true if successful
+ */
+ public boolean connect() {
+ if(nodeAddress == null || port == 0) {
+ Logger.warning(this, "Address or port not defined !
Unable to connect\n");
+ return false;
+ }
+
+ if(socket != null && !socket.isClosed())
+ disconnect();
+
+ try {
+ socket = new Socket(nodeAddress, port);
+
+ } catch(java.net.UnknownHostException e) {
+ Logger.error(this, "Error while trying to connect to
"+nodeAddress+":"+port+" : "+
+ e.toString());
+ socket = null;
+ return false;
+ } catch(java.io.IOException e) {
+ Logger.error(this, "Error while trying to connect to
"+nodeAddress+":"+port+" : "+
+ e.toString());
+ socket = null;
+ return false;
+ }
+
+ if(!socket.isConnected()) {
+ Logger.warning(this, "Unable to connect, but no
exception ?! WTF ?\n");
+ Logger.warning(this, "Will try to continue ...\n");
+ }
+
+ try {
+ in = socket.getInputStream();
+ out = socket.getOutputStream();
+ } catch(java.io.IOException e) {
+ Logger.error(this, "Socket and connection established,
but unable to get in/output streams ?! : "+e.toString());
+ return false;
+ }
+
+ reader = new BufferedReader(new InputStreamReader(in));
+
+ setChanged();
+ notifyObservers();
+
+ return true;
+ }
+
+
+ public boolean isConnected() {
+ if(socket == null)
+ return false;
+ else
+ return socket.isConnected();
+ }
+
+
+
+ public boolean write(String toWrite) {
+ Logger.asIt(this, "Thaw >>> Node :");
+ Logger.asIt(this, toWrite);
+
+
+ if(out != null && socket != null && socket.isConnected()) {
+ try {
+ out.write(toWrite.getBytes());
+ } catch(java.io.IOException e) {
+ Logger.warning(this, "Unable to write() on the
socket ?! : "+ e.toString());
+ return false;
+ }
+ } else {
+ Logger.warning(this, "Cannot write if disconnected
!\n");
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Read a line.
+ * @return null if error
+ */
+ public String readLine() {
+ String result;
+
+ if(in != null && socket != null && socket.isConnected()) {
+ try {
+ /*
+ reader = new BufferedReader(new
InputStreamReader(in));
+ result = reader.readLine();
+ */
+
+ result = reader.readLine();
+
+ Logger.asIt(this, "Thaw <<< Node : "+result);
+
+ return result;
+
+ } catch (java.io.IOException e) {
+ Logger.error(this, "Unable to read() on the
socket ?! : "+e.toString());
+ return null;
+ }
+ } else {
+ Logger.warning(this, "Cannot read if disconnected =>
null");
+ }
+
+ return null;
+ }
+
+
+ /**
+ * Use this when you want to fetch the data still waiting on the socket.
+ */
+ public InputStream getInputStream() {
+ return in;
+ }
+
+
+ /**
+ * Use this when you want to send raw data.
+ */
+ public OutputStream getOutputStream() {
+ return out;
+ }
+
+}
Added: trunk/apps/Thaw/src/thaw/fcp/FCPMessage.java
===================================================================
--- trunk/apps/Thaw/src/thaw/queue/FCPMessage.java 2006-06-30 20:35:07 UTC
(rev 9412)
+++ trunk/apps/Thaw/src/thaw/fcp/FCPMessage.java 2006-07-06 17:38:01 UTC
(rev 9478)
@@ -0,0 +1,136 @@
+package thaw.fcp;
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+import thaw.core.Logger;
+
+/**
+ * This class is a generic class, able to handle all kind of FCPMessage.
+ * Raw data are NOT stored inside. You have to handle them by yourself
+ * (FCPConnection.getInputStream() / FCPConnection.getOutputStream())
+ * after reading / writing a message with this class.
+ */
+public class FCPMessage {
+
+ private String messageName = null;
+ private Hashtable fields = null; /* String (field) -> String (value) ;
See http://wiki.freenetproject.org/FreenetFCPSpec2Point0 */
+ private long dataWaiting = 0;
+
+
+ public FCPMessage() {
+ fields = new Hashtable();
+ }
+
+ /**
+ * As you can't fetch the value returns by loadFromRawMessage(), this
constructor is not recommanded.
+ */
+ public FCPMessage(String rawMessage) {
+ this();
+ loadFromRawMessage(rawMessage);
+ }
+
+
+ /**
+ * Raw message does not need to finish by "EndMessage" / "Data".
+ */
+ public boolean loadFromRawMessage(String rawMessage) {
+ int i;
+
+ String[] lines = rawMessage.split("\n");
+
+ /* TODO : Find why some messages from the node starts with an
'\n' */
+
+ for(i = 0 ; lines[i].equals("");) {
+ i++;
+ }
+
+
+ setMessageName(lines[i]);
+
+
+ for(i++; i < lines.length ; i++) {
+ /* Empty lines are ignored. */
+ /* Line not containing '=' (like "Data" or
"EndMessage") are ignored */
+ if(lines[i].equals("") || !lines[i].contains("="))
+ continue;
+
+ String[] affectation = lines[i].split("=");
+
+ setValue(affectation[0], affectation[1]);
+ }
+
+ return true;
+ }
+
+
+ public String getMessageName() {
+ return messageName;
+ }
+
+ public void setMessageName(String name) {
+ if(name == null || name.equals("")) {
+ Logger.notice(this, "Setting name to empty ? weird");
+ }
+
+ if(name.contains("\n")) {
+ Logger.notice(this, "Name shouldn't contain '\n'");
+ }
+
+ messageName = name;
+ }
+
+ public String getValue(String field) {
+ return ((String)fields.get(field));
+ }
+
+ public void setValue(String field, String value) {
+ if(field.equals("DataLength")) {
+ Logger.warning(this, "Trying to add field 'DataLength'
to a message ! You don't have to !\n");
+ return;
+ }
+
+ fields.put(field, value);
+ }
+
+
+ /**
+ * Returns the amount of data waiting on socket (in octets).
+ * @return if > 0 : Data are still waiting, if == 0 : No data waiting,
if < 0 : These data are now unavailable.
+ */
+ public long getAmountOfDataWaiting() {
+ return dataWaiting;
+ }
+
+
+ public void setAmountOfDataWaiting(long amount) {
+ this.dataWaiting = amount;
+ }
+
+
+ /**
+ * Generate FCP String to send.
+ * If amount of data waiting is set to > 0, then, a field "DataLength"
is added,
+ * and resulting string finish by "Data", else resulting string simply
finish by "EndMessage".
+ */
+ public String toString() {
+ String result = "";
+
+ result = result + getMessageName() + "\n";
+
+ for(Enumeration fieldNames = fields.keys() ;
fieldNames.hasMoreElements();) {
+ String fieldName = ((String)fieldNames.nextElement());
+
+ result = result + fieldName + "=" + getValue(fieldName)
+ "\n";
+ }
+
+ if(getAmountOfDataWaiting() == 0)
+ result = result + "EndMessage\n";
+ else {
+ result = result + "DataLength="+ (new
Long(getAmountOfDataWaiting())).toString();
+ result = result + "Data\n";
+ }
+
+ return result;
+ }
+}
Added: trunk/apps/Thaw/src/thaw/fcp/FCPQuery.java
===================================================================
--- trunk/apps/Thaw/src/thaw/queue/FCPQuery.java 2006-06-30 20:35:07 UTC
(rev 9412)
+++ trunk/apps/Thaw/src/thaw/fcp/FCPQuery.java 2006-07-06 17:38:01 UTC (rev
9478)
@@ -0,0 +1,17 @@
+package thaw.fcp;
+
+interface FCPQuery {
+
+ public boolean start(FCPQueryManager queryManager);
+ public boolean stop(FCPQueryManager queryManager);
+
+ /**
+ * Used by the QueueManager only.
+ * Currently these priority are the same
+ * as FCP priority, but it can change in the
+ * future.
+ * -1 = No priority
+ */
+ public int getThawPriority();
+
+}
Added: trunk/apps/Thaw/src/thaw/fcp/FCPQueryManager.java
===================================================================
--- trunk/apps/Thaw/src/thaw/queue/FCPQueryManager.java 2006-06-30 20:35:07 UTC
(rev 9412)
+++ trunk/apps/Thaw/src/thaw/fcp/FCPQueryManager.java 2006-07-06 17:38:01 UTC
(rev 9478)
@@ -0,0 +1,112 @@
+package thaw.fcp;
+
+import java.util.Observable;
+
+import thaw.core.Logger;
+
+/**
+ * Manage all fcp messages (see corresponding object of each kind of query).
+ * Call observers each type a new message is received. The given object is
+ * the
+ */
+public class FCPQueryManager extends Observable implements Runnable {
+ private Thread me;
+
+ private FCPConnection connection;
+ private FCPMessage latestMessage;
+
+
+ public FCPQueryManager(FCPConnection connection) {
+ me = null;
+ latestMessage = null;
+ setConnection(connection);
+ }
+
+ /**
+ * If you call yourself this function, you will probably have to call
+ * resetQueue() of FCPQueueManager.
+ */
+ public void setConnection(FCPConnection connection) {
+ this.connection = connection;
+ }
+
+ /**
+ * Try to not directly call functions from FCPConnection.
+ */
+ public FCPConnection getConnection() {
+ return connection;
+ }
+
+ public boolean writeMessage(FCPMessage message) {
+ return connection.write(message.toString());
+ }
+
+ /**
+ * Blocking until a message is reveived.
+ * More exactly, read until "Data\n" or "EndMessage\n" is read.
+ */
+ public FCPMessage readMessage() {
+ String whatsUp = new String("");
+ FCPMessage result = new FCPMessage();
+
+ while(true) {
+ String read = new String("");
+
+ read = connection.readLine();
+
+ if(read == null) {
+ Logger.notice(this, "readLine() returned null
=> disconnected ?");
+ return null;
+ }
+
+ if(read.equals("Data") || read.equals("EndMessage")) {
+ break;
+ }
+
+ whatsUp = whatsUp + "\n"+ read;
+ }
+
+ Logger.verbose(this, "Parsing message ...");
+
+ result.loadFromRawMessage(whatsUp);
+
+ return result;
+ }
+
+
+ /**
+ * Will listen in loop for new incoming messages.
+ */
+ public void run() {
+
+ while(true) {
+ latestMessage = readMessage();
+
+ Logger.debug(this, "Message received. Notifying
observers");
+
+ if(latestMessage != null) {
+ setChanged();
+ notifyObservers(latestMessage);
+ } else {
+ Logger.info(this, "Stopping listening");
+ return;
+ }
+ }
+
+ }
+
+
+ /**
+ * Create the thread listening for incoming message.
+ */
+ public void startListening() {
+ if(connection.isConnected()) {
+ me = new Thread(this);
+ me.start();
+ } else {
+ Logger.warning(this, "Not connected, so not listening
on the socket");
+ }
+ }
+
+}
+
Added: trunk/apps/Thaw/src/thaw/fcp/FCPQueueManager.java
===================================================================
--- trunk/apps/Thaw/src/thaw/queue/FCPQueueManager.java 2006-06-30 20:35:07 UTC
(rev 9412)
+++ trunk/apps/Thaw/src/thaw/fcp/FCPQueueManager.java 2006-07-06 17:38:01 UTC
(rev 9478)
@@ -0,0 +1,50 @@
+package thaw.fcp;
+
+import thaw.core.Logger;
+
+
+public class FCPQueueManager {
+
+ private FCPQueryManager queryManager;
+ private int maxDownloads, maxInsertions;
+
+
+ /**
+ * Calls setQueryManager() and then resetQueue().
+ */
+ public FCPQueueManager(FCPQueryManager queryManager,
+ int maxDownloads, int maxInsertions) {
+ setMaxDownloads(maxDownloads);
+ setMaxInsertions(maxInsertions);
+
+ setQueryManager(queryManager);
+ resetQueue();
+ }
+
+ public void setMaxDownloads(int maxDownloads) {
+ this.maxDownloads = maxDownloads;
+ }
+
+ public void setMaxInsertions(int maxInsertions) {
+ this.maxInsertions = maxInsertions;
+ }
+
+ /**
+ * You should call resetQueue() after calling this function.
+ */
+ public void setQueryManager(FCPQueryManager queryManager) {
+ this.queryManager = queryManager;
+ }
+
+
+ /**
+ * Will purge the current known queue, and reload the queue according
to the node.
+ * Assume you have already called FCPConnection.connect().
+ */
+ public void resetQueue() {
+ /* TODO */
+ }
+
+
+}
+
Modified: trunk/apps/Thaw/src/thaw/i18n/thaw.properties
===================================================================
--- trunk/apps/Thaw/src/thaw/i18n/thaw.properties 2006-07-06 16:08:28 UTC
(rev 9477)
+++ trunk/apps/Thaw/src/thaw/i18n/thaw.properties 2006-07-06 17:38:01 UTC
(rev 9478)
@@ -38,6 +38,9 @@
thaw.common.priority=Priority
+## Errors
+thaw.error.idAlreadyUsed=Unable to connect. Our Id is already used by another
client connected to the node.
+
## Menus
thaw.menu.file=File
thaw.menu.item.options=Options
@@ -46,6 +49,7 @@
## Status bar
thaw.statusBar.initPlugins=Loading plugins ...
thaw.statusBar.ready=Ready
+thaw.statusBar.connecting=Connecting ...
## Config
thaw.config.windowName=Configuration
@@ -58,6 +62,8 @@
thaw.config.maxSimultaneousDownloads=Maximum simultaneous downloads
thaw.config.maxSimultaneousInsertions=Maximum simultaneous insertions
+thaw.config.thawId=Thaw ID
+
thaw.config.pluginsLoaded=Plugins loaded:
##?Plugins