//
// This class provides a 'shell' for running arbitrary classes in the
// cgi... directory tree.  Class files in this tree should extend class CGI
// and override the WWWCGI() method.  Upon a new connection, a new instance
// of the class is created and WWWCGI() is invoked.
//
// Methods:
//    String cgi_info(String name)	Returns value CGI variable 'name'.
//    int write(String)			CGI routines.
//    int writeln(String)
//
import java.lang.*;
import java.util.*;
import java.io.*;
import WWWJexec.*;

public class CGI {
   public Hashtable var;			// variable strings.

   public final String cgi_info ( String name ) {
	int i;
	if ( var.containsKey(name) ) {
	    return (String) var.get(name);
	} else {
	    return "";
	}
   }
   public final boolean cgi_info_exists ( String name ) {
	int i;
	if ( var.containsKey(name) ) {
	    return true;
	} else {
	    return false;
	}
   }

   public int write(String str) {
	return this.logical_link.write ( str );
   }
   public int writeln(String str) {
	return this.logical_link.write ( str+ "\n" );
   }

   ////////////////////////////////////////////////////////////////////////////
   //
   // Setup routine called by setup_invoke, initialize the class data
   // by exhanging messages with the web server and place in CGI mode.
   // The setup routine returns an argument list to be used in calling
   // the main routine (WWWCGI).
   //
   public final java.lang.Object[] setup_env (WWWJexec link) {
	java.lang.Object[] result = {};		// Empty list.
	logical_link = link;
	state = 0;
	vcount = 0;
	try {
	    var = WWWJexec.CGI_table(link);
	} catch ( java.io.IOException e ) {
	    state = -1;		/* flag error */
	    return result;
	}
	link.write ( "<DNETCGI>" );
	return result;			// null arguments.
   }
   //
   // Teardown called by shell_invoke after WWWCGI() method returns.
   // Send terminal token to signal end-of-data and close link.
   //
   public final void teardown_env ( WWWJexec link ) {
	link.write ( "</DNETCGI>" );
	try { String dummy = link.read(); }
	catch (IOException e) {
	   // Expect to get an I/O exception since server should close
	   // link after receiving </DNETCGI>
	}
	link.close ( );
   }
   //
   // Define non-shell WWWrun that WWWJexec will invoke if this class is
   // referenced explicity as the target class.  Give error message.
   //
   public static void WWWrun ( WWWJexec link ) throws IOException {
     link.write ( "<DNETRECMODE>" );
     link.write ( "<DNETTEXT>" );
     link.write ( "200 OK text" );
     link.write ( 
	"This is a 'Shell' class, you must specify a related class file to execute." );
     link.write ( "</DNETTEXT>" );
     link.close();
   }
   //
   // Define fallback WWWCGI that will be invoked if target sub-class fails
   // to define 1.
   //
   public void WWWCGI() {
      this.logical_link.write ( "Content-type: text/plain\n\n" );
      this.logical_link.write ( "Dummy WWWCGI, must be overridden" );
   }

   ////////////////////////////////////////////////////////////////////////////
   // Main entry point for class shell, called by WWWJexec object JNI level upon
   // each new connection.
   //
   // Arguments:
   //    WWWJexec link			Handle for network I/O between this
   //                                   thread and the web server client thread.
   //    java.lang.Class target		Class record for actual class
   //					referenced in HTTP request.
   // 
   public static void WWWrun ( WWWJexec link, java.lang.Class target ) throws IOException {
	java.lang.Object[] args = { link };
        //
        // Create new instance of target class invoke setup, main, teardown
        // routines.
        //
	boolean result = false;
	String errmsg = "InvocationError";
	try {
	    java.lang.Object obj = target.newInstance();
            //
            // Invoke service routine in created class using support routine
	    // in WWWjexec class (standard error messages).
            //
	    result = link.shell_invoke ( obj, 
		"setup_env", "WWWCGI", "teardown_env", args );
	} catch ( java.lang.InstantiationException e2 ) {
	    errmsg = "InstantiationException";
	} catch ( java.lang.IllegalAccessException e3 ) {
	    errmsg = "IllegalAccessException";
	}
        if ( result == false ) {
	    link.write ( "<DNETTEXT>" );
	    link.write ( "500 instantiation error" );
	    link.write ( "Could not make instance object of target class" );
	    link.write ( errmsg );
	    link.write ( "</DNETTEXT>" );
        }
   }
   ////////////////////////////////////////////////////////////////////
   //  Private fields.
   //
   private int state;			// -1 error, 0 OK
   private WWWJexec logical_link;	// File descriptor.
   private int vcount;			// number of CGI var strings.
}
