Package org.jmule.core.servermanager

Source Code of org.jmule.core.servermanager.ServerManagerImpl

/*
*  JMule - Java file sharing client
*  Copyright (C) 2007-2008 JMule team ( jmule@jmule.org / http://jmule.org )
*
*  Any parts of this program derived from other projects, or contributed
*  by third-party developers are copyrighted by their respective authors.
*
*  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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*
*/
package org.jmule.core.servermanager;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.jmule.core.JMuleAbstractManager;
import org.jmule.core.JMuleManagerException;
import org.jmule.core.configmanager.ConfigurationManager;
import org.jmule.core.downloadmanager.DownloadManagerSingleton;
import org.jmule.core.downloadmanager.InternalDownloadManager;
import org.jmule.core.edonkey.ClientID;
import org.jmule.core.edonkey.E2DKConstants;
import org.jmule.core.edonkey.ED2KServerLink;
import org.jmule.core.edonkey.E2DKConstants.ServerFeatures;
import org.jmule.core.edonkey.metfile.ServerMet;
import org.jmule.core.edonkey.metfile.ServerMetException;
import org.jmule.core.edonkey.packet.tag.TagList;
import org.jmule.core.networkmanager.InternalNetworkManager;
import org.jmule.core.networkmanager.NetworkManagerException;
import org.jmule.core.networkmanager.NetworkManagerSingleton;
import org.jmule.core.servermanager.Server.ServerStatus;
import org.jmule.core.sharingmanager.InternalSharingManager;
import org.jmule.core.sharingmanager.SharingManagerSingleton;
import org.jmule.core.statistics.JMuleCoreStats;
import org.jmule.core.statistics.JMuleCoreStatsProvider;
import org.jmule.core.utils.Convert;
import org.jmule.core.utils.timer.JMTimer;
import org.jmule.core.utils.timer.JMTimerTask;

/**
*
* @author javajox
* @author binary256
* @version $$Revision: 1.15 $$
* Last changed by $$Author: binary255 $$ on $$Date: 2010/01/09 18:07:34 $$
*/
public class ServerManagerImpl extends JMuleAbstractManager implements InternalServerManager  {
  private Collection<Server> server_list = new ConcurrentLinkedQueue<Server>();
  private Server connected_server = null;

  private InternalNetworkManager _network_manager;
  private InternalSharingManager _sharing_manager;

  private ServerMet server_met;

  private List<ServerManagerListener> listener_list = new LinkedList<ServerManagerListener>();

  private boolean auto_connect_started = false;
  private List<Server> candidate_servers = new ArrayList<Server>();

  private InternalDownloadManager _download_manager;
 
  private boolean reconnect_to_server = false;
  private int reconnect_count = 0;
 
  private Comparator<Server> compare_servers_by_ping = new Comparator<Server>() {
    public int compare(Server object1, Server object2) {
      if (object1.getPing() < object2.getPing()) {
        return -1;
      } else if (object1.getPing() > object2.getPing()) {
        return +1;
      }
      return 0;
    }
  };
 
  private JMTimer server_manager_timer;
  private JMTimerTask servers_udp_query;
  private JMTimerTask store_metadata_task;
  private JMTimerTask reconnect_task;

  ServerManagerImpl() {
  }
 
