
/**
 * InterfaceDefinition.java
 *
 *
 * Created: Fri May  4 23:56:14 2001
 *
 * @author <a href="mailto: "Jan Newmarch</a>
 * @version
 */

import java.io.*;
import java.text.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;

import servicefinder.ServiceFinder;
import net.jini.core.lookup.ServiceItem;
import java.lang.reflect.Method;

public class InterfaceDefinition extends HttpServlet{

    public void doGet(HttpServletRequest request,
                      HttpServletResponse response)
        throws IOException, ServletException
    {
        response.setContentType("text/html");

        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<head>");

        out.println("<title>" + "Interface Definition" + "</title>");
        out.println("</head>");
        out.println("<body>");

        HttpSession session = request.getSession();
	ServiceFinder finder = (ServiceFinder) 
	    session.getAttribute("ServiceFinder");
	if (finder == null) {
	    out.println("Can't find service finder - try reloading main page");
	    out.println("</body> </html>");
	    return;
	}

        String interfaceName = request.getParameter("interface");
	if (interfaceName == null) {
	    out.println("No interface parameter supplied");
	    out.println("</body> </html>");
	}

	out.println("<center> <h1> Information about interface " +
		    interfaceName +
		    "</h1> </center>");

	// we can't get ask for the class of the interface, since
	// we may not have its class definition. So we have to
	// look for it as an interface of one of the services,
	// which will involve a recursive search
	ServiceItem[] services = null;
	try {
	    services = finder.getServices();
	} catch(java.rmi.RemoteException e) {
	    out.println("<pre>" + e.toString() + "</pre>");
	    out.println("</body>\n</html>");
	    return;
	}

	Class cls = null;
	for (int n = 0; n < services.length; n++) {
	    Class service = services[n].service.getClass();
	    cls = getInterface(interfaceName, service);
	    if (cls != null) {
		break;
	    }
	}
	if (cls == null) {
	    out.println("Can't find interface definition");
	    out.println("</body>\n</html>");
	    return;
	}
	printDefinition(out, cls);

        out.println("</body>");
        out.println("</html>");
    }

    public void doPost(HttpServletRequest request,
                      HttpServletResponse response)
        throws IOException, ServletException
    {
        doGet(request, response);
    }

    /**
     * This needs to be called recursively as we walk
     * up the tree of interface definitions
     */
    Class getInterface(String interfaceName, Class iface) {
	if (iface.getName().equals(interfaceName)) {
	    return iface;
	}

	Class[] parentInterfaces = iface.getInterfaces();
	for (int n= 0; n < parentInterfaces.length; n++) {
	    Class ret = getInterface(interfaceName, parentInterfaces[n]);
	    if (ret != null) {
		return ret;
	    }
	}	
	return null;
    }

    void printDefinition(PrintWriter out, Class cls) {
	out.print("<pre>\ninterface " + cls.getName());
	Class[] ifaces = cls.getInterfaces();
	if (ifaces.length > 0) {
	    out.println(" implements");
	    out.print("        " + ifaces[0].getName());
	    for (int n = 1; n < ifaces.length; n++) {
		out.print(", \n        " + ifaces[n].getName());
	    }
	}
	out.println(" {");

	Method[] methods = cls.getDeclaredMethods();
	for (int n = 0; n < methods.length; n++) {
	    printMethodDefinition(out, methods[n]);
	}
	out.println("};\n</pre>");
    }

    void printMethodDefinition(PrintWriter out, Method meth) {
	out.print("    " + typeName(meth.getReturnType()) + 
		    " " + meth.getName() + "(");
	Class[] params = meth.getParameterTypes();
	if (params.length > 0) {
	    out.print(params[0].getName());
	}
	for (int n = 1; n < params.length; n++) {
	    out.print(", " + typeName(params[n]));
	}
	out.println(");");
    }

    /**
     * return the type as a string
     * for simple types, just use getName()
     * but for arrays and primitive types, need more complex stuff
     */
    String typeName(Class type) {
	if (type.isArray()) {
	    // recursive call to build string
	    return typeName(type.getComponentType()) + "[]";
	}
	if (type.isPrimitive()) {
	    if (type == Boolean.TYPE) {
		return "boolean";
	    } else if (type == Character.TYPE) {
		return "char";
	    } else if (type == Byte.TYPE) {
		return "byte";
	    } else if (type == Short.TYPE) {
		return "short";
	    } else if (type == Integer.TYPE) {
		return "int";
	    } else if (type == Long.TYPE) {
		return "long";
	    } else if (type == Float.TYPE) {
		return "float";
	    } else if (type == Double.TYPE) {
		return "double";
	    } else if (type == Void.TYPE) {
		return "void";
	    }
	}
	return type.getName();
    }
}// InterfaceDefinition
