is.codion.common.rmi.server.DefaultServerLocator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of codion-common-rmi Show documentation
Show all versions of codion-common-rmi Show documentation
Codion Application Framework
The newest version!
/*
* This file is part of Codion.
*
* Codion 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 3 of the License, or
* (at your option) any later version.
*
* Codion 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 Codion. If not, see .
*
* Copyright (c) 2010 - 2024, Björn Darri Sigurðsson.
*/
package is.codion.common.rmi.server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serial;
import java.io.Serializable;
import java.rmi.NotBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import static java.util.Objects.requireNonNull;
final class DefaultServerLocator implements Server.Locator {
private static final Logger LOG = LoggerFactory.getLogger(DefaultServerLocator.class);
private final String hostName;
private final String namePrefix;
private final int registryPort;
private final int port;
private DefaultServerLocator(DefaultBuilder builder) {
this.hostName = requireNonNull(builder.hostName, "hostName must be specified");
this.namePrefix = requireNonNull(builder.namePrefix, "namePrefix must be specified");
this.registryPort = builder.registryPort;
this.port = builder.port;
}
@Override
public Server locateServer()
throws RemoteException, NotBoundException {
List> servers = findServers(hostName, registryPort, namePrefix, port);
if (!servers.isEmpty()) {
return servers.get(0);
}
throw new NotBoundException("'" + namePrefix + "' is not available, see LOG for details. Host: "
+ hostName + (port != -1 ? ", port: " + port : "") + ", registryPort: " + registryPort);
}
static Registry initializeRegistry(int registryPort) throws RemoteException {
LOG.info("Initializing registry on port: {}", registryPort);
Registry localRegistry = LocateRegistry.getRegistry(registryPort);
try {
localRegistry.list();
LOG.info("Registry listing available on port: {}", registryPort);
return localRegistry;
}
catch (Exception e) {
LOG.info("Trying to locate registry: {}", e.getMessage());
LOG.info("Creating registry on port: {}", registryPort);
return LocateRegistry.createRegistry(registryPort);
}
}
private static List> findServers(String hostNames,
int registryPort,
String serverNamePrefix,
int requestedServerPort)
throws RemoteException {
List> servers = new ArrayList<>();
for (String hostName : hostNames.split(",")) {
servers.addAll(findServersOnHost(hostName, registryPort, serverNamePrefix, requestedServerPort));
}
servers.sort(new ServerComparator<>());
return servers;
}
private static List> findServersOnHost(String hostName,
int registryPort,
String serverNamePrefix,
int requestedServerPort)
throws RemoteException {
LOG.info("Searching for servers, host: \"{}\", server name prefix: \"{}\", requested server port: {}, registry port {}",
hostName, serverNamePrefix, requestedServerPort, registryPort);
List> servers = new ArrayList<>();
Registry registry = LocateRegistry.getRegistry(hostName, registryPort);
for (String serverName : registry.list()) {
if (serverName.startsWith(serverNamePrefix)) {
addIfReachable(serverName, requestedServerPort, registry, servers);
}
}
return servers;
}
private static void addIfReachable(String serverName, int requestedServerPort,
Registry registry, List> servers) {
LOG.info("Found server \"{}\"", serverName);
try {
Server server = getIfReachable((Server) registry.lookup(serverName), requestedServerPort);
if (server != null) {
LOG.info("Adding server \"{}\"", serverName);
servers.add(server);
}
}
catch (Exception e) {
LOG.error("Server \"{}\" is unreachable", serverName, e);
}
}
private static Server getIfReachable(Server server,
int requestedServerPort) throws RemoteException {
ServerInformation serverInformation = server.serverInformation();
if (requestedServerPort != -1 && serverInformation.serverPort() != requestedServerPort) {
LOG.warn("Server \"{}\" is serving on port {}, requested port was {}",
serverInformation.serverName(), serverInformation.serverPort(), requestedServerPort);
return null;
}
if (server.connectionsAvailable()) {
return server;
}
LOG.warn("No connections available in server \"{}\"", serverInformation.serverName());
return null;
}
private static final class ServerComparator implements Comparator>, Serializable {
@Serial
private static final long serialVersionUID = 1;
@Override
public int compare(Server o1, Server o2) {
try {
return Integer.compare(o1.serverLoad(), o2.serverLoad());
}
catch (RemoteException e) {
return 1;
}
}
}
static final class DefaultBuilder implements Server.Locator.Builder {
private String hostName = ServerConfiguration.RMI_SERVER_HOSTNAME.get();
private String namePrefix = ServerConfiguration.SERVER_NAME_PREFIX.get();
private int registryPort = ServerConfiguration.REGISTRY_PORT.get();
private int port = ServerConfiguration.SERVER_PORT.get();
@Override
public Builder hostName(String hostName) {
this.hostName = requireNonNull(hostName);
return this;
}
@Override
public Builder namePrefix(String namePrefix) {
this.namePrefix = requireNonNull(namePrefix);
return this;
}
@Override
public Builder registryPort(int registryPort) {
this.registryPort = registryPort;
return this;
}
@Override
public Builder port(int port) {
this.port = port;
return this;
}
@Override
public Server.Locator build() {
return new DefaultServerLocator(this);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy