Connector.java

Index Score
xnap.plugin.nap.util
XNap 2

View: Reasons, Metrics, Source Code

These are the metrics that contribute to the Enerjy Score for this file, ranked by impact. So the metrics listed at the top influence the score to a greater extent that the metrics listed at the bottom.

MetricDescription
/* * XNap * * A pure java file sharing client. * * See AUTHORS for copyright information. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package xnap.plugin.nap.util; import xnap.*; import xnap.io.*; import xnap.net.*; import xnap.net.event.*; import xnap.plugin.nap.net.*; import xnap.plugin.nap.net.msg.MessageHandler; import xnap.plugin.nap.net.msg.client.*; import xnap.user.UserManager; import xnap.util.*; import xnap.util.event.*; import java.beans.*; import java.io.IOException; import java.util.*; import java.text.*; import org.apache.log4j.Logger; public class Connector extends EventVector implements Runnable, PropertyChangeListener, StatusChangeListener, ListListener { //--- Constant(s) --- /** * Timeout before connect retry if login failed. */ public static final int LOGIN_INTERVAL = 180 * 1000; /** * Timeout before connect retry if connection failed. */ public static final int FAILED_INTERVAL = 60 * 1000; //--- Data field(s) --- protected static Logger logger = Logger.getLogger(Connector.class); protected static Connector singleton; private Preferences prefs = Preferences.getInstance(); private NapPreferences napPrefs = NapPreferences.getInstance(); private int maxConnect = napPrefs.getMaxAutoconnectServers(); private int maxTrying = 2 * maxConnect; private int connectedCount = 0; private int tryingCount = 0; private String stats; private boolean die = false; private Thread runner = null; private boolean enabled = false; private NapListener listener = new NapListener(); private Object lock = new Object(); protected StatusListener statusListener; protected LinkedList statsListener = new LinkedList(); protected ServerVector connectedServers = new ServerVector(); protected HashSet connectedNetworks = new HashSet(); protected int repositoryIndex = 0; protected boolean addedTemporary = false; //--- Constructor(s) --- private Connector() { prefs.addPropertyChangeListener(this); Repository.getInstance().addListListener(this); } //--- Method(s) --- public static synchronized Connector getInstance() { if (singleton == null) { singleton = new Connector(); } return singleton; } public synchronized void setStatus(String newValue) { if (statusListener != null) { statusListener.setStatus(newValue); } } public synchronized void setStatusListener(StatusListener newValue) { statusListener = newValue; } public synchronized void setStats(String newValue) { for (Iterator i = statsListener.iterator(); i.hasNext();) { ((StatusListener)i.next()).setStatus(newValue); } } public synchronized void addStatsListener(StatusListener newValue) { statsListener.add(newValue); } public synchronized void removeStatsListener(StatusListener newValue) { statsListener.remove(newValue); } public synchronized void elementAdded(ListEvent e) { if (e.getSource() == Repository.getInstance()) { if (!napPrefs.getLimitSharesPerServer()) { RepositoryFile f = (RepositoryFile)e.getElement(); MessageHandler.send(new ShareFileMessage(e.getIndex(), f)); } } } public synchronized void elementRemoved(ListEvent e) { if (e.getSource() == Repository.getInstance()) { // FIX ME: check if file is really shared RepositoryFile f = (RepositoryFile)e.getElement(); MessageHandler.send(new UnshareFileMessage(e.getIndex(), f)); } } public boolean addServer(String url, String network, boolean login) { StringTokenizer s = new StringTokenizer(url, ":"); if (s.countTokens() != 2) return false; String ip = s.nextToken(); int port = 0; try { port = Integer.parseInt(s.nextToken()); } catch (NumberFormatException e) { } if (ip.length() == 0 || port < PortRange.MIN_PORT || port > PortRange.MAX_PORT) { return false; } Server server = new Server(ip, port, network); addServer(server); if (login) { login(server); } return true; } public synchronized void addServer(int i, Server server) { if (!super.contains(server)) { server.setListener(listener); super.add(server); addedTemporary |= server.isTemporary(); server.addStatusChangeListener(this); wakeup(); } } public synchronized void addServer(Server server) { addServer(super.size(), server); } public synchronized void removeServer(Server server) { server.logout(); server.removeStatusChangeListener(this); super.remove(server); } public synchronized void removeAllServers() { for (Iterator i = super.iterator(); i.hasNext();) { Server server = (Server)i.next(); server.logout(); server.removeStatusChangeListener(this); } super.clear(); } public synchronized Server getServer(String host) { for (Iterator it = super.iterator(); it.hasNext();) { Server s = (Server)it.next(); if (s.getHost().equals(host)) { return s; } } return null; } public synchronized Server[] getServers() { Server[] list = new Server[super.size()]; int i = 0; for (Iterator it = super.iterator(); it.hasNext(); i++) { list[i] = (Server)it.next(); } return list; } public int getConnectedCount() { return connectedCount; } public EventVector getConnectedServers() { return connectedServers; } public boolean isEnabled() { return enabled; } public void setEnabled(boolean newValue) { enabled = newValue; if (enabled) { if (runner != null) { wakeup(); } if (!runner.isAlive()) { logger.debug("OpenNapConnector Thread died"); runner = new Thread(this, "OpenNapConnector"); runner.start(); } } } public void init() { updateListener(); runner = new Thread(this, "OpenNapConnector"); runner.start(); (new Thread("ConnectorInit") { public void run() { try { addFromFile(napPrefs.getServerFile(), false); } catch (IOException e) { logger.debug("could not add hosts from file" , e); } if (napPrefs.getAutoLoadNapigator()) { try { addFromFile(napPrefs.getNapigatorFile(), true); } catch (IOException e) { } } if (napPrefs.getAutoFetchNapigator()) { fetchServerLists(); // addFromURL(napPrefs.getNapigatorURL()); } } } ).start(); updateStats(); } public void fetchServerLists() { setStatus(XNap.tr("Downloading list of OpenNap servers") + "..."); Runnable r = new Runnable() { public void run() { String urls = napPrefs.getNapigatorURL(); StringTokenizer t = new StringTokenizer(urls, "\n"); while (t.hasMoreTokens()) { String url = t.nextToken().trim(); if (!url.startsWith("#")) { addFromURL(url); } } updateStats(); } }; Thread t = new Thread(r, "AskNapigator"); t.start(); } public void addFromURL(String url) { Server s; Napigator napigator = new Napigator(); try { napigator.connect(url); } catch (IOException e) { setStatus("Could not open " + url + "(" + e.getMessage() + ")"); return; } while ((s = napigator.nextServer()) != null) { s.setTemporary(true); addServer(0, s); } } private void wakeup() { if (isEnabled()) { synchronized (lock) { lock.notify(); } } } /** * Auto connects <code>maxConnect</code> hosts. */ public void run() { int next = 0; while (!die) { if (next > super.size()) next = 0; int start = next; boolean looped = false; while (super.size() > 0 && connectedCount <= maxConnect && tryingCount <= maxTrying) { try { Server s = (Server)super.get(next); if (!s.isReady() && canReconnect(s) && (s.getNetwork().equals("") || connectedNetworks.add(s.getNetwork()))) { // start login thread login(s); } } catch (ArrayIndexOutOfBoundsException e) { // FIX: some servers could have been removed in the meantime } next++; if (next >= super.size()) { next = 0; looped = true; } if (looped && next >= start) break; } synchronized (lock) { try { lock.wait(); } catch (InterruptedException e) { } } } } public boolean canReconnect(Server s) { long diff = System.currentTimeMillis() - s.getLastLogin(); switch (s.getStatus()) { case Server.STATUS_LOGIN_FAILED: return diff > LOGIN_INTERVAL; case Server.STATUS_FAILED: return diff > FAILED_INTERVAL; case Server.STATUS_ERROR: return false; default: return true; } } public void die() { die = true; synchronized (lock) { lock.notify(); } try { saveToFile(napPrefs.getServerFile(), false); } catch (IOException e) { } if (addedTemporary) { try { saveToFile(napPrefs.getNapigatorFile(), true); } catch (IOException e) { } } removeAllServers(); listener.die(); singleton = null; } public void addFromFile(String filename, boolean temporary) throws IOException { ServerFile reader; if (filename.endsWith(".dat")) { reader = new TrippyMXFile(filename); } else { reader = new ServerFile(filename); } try { Server s; reader.openReader(); while ((s = reader.readServer()) != null) { s.setTemporary(temporary); addServer(s); } } catch (IOException e) { throw(e); } finally { reader.close(); } } public void saveToFile(String filename, boolean temporary) throws IOException { ServerFile writer = new ServerFile(filename); try { writer.openWriter(); for (Iterator i = super.iterator(); i.hasNext();) { Server s = (Server)i.next(); if (s.isTemporary() == temporary) { writer.writeServer(s); } } } catch (IOException e) { throw(e); } finally { writer.close(); } } public void propertyChange(PropertyChangeEvent e) { String p = e.getPropertyName(); if (p.equals("firewalled") || p.equals("useSinglePort") || p.equals("localPort")) { updateListener(); } else if (p.equals("maxAutoconnectServers")) { maxConnect = napPrefs.getMaxAutoconnectServers(); maxTrying = 2 * maxConnect; wakeup(); } } private void updateListener() { if (prefs.isFirewalled()) { listener.setPortRange(null); } else { PortRange range = new PortRange(napPrefs.getLocalPortRange()); listener.setPortRange(range); if (listener.getPort() == 0) { setStatus("Could not start listener (check local port)"); } } } public void statusChange(StatusChangeEvent e) { switch (e.getNewStatus()) { case Server.STATUS_CONNECTING: if (e.getOldStatus() == Server.STATUS_NOT_CONNECTED) { tryingCount++; } break; case Server.STATUS_CONNECTED: if (e.getOldStatus() == Server.STATUS_CONNECTING) { Server s = (Server)e.getSource(); tryingCount--; connectedCount++; connectedServers.add(s); ChatManager.getInstance().addServer(s); SearchManager.getInstance().readyToSearch(true); if (getConnectedCount() >= napPrefs.getMaxAutoconnectServers() / 2) { SearchManager.getInstance().resumeDownloads(); } postLogin(s); } updateStats(); wakeup(); break; case Server.STATUS_NOT_CONNECTED: case Server.STATUS_LOGIN_FAILED: case Server.STATUS_FAILED: case Server.STATUS_ERROR: Server s = (Server)e.getSource(); if (e.getOldStatus() == Server.STATUS_CONNECTING) { tryingCount--; } else if (e.getOldStatus() == Server.STATUS_CONNECTED) { connectedServers.remove(s); ChatManager.getInstance().removeServer(s); connectedCount--; SearchManager.getInstance().readyToSearch(false); } connectedNetworks.remove(s.getNetwork()); if (s.isTemporary() && e.getNewStatus() == Server.STATUS_ERROR && napPrefs.getRemoveFailedServers()) { // FIX: breaks gui removeServer(s); } updateStats(); wakeup(); break; case Server.STATUS_NEW_STATS: updateStats(); break; } } public void login(final Server s) { s.login(false); } public void logout(Server s) { if (s.isReady()) { if (s.isConnected()) { MessageHandler.send(s, new UnshareAllFilesMessage()); } s.logout(); } } public String getStats() { return stats; } private void updateStats() { long userCount = 0; long fileCount = 0; long fileSize = 0; try { for (Iterator i = super.iterator(); i.hasNext();) { Server s = (Server)i.next(); if (s.isConnected()) { userCount += s.getUserCount(); fileCount += s.getFileCount(); fileSize += s.getFileSize(); } } } catch (Exception e) { } String oldValue = stats; // gb -> byte fileSize = fileSize * 1024 * 1024 * 1024; stats = (Formatter.formatNumber(connectedCount) + " " + XNap.tr("Servers") + " / " + Formatter.formatNumber(userCount) + " " + XNap.tr("Users")+" / " + Formatter.formatNumber(fileCount) + " " + XNap.tr("Files") + " / " + Formatter.formatSize(fileSize) + " " + XNap.tr("Shared")); setStats(stats); } public void postLogin(Server server) { // add hotlist users Object[] users = UserManager.getInstance().toArray(); for (int i = 0; i < users.length; i++) { if (users[i] instanceof GlobalUser) { GlobalUser u = (GlobalUser)users[i]; if (!u.isTemporary()) { AddHotlistEntryMessage msg = new AddHotlistEntryMessage(u.getName()); MessageHandler.sendLater(server, msg); } } } // share files if (napPrefs.getLimitSharesPerServer()) { int start; int left = napPrefs.getMaxSharesPerServer(); int size = Repository.getInstance().size(); int toShare = Math.min(left, size); while (toShare > 0) { synchronized(Connector.this) { start = repositoryIndex; repositoryIndex += toShare; if (repositoryIndex >= size) { repositoryIndex = 0; start = 0; } } int count = shareFiles(server, start, toShare); if (count == -1) { return; } toShare -= count; } } else { shareFiles(server, 0, Repository.getInstance().size()); } /** * Acctually send messages. */ MessageHandler.sendPending(server); } /** * Returns the number of files that have been shared. * * @return -1, if server disconnected */ public int shareFiles(Server server, int start, int count) { // the repository never shrinks int shared = 0; logger.debug("sharing index " + start + " - " + (start + count)); server.setShared(new Range(start, start + count - 1)); for (int i = 0; i < count; i++) { RepositoryFile f = Repository.getInstance().getFile(start + i); if (f != null) { if (!server.isReady()) { return -1; } ShareFileMessage msg = new ShareFileMessage(start + i, f); MessageHandler.sendLater(server, msg); shared++; } } return shared; } /** * Wrapper. */ public static class ServerVector extends EventVector { public void add(Server s) { super.add(s); } public void remove(Server s) { super.remove(s); } } }

The table below shows all metrics for Connector.java.

MetricValueDescription