package dslab.nameserver; import java.io.InputStream; import java.io.PrintStream; import java.rmi.*; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.UnicastRemoteObject; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import at.ac.tuwien.dsg.orvell.Shell; import at.ac.tuwien.dsg.orvell.StopShellException; import dslab.ComponentFactory; import dslab.util.Config; public class Nameserver implements INameserver { private Registry registry; private String componentId; private PrintStream out; private String registryName; private INameserverRemote nameserverRemote; private NameServerRemote nameServerLocal; private Shell shell; private Thread shellThread; /** * 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) { this.componentId = componentId; this.out = out; // only root nameserver creates RMI registry registryName = config.getString("root_id"); String registryHost = config.getString("registry.host"); int registryPort = config.getInt("registry.port"); if (this.componentId.equals("ns-root")) { // Root Nameserver nameServerLocal = new NameServerRemote("root"); try { nameserverRemote = (INameserverRemote) UnicastRemoteObject.exportObject(nameServerLocal, 0); registry = LocateRegistry.createRegistry(registryPort); registry.rebind(registryName, nameserverRemote); System.out.println("Nameserver bound."); } catch (RemoteException e) { System.err.println("Nameserver exception:"); e.printStackTrace(); } } else { // Zone Nameserver String domain = config.getString("domain"); nameServerLocal = new NameServerRemote(domain); try { registry = LocateRegistry.getRegistry(registryHost, registryPort); nameserverRemote = (INameserverRemote) registry.lookup(registryName); UnicastRemoteObject.exportObject(nameServerLocal, 0); nameserverRemote.registerNameserver(domain, nameServerLocal); } catch (RemoteException | NotBoundException e) { e.printStackTrace(); } catch (InvalidDomainException e) { e.printStackTrace(); } catch (AlreadyRegisteredException e) { e.printStackTrace(); } System.out.printf("Zone Nameserver %s started!%n", domain); } shell = new Shell(in, out) .register("nameservers", ((input, context) -> this.nameservers())) .register("addresses", ((input, context) -> this.addresses())) .register("shutdown", (((input, context) -> { System.out.println("shutting down..."); this.shutdown(); throw new StopShellException(); }))); shellThread = new Thread(shell); } @Override public void run() { shellThread.start(); } @Override public void nameservers() { out.printf("Nameservers stored in the nameserver %s:%n", componentId); List nameservers = nameServerLocal.getNameservers(); out.println(nameservers); AtomicInteger count = new AtomicInteger(0); nameservers.forEach(nameserver -> out.printf("%d. %s%n", count.incrementAndGet(), nameserver)); } @Override public void addresses() { this.out.println(nameServerLocal.getAddresses()); } @Override public void shutdown() { // shell is already interrupted // so just close other things try { UnicastRemoteObject.unexportObject(nameServerLocal, true); } catch (NoSuchObjectException e) { e.printStackTrace(); } if (this.componentId.equals("ns-root")) { try { this.registry.unbind(registryName); UnicastRemoteObject.unexportObject(this.registry, true); } catch(RemoteException | NotBoundException e){ e.printStackTrace(); } } } public static void main(String[] args) throws Exception { INameserver component = ComponentFactory.createNameserver(args[0], System.in, System.out); component.run(); } }