  public void initialize() {
    try {
      super.initialize();
    } catch (JMuleManagerException e) {
      e.printStackTrace();
      return;
    }

    _network_manager = (InternalNetworkManager) NetworkManagerSingleton
        .getInstance();
    _sharing_manager = (InternalSharingManager) SharingManagerSingleton
        .getInstance();
    try {
      server_met = new ServerMet(ConfigurationManager.SERVER_MET);
    } catch (ServerMetException e) {
    }
   
    Set<String> types = new HashSet<String>();
    types.add(JMuleCoreStats.ST_NET_SERVERS_COUNT);
    types.add(JMuleCoreStats.ST_NET_SERVERS_DEAD_COUNT);
    types.add(JMuleCoreStats.ST_NET_SERVERS_ALIVE_COUNT);
   
    JMuleCoreStats.registerProvider(types, new JMuleCoreStatsProvider() {
      public void updateStats(Set<String> types,Map<String, Object> values) {
        if (types.contains(JMuleCoreStats.ST_NET_SERVERS_COUNT)) {
          values.put(JMuleCoreStats.ST_NET_SERVERS_COUNT, getServersCount());
        }
        if (types.contains(JMuleCoreStats.ST_NET_SERVERS_DEAD_COUNT)) {
          int dead_servers_count = 0;
          for(Server server : server_list)
            if (server.isDown())  dead_servers_count++;
          values.put(JMuleCoreStats.ST_NET_SERVERS_DEAD_COUNT, dead_servers_count);
        }
        if (types.contains(JMuleCoreStats.ST_NET_SERVERS_ALIVE_COUNT)) {
          int alive_servers_count = 0;
          for(Server server : server_list)
            if (!server.isDown())  alive_servers_count++;
          values.put(JMuleCoreStats.ST_NET_SERVERS_ALIVE_COUNT, alive_servers_count);
        }
       
      }
    });

    server_manager_timer = new JMTimer();
    servers_udp_query = new JMTimerTask() {
      Random random = new Random();
      public void run() {
        for(Server server : server_list) {
          byte[] bytes = new byte[4];
          random.nextBytes(bytes);
          bytes[2] = (byte)0xFF;
          bytes[3] = (byte)0xFF;
          int challenge = Convert.byteToInt(bytes);
          byte[] byte_challenge = Convert.intToByteArray(challenge);
                   
          challenge = Convert.byteToInt(byte_challenge);
          server.setChallenge(challenge);
          _network_manager.sendServerUDPStatusRequest(server.getAddress(), server.getPort() + 4, challenge);
          _network_manager.sendServerUDPDescRequest(server.getAddress(), server.getPort() + 4);
        }
      }
    };
   
    store_metadata_task = new JMTimerTask() {
      public void run() {
        try {
          storeServerList();
        } catch (ServerManagerException e) {
          e.printStackTrace();
        }
      }
    };
   
    _download_manager = (InternalDownloadManager) DownloadManagerSingleton.getInstance();
   
  }

  public void start() {
    try {
      super.start();
    } catch (JMuleManagerException e) {
      e.printStackTrace();
      return;
    }
    server_manager_timer.addTask(servers_udp_query,
        ConfigurationManager.SERVER_UDP_QUERY_INTERVAL, true);
    server_manager_timer.addTask(store_metadata_task,
        ConfigurationManager.SERVER_LIST_STORE_INTERVAL, true);
  }
 
  public void shutdown() {
    try {
      super.shutdown();
    } catch (JMuleManagerException e) {
      e.printStackTrace();
      return;
    }
    server_manager_timer.cancelAllTasks();
  }

  public void addServerListListener(ServerManagerListener serverListListener) {
    listener_list.add(serverListListener);
  }

  public void clearServerList() {
    server_list.clear();
    notifyServerListCleared();
  }

  public void connect() throws ServerManagerException {
    auto_connect_started = true;
    reconnect_to_server = false;
    candidate_servers.addAll(server_list);
    requestNextAutoConnectServer();
    notifyAutoConnectStarted();
  }

  public void connect(Server server) throws ServerManagerException {
    if (connected_server != null)
      throw new ServerManagerException(
          "JMule is already connected (connecting) to another server");
    if (reconnect_task != null)
      synchronized (reconnect_task) {
        server_manager_timer.removeTask(reconnect_task);
      }
    String ip = server.getAddress();
    int port = server.getPort();
    if (hasServer(ip, port)) {
      connected_server = server;
      connected_server.setStatus(ServerStatus.CONNECTING);
      try {
        _network_manager.connectToServer(ip, port);
      } catch (NetworkManagerException e) {
        throw new ServerManagerException(e);
      }
      notifyIsConnecting(connected_server);
    }

  }

  public void disconnect() throws ServerManagerException {
    if (connected_server == null)
      throw new ServerManagerException("JMule is not connected to server");
    if (reconnect_task != null)
      synchronized (reconnect_task) {
        server_manager_timer.removeTask(reconnect_task);
      }
    reconnect_to_server = false;
    reconnect_count = 0;
    try {
      _network_manager.disconnectFromServer();
    } catch (NetworkManagerException e) {
      throw new ServerManagerException(e);
    }
   
    connected_server.setStatus(ServerStatus.DISCONNECTED);
    notifyDisconnected(connected_server);
    connected_server = null;
  }

