
package nameserver;

import java.rmi.RMISecurityManager;
import net.jini.discovery.LookupDiscovery;
import net.jini.core.lookup.ServiceTemplate;
import net.jini.discovery.LookupDiscoveryManager;
import net.jini.lookup.ServiceDiscoveryManager;
import net.jini.lookup.LookupCache;
import net.jini.core.lookup.ServiceItem;
import net.jini.lease.LeaseRenewalManager;
import net.jini.lookup.ServiceItemFilter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.MalformedURLException;

import java.io.*;

/**
 * NameServer.java
 *
 *
 * Created: Sun Mar 5 2000
 *
 * @author Jan Newmarch
 * @version 1.0
 */

public class NameServer {

    private static final long WAITFOR = 100000L;
    private static final int PORT = 8000;
    private static final int MAXMATCHES = Integer.MAX_VALUE;
    private LookupCache cache = null;
    private String url;

    public static void main(String argv[]) {
	new NameServer();
    }

    public NameServer() {
	ServiceDiscoveryManager clientMgr = null;

	System.setSecurityManager(new RMISecurityManager());

        try {
            LookupDiscoveryManager mgr =
                new LookupDiscoveryManager(LookupDiscovery.ALL_GROUPS,
                                           null /* unicast locators */,
                                           null /* DiscoveryListener */);
	    clientMgr = new ServiceDiscoveryManager(mgr, 
						new LeaseRenewalManager());
	} catch(Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
  
	try {
	    cache = clientMgr.createLookupCache(null, /* wildcard template */ 
						null, /* no filter */ 
						null /* no listener */);
	} catch(Exception e) {
	    e.printStackTrace();
	    System.exit(1);
	}
System.out.println("entering server loop");
	/* a really simple server loop
	 */
	try {
	    ServerSocket listener = new ServerSocket(PORT);
	    while (true) {
		Socket connection = listener.accept();
System.out.println("opened connection");
		BufferedReader in = new BufferedReader(
					new InputStreamReader(
					    connection.getInputStream()));
		PrintStream out = new PrintStream(connection.getOutputStream());
		String line = in.readLine();
		// line expected to be in form "GET url HTTP/1.1"
		int start = line.indexOf('/') + 1;
		int end = line.indexOf(' ', start);
		if (start == 0 || end == -1) {
		    throw new MalformedURLException();
		}
		url = line.substring(start, end);
System.out.println("url is \"" + url + "\"");
		if (url.equals("")) {
		    listDir(out);
		} else {
		    sendObject(out);
		}
		out.close();
	    }
	} catch(Exception e) {
	    // return error message
	}
    }

    protected void listDir(PrintStream out) throws IOException {
	out.print("HTTP/1.1 200 \r\n");
	out.print("Content-Type: text/html\r\n\r\n");
	out.print("<html><body> <h1>Services</h1>\r\n");
	out.print("<ul>\r\n");
	ServiceItem[] items = cache.lookup(null, MAXMATCHES);
	for (int n = 0; n < items.length; n++) {
	    Object service = items[n].service;
	    // Find all the interfaces this implements and list them
	    // ignore ones like Remote and Serializable.
	    // For now, just print the classes :-(
	    out.print("<li> " + service.getClass().toString());
	    out.print("</li>\r\n");
	}
	out.print("</ul>\r\n</body></html>\r\n");
    }

    protected void sendObject(PrintStream out) throws IOException {
	Class cls = null;
	try {
	     cls = Class.forName(url);
	} catch(Exception e) {
	    // can't find the interface object for this name
	    out.print("HTTP/1.1 404 " + url + " interface not found\r\n\r\n");
	    return;
	}

	ServiceItemFilter filter = new Filter(cls);
	ServiceItem item = cache.lookup(filter);
	if (item == null) {
	    // can't find an implementation of this interface
	    out.print("HTTP/1.1 404 " + url + " service not found\r\n\r\n");
	    return;
	}

	// write the service item to a byte array so we can find out
	// how big it is
	ByteArrayOutputStream ostream = new ByteArrayOutputStream();
	ObjectOutputStream p = new ObjectOutputStream(ostream);
	p.writeObject(item);
	byte[] bytes = ostream.toByteArray();

	// Prepare HTTP header
	out.print("HTTP/1.1 200 \r\n");
	out.print("Content-Length: " + bytes.length +"\r\n");
	out.print("Content-Type: application/x-jini\r\n\r\n");

	System.out.println("Content-length: " + bytes.length);

	// now write the object to the output stream
	out.write(bytes);
    }

    class Filter implements ServiceItemFilter {
	private Class cls;

	public Filter(Class cls) {
	    this.cls = cls;
	}

	public boolean check(ServiceItem item) {
	    if (cls.isInstance(item.service)) {
		return true;
	    } else {
		return false;
	    }
	}
    }
} // NameServer




