OpenNapServer.java
| Index Score | ||
|---|---|---|
![]() |
![]() |
org.xnap.plugin.opennap.net |
![]() |
![]() |
XNap 3 |
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.
/*
* XNap - A P2P framework and client.
*
* See the file 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.
*
* 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 org.xnap.plugin.opennap.net;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import javax.swing.Action;
import org.xnap.XNap;
import org.xnap.chat.AbstractChatProvider;
import org.xnap.chat.ChannelInfo;
import org.xnap.chat.ChatManager;
import org.xnap.event.StateListener;
import org.xnap.event.StateSupport;
import org.xnap.gui.action.AbstractListChannelsAction;
import org.xnap.gui.action.JoinChannelAction;
import org.xnap.plugin.opennap.OpenNapPlugin;
import org.xnap.plugin.opennap.net.msg.MessageHandler;
import org.xnap.plugin.opennap.net.msg.client.ListChannelsMessage;
import org.xnap.plugin.opennap.user.OpenNapUser;
import org.xnap.plugin.opennap.util.OpenNapServerVersion;
import org.xnap.util.FiniteStateMachine;
import org.xnap.util.Preferences;
import org.xnap.util.Range;
import org.xnap.util.State;
import org.xnap.util.StringHelper;
import org.xnap.util.prefs.StringValidator;
public class OpenNapServer extends AbstractChatProvider {
//--- Constant(s) ---
public static final int DEFAULT_PORT = 8888;
public static final int DEFAULT_META_PORT = 8875;
/**
* 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;
private static final Hashtable TRANSITION_TABLE;
static {
State[][] table = new State[][] {
{ State.DISCONNECTED,
State.CONNECTING, },
{ State.CONNECTING,
State.CONNECTED, State.ERROR, State.FAILED },
{ State.CONNECTED,
State.DISCONNECTING, State.FAILED },
{ State.DISCONNECTING,
State.DISCONNECTED },
{ State.ERROR,
State.DISCONNECTED },
{ State.FAILED,
State.DISCONNECTED },
};
TRANSITION_TABLE = FiniteStateMachine.createStateTable(table);
}
//--- Data field(s) ---
private static Preferences prefs = Preferences.getInstance();
private OpenNapServerData data;
private OpenNapServerRunner runner;
private int fileCount = -1;
private int fileSize = -1;
private int userCount = -1;
private boolean newUser;
private String remoteIP = null;
/**
* Server was fetched from index service.
*/
private boolean temporary = false;
private String redirectedHost;
private int redirectedPort;
/**
* The time of the next auto connect attempt.
*/
private long nextAutoConnectTime = 0;
/**
* The listener for incoming download and direct browse request.
*/
private OpenNapListener listener = null;
/**
* Maps nicks to {@link OpenNapUser} objects.
*/
private Hashtable userByNick = new Hashtable();
/**
* Maps channel names to {@link OpenNapChannel} objects.
*/
private Hashtable channelByName = new Hashtable();
/**
* The version of the software running on the remote server. Used
* by {@link MessageSender}.
*/
private OpenNapServerVersion version = OpenNapServerVersion.UNKNOWN;
/**
* A list of {@link Range} objects.
*
* The range of the files from the {@link Library} that have been
* shared on this server.
*/
private LinkedList shared = new LinkedList();
private StateMachine sm = new StateMachine();
private StateSupport ss = new StateSupport(this);
private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
private OpenNapNetwork network;
//--- Constructor(s) ---
public OpenNapServer(String host, String ip, int port, String network,
int fileCount, int fileSize, int userCount,
boolean autoConnect)
{
this.data = new OpenNapServerData();
setHost(host);
setIP(ip);
setNetworkName(network);
setPort(port);
setStats(userCount, fileCount, fileSize);
if (autoConnect) {
this.connect();
}
}
public OpenNapServer(String host, int port, String network)
{
this(host, null, port, network, -1, -1, -1, false);
}
public OpenNapServer(String host, int port, String network,
boolean autoConnect)
{
this(host, null, port, network, -1, -1, -1, autoConnect);
}
public OpenNapServer(String host, int port)
{
this(host, port, "");
}
public OpenNapServer(String host, int port, boolean autoConnect)
{
this(host, port, "", autoConnect);
}
public OpenNapServer()
{
this("", DEFAULT_PORT);
}
public OpenNapServer(OpenNapServerData data)
{
this.data = data;
}
//--- Method(s) ---
public void addPropertyChangeListener(PropertyChangeListener l)
{
pcs.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l)
{
pcs.removePropertyChangeListener(l);
}
public void addStateListener(StateListener listener)
{
ss.addStateListener(listener);
}
public void removeStateListener(StateListener listener)
{
ss.removeStateListener(listener);
}
public boolean canAutoRemove()
{
return isTemporary() && sm.getState() == State.ERROR;
}
/**
* Connects to the server.
*/
public void connect()
{
setState(State.CONNECTING);
}
/**
* Disconnects from the server.
*/
public void disconnect()
{
setState(State.DISCONNECTING);
}
/**
* Adds the channel to the {@link ChatManager} and joins the channel.
*/
public void join(String name)
{
OpenNapChannel c = getChannel(name, true);
c.join();
}
/**
* Returns true if <code>obj</code> has the same hostname and port.
*/
public boolean equals(Object obj)
{
if (obj instanceof OpenNapServer) {
OpenNapServer s = (OpenNapServer)obj;
return (getHost().equalsIgnoreCase(s.getHost())
&& getPort() == s.getPort());
}
return false;
}
public synchronized OpenNapChannel getChannel(String name, boolean add)
{
OpenNapChannel c = (OpenNapChannel)channelByName.get(name);
if (c == null) {
c = new OpenNapChannel(this, name);
channelByName.put(name, c);
}
if (add && !ChatManager.getInstance().contains(c)) {
ChatManager.getInstance().add(c);
}
return c;
}
public synchronized OpenNapChannel getChannel(String name)
{
return getChannel(name, false);
}
public Action[] getActions()
{
return new Action[] {
new JoinChannelAction(this), new ListChannelsAction(),
};
}
public String getAutoJoinChannels()
{
return data.autoJoinChannels;
}
public boolean getAutoConnect()
{
return data.autoConnect;
}
public ChannelInfo[] getChannels()
{
return (OpenNapChannel[])channelByName.values().toArray
(new OpenNapChannel[0]);
}
public String getEmail()
{
return (data.email != null) ? data.email : prefs.getEmail();
}
public int getFileCount()
{
return fileCount;
}
public int getFileSize()
{
return fileSize;
}
public String getHost()
{
return data.host;
}
public String getIP()
{
return remoteIP;
}
/**
* Returns the absolute time of the last successful connect.
*/
public long getLastConnect()
{
return data.lastConnect;
}
/**
* Returns the associated listener for incoming requests. Needed
* for reverse downloads.
*/
public OpenNapListener getListener()
{
return listener;
}
public OpenNapUser getLocalPeer()
{
return getUser(getNick());
}
/**
* Returns port of listener or 0 if there is no listener running, which
* means XNap is behind a firewall.
*/
public int getLocalPort()
{
return (listener != null) ? listener.getPort() : 0;
}
/**
*
*/
public String getName()
{
String network = getNetwork().getName();
if (network.length() > 0) {
return network;
}
else {
return getHost();
}
}
/**
* Returns the name of the network this server is part of.
*/
public String getNetworkName()
{
return data.networkName;
}
/**
* Returns the network this server is part of.
*/
public OpenNapNetwork getNetwork()
{
return network;
}
/**
* Returns the absolute time of the next reconnect
*
* @return -1, if the server last connect failed unrecoverably; *
* absolute time of next wished connect attempt in milli seconds,
* otherwise
*/
public long getNextAutoConnectTime()
{
return nextAutoConnectTime;
}
public String getNick()
{
return (data.nick != null) ? data.nick : prefs.getUsername();
}
/**
* Returns the password used for the login.
*/
public String getPassword()
{
return (data.password != null) ? data.password : prefs.getPassword();
}
/**
* Returns the remote port.
*/
public int getPort()
{
return data.port;
}
public String getRedirectedHost()
{
return redirectedHost;
}
public int getRedirectedPort()
{
return redirectedPort;
}
public OpenNapServerRunner getRunner()
{
return runner;
}
/**
* Returns the index range of shared files.
*/
public Range[] getShared()
{
synchronized (shared) {
return (Range[])shared.toArray(new Range[0]);
}
}
public void setShared(Range range)
{
synchronized (shared) {
shared.add(range);
}
}
public String getStatus()
{
return sm.getDescription();
}
public OpenNapUser getUser(String nick)
{
synchronized (userByNick) {
OpenNapUser u = (OpenNapUser)userByNick.get(nick);
if (u == null) {
u = new OpenNapUser(nick, this);
userByNick.put(nick, u);
u.getParent().add(this);
}
return u;
}
}
public int getUserCount()
{
return userCount;
}
public OpenNapServerVersion getVersion()
{
return version;
}
public boolean isConnected()
{
return (sm.getState() == State.CONNECTED);
}
public boolean isDisconnected()
{
return (sm.getState() == State.DISCONNECTED);
}
public boolean isLoginCustomized()
{
return (data.nick != null) || (data.password != null)
|| (data.email != null);
}
public boolean isNewUser()
{
return newUser;
}
public boolean isRedirector()
{
return data.redirector;
}
public boolean isTemporary()
{
return temporary;
}
public synchronized void removeChannel(OpenNapChannel c)
{
channelByName.remove(c.getName());
ChatManager.getInstance().remove(c);
}
public void setAutoConnect(boolean newvalue)
{
// boolean oldValue = getAutoConnect();
data.autoConnect = newvalue;
// pcs.firePropertyChange("autoConnect", oldValue,
// autoConnect);
}
public void setAutoJoinChannels(String autoJoinChannels)
{
String oldValue = getAutoJoinChannels();
data.autoJoinChannels = autoJoinChannels;
pcs.firePropertyChange("autoJoinChannels", oldValue,
autoJoinChannels);
}
/**
* @exception IllegalArgumentException if newValue is invalid.
*/
public void setEmail(String email)
{
if (email != null) {
StringValidator.EMAIL.validate(email);
}
String oldValue = getEmail();
data.email = email;
pcs.firePropertyChange("email", oldValue, email);
}
public void setHost(String host)
{
String oldValue = getHost();
data.host = host;
pcs.firePropertyChange("host", oldValue, host);
}
/**
* OpenNapigator sends an ip which is sometimes more reliable than
* the hostname.
*/
public void setIP(String newValue)
{
remoteIP = newValue;
}
public void setLastConnect(long lastConnect)
{
this.data.lastConnect = lastConnect;
}
public void setListener(OpenNapListener newValue)
{
listener = newValue;
}
public void setNetwork(OpenNapNetwork network)
{
OpenNapNetwork oldValue = getNetwork();
synchronized (sm) {
if (oldValue != null) {
oldValue.remove(this);
if (sm.getState() == State.CONNECTING) {
oldValue.setConnecting(this, false);
network.setConnecting(this, true);
}
else if (sm.getState() == State.CONNECTED) {
oldValue.setConnected(this, false);
network.setConnected(this, true);
}
}
this.network = network;
setNetworkName(network.getName());
network.setStats(this, userCount, fileCount, fileSize);
}
pcs.firePropertyChange("network", oldValue, this.network);
}
public void setNetworkName(String networkName)
{
data.networkName = networkName;
}
/**
* Set <code>newUser</code> to true to create a new account on the
* next logon.
*/
public void setNewUser(boolean newUser)
{
this.newUser = newUser;
}
/**
* @exception IllegalArgumentException if <code>nick</code> is invalid.
*/
public void setNick(String nick)
{
if (nick != null) {
StringValidator.REGULAR_STRING.validate(nick);
}
String oldValue = getNick();
data.nick = nick;
pcs.firePropertyChange("nick", oldValue, nick);
}
/**
* @exception IllegalArgumentException if <code>password</code> is invalid.
*/
public void setPassword(String password)
{
if (password != null) {
StringValidator.REGULAR_STRING.validate(password);
}
String oldValue = getPassword();
data.password = password;
pcs.firePropertyChange("password", oldValue, password);
}
public void setPort(int port)
{
int oldValue = getPort();
data.port = port;
pcs.firePropertyChange("port", new Integer(oldValue),
new Integer(port));
}
public void setRedirectedHost(String redirectedHost)
{
String oldValue = getRedirectedHost();
this.redirectedHost = redirectedHost;
pcs.firePropertyChange("redirectedHost", oldValue, redirectedHost);
}
public void setRedirectedPort(int redirectedPort)
{
int oldValue = getRedirectedPort();
this.redirectedPort = redirectedPort;
pcs.firePropertyChange("redirectedPort", new Integer(oldValue),
new Integer(redirectedPort));
}
public void setRedirector(boolean redirector)
{
boolean oldValue = isRedirector();
data.redirector = redirector;
pcs.firePropertyChange("redirector", new Boolean(oldValue),
new Boolean(redirector));
}
public void setStats(int userCount, int fileCount, int fileSize)
{
this.userCount = userCount;
this.fileCount = fileCount;
this.fileSize = fileSize;
pcs.firePropertyChange("stats", null, null);
if (network != null) {
network.setStats(this, userCount, fileCount, fileSize);
}
}
public void setTemporary(boolean temporary)
{
boolean oldValue = isTemporary();
this.temporary = temporary;
pcs.firePropertyChange("temporary", new Boolean(oldValue),
new Boolean(temporary));
}
public void setVersion(String newValue)
{
version = new OpenNapServerVersion(newValue);
}
public String toString()
{
StringBuffer sb = new StringBuffer();
sb.append(getHost());
sb.append(":");
sb.append(getPort());
String network = getNetwork().getName();
if (network.length() > 0) {
sb.append(" (");
sb.append(network);
sb.append(")");
}
return sb.toString();
}
void setState(State newState, String description)
{
sm.setState(newState, description);
ss.fireStateChanged();
}
void setState(State newState)
{
sm.setState(newState);
ss.fireStateChanged();
}
void setStateDescription(String description)
{
sm.setDescription(description);
pcs.firePropertyChange("status", null, null);
}
//--- Inner Class(es) ---
private class StateMachine extends FiniteStateMachine
{
//--- Constructor(s) ---
public StateMachine()
{
super(State.DISCONNECTED, TRANSITION_TABLE);
}
//--- Method(s) ---
protected synchronized void stateChanged(State oldState,
State newState)
{
if (newState == State.CONNECTING) {
getNetwork().setConnecting(OpenNapServer.this, true);
runner = new OpenNapServerRunner(OpenNapServer.this);
runner.start();
}
else if (newState == State.CONNECTED) {
data.lastConnect = System.currentTimeMillis();
synchronized (shared) {
shared.clear();
}
getNetwork().setConnected(OpenNapServer.this, true);
OpenNapPlugin.getServerManager().setConnected
(OpenNapServer.this, true);
ChatManager.getInstance().add(OpenNapServer.this);
String autoJoin = OpenNapServer.this.getAutoJoinChannels();
if (autoJoin != null && autoJoin.length() > 0) {
// auto join channels
String[] channels = StringHelper.toArray(autoJoin, ";");
for (int i = 0; i < channels.length; i++) {
OpenNapServer.this.join(channels[i]);
}
}
}
else if (newState == State.DISCONNECTING) {
runner.disconnect();
nextAutoConnectTime = System.currentTimeMillis();
}
else if (newState == State.ERROR) {
nextAutoConnectTime = -1;
}
else if (newState == State.FAILED) {
nextAutoConnectTime
= System.currentTimeMillis() + FAILED_INTERVAL;
}
else if (newState == State.DISCONNECTED) {
synchronized (OpenNapServer.this) {
// close all open chat channelByName
for (Iterator i = channelByName.values().iterator();
i.hasNext();) {
((OpenNapChannel)i.next()).setJoined
(false, XNap.tr("server disconnected"));
}
}
}
if (oldState == State.CONNECTING) {
getNetwork().setConnecting(OpenNapServer.this, false);
}
else if (oldState == State.CONNECTED) {
getNetwork().setConnected(OpenNapServer.this, false);
ChatManager.getInstance().remove(OpenNapServer.this);
OpenNapPlugin.getServerManager().setConnected
(OpenNapServer.this, false);
}
}
}
/**
* Queries the list of channels from the server.
*/
private class ListChannelsAction extends AbstractListChannelsAction {
public void actionPerformed(ActionEvent event)
{
MessageHandler.send(OpenNapServer.this, new ListChannelsMessage());
}
}
}
The table below shows all metrics for OpenNapServer.java.