  public Server getConnectedServer() {
    return connected_server;
  }

  public Server getServer(String ip, int port) {
    for (Server server : server_list)
      if (server.getAddress().equals(ip))
        if (server.getPort() == port)
          return server;
    return null;
  }
 
  private Server getServer(String ip) {
    for (Server server : server_list)
      if (server.getAddress().equals(ip))
          return server;
    return null;
  }

  public List<Server> getServers() {
    List<Server> result = new LinkedList<Server>();
    result.addAll(server_list);
    return result;
  }

  public int getServersCount() {
    return server_list.size();
  }

  public boolean hasServer(String address, int port) {
    for (Server server : server_list)
      if (server.getAddress().equals(address))
        if (server.getPort() == port)
          return true;
    return false;
  }
 
  public boolean hasServer(Server server) {
    if (server_list.contains(server))
      return true;
    else
      return false;
  }

  protected boolean iAmStoppable() {
    return false;
  }

  public void importList(String fileName) throws ServerManagerException {
    ServerMet server_met;
    try {
      server_met = new ServerMet(fileName);
      server_met.load();
    } catch (ServerMetException cause) {
      throw new ServerManagerException(cause);
    }

    List<String> ip_list = server_met.getIPList();
    List<Integer> port_list = server_met.getPortList();
    List<TagList> tag_list = server_met.getTagList();

    for (int i = 0; i < ip_list.size(); i++) {
      try {
        Server server = newServer(ip_list.get(i), port_list.get(i));
        server.setTagList(tag_list.get(i));
      } catch (ServerManagerException cause) {
        cause.printStackTrace();
      }
    }
    server_met.close();

  }
 
  public boolean isConnected() {
    return connected_server != null;
  }

  public void loadServerList() throws ServerManagerException {
    try {
      server_met.load();
      List<String> ip_list = server_met.getIPList();
      List<Integer> port_list = server_met.getPortList();
      List<TagList> tag_list = server_met.getTagList();

      for (int i = 0; i < ip_list.size(); i++) {
        try {
          Server server = newServer(ip_list.get(i), port_list.get(i));
          server.setTagList(tag_list.get(i));
        } catch (ServerManagerException cause) {
          cause.printStackTrace();
        }
      }
    } catch (Throwable cause) {
      throw new ServerManagerException(cause);
    }
  }

  public Server newServer(ED2KServerLink serverLink)
      throws ServerManagerException {
    String serverIP = serverLink.getServerAddress();
    int serverPort = serverLink.getServerPort();
    if (hasServer(serverIP, serverPort))
      throw new ServerManagerException("Server " + serverIP + " : "
          + serverPort + " already exists");
    Server server = new Server(serverLink);
    server_list.add(server);
    notifyServerAdded(server);
    return server;
  }

  public Server newServer(String serverIP, int serverPort)
      throws ServerManagerException {
    if (hasServer(serverIP, serverPort))
      throw new ServerManagerException("Server " + serverIP + " : "
          + serverPort + " already exists");
    Server server = new Server(serverIP, serverPort);
    server_list.add(server);
    notifyServerAdded(server);
    return server;
  }

  private void notifyAutoConnectStarted() {
    for (ServerManagerListener listener : listener_list)
      try {
        listener.autoConnectStarted();
      } catch (Throwable cause) {
        cause.printStackTrace();
      }
  }

  private void notifyAutoConnectFailed() {
    for (ServerManagerListener listener : listener_list)
      try {
        listener.autoConnectFailed();
      } catch (Throwable cause) {
        cause.printStackTrace();
      }
  }

  private void notifyConnected(Server server) {
    for (ServerManagerListener listener : listener_list)
      try {
        listener.connected(server);
      } catch (Throwable cause) {
        cause.printStackTrace();
      }
  }

  private void notifyDisconnected(Server server) {
    for (ServerManagerListener listener : listener_list)
      try {
        listener.disconnected(server);
      } catch (Throwable cause) {
        cause.printStackTrace();
      }
  }

