[libinline-java-perl] 01/398: Initial revision

Jonas Smedegaard dr at jones.dk
Thu Feb 26 11:42:35 UTC 2015


This is an automated email from the git hooks/post-receive script.

js pushed a commit to tag 0.55
in repository libinline-java-perl.

commit 9e3dcac18fd03535a5a8ecda96f1055ba42fd39c
Author: patrick <>
Date:   Wed Feb 28 15:07:10 2001 +0000

    Initial revision
---
 Java.pm          | 707 ++++++++++++++++++++++++++++++++++++++++++++++
 Java/Init.pm     | 205 ++++++++++++++
 Java/Object.pm   | 155 +++++++++++
 Java/Protocol.pm | 837 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 1904 insertions(+)

diff --git a/Java.pm b/Java.pm
new file mode 100644
index 0000000..c5d3923
--- /dev/null
+++ b/Java.pm
@@ -0,0 +1,707 @@
+package Inline::Java;
+ at Inline::Java::ISA = qw(Inline) ;
+
+
+use strict ;
+
+
+$Inline::Java::VERSION = '0.01' ;
+
+# DEBUG is set via the JAVA_DEBUG config
+$Inline::Java::private::DEBUG = undef ;
+
+
+require Inline ;
+use Config ;
+use Data::Dumper ;
+use FindBin ;
+use Carp ;
+use Cwd qw(cwd abs_path) ;
+
+use IO::Socket ;
+
+use Inline::Java::private::Object ;
+use Inline::Java::private::Protocol ;
+# Must be last.
+use Inline::Java::private::Init ;
+
+
+# Stores a list of the Java interpreters running
+my @CHILDREN = () ;
+my $CHILD_CNT = 0 ;
+my $DONE = 0 ;
+
+
+# This stuff is to control the termination of the Java Interpreter
+sub done {
+	my $signal = shift ;
+
+	$DONE = 1 ;
+
+	if (! $signal){
+		debug("killed by natural death.") ;
+	}
+	else{
+		debug("killed by signal SIG$signal.") ;
+	}
+
+	foreach my $pid (@CHILDREN){
+		my $ok = kill 9, $pid ;
+		debug("killing $pid...", ($ok ? "ok" : "failed")) ;
+	}
+
+	exit 1 ;
+}
+END {
+	if (! $DONE){
+		done() ;
+	}
+}
+use sigtrap 'handler', \&done, 'normal-signals' ;
+
+
+
+
+# Register this module as an Inline language support module
+sub register {
+    return {
+	    language => 'Java',
+	    aliases => ['JAVA', 'java'],
+	    type => 'compiled',
+	    suffix => 'jdat',
+	   };
+}
+
+
+# Validate the Java config options
+sub usage_validate {
+    my $key = shift;
+    return <<END;
+The value of config option '$key' must be a string or an array ref
+
+END
+}
+
+
+sub validate {
+	my $o = shift ;
+
+	return $o->_validate(0, @_) ;
+}
+
+
+# Here validate is overridden because some of the config options are needed
+# at load as well.
+sub _validate {
+	my $o = shift ;
+	my $ignore_other_configs = shift ;
+
+	if (! exists($o->{Java}->{JAVA_PORT})){
+		$o->{Java}->{JAVA_PORT} = 7890 ;
+	}
+	if (! exists($o->{Java}->{JAVA_STARTUP_DELAY})){
+		$o->{Java}->{JAVA_STARTUP_DELAY} = 15 ;
+	}
+	if (! exists($o->{Java}->{JAVA_DEBUG})){
+		$o->{Java}->{JAVA_DEBUG} = 0 ;
+	}
+
+    while (@_) {
+		my ($key, $value) = (shift, shift) ;
+		if ($key eq 'JAVA_BIN'){
+		    $o->{Java}->{$key} = $value ;
+		}
+		elsif ($key eq 'JAVA_CLASSPATH'){
+		    $o->{Java}->{$key} = $value ;
+		}
+		elsif (
+			($key eq 'JAVA_PORT')||
+			($key eq 'JAVA_STARTUP_DELAY')){
+
+			if ($value !~ /^\d+$/){
+				croak "config '$key' must be an integer" ;
+			}
+			if (! $value){
+				croak "config '$key' can't be zero" ;
+			}
+		    $o->{Java}->{$key} = $value ;
+		}
+		elsif ($key eq 'JAVA_DEBUG'){
+		    $o->{Java}->{$key} = $value ;
+			$Inline::Java::private::DEBUG = $value ;
+		}
+		else{
+			if (! $ignore_other_configs){
+				croak "'$key' is not a valid config option for Inline::Java\n";	
+			}
+		}
+	}
+
+	$o->set_classpath() ; 
+	$o->set_java_bin() ; 
+
+	debug("validate done.") ;
+}
+
+
+
+# Parse and compile Java code
+sub build {
+	my $o = shift ;
+
+	my $install_lib = $o->{install_lib} ;
+	my $modpname = $o->{modpname} ;
+	my $install = "$install_lib/auto/$modpname" ;
+
+	$o->write_java ;
+	$o->write_makefile ;
+	$o->compile ;
+
+	$o->{Java}->{built} = 1 ;
+
+	set_classpath($install) ;
+}
+
+
+# Return a small report about the Java code.
+sub info {
+    my $o = shift;
+
+	if (! $o->{Java}->{built}){
+		$o->build ;
+	}
+	if (! $o->{Java}->{loaded}){
+		$o->load ;
+	}
+
+	my $info = '' ;
+	my $d = $o->{Java}->{data} ;
+
+    my %classes = %{$d->{classes}} ;
+ 	$info .= "The following Java classes have been bound to Perl:\n" ;
+    foreach my $class (sort keys %classes) {
+		$info .= "\tclass $class:\n" ;
+
+		if (defined($d->{classes}->{$class}->{constructors})){
+			foreach my $const (@{$d->{classes}->{$class}->{constructors}}) {
+				my $sign = $const ;
+				my $name = $class ;
+				$name =~ s/^(.*)::// ;
+				$info .= "\t\tpublic $name(" . join(", ", @{$sign}) . ")\n" ;
+			}
+		}
+		foreach my $method (sort keys %{$d->{classes}->{$class}->{methods}->{static}}) {
+			my $sign = $d->{classes}->{$class}->{methods}->{static}->{$method} ;
+			if (defined($sign)){
+				foreach my $s (@{$sign}){
+					$info .= "\t\tpublic static $method(" . join(", ", @{$s}) . ")\n" ;
+				}
+			}
+		}
+		foreach my $method (sort keys %{$d->{classes}->{$class}->{methods}->{instance}}) {
+			my $sign = $d->{classes}->{$class}->{methods}->{instance}->{$method} ;
+			if (defined($sign)){
+				foreach my $s (@{$sign}){
+					$info .= "\t\tpublic $method(" . join(", ", @{$s}) . ")\n" ;
+				}
+			}
+		}
+    }
+
+
+    return $info ;
+}
+
+
+# Writes the java code.
+sub write_java {
+	my $o = shift ;
+
+	my $build_dir = $o->{build_dir} ;
+	my $modfname = $o->{modfname} ;
+	my $code = $o->{code} ;
+
+    $o->mkpath($o->{build_dir}) ;
+
+	open(JAVA, ">$build_dir/$modfname.java") or 
+		croak "Can't open $build_dir/$modfname.java: $!" ;
+
+	Inline::Java::private::Init::DumpJavaCode(\*JAVA, $modfname, $code) ;
+
+	close(JAVA) ;
+
+	debug("write_java done.") ;
+}
+
+
+# Writes the makefile.
+sub write_makefile {
+	my $o = shift ;
+
+	my $build_dir = $o->{build_dir} ;
+	my $install_lib = $o->{install_lib} ;
+	my $modpname = $o->{modpname} ;
+	my $modfname = $o->{modfname} ;
+
+	my $install = "$install_lib/auto/$modpname" ;
+    $o->mkpath($install) ;
+
+	my $javac = $o->{Java}->{JAVA_BIN} . "/javac" ;
+	my $java = $o->{Java}->{JAVA_BIN} . "/java" ;
+
+	my $debug = ($Inline::Java::private::DEBUG ? "true" : "false") ;
+
+	open(MAKE, ">$build_dir/Makefile") or 
+		croak "Can't open $build_dir/Makefile: $!" ;
+
+	print MAKE "class:\n" ;
+	print MAKE "\t$javac $modfname.java > cmd.out 2<&1\n" ;
+	print MAKE "\tcp -f *.class $install\n" ;
+	print MAKE "\n" ;
+	print MAKE "report:\n" ;
+	print MAKE "\t$java $modfname report $debug *.class > cmd.out 2<&1\n" ;
+	print MAKE "\tcp -f *.jdat $install\n" ;
+
+	close(MAKE) ;
+
+	debug("write_makefile done.") ;
+}
+
+
+sub set_classpath {
+	my $o = shift ;
+	my $path = shift ;
+
+	my @cp = split(/:/, "$ENV{CLASSPATH}:$o->{Java}->{JAVA_CLASSPATH}:$path") ;
+	my %cp = map { ($_ !~ /^\s*$/ ? ($_, 1) : ()) } @cp ;
+
+	$ENV{CLASSPATH} = join(":", keys %cp) ;
+
+	debug("  classpath: " . $ENV{CLASSPATH}) ;
+}
+
+
+sub set_java_bin {
+	my $o = shift ;
+
+	my $cjb = $o->{Java}->{JAVA_BIN} ;
+	my $ejb = $ENV{JAVA_BIN} ;
+	if ($cjb){
+		$cjb =~ s/\/+$// ;
+		return $o->find_java_bin($cjb) ;
+	}
+	elsif ($ejb) {
+		$ejb =~ s/\/+$// ;
+		$o->{Java}->{JAVA_BIN} = $ejb ;
+		return $o->find_java_bin($ejb) ;
+	}
+
+	# Java binaries are assumed to be in $ENV{PATH} ;
+	my @path = split(/:/, $ENV{PATH}) ;
+	return $o->find_java_bin(@path) ;
+}
+
+
+sub find_java_bin {
+	my $o = shift ;
+	my @paths = @_ ;
+	
+	my $found = 0 ;
+	foreach my $p (@paths){
+		if ($p !~ /^\s*$/){
+			$p =~ s/\/+$// ;
+			my $home = (getpwuid($<))[7] ;
+			$p =~ s/^~/$home/ ;
+	
+			my $java = $p . "/java" ;
+			if (-f $java){
+				debug("  found java binaries in $p") ;
+				$o->{Java}->{JAVA_BIN} = $p ;
+				$found = 1 ;
+				last ;
+			}	
+		}
+	}
+
+	if (! $found){
+		croak 
+			"Can't locate your java binaries ('java' and 'javac'). Please set one of the following to the proper directory:\n" .
+		    "  - The JAVA_BIN config option;\n" .
+		    "  - The JAVA_BIN environment variable;\n" .
+		    "  - The PATH environment variable.\n" ;
+	}
+}
+
+
+# Run the build process.
+sub compile {
+	my $o = shift ;
+
+	my $build_dir = $o->{build_dir} ;
+	my $modpname = $o->{modpname} ;
+	my $modfname = $o->{modfname} ;
+	my $install_lib = $o->{install_lib} ;
+
+	my $cwd = &cwd ;
+
+	my $make = $Config::Config{make} ;
+	if (! $make){
+		croak "Can't locate your make binary" ;
+	}
+
+	foreach my $cmd (
+		"make -s class",
+		"make -s report",
+		) {
+
+		chdir $build_dir ;
+		my $res = system($cmd) ;
+		$res and do {
+			$o->error_copy ;
+			croak $o->error_msg($cmd, $cwd) ;
+		} ;
+
+	    chdir $cwd ;
+	}
+
+    if ($o->{config}{CLEAN_AFTER_BUILD} and 
+		not $o->{config}{REPORTBUG}){
+		$o->rmpath($o->{config}{DIRECTORY} . 'build/', $modpname) ;
+    }	
+
+	debug("compile done.") ;
+}
+
+
+sub error_msg {
+	my $o = shift ;
+	my $cmd = shift ;
+	my $cwd = shift ;
+
+	my $build_dir = $o->{build_dir} ;
+	my $error = `cat cmd.out` ;
+
+	return <<MSG
+
+A problem was encountered while attempting to compile and install your Inline
+$o->{language} code. The command that failed was:
+  $cmd
+
+The build directory was:
+$build_dir
+
+The error message was:
+$error
+
+To debug the problem, cd to the build directory, and inspect the output files.
+
+MSG
+;
+}
+
+
+# Load and Run the Java Code.
+sub load {
+    my $o = shift ;
+	
+	if ($o->{mod_exists}){
+		# In this case, the options are not rechecked, and therefore
+		# the defaults not registered. We must force it
+		$o->_validate(1, %{$o->{config}}) ;
+	}
+
+	my $install_lib = $o->{install_lib} ;
+	my $modpname = $o->{modpname} ;
+	my $modfname = $o->{modfname} ;
+
+	my $class_dir = "$install_lib/auto/$modpname" ;
+	my $class = $modfname ;
+
+	# Now we must open the jdat file and read it's contents.
+	if (! open(JDAT, "$class_dir/$class.jdat")){
+		croak "Can't open $class_dir/$class.jdat code information file" ;
+	}
+	my @lines = <JDAT> ;
+	close(JDAT) ;
+
+	debug(@lines) ;
+
+	$o->load_jdat(@lines) ;
+	$o->bind_jdat() ;
+
+	my $java = $o->{Java}->{JAVA_BIN} . "/java" ;
+
+	debug("  load is forking.") ;
+	my $pid = fork() ;
+	if (! defined($pid)){
+		croak "Can't fork to start Java interpreter" ;
+	}
+	$CHILD_CNT++ ;
+
+	if ($pid){
+		# parent here
+		debug("  parent here.") ;
+
+		push @CHILDREN, $pid ;
+
+		$o->setup_socket() ;		
+	
+		$o->{Java}->{loaded} = 1 ;
+		debug("load done.") ;
+	}
+	else{
+		# child here
+		debug("  child here.") ;
+
+		my $port = $o->{Java}->{JAVA_PORT} + ($CHILD_CNT - 1) ;
+		my $debug = ($Inline::Java::private::DEBUG ? "true" : "false") ;
+		debug("    $java $class run $debug $port") ;
+
+		chdir $class_dir ;
+		exec $java, $class, "run", $debug, $port, 
+			or croak "Can't exec Java interpreter" ;
+	}
+}
+
+
+# Load the jdat code information file.
+sub load_jdat {
+	my $o = shift ;
+	my @lines = @_ ;
+
+	$o->{Java}->{data} = {} ;
+	my $d = $o->{Java}->{data} ;
+
+	my $current_class = undef ;
+	foreach my $line (@lines){
+		chomp($line) ;
+		if ($line =~ /^class ([\w.\$]+)$/){
+			# We found a class definition
+			$current_class = $1 ;
+			$current_class =~ s/\$/::/g ;
+			$d->{classes}->{$current_class} = {} ;
+			$d->{classes}->{$current_class}->{constructors} = undef ;
+			$d->{classes}->{$current_class}->{methods} = {} ;
+			$d->{classes}->{$current_class}->{methods}->{static} = {} ;
+			$d->{classes}->{$current_class}->{methods}->{instance} = {} ;
+			$d->{classes}->{$current_class}->{fields} = {} ;
+			$d->{classes}->{$current_class}->{fields}->{static} = {} ;
+			$d->{classes}->{$current_class}->{fields}->{instance} = {} ; 
+		}
+		elsif ($line =~ /^constructor \((.*)\)$/){
+			my $signature = $1 ;
+
+			if (! defined($d->{classes}->{$current_class}->{constructors})){
+				$d->{classes}->{$current_class}->{constructors} = [] ;
+			}
+			else {
+				croak "Can't bind class $current_class: class has more than one constructor" ;
+			}
+			push @{$d->{classes}->{$current_class}->{constructors}}, [split(", ", $signature)] ;
+		}
+		elsif ($line =~ /^method (\w+) ([\w.\$]+) (\w+)\((.*)\)$/){
+			my $static = $1 ;
+			my $declared_in = $2 ;
+			my $method = $3 ;
+			my $signature = $4 ;
+
+			if ($declared_in ne $current_class){
+				next ;
+			}
+			if (! defined($d->{classes}->{$current_class}->{methods}->{$static}->{$method})){
+				$d->{classes}->{$current_class}->{methods}->{$static}->{$method} = [] ;
+			}
+			else{
+				croak "Can't bind class $current_class: class has more than one '$method' method" ;
+			}
+			push @{$d->{classes}->{$current_class}->{methods}->{$static}->{$method}}, [split(", ", $signature)] ;
+		}
+		elsif ($line =~ /^field (\w+) ([\w.\$]+) (\w+) ([\w.]+)$/){
+			my $static = $1 ;
+			my $declared_in = $2 ;
+			my $field = $3 ;
+			my $type = $4 ;
+
+			if ($declared_in ne $current_class){
+				next ;
+			}
+
+			$d->{classes}->{$current_class}->{fields}->{$static}->{$field} = $type ;
+		}
+	}
+
+	# debug_obj($d) ;
+}
+
+
+# Binds the classes and the methods to Perl
+sub bind_jdat {
+	my $o = shift ;
+
+	my $d = $o->{Java}->{data} ;
+	my $modfname = $o->{modfname} ;
+
+	my $c = ":" ;
+    my %classes = %{$d->{classes}} ;
+    foreach my $class (sort keys %classes) {
+		my $java_class = $class ;
+		$java_class =~ s/::/\$/g ;
+		my $class_name = $class ;
+		$class_name =~ s/^(.*)::// ;
+		my $code = <<CODE;
+package $o->{pkg}::$class ;
+\@$o->{pkg}::$class$c:ISA = qw(Inline::Java::private::Object) ;
+\$$o->{pkg}::$class$c:EXISTS = 1 ;
+
+CODE
+
+		if (defined($d->{classes}->{$class}->{constructors})){
+			my @sign = @{$d->{classes}->{$class}->{constructors}->[0]} ;
+			my $signature = "'" . join("', '", @sign). "'" ;
+			my $pkg = $o->{pkg} ;
+			$code .= <<CODE;
+
+sub new {
+	my \$class = shift ;
+	my \@args = \@_ ;
+	
+	my \$err = \$class->__validate_prototype([\@args], [($signature)]) ;
+	croak \$err if \$err ;
+
+	return \$class->__new('$java_class', '$pkg', '$modfname', -1, \@_) ;
+}
+
+
+sub $class_name {
+	return new(\@_) ;
+}
+
+CODE
+		}
+
+
+		foreach my $method (sort keys %{$d->{classes}->{$class}->{methods}->{static}}) {
+			my @sign = @{$d->{classes}->{$class}->{methods}->{static}->{$method}->[0]} ;
+			my $signature = "'" . join("', '", @sign). "'" ;
+			my $pkg = $o->{pkg} ;
+			$code .= <<CODE;
+
+sub $method {
+	my \$class = shift ;
+	my \@args = \@_ ;
+	
+	my \$err = \$class->__validate_prototype([\@args], [($signature)]) ;
+	croak \$err if \$err ;
+	
+	my \$proto = new Inline::Java::private::Protocol(undef, '$modfname') ;
+
+	return \$proto->CallStaticJavaMethod('$java_class', '$pkg', '$method', \@args) ;
+}
+
+
+sub $class_name {
+	return new(\@_) ;
+}
+
+CODE
+		}
+
+
+		foreach my $method (sort keys %{$d->{classes}->{$class}->{methods}->{instance}}) {
+			my @sign = @{$d->{classes}->{$class}->{methods}->{instance}->{$method}->[0]} ;
+			my $signature = "'" . join("', '", @sign). "'" ;
+			$code .= <<CODE;
+
+sub $method {
+	my \$this = shift ;
+	my \@args = \@_ ;
+	
+	my \$err = \$this->__validate_prototype([\@args], [($signature)]) ;
+	croak \$err if \$err ;
+	
+	return \$this->{private}->{proto}->CallJavaMethod('$method', \@args) ;
+}
+
+
+sub $class_name {
+	return new(\@_) ;
+}
+
+CODE
+		}
+		
+		debug($code) ;
+
+		eval $code ;
+		croak $@ if $@ ;
+	
+	}
+}
+
+
+# Sets up the communication socket to the Java program
+sub setup_socket {
+	my $o = shift ;
+
+	my $timeout = $o->{Java}->{JAVA_STARTUP_DELAY} ;
+	my $port = $o->{Java}->{JAVA_PORT} + ($CHILD_CNT - 1) ;
+
+	my $modfname = $o->{modfname} ;
+	my $socket = undef ;
+
+	my $last_words = "timeout\n" ;
+	eval {
+		local $SIG{ALRM} = sub { die($last_words) ; } ;
+		alarm($timeout) ;
+
+		while (1){
+			$socket = new IO::Socket::INET(
+				PeerAddr => 'localhost',
+				PeerPort => $port,
+				Proto => 'tcp') ;
+			if ($socket){
+				last ;
+			}
+		}
+
+		alarm(0) ;
+	} ;
+	if ($@){
+		if ($@ eq $last_words){
+			croak "Java program taking more than $timeout seconds to start. Increase config JAVA_STARTUP_DELAY if necessary." ;
+		}
+		else{
+			croak $@ ;
+		}
+	}
+	if (! $socket){
+		croak "Can't connect to Java program: $!" ;
+	}
+
+	$socket->autoflush(1) ;
+	$Inline::Java::private::Protocol::socket->{$modfname} = $socket ;
+}
+
+
+sub debug {
+	if ($Inline::Java::private::DEBUG){
+		my $str = join("", @_) ;
+		while (chomp($str)) {}
+		print STDERR "perl: $str\n" ;
+	}
+}
+
+
+sub debug_obj {
+	my $obj = shift ;
+
+	if ($Inline::Java::private::DEBUG){
+		print STDERR Dumper($obj) ;
+	}
+}
+
+
+
+1 ;
+
+__END__
diff --git a/Java/Init.pm b/Java/Init.pm
new file mode 100644
index 0000000..efa71cb
--- /dev/null
+++ b/Java/Init.pm
@@ -0,0 +1,205 @@
+package Inline::Java::private::Init ;
+
+my $DATA = join('', <DATA>) ;
+my $OBJECT_DATA = join('', <Inline::Java::private::Object::DATA>) ;
+my $PROTO_DATA = join('', <Inline::Java::private::Protocol::DATA>) ;
+
+sub DumpJavaCode {
+	my $fh = shift ;
+	my $modfname = shift ;
+	my $code = shift ;
+
+	my $java = $DATA ;
+	my $java_obj = $OBJECT_DATA ;
+	my $java_proto = $PROTO_DATA ;
+
+	$java =~ s/<INLINE_JAVA_OBJECT>/$java_obj/g ;
+	$java =~ s/<INLINE_JAVA_PROTOCOL>/$java_proto/g ;
+	$java =~ s/<INLINE_JAVA_CODE>/$code/g ;
+
+	$java =~ s/<INLINE_MODFNAME>/$modfname/g ;
+
+	print $fh $java ;
+}
+
+
+
+1 ;
+
+
+
+__DATA__
+
+import java.net.* ;
+import java.io.* ;
+import java.util.* ;
+import java.lang.reflect.* ;
+
+
+<INLINE_JAVA_CODE>
+
+
+public class <INLINE_MODFNAME> {
+	public ServerSocket ss ;
+	String module = "<INLINE_MODFNAME>" ;
+	boolean debug = false ;
+
+	public HashMap objects = new HashMap() ;
+	public int objid = 1 ;
+
+	<INLINE_MODFNAME>(String[] argv) {
+		String mode = argv[0] ;
+		debug = new Boolean(argv[1]).booleanValue() ;
+
+		if (mode.equals("report")){
+			Report(argv, 2) ;
+		}
+		else if (mode.equals("run")){
+			int port = Integer.parseInt(argv[2]) ;
+
+			try {
+				ss = new ServerSocket(port) ;
+				Socket client = ss.accept() ;
+					
+				BufferedReader br = new BufferedReader(
+					new InputStreamReader(client.getInputStream())) ;
+				BufferedWriter bw = new BufferedWriter(
+					new OutputStreamWriter(client.getOutputStream())) ;
+
+				while (true){
+					String cmd = br.readLine() ;
+					debug("  packet recv is " + cmd) ;
+
+					if (cmd != null){
+						InlineJavaProtocol ijp = new InlineJavaProtocol(this, cmd) ;
+						try {
+							ijp.Do() ;
+							debug("  packet sent is " + ijp.response) ;
+							bw.write(ijp.response + "\n") ;
+							bw.flush() ;					
+						}
+						catch (InlineJavaException e){
+							String err = "error scalar:" + ijp.unpack(e.getMessage()) ;
+							debug("  packet sent is " + err) ;
+							bw.write(err + "\n") ;
+							bw.flush() ;
+						}
+					}
+					else{
+						System.exit(1) ;
+					}
+				}
+			}
+			catch (IOException e){
+				System.err.println("Can't open server socket on port " + String.valueOf(port)) ;
+			}
+			System.exit(1) ;
+		}
+		else{
+			System.err.println("Invalid startup mode " + mode) ;
+			System.exit(1) ;
+		}
+	}
+
+
+	void Report (String [] class_list, int idx){
+		// First we must open the file
+		try {
+			File dat = new File(module + ".jdat") ;
+			PrintWriter pw = new PrintWriter(new FileWriter(dat)) ;
+
+			for (int i = idx ; i < class_list.length ; i++){
+				if (! class_list[i].startsWith(module)){
+					StringBuffer name = new StringBuffer(class_list[i]) ;
+					name.replace(name.length() - 6, name.length(), "") ;
+					Class c = Class.forName(name.toString()) ;
+															
+					pw.println("class " + c.getName()) ;
+					Constructor constructors[] = c.getConstructors() ;
+					Method methods[] = c.getMethods() ;
+					Field fields[] = c.getFields() ;
+
+					for (int j = 0 ; j < constructors.length ; j++){
+						Constructor x = constructors[j] ;
+						String sign = CreateSignature(x.getParameterTypes()) ;
+						Class decl = x.getDeclaringClass() ;
+						pw.println("constructor" + " " + sign) ;
+					}
+					for (int j = 0 ; j < methods.length ; j++){
+						Method x = methods[j] ;
+						String stat = (Modifier.isStatic(x.getModifiers()) ? " static " : " instance ") ;
+						String sign = CreateSignature(x.getParameterTypes()) ;
+						Class decl = x.getDeclaringClass() ;
+						pw.println("method" + stat + decl.getName() + " " + x.getName() + sign) ;
+					}
+					for (int j = 0 ; j < fields.length ; j++){
+						Field x = fields[j] ;
+						String stat = (Modifier.isStatic(x.getModifiers()) ? " static " : " instance ") ;
+						Class decl = x.getDeclaringClass() ;
+						Class type = x.getType() ;
+						pw.println("field" + stat + decl.getName() + " " + x.getName() + " " + type.getName()) ;
+					}					
+				}
+			}
+
+			pw.close() ; 
+		}
+		catch (IOException e){
+			System.err.println("Problems writing to " + module + ".jdat file: " + e.getMessage()) ;
+			System.exit(1) ;			
+		}
+		catch (ClassNotFoundException e){
+			System.err.println("Can't find class: " + e.getMessage()) ;
+			System.exit(1) ;
+		}
+	}
+
+
+	String CreateSignature (Class param[]){
+		StringBuffer ret = new StringBuffer() ;
+		for (int i = 0 ; i < param.length ; i++){
+			if (i > 0){
+				ret.append(", ") ;
+			}
+			ret.append(param[i].getName()) ;
+		}
+
+		return "(" + ret.toString() + ")" ;
+	}
+
+
+	public static void main(String[] argv) {
+		new <INLINE_MODFNAME>(argv) ;
+	}
+
+
+	public void debug(String s) {
+		if (debug){
+			System.err.println("java: " + s) ;
+		}
+	}
+
+
+	<INLINE_JAVA_OBJECT>
+
+
+
+	<INLINE_JAVA_PROTOCOL>
+
+
+	class InlineJavaException extends Exception {
+		InlineJavaException(String s) {
+			super(s) ;
+		}
+	}
+
+
+	class InlineJavaCastException extends InlineJavaException {
+		InlineJavaCastException(String m){
+			super(m) ;
+		}
+	}
+}
+
+
+
diff --git a/Java/Object.pm b/Java/Object.pm
new file mode 100644
index 0000000..ae01bea
--- /dev/null
+++ b/Java/Object.pm
@@ -0,0 +1,155 @@
+package Inline::Java::private::Object ;
+ at Inline::Java::private::Object::ISA = qw(Tie::StdHash) ;
+
+
+use strict ;
+
+use Carp ;
+use Data::Dumper ;
+use Tie::Hash ;
+use Inline::Java::private::Protocol ;
+
+
+
+# Bogus constructor. We fall here if no public constructor is defined
+# in the Java class.
+sub new {
+	my $class = shift ;
+	
+	croak "No public constructor defined for class $class" ;
+}
+
+
+# Constructor. Here we create a new object that will be linked
+# to a real Java object.
+sub __new {
+	my $class = shift ;
+	my $java_class = shift ;
+	my $pkg = shift ;
+	my $module = shift ;
+	my $objid = shift ;
+	my @args = @_ ;
+
+	my %this = () ;
+	tie %this, 'Inline::Java::private::Object' ;
+	bless (\%this, $class) ;
+
+	my $this = \%this ;
+	$this->{private} = {} ;
+	$this->{private}->{class} = $java_class ;
+	$this->{private}->{pkg} = $pkg ;
+	$this->{private}->{proto} = new Inline::Java::private::Protocol($this->{private}, $module) ;
+	if ($objid <= 0){
+		$this->{private}->{proto}->CreateJavaObject($java_class, @args) ;
+		Inline::Java::debug("Object created in perl script ($class):") ;
+	}
+	else{
+		$this->{private}->{id} = $objid ;
+		Inline::Java::debug("Object created in java ($class):") ;
+	}
+	Inline::Java::debug_obj($this->private()) ;
+
+	return $this ;
+}
+
+
+sub __validate_prototype {
+	return undef ;
+}
+
+
+sub private {
+	my $this = shift ;
+
+	return $this->{private} ;
+}
+
+
+# Here an object in destroyed
+sub DESTROY {
+	my $this = shift ;
+
+	if (! $this->{private}->{deleted}){
+		$this->{private}->{deleted} = 1 ;
+		$this->{private}->{proto}->DeleteJavaObject() ;
+	}
+}
+
+
+sub TIEHASH {
+	my $class = shift ;
+
+	return $class->SUPER::TIEHASH(@_) ;
+}
+
+
+sub STORE {
+	my $this = shift ;
+	my $key = shift ;
+	my $value = shift ;
+
+	if ($key eq "private"){
+		return $this->SUPER::STORE($key, $value) ;
+	}
+
+	my $priv = $this->FETCH("private") ;
+	$priv->{proto}->SetMember($key, $value) ;
+}
+
+
+sub FETCH {
+	my $this = shift ;
+	my $key = shift ;
+
+	if ($key eq "private"){
+		return $this->SUPER::FETCH($key) ;
+	}
+
+	my $priv = $this->FETCH("private") ;
+	return $priv->{proto}->GetMember($key) ;
+}
+
+
+sub FIRSTKEY { 
+	croak "Operation FIRSTKEY not supported on Java object" ;
+}
+
+
+sub NEXTKEY { 
+	croak "Operation NEXTKEY not supported on Java object" ;
+}
+
+
+sub EXISTS { 
+	croak "Operation EXISTS not supported on Java object" ;
+}
+
+
+sub DELETE { 
+	croak "Operation DELETE not supported on Java object" ;
+}
+
+
+sub CLEAR { 
+	croak "Operation CLEAR not supported on Java object" ;
+}
+
+
+# sub AUTOLOAD {
+# 	my $this = shift ;
+# 	my @args = @_ ;
+
+# 	use vars qw($AUTOLOAD) ;
+# 	my $func_name = $AUTOLOAD ;
+# 	# Strip package from $func_name, Java will take of finding the correct
+# 	# method.
+# 	$func_name =~ s/^(.*)::// ;
+
+# 	Inline::Java::debug("$func_name") ;
+
+# 	$this->{private}->{proto}->CallJavaMethod($func_name, @args) ;
+# }
+
+
+
+1 ;
diff --git a/Java/Protocol.pm b/Java/Protocol.pm
new file mode 100644
index 0000000..882453d
--- /dev/null
+++ b/Java/Protocol.pm
@@ -0,0 +1,837 @@
+package Inline::Java::private::Protocol ;
+
+
+use strict ;
+
+
+use Carp ;
+use Data::Dumper ;
+
+
+# This will be set when the code is loaded.
+$Inline::Java::private::Protocol::socket = {} ;
+
+
+sub new {
+	my $class = shift ;
+	my $obj = shift ;
+	my $module = shift ;
+
+	my $this = {} ;
+	$this->{obj_priv} = $obj || {} ;
+	if ($obj){
+		$this->{pkg} = $obj->{pkg} ;
+	}
+	$this->{module} = $module ;
+
+	bless($this, $class) ;
+	return $this ;
+}
+
+
+sub CreateJavaObject {
+	my $this = shift ;
+	my $class = shift ;
+	my @args = @_ ;
+
+	Inline::Java::debug("creating object new $class(" . join(", ", @args) . ")") ; 	
+
+	my $data = join(" ", 
+		"create_object", 
+		$this->ValidateClass($class),
+		$this->ValidateArgs(@args),
+	) ;
+
+	Inline::Java::debug("  packet sent is $data") ;		
+
+	return $this->Send($data, 1) ;
+}
+
+
+sub CallStaticJavaMethod {
+	my $this = shift ;
+	my $class = shift ;
+	my $pkg = shift ;
+	my $method = shift ;
+	my @args = @_ ;
+
+	$this->{pkg} = $pkg ;
+
+	Inline::Java::debug("calling $class.$method(" . join(", ", @args) . ")") ;
+
+	my $data = join(" ", 
+		"call_static_method", 
+		$this->ValidateClass($class),
+		$this->ValidateMethod($method),
+		$this->ValidateArgs(@args),
+	) ;
+
+	Inline::Java::debug("  packet sent is $data") ;		
+
+	return $this->Send($data) ;
+}
+
+
+sub CallJavaMethod {
+	my $this = shift ;
+	my $method = shift ;
+	my @args = @_ ;
+
+	my $id = $this->{obj_priv}->{id} ;
+	my $class = $this->{obj_priv}->{class} ;
+	Inline::Java::debug("calling object($id).$method(" . join(", ", @args) . ")") ;
+
+	my $data = join(" ", 
+		"call_method", 
+		$id,		
+		$this->ValidateClass($class),
+		$this->ValidateMethod($method),
+		$this->ValidateArgs(@args),
+	) ;
+
+	Inline::Java::debug("  packet sent is $data") ;		
+
+	return $this->Send($data) ;
+}
+
+
+sub DeleteJavaObject {
+	my $this = shift ;
+
+	if (defined($this->{obj_priv}->{id})){
+		my $id = $this->{obj_priv}->{id} ;
+		my $class = $this->{obj_priv}->{class} ;
+
+		Inline::Java::debug("deleting object $this $id ($class)") ;
+
+		my $data = join(" ", 
+			"delete_object", 
+			$id,
+		) ;
+
+		Inline::Java::debug("  packet sent is $data") ;		
+
+		$this->Send($data) ;
+	}
+}
+
+
+sub ValidateClass {
+	my $this = shift ;
+	my $class = shift ;
+
+	if ($class !~ /^(\w+)((\.(\w+))+)?/){
+		croak "Invalid Java class name $class" ;
+	}	
+
+	return $class ;
+}
+
+
+sub ValidateMethod {
+	my $this = shift ;
+	my $method = shift ;
+
+	if ($method !~ /^(\w+)$/){
+		croak "Invalid Java method name $method" ;
+	}	
+
+	return $method ;
+}
+
+
+sub ValidateArgs {
+	my $this = shift ;
+	my @args = @_ ;
+
+	my @ret = () ;
+	foreach my $arg (@args){
+		if (! defined($arg)){
+			push @ret, "undef:" ;
+		}
+		elsif (ref($arg)){
+			if (! UNIVERSAL::isa($arg, "Inline::Java::private::Object")){
+				croak "A Java method can only have Java objects or scalars as arguments" ;
+			}
+			my $class = $arg->{private}->{class} ;
+			my $id = $arg->{private}->{id} ;
+			push @ret, "object:$class:$id" ;
+		}
+		else{
+			push @ret, "scalar:" . join(".", unpack("C*", $arg)) ;
+		}
+	}
+
+	return @ret ;
+}
+
+
+sub Send {
+	my $this = shift ;
+	my $data = shift ;
+	my $const = shift ;
+
+	my $sock = $Inline::Java::private::Protocol::socket->{$this->{module}} ;
+	print $sock $data . "\n" or
+		croak "Can't send packet over socket: $!" ;
+
+	my $resp = <$sock> ;
+	Inline::Java::debug("  packet recv is $resp") ;
+
+	if (! $resp){
+		croak "Can't receive packet over socket: $!" ;
+	}
+	elsif ($resp =~ /^error scalar:([\d.]*)$/){
+		croak pack("C*", split(/\./, $1)) ;
+	}
+	elsif ($resp =~ /^ok scalar:([\d.]*)$/){
+		return pack("C*", split(/\./, $1)) ;
+	}
+	elsif ($resp =~ /^ok undef:$/){
+		return undef ;
+	}
+	elsif ($resp =~ /^ok object:(\d+):(.*)$/){
+		# Create the Perl object wrapper and return it.
+		my $id = $1 ;
+		my $class = $2 ;
+		if ($const){
+			$this->{obj_priv}->{class} = $class ;
+			$this->{obj_priv}->{id} = $id ;
+		}
+		else{
+			my $perl_class = $class ;
+			$perl_class =~ s/[.\$]/::/g ;
+			my $pkg = $this->{pkg} ;
+			$perl_class = $pkg . "::" . $perl_class ;
+			Inline::Java::debug($perl_class) ;
+
+			my $obj = undef ;
+			if (defined(${$perl_class . "::" . "EXISTS"})){
+				Inline::Java::debug("  returned class exists!") ;
+				$obj = $perl_class->__new($class, $pkg, $this->{module}, $id) ;
+			}
+			else{
+				Inline::Java::debug("  returned class doesn't exist!") ;
+				$obj = Inline::Java::private::Object->__new($class, $pkg, $this->{module}, $id) ;
+			}
+			return $obj ;
+		}
+	}
+}
+
+
+1 ;
+
+
+
+__DATA__
+
+
+class InlineJavaProtocol {
+	<INLINE_MODFNAME> main ;
+	String cmd ;
+	String response ;
+
+	InlineJavaProtocol(<INLINE_MODFNAME> _m, String _cmd) {
+		main = _m ;
+		cmd = _cmd ;
+	}
+
+
+	void Do() throws InlineJavaException {
+		StringTokenizer st = new StringTokenizer(cmd, " ") ;
+		String c = st.nextToken() ;
+
+		if (c.equals("call_static_method")){
+			CallStaticJavaMethod(st) ;
+		}		
+		if (c.equals("call_method")){
+			CallJavaMethod(st) ;
+		}		
+		else if (c.equals("create_object")){
+			CreateJavaObject(st) ;
+		}
+		else if (c.equals("delete_object")){
+			DeleteJavaObject(st) ;
+		}
+	}
+
+
+	void CallStaticJavaMethod(StringTokenizer st) throws InlineJavaException {
+		String class_name = st.nextToken() ;
+		String method = st.nextToken() ;
+		Class c = ValidateClass(class_name) ;
+		ArrayList f = ValidateMethod(false, c, method, st) ;
+
+		Method m = (Method)f.get(0) ;
+		String name = m.getName() ;
+		Object p[] = (Object [])f.get(1) ;
+		try {
+			Object ret = m.invoke(null, p) ;
+			SetResponse(ret) ;
+		}
+		catch (IllegalAccessException e){
+			throw new InlineJavaException("You are not allowed to invoke static method " + name) ;
+		}
+		catch (IllegalArgumentException e){
+			throw new InlineJavaException("Arguments for static method " + name + " are incompatible:" + e.getMessage()) ;
+		}
+		catch (InvocationTargetException e){
+			Throwable t = e.getTargetException() ;
+			String type = t.getClass().getName() ;
+			String msg = t.getMessage() ;
+			throw new InlineJavaException(
+				"Method " + name + " threw exception " + type + ": " + msg) ;
+		}
+	}
+
+
+	void CallJavaMethod(StringTokenizer st) throws InlineJavaException {
+		int id = Integer.parseInt(st.nextToken()) ;
+		String class_name = st.nextToken() ;
+		String method = st.nextToken() ;
+		Class c = ValidateClass(class_name) ;
+		ArrayList f = ValidateMethod(false, c, method, st) ;
+
+		Method m = (Method)f.get(0) ;
+		String name = m.getName() ;
+		Integer oid = new Integer(id) ;
+		Object o = main.objects.get(oid) ;
+		if (o == null){
+			throw new InlineJavaException("Object " + oid.toString() + " is not in HashMap!") ;
+		}
+		Object p[] = (Object [])f.get(1) ;
+		try {
+			Object ret = m.invoke(o, p) ;
+			SetResponse(ret) ;
+		}
+		catch (IllegalAccessException e){
+			throw new InlineJavaException("You are not allowed to invoke method " + name) ;
+		}
+		catch (IllegalArgumentException e){
+			throw new InlineJavaException("Arguments for static " + name + " are incompatible:" + e.getMessage()) ;
+		}
+		catch (InvocationTargetException e){
+			Throwable t = e.getTargetException() ;
+			String type = t.getClass().getName() ;
+			String msg = t.getMessage() ;
+			throw new InlineJavaException(
+				"Method " + name + " threw exception " + type + ": " + msg) ;
+		}
+	}
+
+
+	void CreateJavaObject(StringTokenizer st) throws InlineJavaException {
+		String class_name = st.nextToken() ;
+		Class c = ValidateClass(class_name) ;
+
+		ArrayList f = ValidateMethod(true, c, class_name, st) ;
+
+		Constructor con = (Constructor)f.get(0) ;
+		String name = class_name ;
+		Object p[] = (Object [])f.get(1) ;
+
+		Object o = CreateObject(c, p) ;
+		SetResponse(o) ;
+	}
+
+
+	void DeleteJavaObject(StringTokenizer st) throws InlineJavaException {
+		int id = Integer.parseInt(st.nextToken()) ;
+
+		Integer oid = new Integer(id) ;
+		Object o = main.objects.remove(oid) ;
+
+		SetResponse(null) ;
+	}
+
+	
+	Object CreateObject(Class p, Object args[]) throws InlineJavaException {
+		Class clist[] = new Class [args.length] ;
+		for (int i = 0 ; i < args.length ; i++){
+			clist[i] = args[i].getClass() ;
+		}
+
+		p = FindWrapper(p) ;
+
+		String name = p.getName() ;
+		Object ret = null ;
+		try {
+			Constructor con = (Constructor)p.getConstructor(clist) ;
+			ret = con.newInstance(args) ;
+		}
+		catch (NoSuchMethodException e){
+			throw new InlineJavaException("Constructor for class " + name + " with specified signature not found") ;
+		}
+		catch (InstantiationException e){
+			throw new InlineJavaException("You are not allowed to instantiate object of class " + name) ;
+		}
+		catch (IllegalAccessException e){
+			throw new InlineJavaException("You are not allowed to instantiate object of class " + name + " using the specified constructor") ;
+		}
+		catch (IllegalArgumentException e){
+			throw new InlineJavaException("Arguments to constructor are incompatible for class " + name) ;
+		}
+		catch (InvocationTargetException e){
+			Throwable t = e.getTargetException() ;
+			String type = t.getClass().getName() ;
+			String msg = t.getMessage() ;
+			throw new InlineJavaException(
+				"Constructor for class " + name + " threw exception " + type + ": " + msg) ;
+		}
+
+		return ret ;
+	}
+
+
+	Class ValidateClass(String name) throws InlineJavaException {
+		try {
+			Class c = Class.forName(name) ;
+			return c ;
+		}
+		catch (ClassNotFoundException e){
+			throw new InlineJavaException("Class " + name + " not found") ;
+		}
+	}
+
+
+	ArrayList ValidateMethod(boolean constructor, Class c, String name, StringTokenizer st) throws InlineJavaException {
+		Member ma[] = (constructor ? (Member [])c.getConstructors() : (Member [])c.getMethods()) ;
+		ArrayList ret = new ArrayList(ma.length) ;
+
+		// Extract the arguments
+		ArrayList args = new ArrayList() ;
+		while (st.hasMoreTokens()){
+			args.add(args.size(), st.nextToken()) ;
+		}
+
+		ArrayList ml = new ArrayList(ma.length) ;
+		for (int i = 0 ; i < ma.length ; i++){
+			Member m = ma[i] ;
+			if (m.getName().equals(name)){
+				main.debug("found a " + name + (constructor ? " constructor" : " method")) ;
+
+				Class params[] = null ;
+				if (constructor){
+					params = ((Constructor)m).getParameterTypes() ;
+				}
+				else{
+					params = ((Method)m).getParameterTypes() ;
+				}
+			 	if (params.length == args.size()){
+					// We have the same number of arguments
+					ml.add(ml.size(), m) ;
+					main.debug("  has the correct number of params (" +  String.valueOf(args.size()) + ") and signature is " + CreateSignature(params)) ;
+				}
+			}
+		}
+
+		// Now we got a list of matching methods. 
+		// We have to figure out which one we will call.
+		if (ml.size() == 0){
+			throw new InlineJavaException(
+				(constructor ? "Constructor " : "Method ") + 
+				name + " with " + String.valueOf(args.size()) + " parameters not found in class " + c.getName()) ;
+		}
+		else if (ml.size() == 1){
+			// Now we need to force the arguments received to match
+			// the methods signature.
+			Member m = (Member)ml.get(0) ;
+			Class params[] = null ;
+			if (constructor){
+				params = ((Constructor)m).getParameterTypes() ;
+			}
+			else{
+				params = ((Method)m).getParameterTypes() ;
+			}
+			ret.add(0, m) ;
+			ret.add(1, CastArguments(params, args)) ;
+		}
+		else{
+			throw new InlineJavaException("Don't know which signature of " + name + " to call") ;
+		}
+
+		return ret ;
+	}
+
+
+	Object [] CastArguments (Class [] params, ArrayList args) throws InlineJavaException {
+		Object ret[] = new Object [params.length] ;
+	
+		for (int i = 0 ; i < params.length ; i++){	
+			// Here the args are all strings or objects (or undef)
+			// we need to match them to the prototype.
+			Class p = params[i] ;
+			main.debug("    arg " + String.valueOf(i) + " of signature is " + p.getName()) ;
+
+			ArrayList tokens = new ArrayList() ;
+			StringTokenizer st = new StringTokenizer((String)args.get(i), ":") ;
+			for (int j = 0 ; st.hasMoreTokens() ; j++){
+				tokens.add(j, st.nextToken()) ;
+			}
+			if (tokens.size() == 1){
+				tokens.add(1, "") ;
+			}
+			String type = (String)tokens.get(0) ;
+			
+			// We need to separate the primitive types from the 
+			// reference types.
+			boolean num = ClassIsNumeric(p) ;
+			if ((num)||(ClassIsString(p))){
+				String text = "string" ;
+				if (num){
+					text = "number" ;
+				}
+				if (type.equals("undef")){
+					main.debug("  args is undef -> forcing to " + text + " 0") ;
+					ret[i] = CreateObject(p, new Object [] {"0"}) ;
+					main.debug("    result is " + ret[i].toString()) ;
+				}
+				else if (type.equals("scalar")){
+					String arg = pack((String)tokens.get(1)) ;
+					main.debug("  args is scalar -> forcing to " + text) ;
+					try	{							
+						ret[i] = CreateObject(p, new Object [] {arg}) ;
+						main.debug("    result is " + ret[i].toString()) ;
+					}
+					catch (NumberFormatException e){
+						throw new InlineJavaCastException("Can't convert " + arg + " to some primitive " + text) ;
+					}
+				}
+				else{
+					throw new InlineJavaCastException("Can't convert reference to primitive " + text) ;
+				}
+			}
+			else if ((p == java.lang.Boolean.class)||(p == boolean.class)){
+				main.debug("  class java.lang.Boolean is primitive bool") ;
+				if (type.equals("undef")){
+					main.debug("  args is undef -> forcing to bool false") ;
+					ret[i] = new Boolean("false") ;
+					main.debug("    result is " + ret[i].toString()) ;
+				}
+				else if (type.equals("scalar")){
+					String arg = pack(((String)tokens.get(1)).toLowerCase()) ;
+					main.debug("  args is scalar -> forcing to bool") ;
+					if ((arg.equals(""))||(arg.equals("0"))||(arg.equals("false"))){
+						arg = "false" ;
+					}
+					else{
+						arg = "true" ;
+					}
+					ret[i] = new Boolean(arg) ;
+					main.debug("    result is " + ret[i].toString()) ;
+				}
+				else{
+					throw new InlineJavaCastException("Can't convert reference to primitive bool") ;
+				}
+			}
+			else if ((p == java.lang.Character.class)||(p == char.class)){
+				main.debug("  class java.lang.Character is primitive char") ;
+				if (type.equals("undef")){
+					main.debug("  args is undef -> forcing to char '\0'") ;
+					ret[i] = new Character('\0') ;
+					main.debug("    result is " + ret[i].toString()) ;
+				}
+				else if (type.equals("scalar")){
+					String arg = pack((String)tokens.get(1)) ;
+					main.debug("  args is scalar -> forcing to char") ;
+					char c = '\0' ;
+					if (arg.length() == 1){
+						c = arg.toCharArray()[0] ;
+					}
+					else if (arg.length() > 1){
+						throw new InlineJavaCastException("Can't convert " + arg + " to primitive char") ;
+					}
+					ret[i] = new Character(c) ;
+					main.debug("    result is " + ret[i].toString()) ;
+				}
+				else{
+					throw new InlineJavaCastException("Can't convert reference to primitive char") ;
+				}
+			}
+			else {
+				main.debug("  class " + p.getName() + " is reference") ;
+				// We know that what we expect here is a real object
+				if (type.equals("undef")){
+					main.debug("  args is undef -> forcing to null") ;
+					ret[i] = null ;
+				}
+				else if (type.equals("scalar")){
+					if (p == java.lang.Object.class){
+						String arg = pack((String)tokens.get(1)) ;
+						ret[i] = arg ;
+					}
+					else{
+						throw new InlineJavaCastException("Can't convert primitive to reference") ;
+					}
+				}
+				else{
+					// We need an object and we got an object...
+					main.debug("  class " + p.getName() + " is reference") ;
+
+					String class_name = (String)tokens.get(1) ;
+					String objid = (String)tokens.get(2) ;
+
+					Class c = ValidateClass(class_name) ;
+					// We need to check if c extends p
+					Class parent = c ;
+					boolean got_it = false ;
+					while (parent != null){
+						main.debug("    parent is " + parent.getName()) ;
+						if (parent == p){
+							got_it = true ;
+							break ;
+						}
+						parent = parent.getSuperclass() ;
+					}
+
+					if (got_it){
+						main.debug("    " + c.getName() + " is a kind of " + p.getName()) ;
+						// get the object from the hash table
+						Integer oid = new Integer(objid) ;
+						Object o = main.objects.get(oid) ;
+						if (o == null){
+							throw new InlineJavaException("Object " + oid.toString() + " is not in HashMap!") ;
+						}
+						ret[i] = o ;
+					}
+					else{
+						throw new InlineJavaCastException("Can't cast a " + c.getName() + " to a " + p.getName()) ;
+					}
+				}
+			}			
+		}
+
+		return ret ;
+	}
+
+
+	String CreateSignature (Class param[]){
+		StringBuffer ret = new StringBuffer() ;
+		for (int i = 0 ; i < param.length ; i++){
+			if (i > 0){
+				ret.append(", ") ;
+			}
+			ret.append(param[i].getName()) ;
+		}
+
+		return "(" + ret.toString() + ")" ;
+	}
+
+
+	Class FindWrapper (Class p){
+		Class [] list = {
+			byte.class,
+			short.class,
+			int.class,
+			long.class,
+			float.class,
+			double.class,
+			boolean.class,
+			char.class,
+			void.class,
+		} ;
+		Class [] listw = {
+			java.lang.Byte.class,
+			java.lang.Short.class,
+			java.lang.Integer.class,
+			java.lang.Long.class,
+			java.lang.Float.class,
+			java.lang.Double.class,
+			java.lang.Boolean.class,
+			java.lang.Character.class,
+			java.lang.Void.class,
+		} ;
+
+		for (int i = 0 ; i < list.length ; i++){
+			if (p == list[i]){
+				return listw[i] ;
+			}
+		}
+
+		return p ;
+	}
+
+
+	boolean ClassIsPrimitive (Class p){
+		String name = p.getName() ;
+
+		if ((ClassIsNumeric(p))||(ClassIsString(p))){
+			return true ;
+		}
+
+		Class [] list = {
+			java.lang.Boolean.class,
+			java.lang.Character.class,
+			java.lang.Void.class,
+			boolean.class,
+			char.class,
+			void.class,
+		} ;
+
+		for (int i = 0 ; i < list.length ; i++){
+			main.debug("  comparing " + name + " with " + list[i].getName()) ;
+			if (p == list[i]){
+				main.debug("  class " + name + " is primitive") ;
+				return true ;
+			}
+		}
+
+		main.debug("  class " + name + " is reference") ;
+		return false ;
+	}
+
+
+	boolean ClassIsNumeric (Class p){
+		String name = p.getName() ;
+
+		Class [] list = {
+			java.lang.Byte.class,
+			java.lang.Short.class,
+			java.lang.Integer.class,
+			java.lang.Long.class,
+			java.lang.Float.class,
+			java.lang.Double.class,
+			byte.class,
+			short.class,
+			int.class,
+			long.class,
+			float.class,
+			double.class,
+		} ;
+
+		for (int i = 0 ; i < list.length ; i++){
+			main.debug("  comparing " + name + " with " + list[i].getName()) ;
+			if (p == list[i]){
+				main.debug("  class " + name + " is primitive numeric") ;
+				return true ;
+			}
+		}
+
+		return false ;
+	}
+
+
+	boolean ClassIsString (Class p){
+		String name = p.getName() ;
+
+		Class [] list = {
+			java.lang.String.class,
+			java.lang.StringBuffer.class,
+		} ;
+
+		for (int i = 0 ; i < list.length ; i++){
+			main.debug("  comparing " + name + " with " + list[i].getName()) ;
+			if (p == list[i]){
+				main.debug("  class " + name + " is primitive string") ;
+				return true ;
+			}
+		}
+
+		return false ;
+	}
+
+	
+	boolean ClassIsReference (Class p){
+		String name = p.getName() ;
+
+		if (ClassIsPrimitive(p)){
+			return false ;
+		}
+
+		main.debug("  class " + name + " is reference") ;
+
+		return true ;
+	}
+
+
+	void SetResponse (Object o){
+		if (o == null){
+			response = "ok undef:" ;
+		}
+		// Split between Numeric, String, Boolean and Character and Void
+		else if (ClassIsPrimitive(o.getClass())){
+			response = "ok scalar:" + unpack(o.toString()) ;
+		}
+		else {
+			// Here we need to register the object in order to send
+			// it back to the Perl script.
+			main.objects.put(new Integer(main.objid), o) ;
+			response = "ok object:" + String.valueOf(main.objid) +
+				":" + o.getClass().getName() ;
+			main.objid++ ;
+		}
+	}
+
+
+	public String pack(String s){
+		StringTokenizer st = new StringTokenizer(s, ".") ;
+		StringBuffer sb = new StringBuffer() ;
+		while (st.hasMoreTokens()){
+			String ss = st.nextToken() ; 
+			byte b[] = {(byte)Integer.parseInt(ss)} ;
+			sb.append(new String(b)) ;
+		}
+	
+		return sb.toString() ;
+	}
+
+
+	public String unpack(String s){
+		byte b[] = s.getBytes() ;
+		StringBuffer sb = new StringBuffer() ;
+		for (int i = 0 ; i < b.length ; i++){
+			if (i > 0){
+				sb.append(".") ;
+			}
+			sb.append(String.valueOf(b[i])) ;
+		}
+
+		return sb.toString() ;
+	}
+
+
+	public void test(String argv[]){
+		Class list[] = {
+			java.lang.Exception.class,
+//			java.lang.Byte.class,
+//			java.lang.Short.class,
+//			java.lang.Integer.class,
+//			java.lang.Long.class,
+//			java.lang.Float.class,
+//			java.lang.Double.class,
+//			java.lang.String.class,
+//			java.lang.StringBuffer.class,
+//			java.lang.Boolean.class,
+//			java.lang.Character.class,
+		} ;
+
+		ArrayList args[] = new ArrayList [1] ;
+		for (int j = 0 ; j < 1 ; j++){
+			args[j] = new ArrayList(1) ;
+		}
+		args[0].add(0, "object:666:java.lang.Exception") ;
+//		args[0].add(0, "undef:") ;
+//		args[1].add(0, "scalar:66") ;
+//		args[2].add(0, "scalar:666") ;
+//		args[3].add(0, "scalar:a") ;
+//		args[4].add(0, "scalar:AB") ;
+//		args[5].add(0, "scalar:1") ;
+//		args[6].add(0, "scalar:") ;
+
+		for (int j = 0 ; j < args.length ; j++){
+			for (int i = 0; i < list.length ; i++){
+				Class proto[] = new Class[1] ;
+				proto[0] = list[i] ;
+				try	{
+					CastArguments(proto, args[j]) ;
+				}
+				catch (InlineJavaException e){
+					main.debug("InlineJavaException caught: " + e.getMessage()) ;
+				}			
+			}
+			main.debug("") ;
+		}
+	}
+}
+

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-perl/packages/libinline-java-perl.git



More information about the Pkg-perl-cvs-commits mailing list