DS-Lab / src / main / java / dslab / nameserver / Nameserver.java
Nameserver.java
Raw
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();
    }
}