<?php

  // Babelj is a language server library for Java.
  // Copyright (C) 1999  Pharmatrak
  //
  // This library is free software; you can redistribute it and/or
  // modify it under the terms of the GNU Library General Public
  // License as published by the Free Software Foundation; either
  // version 2 of the License, or (at your option) any later version.
  // 
  // This library is distributed in the hope that it will be useful,
  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  // Library General Public License for more details.
  // 
  // You should have received a copy of the GNU Library General Public
  // License along with this library; if not, write to the
  // Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  // Boston, MA  02111-1307, USA.
  //
  // @author  Timothy W Macinta (twm@alum.mit.edu)
  //
  // Unimplemented commands:  none!

Class Babelj {
  
  var $exception_level = E_WARNING;
  var $last_type_template = 0;
  var $sock;


  //
  // Start of user callable functions
  //

  function connect ($port = 9988) {
    $this->sock = fsockopen("127.0.0.1", $port);
    $this->writeString("babelj_version\nBabelj Version 0.1\n");
    $this->flush();
    return $this->readObject();
  }

  function disconnect () {
    $this->writeString("logout\n");
    $this->flush();
    $retval = $this->readObject();
    fclose($this->sock);
    return $retval;
  }

  function methodCall($obj_ref, $method_name, $args, $type_template = 0) {
    $this->writeString("method_call\n");
    $this->writeObject($obj_ref, "ref");
    $this->writeObject($method_name, "string");
    $this->writeObject($args, $type_template);
    $this->flush();
    return $this->readObject();
  }

  function staticMethodCall($class_name, $method_name, $args, $type_template = 0) {
    $this->writeString("static_method_call\n");
    $this->writeObject($class_name, "string");
    $this->writeObject($method_name, "string");
    $this->writeObject($args, $type_template);
    $this->flush();
    return $this->readObject();
  }

  function newInstanceCall($class_name, $args, $type_template = 0) {
    $this->writeString("new_instance\n");
    $this->writeObject($class_name, "string");
    $this->writeObject($args, $type_template);
    $this->flush();
    return $this->readObject();
  }

  function getStaticField($class_name, $field_name) {
    $this->writeString("get_static_field\n");
    $this->writeObject($class_name, "string");
    $this->writeObject($field_name, "string");
    $this->flush();
    return $this->readObject();
  }
  
  function getField($obj_ref, $field_name) {
    $this->writeString("get_field\n");
    $this->writeObject($obj_ref, "ref");
    $this->writeObject($field_name, "string");
    $this->flush();
    return $this->readObject();
  }
  
  function freeRef($obj_ref) {
    $this->writeString("free_ref\n");
    $this->writeObject($obj_ref, "ref");
    return $this->readObject();
  }

  function lastWasException() {
    return $this->last_type_template == "exception";
  }

  function lastWasNull() {
    return $this->last_type_template == "null";
  }

  function getLastTypeTemplate() {
    return $this->last_type_template;
  }

  function getExceptionLevel() {
    return $this->exception_level;
  }

  function setExceptionLevel($new_level) {
    $this->exception_level = $new_level;
  }


  
  ///
  ///
  /// End of User Callable Functions.
  /// Please do not use the rest of these
  /// functions in external code as they
  /// are not part of the API and are
  /// subject to change.
  ///
  ///

  
  function writeObject($obj, $type_template = "") {

    // recursively write arrays

    if (is_array($obj)) {
      reset($obj);
      $c = count($obj);
      $this->writeString("array\n");
      $this->writeString($c);
      $this->writeString("\n");
      if (is_array($type_template)) reset($type_template);
      while (list($key, $val) = each($obj)) {
	if (is_array($type_template)) {
	  list($key2, $val2) = each($type_template);
	  $this->writeObject($val, $val2);
	} else {
	  $this->writeObject($val, $type_template);
	}
      }
      return;
    }

    // write non-arrays

    if ($type_template == "") {
 echo "writeObject($obj, $type_template)";
      $type_template = "var";
    }
    $this->writeString($type_template);
    $this->writeString("\n");
    if ($type_template == "string" || $type_template == "var") {
      $le = strlen($obj);
      $this->writeString($le);
      $this->writeString("\n");
      $this->writeString($obj);
      return;
    } else if ($type_template == "boolean") {
      if ($obj) $this->writeString("true\n");
      else $this->writeString("false\n");
    } else if ($type_template == "null") {
      return;
    } else {
      $this->writeString($obj);
      $this->writeString("\n");
      return;
    }
  }

  function readObject() {
    $type_template = $this->readString();
    $this->last_type_template = $type_template;

    // catch exceptions

    if ($type_template == "exception") {
      $explain = $this->readObject();
      php3_error($this->exception_level, "Exception from Java.");
      return $explain;
    }

    // recursively read arrays

    if ($type_template == "array") {
      $ar_size = $this->readString();
      if ($ar_size == 0) return array();
      while ($ar_size > 0) {
	$a[] = $this->readObject();
	$ar_size--;
      }
      return $a;
    }

    // read non-arrays

    if ($type_template == "string" || $type_template == "var") {
      $le = $this->readString();
      return $this->readString($le);
    } else if ($type_template == "boolean") {
      $obj = $this->readString();
      if ($obj == "true") return 1;
      else return 0;
    } else if ($type_template == "null") {
      return 0;
    } else {
      return $this->readString();
    }
  }

  function readString($len = -1) {
    $s = "";
    if ($len < 0) {
      while (!feof($this->sock)) {
	$c = fgetc($this->sock);
	if ($c == "\n") {
	  return $s;
	}
	$s = $s . $c;
      }
    } else {
      while ($len > 0 && !feof($this->sock)) {
	$s = $s . fgetc($this->sock);
	$len--;
      }
    }
    return $s;
  }

  function writeString($val) {
    //><font color="#FF0000">< echo $val; ></font><
    fwrite($this->sock, $val);
  }

  function flush() {
    // hmmm... this thing should probably be buffered at some point
  }

}
  
?>
