From f58c676a286a7cd8d37c3f510e787144a9bff5ad Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20=E2=80=98Bombe=E2=80=99=20Roden?= Date: Wed, 14 May 2008 06:50:54 +0000 Subject: [PATCH] make connections work git-svn-id: http://trooper/svn/projects/jSite/trunk@871 c3eda9e8-030b-0410-8277-bc7414b0a119 --- src/net/pterodactylus/jsite/core/Core.java | 4 +- src/net/pterodactylus/jsite/core/CoreImpl.java | 31 +++- src/net/pterodactylus/jsite/core/CoreListener.java | 10 ++ src/net/pterodactylus/jsite/core/Node.java | 113 ++++++++++--- src/net/pterodactylus/jsite/core/NodeListener.java | 17 +- src/net/pterodactylus/jsite/core/NodeManager.java | 188 +++++++++------------ .../pterodactylus/jsite/core/RequestManager.java | 77 +++++---- .../pterodactylus/jsite/gui/ManageNodesDialog.java | 21 ++- .../pterodactylus/jsite/gui/SwingInterface.java | 17 +- src/net/pterodactylus/jsite/i18n/jSite.properties | 16 +- .../pterodactylus/jsite/i18n/jSite_de.properties | 16 +- 11 files changed, 324 insertions(+), 186 deletions(-) diff --git a/src/net/pterodactylus/jsite/core/Core.java b/src/net/pterodactylus/jsite/core/Core.java index f04bb40..38e8914 100644 --- a/src/net/pterodactylus/jsite/core/Core.java +++ b/src/net/pterodactylus/jsite/core/Core.java @@ -51,10 +51,12 @@ public interface Core { * * @param node * The node to add + * @return true if the node was added, false + * if it was not added because it was already known * @throws UnknownHostException * if the hostname of the node can not be resolved */ - public void addNode(Node node) throws UnknownHostException; + public boolean addNode(Node node) throws UnknownHostException; /** * Removes the given node from the core. diff --git a/src/net/pterodactylus/jsite/core/CoreImpl.java b/src/net/pterodactylus/jsite/core/CoreImpl.java index 682199e..07c6345 100644 --- a/src/net/pterodactylus/jsite/core/CoreImpl.java +++ b/src/net/pterodactylus/jsite/core/CoreImpl.java @@ -237,6 +237,20 @@ public class CoreImpl implements Core, NodeListener, RequestListener { } /** + * Notifies all listeners that a connection to a node has failed. + * + * @param node + * The node that could not be connected + * @param cause + * The cause of the failure + */ + private void fireNodeConnectionFailed(Node node, Throwable cause) { + for (CoreListener coreListener: coreListeners) { + coreListener.nodeConnectionFailed(node, cause); + } + } + + /** * Notifies all listeners that the given node was disconnected. * * @param node @@ -403,9 +417,8 @@ public class CoreImpl implements Core, NodeListener, RequestListener { /** * {@inheritDoc} */ - public void addNode(Node node) throws UnknownHostException { - nodeManager.addNode(node); - fireNodeAdded(node); + public boolean addNode(Node node) throws UnknownHostException { + return nodeManager.addNode(node); } /** @@ -413,7 +426,6 @@ public class CoreImpl implements Core, NodeListener, RequestListener { */ public void removeNode(Node node) { nodeManager.removeNode(node); - fireNodeRemoved(node); } /** @@ -479,6 +491,13 @@ public class CoreImpl implements Core, NodeListener, RequestListener { /** * {@inheritDoc} */ + public void nodeConnectionFailed(Node node, Throwable cause) { + fireNodeConnectionFailed(node, cause); + } + + /** + * {@inheritDoc} + */ public void nodeDisconnected(Node node, Throwable throwable) { fireNodeDisconnected(node, throwable); } @@ -500,6 +519,6 @@ public class CoreImpl implements Core, NodeListener, RequestListener { * boolean) */ public void requestProgressed(Node node, Request request, int totalBlocks, int requiredBlocks, int successfulBlocks, int failedBlocks, int fatallyFailedBlocks, boolean finalizedTotal) { - fireRequestProgressed(node, request, totalBlocks, requiredBlocks, successfulBlocks, failedBlocks, fatallyFailedBlocks, finalizedTotal); - } + fireRequestProgressed(node, request, totalBlocks, requiredBlocks, successfulBlocks, failedBlocks, fatallyFailedBlocks, finalizedTotal); + } } diff --git a/src/net/pterodactylus/jsite/core/CoreListener.java b/src/net/pterodactylus/jsite/core/CoreListener.java index fb109d7..04b063e 100644 --- a/src/net/pterodactylus/jsite/core/CoreListener.java +++ b/src/net/pterodactylus/jsite/core/CoreListener.java @@ -163,6 +163,16 @@ public interface CoreListener { public void nodeConnected(Node node); /** + * Notifies a listener that a connection to a node has failed. + * + * @param node + * The node that could not be connected + * @param cause + * The cause of the failure + */ + public void nodeConnectionFailed(Node node, Throwable cause); + + /** * Notifies all listeners that the core disconnected from the given node. * * @param node diff --git a/src/net/pterodactylus/jsite/core/Node.java b/src/net/pterodactylus/jsite/core/Node.java index b3a98e9..afcce6a 100644 --- a/src/net/pterodactylus/jsite/core/Node.java +++ b/src/net/pterodactylus/jsite/core/Node.java @@ -19,14 +19,23 @@ package net.pterodactylus.jsite.core; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + /** * Container for a Freenet node. - * + * * @author David ‘Bombe’ Roden <bombe@freenetproject.org> * @version $Id$ */ public class Node { + /** Property change listeners. */ + private final List propertyChangeListeners = Collections.synchronizedList(new ArrayList()); + /** The name of the node. */ private String name; @@ -36,9 +45,55 @@ public class Node { /** The port number of the node. */ private int port; + // + // EVENT MANAGEMENT + // + + /** + * Adds a property change listener. + * + * @param propertyChangeListener + * The property change listener to add + */ + public void addPropertyChangeListener(PropertyChangeListener propertyChangeListener) { + propertyChangeListeners.add(propertyChangeListener); + } + + /** + * Removes a property change listener. + * + * @param propertyChangeListener + * The property change listener to remove + */ + public void removePropertyChangeListener(PropertyChangeListener propertyChangeListener) { + propertyChangeListeners.remove(propertyChangeListener); + } + + /** + * Notifies all listeners that a property has changed. + * + * @param property + * The name of the property + * @param oldValue + * The old value of the property + * @param newValue + * The new value of the property + */ + private void firePropertyChange(String property, Object oldValue, Object newValue) { + PropertyChangeEvent propertyChangeEvent = new PropertyChangeEvent(this, property, oldValue, newValue); + for (PropertyChangeListener propertyChangeListener: propertyChangeListeners) { + propertyChangeListener.propertyChange(propertyChangeEvent); + } + + } + + // + // ACCESSORS + // + /** * Returns the user-given name of the node. - * + * * @return The name of the node */ public String getName() { @@ -47,17 +102,21 @@ public class Node { /** * Sets the user-given name of the node. - * + * * @param name * The name of the node */ public void setName(String name) { + String oldName = this.name; this.name = name; + if (((oldName != null) && (name == null)) || ((oldName == null) && (name != null)) || ((name != null) && !name.equals(oldName))) { + firePropertyChange("name", oldName, name); + } } /** * Returns the hostname of the node. - * + * * @return The hostname of the node */ public String getHostname() { @@ -66,17 +125,21 @@ public class Node { /** * Sets the hostname of the node. - * + * * @param hostname * The hostname of the node */ public void setHostname(String hostname) { + String oldHostname = this.hostname; this.hostname = hostname; + if (((oldHostname != null) && (hostname == null)) || ((oldHostname == null) && (hostname != null)) || ((hostname != null) && !hostname.equals(oldHostname))) { + firePropertyChange("hostname", oldHostname, hostname); + } } /** * Returns the port number of the node. - * + * * @return The port number of the node */ public int getPort() { @@ -85,27 +148,39 @@ public class Node { /** * Sets the port number of the node. - * + * * @param port * The port number of the node */ public void setPort(int port) { + int oldPort = this.port; this.port = port; - } - - /** - * {@inheritDoc} Two Node objects are considered equal if their hostnames - * and their port numbers are equal. - */ - @Override - public boolean equals(Object object) { - if ((object == null) || !(object instanceof Node)) { - return false; + if (oldPort != port) { + firePropertyChange("port", oldPort, port); } - Node node = (Node) object; - return hostname.equals(node.hostname) && port == node.port; } +// /** +// * {@inheritDoc} Two Node objects are considered equal if their hostnames +// * and their port numbers are equal. +// */ +// @Override +// public boolean equals(Object object) { +// if ((object == null) || !(object instanceof Node)) { +// return false; +// } +// Node node = (Node) object; +// return hostname.equals(node.hostname) && port == node.port; +// } + +// /** +// * {@inheritDoc} +// */ +// @Override +// public int hashCode() { +// return hostname.hashCode() ^ (-1 - port); +// } + /** * {@inheritDoc} */ diff --git a/src/net/pterodactylus/jsite/core/NodeListener.java b/src/net/pterodactylus/jsite/core/NodeListener.java index 95254c1..615fbbe 100644 --- a/src/net/pterodactylus/jsite/core/NodeListener.java +++ b/src/net/pterodactylus/jsite/core/NodeListener.java @@ -54,8 +54,21 @@ public interface NodeListener extends EventListener { public void nodeConnected(Node node); /** - * Notifies a listener that a connection to the given node was severed. The - * listener is responsible for + * Notifies a listener that a connection to a node has failed. + * + * @param node + * The node that could not be connected + * @param cause + * The cause of the failure + */ + public void nodeConnectionFailed(Node node, Throwable cause); + + /** + * Notifies a listener that a connection to the given node was severed. If + * the listener needs the high-level client associated with the node for + * anything else (like deregistering as listener from it) it should retrieve + * the high-level client using {@link NodeManager#getHighLevelClient(Node)} + * before this method returns! * * @param node * The node that is now disconnected diff --git a/src/net/pterodactylus/jsite/core/NodeManager.java b/src/net/pterodactylus/jsite/core/NodeManager.java index 971d5c5..c676289 100644 --- a/src/net/pterodactylus/jsite/core/NodeManager.java +++ b/src/net/pterodactylus/jsite/core/NodeManager.java @@ -19,6 +19,8 @@ package net.pterodactylus.jsite.core; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -29,12 +31,10 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; -import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; @@ -49,7 +49,7 @@ import net.pterodactylus.util.logging.Logging; * @author David ‘Bombe’ Roden <bombe@freenetproject.org> * @version $Id$ */ -public class NodeManager implements Iterable, HighLevelClientListener { +public class NodeManager implements Iterable, PropertyChangeListener, HighLevelClientListener { /** Logger. */ private static final Logger logger = Logging.getLogger(NodeManager.class.getName()); @@ -72,9 +72,6 @@ public class NodeManager implements Iterable, HighLevelClientListener { /** All FCP connections. */ private Map nodeClients = Collections.synchronizedMap(new HashMap()); - /** Keeps track of which connection is in use right now. */ - private Set usedConnections = Collections.synchronizedSet(new HashSet()); - /** Maps nodes to high-level clients. */ private Map clientNodes = Collections.synchronizedMap(new HashMap()); @@ -152,6 +149,20 @@ public class NodeManager implements Iterable, HighLevelClientListener { } /** + * Notifies all listeners that a connection to a node has failed. + * + * @param node + * The node that could not be connected + * @param cause + * The cause of the failure + */ + private void fireNodeConnectionFailed(Node node, Throwable cause) { + for (NodeListener nodeListener: nodeListeners) { + nodeListener.nodeConnectionFailed(node, cause); + } + } + + /** * Notifies all listeners that the given node was disconnected. * * @param node @@ -258,7 +269,7 @@ public class NodeManager implements Iterable, HighLevelClientListener { logger.fine("loaded " + loadedNodes.size() + " nodes from config"); synchronized (syncObject) { nodes.clear(); - for (Node node: nodes) { + for (Node node: loadedNodes) { addNode(node); } } @@ -301,20 +312,22 @@ public class NodeManager implements Iterable, HighLevelClientListener { * @see #connect(Node) * @param node * The node to connect to - * @throws UnknownHostException - * if the hostname of the node can not be resolved + * @return true if the node was added, false + * if the node was not added because it was already known */ - public void addNode(Node node) throws UnknownHostException { - synchronized (syncObject) { - if (!nodes.contains(node)) { - HighLevelClient highLevelClient= new HighLevelClient(clientName, node.getHostname(), node.getPort()); - nodes.add(node); - clientNodes.put(highLevelClient, node); - nodeClients.put(node, highLevelClient); - highLevelClient.addHighLevelClientListener(this); - fireNodeAdded(node); - } + public boolean addNode(Node node) { + if (nodes.contains(node)) { + logger.warning("was told to add already known node: " + node); + return false; } + node.addPropertyChangeListener(this); + HighLevelClient highLevelClient = new HighLevelClient(clientName); + nodes.add(node); + clientNodes.put(highLevelClient, node); + nodeClients.put(node, highLevelClient); + highLevelClient.addHighLevelClientListener(this); + fireNodeAdded(node); + return true; } /** @@ -332,6 +345,7 @@ public class NodeManager implements Iterable, HighLevelClientListener { if (nodeClients.containsKey(node)) { disconnect(node); } + node.removePropertyChangeListener(this); fireNodeRemoved(node); } } @@ -344,13 +358,17 @@ public class NodeManager implements Iterable, HighLevelClientListener { */ public void connect(Node node) { HighLevelClient highLevelClient; - synchronized (syncObject) { - highLevelClient = nodeClients.get(node); + highLevelClient = nodeClients.get(node); + if (highLevelClient == null) { + logger.warning("was told to connect to unknown node: " + node); + return; } try { - highLevelClient.connect(); + highLevelClient.connect(node.getHostname(), node.getPort()); + } catch (UnknownHostException uhe1) { + fireNodeConnectionFailed(node, uhe1); } catch (IOException ioe1) { - fireNodeDisconnected(node, ioe1); + fireNodeConnectionFailed(node, ioe1); } } @@ -380,103 +398,21 @@ public class NodeManager implements Iterable, HighLevelClientListener { } /** - * “Borrows” a high-level client for the given node. A borrowed client - * has to be returned to the node manager using - * {@link #returnHighLevelClient(HighLevelClient)} when it is no longer in - * use, i.e. after a message has been sent! This method will block until a - * high-level client for the given node is available. + * Returns the high-level client for a given node. * * @param node * The node to get a high-level client for * @return The high-level client for a node, or null if the * node was disconnected or removed */ - public HighLevelClient borrowHighLevelClient(Node node) { - synchronized (syncObject) { - if (!nodeClients.containsKey(node)) { - return null; - } - HighLevelClient highLevelClient = nodeClients.get(node); - while (nodeClients.containsKey(node) && usedConnections.contains(highLevelClient)) { - try { - syncObject.wait(); - } catch (InterruptedException ie1) { - /* ignore. TODO - check. */ - } - } - if (!nodeClients.containsKey(node)) { - return null; - } - usedConnections.add(highLevelClient); - return highLevelClient; - } - } - - /** - * Returns a borrowed high-level client. - * - * @see #borrowHighLevelClient(Node) - * @param highLevelClient - * The high-level client to return - */ - public void returnHighLevelClient(HighLevelClient highLevelClient) { - synchronized (syncObject) { - if (!clientNodes.containsKey(highLevelClient)) { - return; - } - usedConnections.remove(highLevelClient); - syncObject.notifyAll(); - } + public HighLevelClient getHighLevelClient(Node node) { + return nodeClients.get(node); } // // PRIVATE METHODS // - /** - * Finds a currently unused high-level client, optionally waiting until a - * client is free and marking it used. - * - * @param wait - * true to wait for a free connection, - * false to return null - * @param markAsUsed - * true to mark the connection as used before - * returning it, false not to mark it - * @return An unused FCP connection, or null if no connection - * could be found - */ - @SuppressWarnings("unused") - private HighLevelClient findUnusedClient(boolean wait, boolean markAsUsed) { - synchronized (syncObject) { - HighLevelClient freeHighLevelClient = null; - while (freeHighLevelClient == null) { - for (HighLevelClient highLevelClient: nodeClients.values()) { - if (!usedConnections.contains(highLevelClient)) { - freeHighLevelClient = highLevelClient; - break; - } - } - if (freeHighLevelClient != null) { - if (markAsUsed) { - usedConnections.add(freeHighLevelClient); - } - return freeHighLevelClient; - } - if (!wait) { - return null; - } - try { - syncObject.wait(); - } catch (InterruptedException e) { - /* ignore, just re-check. */ - } - } - /* we never get here, but the compiler doesn't realize. */ - return null; - } - } - // // INTERFACE HighLevelClientListener // @@ -500,15 +436,45 @@ public class NodeManager implements Iterable, HighLevelClientListener { public void clientDisconnected(HighLevelClient highLevelClient, Throwable throwable) { logger.log(Level.FINER, "clientDisconnected(c=" + highLevelClient + ",t=" + throwable + ")"); synchronized (syncObject) { - Node node = clientNodes.remove(highLevelClient); + Node node = clientNodes.get(highLevelClient); if (node == null) { logger.log(Level.WARNING, "got event for unknown client"); return; } - nodeClients.remove(node); - usedConnections.remove(highLevelClient); fireNodeDisconnected(node, throwable); } } + // + // INTERFACE PropertyChangeListener + // + + /** + * {@inheritDoc} + */ + public void propertyChange(PropertyChangeEvent propertyChangeEvent) { + Object eventSource = propertyChangeEvent.getSource(); + if (eventSource instanceof Node) { + String propertyName = propertyChangeEvent.getPropertyName(); + if ("hostname".equals(propertyName) || "port".equals(propertyName)) { + Node node = (Node) eventSource; + HighLevelClient highLevelClient = nodeClients.get(node); + if (highLevelClient == null) { + logger.log(Level.WARNING, "got property change event for unknown node: " + node); + return; + } + if (highLevelClient.isConnected()) { + highLevelClient.disconnect(); + try { + highLevelClient.connect(node.getHostname(), node.getPort()); + } catch (UnknownHostException uhe1) { + fireNodeConnectionFailed(node, uhe1); + } catch (IOException ioe1) { + fireNodeConnectionFailed(node, ioe1); + } + } + } + } + } + } diff --git a/src/net/pterodactylus/jsite/core/RequestManager.java b/src/net/pterodactylus/jsite/core/RequestManager.java index b312d43..002cd17 100644 --- a/src/net/pterodactylus/jsite/core/RequestManager.java +++ b/src/net/pterodactylus/jsite/core/RequestManager.java @@ -159,34 +159,30 @@ public class RequestManager implements NodeListener, HighLevelProgressListener { * if an I/O error occurs while communicating with the node */ private void getRequests(final Node node) throws IOException { - HighLevelClient highLevelClient = nodeManager.borrowHighLevelClient(node); + HighLevelClient highLevelClient = nodeManager.getHighLevelClient(node); if (highLevelClient == null) { logger.log(Level.WARNING, "no client for node: " + node); return; } - try { - HighLevelCallback requestListCallback = highLevelClient.getRequests(); - requestListCallback.addHighLevelCallbackListener(new HighLevelCallbackListener() { + HighLevelCallback requestListCallback = highLevelClient.getRequests(); + requestListCallback.addHighLevelCallbackListener(new HighLevelCallbackListener() { - @SuppressWarnings("synthetic-access") - public void gotResult(HighLevelCallback highLevelCallback) { - RequestListResult requestListResult; - try { - requestListResult = highLevelCallback.getResult(); - } catch (InterruptedException e) { - logger.log(Level.SEVERE, "getResult() blocked and was interrupted"); - return; - } - for (RequestResult requestResult: requestListResult) { - Request request = new Request(requestResult.getIdentifier()); - /* TODO - fill request */ - fireRequestAdded(node, request); - } + @SuppressWarnings("synthetic-access") + public void gotResult(HighLevelCallback highLevelCallback) { + RequestListResult requestListResult; + try { + requestListResult = highLevelCallback.getResult(); + } catch (InterruptedException e) { + logger.log(Level.SEVERE, "getResult() blocked and was interrupted"); + return; } - }); - } finally { - nodeManager.returnHighLevelClient(highLevelClient); - } + for (RequestResult requestResult: requestListResult) { + Request request = new Request(requestResult.getIdentifier()); + /* TODO - fill request */ + fireRequestAdded(node, request); + } + } + }); } // @@ -197,41 +193,37 @@ public class RequestManager implements NodeListener, HighLevelProgressListener { * {@inheritDoc} */ public void nodeAdded(Node node) { - HighLevelClient highLevelClient = nodeManager.borrowHighLevelClient(node); + HighLevelClient highLevelClient = nodeManager.getHighLevelClient(node); if (highLevelClient == null) { + logger.warning("got nodeAdded but no high-level client: " + node); return; } - try { - highLevelClient.addHighLevelProgressListener(this); - } finally { - nodeManager.returnHighLevelClient(highLevelClient); - } + highLevelClient.addHighLevelProgressListener(this); } /** * {@inheritDoc} */ public void nodeRemoved(Node node) { - /* ignore. */ + HighLevelClient highLevelClient = nodeManager.getHighLevelClient(node); + if (highLevelClient == null) { + logger.warning("got nodeRemoved but no high-level client: " + node); + return; + } + highLevelClient.removeHighLevelProgressListener(this); } /** * {@inheritDoc} */ public void nodeConnected(Node node) { - HighLevelClient highLevelClient = nodeManager.borrowHighLevelClient(node); + HighLevelClient highLevelClient = nodeManager.getHighLevelClient(node); if (highLevelClient == null) { logger.log(Level.WARNING, "got no high-level client for node " + node); return; } try { highLevelClient.setWatchGlobal(true); - } catch (IOException ioe1) { - /* ignore exception, disconnects are handled elsewhere. */ - } finally { - nodeManager.returnHighLevelClient(highLevelClient); - } - try { getRequests(node); } catch (IOException e) { /* ignore exception, disconnects are handled elsewhere. */ @@ -241,8 +233,19 @@ public class RequestManager implements NodeListener, HighLevelProgressListener { /** * {@inheritDoc} */ + public void nodeConnectionFailed(Node node, Throwable cause) { + /* we don't care about this. */ + } + + /** + * {@inheritDoc} + */ public void nodeDisconnected(Node node, Throwable throwable) { - /* TODO - remove all requests. */ + HighLevelClient highLevelClient = nodeManager.getHighLevelClient(node); + if (highLevelClient == null) { + logger.warning("got nodeDisconnected from node without high-level client: " + node); + return; + } } // diff --git a/src/net/pterodactylus/jsite/gui/ManageNodesDialog.java b/src/net/pterodactylus/jsite/gui/ManageNodesDialog.java index cf32cae..0598144 100644 --- a/src/net/pterodactylus/jsite/gui/ManageNodesDialog.java +++ b/src/net/pterodactylus/jsite/gui/ManageNodesDialog.java @@ -22,10 +22,12 @@ package net.pterodactylus.jsite.gui; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.event.ActionEvent; +import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.logging.Logger; import javax.swing.AbstractListModel; import javax.swing.BorderFactory; @@ -46,6 +48,7 @@ import net.pterodactylus.jsite.i18n.I18nable; import net.pterodactylus.jsite.i18n.gui.I18nAction; import net.pterodactylus.jsite.i18n.gui.I18nLabel; import net.pterodactylus.jsite.main.Version; +import net.pterodactylus.util.logging.Logging; import net.pterodactylus.util.swing.SwingUtils; /** @@ -56,6 +59,10 @@ import net.pterodactylus.util.swing.SwingUtils; */ public class ManageNodesDialog extends JDialog implements ListSelectionListener, I18nable { + /** The logger.  */ + @SuppressWarnings("unused") + private static final Logger logger = Logging.getLogger(ManageNodesDialog.class.getName()); + /** The core. */ private final Core core; @@ -265,7 +272,17 @@ public class ManageNodesDialog extends JDialog implements ListSelectionListener, newNode.setName(editNodeDialog.getNodeName()); newNode.setHostname(editNodeDialog.getNodeHostname()); newNode.setPort(editNodeDialog.getNodePort()); - nodeListModel.addNode(newNode); + try { + if (!core.addNode(newNode)) { + JOptionPane.showMessageDialog(this, I18n.get("manageNodesDialog.error.nodeAlreadyKnown.message", newNode.getHostname(), newNode.getPort()), I18n.get("manageNodesDialog.error.nodeAlreadyKnown.title"), JOptionPane.ERROR_MESSAGE); + } + } catch (UnknownHostException e) { + /* + * normally this shouldn't throw because the node editor catches + * it. + */ + JOptionPane.showMessageDialog(this, I18n.get("manageNodesDialog.error.nodeUnresolvable.message", newNode.getHostname()), I18n.get("manageNodesDialog.error.nodeUnresolvable.title"), JOptionPane.ERROR_MESSAGE); + } } } @@ -374,7 +391,7 @@ public class ManageNodesDialog extends JDialog implements ListSelectionListener, } /** - * List model for the {@link ManageNodesDialog#nodeList}. TODO + * List model for the {@link ManageNodesDialog#nodeList}. * * @author David ‘Bombe’ Roden <bombe@freenetproject.org> * @version $Id$ diff --git a/src/net/pterodactylus/jsite/gui/SwingInterface.java b/src/net/pterodactylus/jsite/gui/SwingInterface.java index bb0bb9e..0a945db 100644 --- a/src/net/pterodactylus/jsite/gui/SwingInterface.java +++ b/src/net/pterodactylus/jsite/gui/SwingInterface.java @@ -217,6 +217,7 @@ public class SwingInterface implements CoreListener, LoggingListener { if ((mainWindowX != -1) && (mainWindowY != -1) && (mainWindowWidth != -1) && (mainWindowHeight != -1)) { mainWindow.setLocation(mainWindowX, mainWindowY); mainWindow.setSize(mainWindowWidth, mainWindowHeight); + mainWindow.validate(); } logWindow = new LogWindow(); } @@ -681,7 +682,7 @@ public class SwingInterface implements CoreListener, LoggingListener { nodeNodeDisconnectActions.clear(); nodeDisconnectActionNodes.clear(); for (Node node: nodes) { - logger.finer("adding node “" + node + "” to menu"); + logger.finer("adding node “" + node + "” to menus"); Action nodeConnectAction = new AbstractAction(node.getName()) { /** @@ -904,6 +905,7 @@ public class SwingInterface implements CoreListener, LoggingListener { public void nodeAdded(Node node) { logger.log(Level.INFO, "node added: " + node); nodeList.add(node); + logger.log(Level.FINE, "nodeList.size(): " + nodeList.size()); manageNodesDialog.setNodeList(nodeList); rebuildNodeActions(nodeList); mainWindow.refreshNodeMenuItems(); @@ -942,6 +944,17 @@ public class SwingInterface implements CoreListener, LoggingListener { /** * {@inheritDoc} */ + public void nodeConnectionFailed(Node node, Throwable cause) { + Action nodeConnectAction = nodeNodeConnectActions.get(node); + nodeConnectActions.add(nodeConnectAction); + mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.connectionToNodeFailed", node.getName(), node.getHostname(), node.getPort(), (cause != null) ? cause.getMessage() : "no reason given")); + JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.error.nodeConnectionFailed.message", node.getName(), node.getHostname(), node.getPort(), (cause != null) ? cause.getMessage() : "no reason given"), I18n.get("mainWindow.error.nodeConnectionFailed.title"), JOptionPane.ERROR_MESSAGE); + mainWindow.refreshNodeMenuItems(); + } + + /** + * {@inheritDoc} + */ public void nodeDisconnected(Node node, Throwable throwable) { Action nodeConnectAction = nodeNodeConnectActions.get(node); nodeConnectActions.add(nodeConnectAction); @@ -964,7 +977,7 @@ public class SwingInterface implements CoreListener, LoggingListener { */ public void requestProgressed(Request request, int totalBlocks, int requiredBlocks, int successfulBlocks, int failedBlocks, int fatallyFailedBlocks, boolean finalizedTotal) { /* TODO - update table model */ - mainWindow.setStatusBarText(request.getIdentifier() + " @ " + ((10000 * successfulBlocks / requiredBlocks) / 100.0)); + mainWindow.setStatusBarText(request.getIdentifier() + " @ " + ((10000 * successfulBlocks / requiredBlocks) / 100.0) + "%"); } // diff --git a/src/net/pterodactylus/jsite/i18n/jSite.properties b/src/net/pterodactylus/jsite/i18n/jSite.properties index 1985633..0a3ba80 100644 --- a/src/net/pterodactylus/jsite/i18n/jSite.properties +++ b/src/net/pterodactylus/jsite/i18n/jSite.properties @@ -42,15 +42,19 @@ mainWindow.warning.multipleNodesNotAdvancedMode.message: You have enabled mainWindow.error.projectLoadingFailed.title: Loading Projects Failed mainWindow.error.projectLoadingFailed.message: Loading the projects from \u201c{0}\u201d has failed. +mainWindow.error.nodeConnectionFailed.title: Connecting to Node Failed +mainWindow.error.nodeConnectionFailed.message: Connecting to node \u201c{0}\u201d (at {1}:{2,number,#}) has failed: {3} + mainWindow.statusBar.coreLoaded: Core loaded. mainWindow.statusBar.coreStopped: Core stopped. mainWindow.statusBar.projectLoadingDone: Projects loaded. mainWindow.statusBar.projectSavingDone: Projects saved. mainWindow.statusBar.loadingNodesDone: Nodes loaded. mainWindow.statusBar.savingNodesDone: Nodes saved. -mainWindow.statusBar.connectingToNode: Connecting to \u201c{0}\u201d (at {1}:{2})\u2026 -mainWindow.statusBar.connectedToNode: Connected to \u201c{0}\u201d (at {1}:{2}). -mainWindow.statusBar.disconnectedFromNode: Connected to \u201c{0}\u201d (at {1}:{2}). +mainWindow.statusBar.connectingToNode: Connecting to \u201c{0}\u201d (at {1}:{2,number,#})\u2026 +mainWindow.statusBar.connectedToNode: Connected to \u201c{0}\u201d (at {1}:{2,number,#}). +mainWindow.statusBar.connectionToNodeFailed: Connection to \u201c{0}\u201d (at {1}:{2,number,#}) failed: {3} +mainWindow.statusBar.disconnectedFromNode: Disconnected from \u201c{0}\u201d (at {1}:{2,number,#}). # main menus mainWindow.menu.jSite.name: jSite @@ -186,6 +190,12 @@ manageNodesDialog.error.nodeListEmpty.message: The node list is empty. manageNodesDialog.error.nodeConnected.title: Node Is Connected manageNodesDialog.error.nodeConnected.message: The Node \u201c{0}\u201d is still connected. Do you really want to delete it? +manageNodesDialog.error.nodeUnresolvable.title: Node hostname can not be resolved +manageNodesDialog.error.nodeUnresolvable.message: The hostname of the node (\u201c{0}\u201d) can not be resolved. + +manageNodesDialog.error.nodeAlreadyKnown.title: Node Already Known +manageNodesDialog.error.nodeAlreadyKnown.message: There already is a node with the hostname (\u201c{0}\u201d) and port ({1,number,#}). + # the "edit node" dialog editNodeDialog.title: Edit Node diff --git a/src/net/pterodactylus/jsite/i18n/jSite_de.properties b/src/net/pterodactylus/jsite/i18n/jSite_de.properties index 271ab48..fb7e450 100644 --- a/src/net/pterodactylus/jsite/i18n/jSite_de.properties +++ b/src/net/pterodactylus/jsite/i18n/jSite_de.properties @@ -42,15 +42,19 @@ mainWindow.warning.multipleNodesNotAdvancedMode.message: Der einfache Modu mainWindow.error.projectLoadingFailed.title: Laden der Projekte fehlgeschlagen mainWindow.error.projectLoadingFailed.message: Die Projekte aus \u201e{0}\u201c konnten nicht geladen werden. +mainWindow.error.nodeConnectionFailed.title: Verbindung mit Node fehlgeschlagen +mainWindow.error.nodeConnectionFailed.message: Die Verbindung zum Node \u201e{0}\u201c ({1}:{2,number,#}) konnte nicht hergestellt werden: {3} + mainWindow.statusBar.coreLoaded: Kern geladen. mainWindow.statusBar.coreStopped: Kern angehalten. mainWindow.statusBar.projectLoadingDone: Projekte geladen. mainWindow.statusBar.projectSavingDone: Projekte gespeichert. mainWindow.statusBar.loadingNodesDone: Nodes geladen. mainWindow.statusBar.savingNodesDone: Nodes gespeichert. -mainWindow.statusBar.connectingToNode: Verbindung zum Node \u201e{0}\u201c ({1}:{2}) wird hergestellt\u2026 -mainWindow.statusBar.connectedToNode: Verbindung zum Node \u201e{0}\u201c ({1}:{2}) hergestellt. -mainWindow.statusBar.disconnectedFromNode: Verbindung von Node \u201e{0}\u201c ({1}:{2}) getrennt. +mainWindow.statusBar.connectingToNode: Verbindung zum Node \u201e{0}\u201c ({1}:{2,number,#}) wird hergestellt\u2026 +mainWindow.statusBar.connectedToNode: Verbindung zum Node \u201e{0}\u201c ({1}:{2,number,#}) hergestellt. +mainWindow.statusBar.connectionToNodeFailed: Verbindung zu Node \u201e{0}\u201c ({1}:{2,number,#}) fehlgeschlagen: {3} +mainWindow.statusBar.disconnectedFromNode: Verbindung von Node \u201e{0}\u201c ({1}:{2,number,#}) getrennt. # main menus mainWindow.menu.jSite.name: jSite @@ -186,6 +190,12 @@ manageNodesDialog.error.nodeListEmpty.message: Es wurden keine Nodes konfigurier manageNodesDialog.error.nodeConnected.title: Node ist verbunden manageNodesDialog.error.nodeConnected.message: Mit dem Node \u201e{0}\u201c besteht momentan eine Verbindung. Wollen Sie ihn wirklich l\u00f6schen? +manageNodesDialog.error.nodeUnresolvable.title: Hostname des Nodes ung\u00fcltig +manageNodesDialog.error.nodeUnresolvable.message: Der Hostname des Nodes (\u201e{0}\u201c) kann nicht aufgel\u00f6st werden. + +manageNodesDialog.error.nodeAlreadyKnown.title: Node schon bekannt +manageNodesDialog.error.nodeAlreadyKnown.message: Es gibt bereits einen Node mit diesem Hostnamen (\u201e{0}\u201c) und Port ({1,number,#}). + # the "edit node" dialog editNodeDialog.title: Edit Node -- 2.7.4