package dslab.nameserver; import at.ac.tuwien.dsg.orvell.StopShellException; import at.ac.tuwien.dsg.orvell.annotation.Command; import dslab.ComponentFactory; import dslab.util.ComponentId; import dslab.util.Config; import dslab.util.NameserverConfig; import java.io.InputStream; import java.io.PrintStream; import java.rmi.NotBoundException; import java.rmi.RemoteException; import java.rmi.registry.Registry; import java.util.logging.Logger; import static dslab.ComponentFactory.createNameserver; import static dslab.util.Utils.printListing; import static java.lang.System.in; import static java.lang.System.out; import static java.rmi.server.UnicastRemoteObject.exportObject; import static java.rmi.server.UnicastRemoteObject.unexportObject; import static java.util.logging.Level.SEVERE; import static java.util.stream.Collectors.toList; public class Nameserver implements INameserver { private final Logger LOG = Logger.getLogger(Nameserver.class.getSimpleName()); private final NameserverConfig nsConfig; private final NameserverRemote nsRemote; private final Registry registry; private final Runnable shell; /** * Creates a new server instance. * * @param componentId the id of the component that corresponds to the Config resource * @param config the component config * @param in the input stream to read console input from * @param out the output stream to write console output to */ public Nameserver(String componentId, Config config, InputStream in, PrintStream out) throws RemoteException, AlreadyRegisteredException, InvalidDomainException, NotBoundException { ComponentFactory cf = new ComponentFactory(new ComponentId(componentId), config); this.nsConfig = cf.getNameserverConfig(); this.registry = cf.getRegistry(); this.nsRemote = new NameserverRemote(nsConfig.domain()); this.shell = cf.createShell(this, in, out); exportObject(nsRemote, 0); if (nsConfig.isRoot()) { //register root remote with registry registry.rebind(nsConfig.rootId(), nsRemote); } else { //lookup root remote and register with it var root = (INameserverRemote) registry.lookup(nsConfig.rootId()); root.registerNameserver(nsConfig.domain().toString(), nsRemote); } } public static void main(String[] args) throws Exception {createNameserver(args[0], in, out).run();} @Override public void run() { LOG.info("Published remote object for domain " + nsConfig.domain()); shell.run(); } @Override @Command public void nameservers() {printListing(nsRemote.getSortedZones());} @Override @Command public void addresses() { printListing( nsRemote.getMailboxserverAddresses() .stream() .map(x -> x.getKey() + " " + x.getValue()) .collect(toList())); } @Override @Command public void shutdown() { try { unexportObject(nsRemote, true); LOG.info("Unexported " + nsRemote); if (nsConfig.isRoot()) registry.unbind(nsConfig.rootId()); } catch (RemoteException | NotBoundException e) { LOG.log(SEVERE, "Error while unbinding remote object " + nsConfig.rootId(), e); } throw new StopShellException(); } }