[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