  private void notifyIsConnecting(Server server) {
    for (ServerManagerListener listener : listener_list)
      try {
        listener.isConnecting(server);
      } catch (Throwable cause) {
        cause.printStackTrace();
      }
  }

  private void notifyMessage(Server server, String message) {
    for (ServerManagerListener listener : listener_list)
      try {
        listener.serverMessage(server, message);
      } catch (Throwable cause) {
        cause.printStackTrace();
      }
  }

  private void notifyServerAdded(Server server) {
    for (ServerManagerListener listener : listener_list)
      try {
        listener.serverAdded(server);
      } catch (Throwable cause) {
        cause.printStackTrace();
      }
  }

  private void notifyServerConnectingFailed(Server server, Throwable cause) {
    for (ServerManagerListener listener : listener_list)
      try {
        listener.serverConnectingFailed(server, cause);
      } catch (Throwable cause1) {
        cause1.printStackTrace();
      }
  }

  private void notifyServerListCleared() {
    for (ServerManagerListener listener : listener_list)
      try {
        listener.serverListCleared();
      } catch (Throwable cause) {
        cause.printStackTrace();
      }
  }

  private void notifyServerRemoved(Server server) {
    for (ServerManagerListener listener : listener_list)
      try {
        listener.serverRemoved(server);
      } catch (Throwable cause) {
        cause.printStackTrace();
      }
  }

  public void receivedIDChange(ClientID clientID,
      Set<ServerFeatures> serverFeatures) {
    if (connected_server == null) {
      // log, must newer get here
      return;
    }
    reconnect_to_server = true;
    reconnect_count = 0;
   
    connected_server.setClientID(clientID);
    connected_server.setFeatures(serverFeatures);

    connected_server.setStatus(ServerStatus.CONNECTED);

    if (auto_connect_started == true) {
      auto_connect_started = false;
      candidate_servers.clear();
    }

    _sharing_manager.startSharingFilesToServer();
    _download_manager.connectedToServer(connected_server);
    notifyConnected(connected_server);

  }

  public void receivedMessage(String message) {
    notifyMessage(connected_server, message);
    for(String error_message : E2DKConstants.SERVER_ERROR_MESSAGES) {
      if (message.contains(error_message))
        try {
          disconnect();
        } catch (ServerManagerException e) {
          e.printStackTrace();
        }
    }
  }

  public void receivedNewServerDescription(String ip, int port,
      int challenge, TagList tagList) {   
    Server server = getServer(ip, port);
    if (server == null)
      return;
    server.setPing(challenge);
   
    server.getTagList().addTag(tagList, true);
  }

  public void receivedServerDescription(String ip, int port, String name,
      String description) {
    Server server = getServer(ip, port);
    if (server == null)
      return;
    server.setName(name);
    server.setDesc(description);
  }

  public void receivedServerList(List<String> ipList, List<Integer> portList) {
    for (int i = 0; i < ipList.size(); i++) {
      try {
        newServer(ipList.get(i), portList.get(i));
      } catch (ServerManagerException e) {
        e.printStackTrace();
      }
    }
  }

  public void receivedServerStatus(int userCount, int fileCount) {
    if (connected_server == null)
      return;
    connected_server.setNumUsers(userCount);
    connected_server.setNumFiles(fileCount);
  }

  public void receivedOldServerStatus(String ip, int port, int challenge, long userCount, long fileCount) {
    Server server = getServer(ip);
    if (server == null) {
      return;
    }
    server.setPing(challenge);
    server.setNumUsers(userCount);
    server.setNumFiles(fileCount);
  }
 
  public void receivedServerStatus(String ip, int port, int challenge,
      long userCount, long fileCount, long softLimit, long hardLimit,
      Set<ServerFeatures> serverFeatures) {
    Server server = getServer(ip);
    if (server == null) {
      return;
    }
    server.setPing(challenge);
    server.setNumUsers(userCount);
    server.setNumFiles(fileCount);
    server.setSoftLimit(Convert.longToInt(softLimit));
    server.setHardLimit(Convert.longToInt(hardLimit));
    server.setFeatures(serverFeatures);
  }

