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.
| Metric | Description | |
|---|---|---|
/*
* 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.
| Metric | Value | Description | |
|---|---|---|---|