  public void removeServer(Server... servers) throws ServerManagerException {
    for (Server server : servers) {
      if (!hasServer(server.getAddress(), server.getPort()))
        throw new ServerManagerException("Server " + server.getAddress() + " : " + server.getPort() + " not found");
      if (connected_server != null)
        if (connected_server.equals(server))
          disconnect();
      server_list.remove(server);
      notifyServerRemoved(server);
    }
    storeServerList();
  }
 
  public void removeServer(List<Server> servers) throws ServerManagerException {
    for (Server server : servers) {
      if (!hasServer(server.getAddress(), server.getPort()))
        throw new ServerManagerException("Server " + server.getAddress() + " : " + server.getPort() + " not found");
      if (connected_server != null)
        if (connected_server.equals(server))
          disconnect();
      server_list.remove(server);
      notifyServerRemoved(server);
    }
    storeServerList();
  }

  public void removeServerListListener(
      ServerManagerListener serverListListener) {
    listener_list.remove(serverListListener);
  }

  public void serverConnectingFailed(String ip, int port, Throwable cause) {
    final Server failed_server = connected_server;
    connected_server = null;
    notifyServerConnectingFailed(failed_server, cause);
    if (auto_connect_started) {
      try {
        requestNextAutoConnectServer();
      } catch (Throwable t) {
        t.printStackTrace();
      }
    } else
   
    if (reconnect_to_server)
      if (reconnect_count < ConfigurationManager.SERVER_RECONNECT_COUNT) {
      reconnect_task = new JMTimerTask() {
        public void run() {
          if (!reconnect_to_server) return;
          reconnect_count++;
          Server cserver = failed_server;
          reconnect_task = null;
          try {
            connect(cserver);
          } catch (ServerManagerException e) {
            e.printStackTrace();
          }
        }
      };
      server_manager_timer.addTask(reconnect_task, ConfigurationManager.SERVER_RECONNECT_TIMEOUT)
       
      } else {
        _download_manager.disconnectedFromServer(connected_server);
        _sharing_manager.stopSharingFilesToServer();
      }
  }

  public void serverDisconnected(String ip, int port) {
    if (connected_server==null) return;
    if (connected_server.getStatus()==ServerStatus.DISCONNECTED) return ;
    connected_server.setStatus(ServerStatus.DISCONNECTED);
    notifyDisconnected(connected_server);
   
    if (auto_connect_started) {
      try {
        requestNextAutoConnectServer();
      } catch (Throwable t) {
        t.printStackTrace();
      }
    } else {
      if (reconnect_to_server)
      if (reconnect_count < ConfigurationManager.SERVER_RECONNECT_COUNT) {
        reconnect_count++;
        Server cserver = connected_server;
        connected_server = null;
        try {
          connect(cserver);
        } catch (ServerManagerException e) {
          e.printStackTrace();
        }
        return;
      }
      _download_manager.disconnectedFromServer(connected_server);
      _sharing_manager.stopSharingFilesToServer();
    }
   
    connected_server = null;
  }

  public void storeServerList() throws ServerManagerException {
    List<String> ip_list = new LinkedList<String>();
    List<Integer> port_list = new LinkedList<Integer>();
    List<TagList> tag_list = new LinkedList<TagList>();

    for (Server server : server_list) {
      ip_list.add(server.getAddress());
      port_list.add(server.getPort());
      tag_list.add(server.getTagList());
    }
    server_met.setIPList(ip_list);
    server_met.setPortList(port_list);
    server_met.setTagList(tag_list);
    try {
      server_met.store();
    } catch (ServerMetException cause) {
      throw new ServerManagerException(cause);
    }
  }

  private void requestNextAutoConnectServer() throws ServerManagerException {
    if (candidate_servers.size() == 0) {
      auto_connect_started = false;
      notifyAutoConnectFailed();
      return;
    }
    Server server = (Server) Collections.min(candidate_servers,
        compare_servers_by_ping);
    candidate_servers.remove(server);
    connect(server);
  }
}
TOP

Related Classes of org.jmule.core.servermanager.ServerManagerImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.