Inline-Java-0.67/0000755000175000017500000000000014202042236013464 5ustar osboxesosboxesInline-Java-0.67/META.json0000644000175000017500000000254114202042236015107 0ustar osboxesosboxes{ "abstract" : "Write Perl classes in Java.", "author" : [ "Patrick LeBoutillier " ], "dynamic_config" : 1, "generated_by" : "ExtUtils::MakeMaker version 7.44, CPAN::Meta::Converter version 2.150010", "license" : [ "artistic_2" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Inline-Java", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "7.30" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "7.30", "File::Which" : "0" } }, "develop" : { "requires" : { "Test::CheckManifest" : "0.9" } }, "runtime" : { "requires" : { "Inline" : "0.68", "MIME::Base64" : "0", "Test" : "1.13", "perl" : "5.008" } } }, "release_status" : "stable", "resources" : { "repository" : { "type" : "git", "url" : "https://github.com/ingydotnet/Inline-Java", "web" : "https://github.com/ingydotnet/Inline-Java" } }, "version" : "0.67", "x_serialization_backend" : "JSON::PP version 4.04" } Inline-Java-0.67/t/0000755000175000017500000000000014202042236013727 5ustar osboxesosboxesInline-Java-0.67/t/no_const.class0000644000175000017500000000034714202030173016601 0ustar osboxesosboxes-  iI()VCodeLineNumberTable SourceFile no_const.java   t/no_constjava/lang/Object! * **    Inline-Java-0.67/t/07_polymorph.t0000644000175000017500000000503114202030173016447 0ustar osboxesosboxesuse strict; use warnings; use Test::More tests => 24; use Inline( Java => 'DATA', STUDY => ['java.util.HashMap', 'java.lang.String'], AUTOSTUDY => 1, ) ; use Inline::Java qw(cast coerce) ; my $t = new types7() ; { my $t1 = new t17() ; is($t->func(5), "int") ; is($t->func(coerce("char", 5)), "char") ; is($t->func(55), "int") ; is($t->func("str"), "string") ; is($t->func(coerce("java.lang.StringBuffer", "str")), "stringbuffer") ; is($t->f($t->{hm}), "hashmap") ; is($t->f(cast("java.lang.Object", $t->{hm})), "object") ; is($t->f(["a", "b", "c"]), "string[]") ; is($t->f(["12.34", "45.67"]), "double[]") ; is($t->f(coerce("java.lang.Object", ['a'], "[Ljava.lang.String;")), "object") ; eval {$t->func($t1)} ; like($@, qr/Can't find any signature/) ; eval {$t->func(cast("int", $t1))} ; like($@, qr/Can't cast (.*) to a int/) ; my $t2 = new t27() ; is($t2->f($t2), "t1") ; is($t1->f($t2), "t1") ; is($t2->f($t1), "t2") ; is($t2->f(cast("t17", $t2)), "t2") ; is($t2->f($t1), "t2") ; # Here we should always get the more specific stuff is($t2->{i}, 7) ; is($t2->{j}, 3.1416) ; # So this should fail eval {$t2->{j} = "string"} ; like($@, qr/Can't convert/) ; # Interfaces my $al = $t1->get_al() ; is($t1->count($al), 0) ; my $hm = new java::util::HashMap() ; $hm->put('key', 'value') ; my $a = $hm->entrySet()->toArray() ; foreach my $e (@{$a}){ is(cast('java.util.Map$Entry', $e)->getKey(), 'key') ; } my $str = new java::lang::String('test') ; is($str, 'test') ; } is($t->__get_private()->{proto}->ObjectCount(), 1) ; __END__ __Java__ import java.util.* ; class t17 { public int i = 5 ; public String j = "toto" ; public t17(){ } public String f(t27 o){ return "t1" ; } public void n(){ } public ArrayList get_al(){ return new ArrayList() ; } public int count(Collection c){ return c.size() ; } } class t27 extends t17 { public int i = 7 ; public double j = 3.1416 ; public t27(){ } public String f(t17 o){ return "t2" ; } public void n(){ } } class types7 { public HashMap hm = new HashMap() ; public types7(){ } public String func(String o){ return "string" ; } public String func(StringBuffer o){ return "stringbuffer" ; } public String func(int o){ return "int" ; } public String func(char o){ return "char" ; } public String f(HashMap o){ return "hashmap" ; } public String f(Object o){ return "object" ; } public String f(String o[]){ return "string[]" ; } public String f(double o[]){ return "double[]" ; } } Inline-Java-0.67/t/types.java0000644000175000017500000000036214202030173015734 0ustar osboxesosboxespackage t ; import java.util.* ; public class types { public types(){ } public String func(){ return "study" ; } public HashMap hm(){ HashMap hm = new HashMap<>() ; hm.put("key", "value") ; return hm ; } } Inline-Java-0.67/t/12_2_perl_objects.t0000755000175000017500000000643514202030173017322 0ustar osboxesosboxesuse strict ; use Test ; use Inline ( Java => 'DATA', ) ; use Inline::Java qw(caught) ; use Data::Dumper ; BEGIN { my $cnt = 21 ; plan(tests => $cnt) ; } my $t = new t16() ; { eval { my $o = new O::b::j(name => 'toto') ; $t->set($o) ; ok($t->get(), $o) ; ok($t->get()->{name}, 'toto') ; check_count(1) ; # po ok($t->round_trip($o), $o) ; check_count(2) ; # po + 1 leaked object ok($t->method_call($o, 'get', ['name']), 'toto') ; check_count(2) ; # po + 1 leaked object ok($t->add_eval(5, 6), 11) ; check_count(2) ; # po + 1 leaked object eval {$t->method_call($o, 'bad', ['bad'])} ; ok($@, qr/Can't locate object method "bad" via package "O::b::j"/) ; check_count(3) ; # po + $o + 1 leaked object eval {$t->round_trip({})} ; ok($@, qr/^Can't convert (.*?) to object org.perl.inline.java.InlineJavaPerlObject/) ; eval {$t->error()} ; ok($@, qr/alone/) ; check_count(3) ; # po + 2 leaked objects $t->dispose($o) ; check_count(2) ; # 2 leaked objects my $jo = $t->create("O::b::j", ['name', 'titi']) ; ok($jo->get("name"), 'titi') ; $t->have_fun() ; ok($jo->get('shirt'), qr/lousy t-shirt/) ; check_count(3) ; # po + 2 leaked objects $t->dispose(undef) ; check_count(2) ; # 2 leaked objects } ; if ($@){ if (caught("java.lang.Throwable")){ $@->printStackTrace() ; die("Caught Java Exception") ; } else{ die $@ ; } } } ok($t->__get_private()->{proto}->ObjectCount(), 1) ; check_count(2) ; # 2 leaked objects sub check_count { ok($_[0], Inline::Java::Callback::ObjectCount()) ; } sub debug_objects { map {print "$_\n"} %{Inline::Java::Callback::__GetObjects()} ; } package O::b::j ; sub new { my $class = shift ; return bless({@_}, $class) ; } sub get { my $this = shift ; my $attr = shift ; return $this->{$attr} ; } sub set { my $this = shift ; my $attr = shift ; my $val = shift ; $this->{$attr} = $val ; } package main ; __END__ __Java__ import org.perl.inline.java.* ; class t16 { InlineJavaPerlObject po = null ; public t16(){ } public void set(InlineJavaPerlObject o){ po = o ; } public InlineJavaPerlObject get(){ return po ; } public int add_eval(int a, int b) throws InlineJavaException, InlineJavaPerlException { Integer i = (Integer)po.eval(a + " + " + b, Integer.class) ; return i.intValue() ; } public String method_call(InlineJavaPerlObject o, String name, Object args[]) throws InlineJavaException, InlineJavaPerlException { String s = (String)o.InvokeMethod(name, args) ; o.Dispose() ; return s ; } public void error() throws InlineJavaException, InlineJavaPerlException { po.eval("die 'alone'") ; } public InlineJavaPerlObject round_trip(InlineJavaPerlObject o) throws InlineJavaException, InlineJavaPerlException { return o ; } public void dispose(InlineJavaPerlObject o) throws InlineJavaException, InlineJavaPerlException { if (o != null){ o.Dispose() ; } if (po != null){ po.Dispose() ; } } public InlineJavaPerlObject create(String pkg, Object args[]) throws InlineJavaException, InlineJavaPerlException { po = new InlineJavaPerlObject(pkg, args) ; return po ; } public void have_fun() throws InlineJavaException, InlineJavaPerlException { po.InvokeMethod("set", new Object [] {"shirt", "I've been to Java and all I got was this lousy t-shirt!"}) ; } } Inline-Java-0.67/t/no_const.java0000644000175000017500000000007514202030173016413 0ustar osboxesosboxespackage t ; public class no_const { public int i = 5 ; } Inline-Java-0.67/t/13_handles.t0000755000175000017500000000401714202030173016037 0ustar osboxesosboxesuse strict ; use Test ; use Inline( Java => 'DATA', ) ; use Inline::Java qw(caught) ; BEGIN { # Leave previous server enough time to die... sleep(1) ; plan(tests => 12) ; } my $t = new t13() ; { my $f = File::Spec->catfile("t", "t13.txt") ; my $o = t13->getWriter($f) ; my $h = new Inline::Java::Handle($o) ; for (my $i = 1 ; $i <= 10 ; $i++){ print $h "$i\n" ; } close($h) ; ok(1) ; $o = t13->getReader($f) ; $h = new Inline::Java::Handle($o) ; for (my $i = 1 ; $i <= 10 ; $i++){ my $l = <$h> ; ok($l, $i) ; } ok(! defined(<$h>)) ; } # It seems that filehandle destruction leaks on certain version # of Perl. We will change this test to a warning. if ($t->__get_private()->{proto}->ObjectCount() != 1){ warn "\nWARNING: Your Perl version ($]) seems to leak tied filehandles. Using\n" . "Inline::Java::Handle objects will result in memory leaks both in Perl\n" . "and in Java\n" ; } __END__ __Java__ import java.io.* ; class t13 { public t13(){ } public static Reader getReader(String file) throws FileNotFoundException { return new FileReader(file) ; } public static Reader getBufferedReader(String file) throws FileNotFoundException { return new BufferedReader(new FileReader(file)) ; } public static InputStream getInputStream(String file) throws FileNotFoundException { return new FileInputStream(file) ; } public static InputStream getBufferedInputStream(String file) throws FileNotFoundException { return new BufferedInputStream(new FileInputStream(file)) ; } public static Writer getWriter(String file) throws IOException { return new FileWriter(file) ; } public static Writer getBufferedWriter(String file) throws IOException { return new BufferedWriter(new FileWriter(file)) ; } public static OutputStream getOutputStream(String file) throws FileNotFoundException { return new FileOutputStream(file) ; } public static OutputStream getBufferedOutputStream(String file) throws FileNotFoundException { return new BufferedOutputStream(new FileOutputStream(file)) ; } } Inline-Java-0.67/t/t16subclass.java0000644000175000017500000000057714202030173016752 0ustar osboxesosboxesclass Lower { int a; public Lower(int p) { a= p; } public String outPrintValues() { return ("a = "+ this.a); } } public class t16subclass extends Lower { private int b; public t16subclass(int p, int q) { super(p); this.b = q; } public int getHigherValues() { return this.b; } public String printValues() { return "a = "+ this.a + "\nb = " + b; } } Inline-Java-0.67/t/03_objects.t0000644000175000017500000000463514202030173016054 0ustar osboxesosboxesuse strict ; use Test ; use Inline( Java => 'DATA', ) ; BEGIN { plan(tests => 16) ; } # Create some objects my $t = new types3() ; { my $obj1 = new obj13() ; eval {my $obj2 = new obj23()} ; ok($@, qr/No public constructor/) ; my $obj11 = new obj113() ; ok($t->_obj1(undef), undef) ; ok($t->_obj1($obj1)->get_data(), "obj1") ; ok($t->_obj11($obj11)->get_data(), "obj11") ; ok($t->_obj1($obj11)->get_data(), "obj11") ; eval {$t->_int($obj1)} ; ok($@, qr/Can't convert (.*) to primitive int/) ; eval {$t->_obj11($obj1)} ; ok($@, qr/is not a kind of/) ; # Inner class my $in = new obj13::inner_obj13($obj1) ; ok($in->{data}, "inner") ; # Receive an unbound object and send it back my $unb = $t->get_unbound() ; ok($t->send_unbound($unb), "al_elem") ; # Unexisting method eval {$t->toto()} ; ok($@, qr/No public method/) ; # Method on unbound object eval {$unb->toto()} ; ok($@, qr/Can't call method/) ; # Incompatible prototype, 1 signature eval {$t->_obj1(5)} ; ok($@, qr/Can't convert/) ; # Incompatible prototype, >1 signature eval {$t->__obj1(5)} ; ok($@, qr/Can't find any signature/) ; # Return a scalar hidden in an object. ok($t->_olong(), 12345) ; # Pass a non-Java object, a hash ref. my $d = {} ; eval {$t->_Object($d)} ; ok($@, qr/Can't convert/) ; } ok($t->__get_private()->{proto}->ObjectCount(), 1) ; __END__ __Java__ import java.util.* ; class obj13 { String data = "obj1" ; public obj13() { } public String get_data(){ return data ; } public class inner_obj13 { public String data = "inner" ; public inner_obj13(){ } } } class obj113 extends obj13 { String data = "obj11" ; public obj113() { } public String get_data(){ return data ; } } class obj23 { String data = "obj2" ; obj23() { } public String get_data(){ return data ; } } class types3 { public types3(){ } public int _int(int i){ return i + 1 ; } public Object _Object(Object o){ return o ; } public obj13 _obj1(obj13 o){ return o ; } public obj13 __obj1(obj13 o, int i){ return o ; } public obj13 __obj1(obj13 o){ return o ; } public obj113 _obj11(obj113 o){ return o ; } public ArrayList get_unbound(){ ArrayList al = new ArrayList<>() ; al.add(0, "al_elem") ; return al ; } public String send_unbound(ArrayList al){ return (String)al.get(0) ; } public Object _olong(){ return Long.valueOf("12345") ; } } Inline-Java-0.67/t/t13.txt0000644000175000017500000000002514202042230015066 0ustar osboxesosboxes1 2 3 4 5 6 7 8 9 10 Inline-Java-0.67/t/14_encoding.t0000755000175000017500000000174714202030173016217 0ustar osboxesosboxesuse strict ; use Test ; use Inline ( Java => 'DATA' ) ; BEGIN { plan(tests => 9) ; } my $t = new t14() ; { ok($t->_String("A"), "A") ; ok($t->_String("\x{41}"), "A") ; ok($t->_String("A"), "\x{41}") ; # This is E9 (233), which is e acute. Although the byte # E9 is invalid in UTF-8, the character 233 is valid and # all should work out. ok($t->_String("\x{E9}"), "\x{E9}") ; my $a = $t->toCharArray("\x{E9}") ; ok(ord($a->[0]) == 233) ; # Send a unicode escape sequence. ok($t->_String("\x{263A}"), "\x{263A}") ; # Generate some binary data my $bin = '' ; for (my $i = 0; $i < 256 ; $i++) { my $c = chr($i) ; $bin .= $c ; } ok($t->_String($bin), $bin) ; # Mix it up ok($t->_String("$bin\x{E9}\x{263A}"), "$bin\x{E9}\x{263A}") ; } ok($t->__get_private()->{proto}->ObjectCount(), 1) ; __END__ __Java__ class t14 { public t14(){ } public String _String(String s){ return s ; } public char [] toCharArray(String s){ return s.toCharArray() ; } } Inline-Java-0.67/t/t16subclass.jar0000644000175000017500000000246114202030173016577 0ustar osboxesosboxesPKKL META-INF/PKPKKLMETA-INF/MANIFEST.MFMLK-. K-*ϳR03r.JM,IMuR33Q/JLIUp/*/J,PK9hBAPKKL Lower.class}PJP=7m6kkVIZtBA(*7ͥĤ䡿-(~8E9sqfΝwQC j*Rfb+h(Xg` ۮ2NOܳCk23M2/ } ܉DP[mv/Ay?vL*Ad{q<64,@ceEc DIS&Ұ2C=/AȐc2k1֑r6ShqU:6#?JΣ@XȠX"S0).@i4E"3^;ސ"]L ϐ&P&> RPKUPPKKLt16subclass.class}QJ@=ilk֥jV- ljj$&%M|P?Jr3.'`UCJ@C!i!1+sQsDZ .Ű 31DwL"zV:g:M8o qÒLKxfJE!C횶RV]k!_p|Ruƥ;uY!]C i|ߴ•ˋE eT4"-Q^G^8t_wKz`Pv[M5}à= $9_aiPpt,Oʅg(|b*"B'9bs.(GOPK8D)ݦ]xE袇p6Eb]ij/B}k4ٗ?t`f~iePK뢌+PKKL META-INF/PKKL9hBA=META-INF/MANIFEST.MFPKKLUP Lower.classPKKL뢌+Jt16subclass.classPK&Inline-Java-0.67/t/02_primitives.t0000644000175000017500000001261014202030173016605 0ustar osboxesosboxesuse strict ; use Test ; use Inline ( Java => 'DATA' ) ; BEGIN { plan(tests => 102) ; } my $t = new types2() ; { my $max = undef ; my $min = undef ; $max = 127 ; $min = -128 ; ok($t->_byte(undef) == 1) ; ok($t->_byte(0) == 1) ; ok($t->_byte($max - 1) == $max) ; ok($t->_byte("$min") == $min + 1) ; eval {$t->_byte($max + 1)} ; ok($@, qr/out of range/) ; eval {$t->_byte($min - 1)} ; ok($@, qr/out of range/) ; ok($t->_Byte(undef) == 0) ; ok($t->_Byte(0) == 0) ; ok($t->_Byte($max) == $max) ; ok($t->_Byte("$min") == $min) ; eval {$t->_Byte($max + 1)} ; ok($@, qr/out of range/) ; eval {$t->_Byte($min - 1)} ; ok($@, qr/out of range/) ; $max = 32767 ; $min = -32768 ; ok($t->_short(undef) == 1) ; ok($t->_short(0) == 1) ; ok($t->_short($max - 1) == $max) ; ok($t->_short("$min") == $min + 1) ; eval {$t->_short($max + 1)} ; ok($@, qr/out of range/) ; eval {$t->_short($min - 1)} ; ok($@, qr/out of range/) ; ok($t->_Short(undef) == 0) ; ok($t->_Short(0) == 0) ; ok($t->_Short($max) == $max) ; ok($t->_Short("$min") == $min) ; eval {$t->_Short($max + 1)} ; ok($@, qr/out of range/) ; eval {$t->_Short($min - 1)} ; ok($@, qr/out of range/) ; $max = 2147483647 ; $min = -2147483648 ; ok($t->_int(undef) == 1) ; ok($t->_int(0) == 1) ; ok($t->_int($max - 1) == $max) ; ok($t->_int("$min") == $min + 1) ; eval {$t->_int($max + 1)} ; ok($@, qr/out of range/) ; eval {$t->_int($min - 1)} ; ok($@, qr/out of range/) ; ok($t->_Integer(undef) == 0) ; ok($t->_Integer(0) == 0) ; ok($t->_Integer($max) == $max) ; ok($t->_Integer("$min") == $min) ; eval {$t->_Integer($max + 1)} ; ok($@, qr/out of range/) ; eval {$t->_Integer($min - 1)} ; ok($@, qr/out of range/) ; $max = 3.4028235e38 ; $min = -3.4028235e38 ; ok($t->_float(undef) == 1) ; ok($t->_float(0) == 1) ; ok($t->_float($max / 2)) ; ok($t->_float($min / 2)) ; ok($t->_float($max - 1)) ; ok($t->_float("$min")) ; eval {$t->_float($max + $max)} ; ok($@, qr/out of range/) ; eval {$t->_float($min + $min)} ; ok($@, qr/out of range/) ; ok($t->_Float(undef) == 0) ; ok($t->_Float(0) == 0) ; ok($t->_Float($max / 2)) ; ok($t->_Float($min / 2)) ; # Equality tests for such large floating point number are not always reliable ok($t->_Float($max)) ; ok($t->_Float("$min")) ; eval {$t->_Float($max + $max)} ; ok($@, qr/out of range/) ; eval {$t->_Float($min + $min)} ; ok($@, qr/out of range/) ; # # Boundary testing for long, double are not predictable enough # to be reliable. # my $val = 123456 ; ok($t->_long(undef) == 1) ; ok($t->_long(0) == 1) ; ok($t->_long($val - 1) == $val) ; ok($t->_long("-$val") == -$val + 1) ; ok($t->_Long(undef) == 0) ; ok($t->_Long(0) == 0) ; ok($t->_Long($val) == $val) ; ok($t->_Long("-$val") == -$val) ; $val = 123456.789 ; ok($t->_double(undef) == 1) ; ok($t->_double(0) == 1) ; ok($t->_double($val - 1) == $val) ; ok($t->_double("-$val") == -$val + 1) ; ok($t->_Double(undef) == 0) ; ok($t->_Double(0) == 0) ; ok($t->_Double($val) == $val) ; ok($t->_Double("-$val") == -$val) ; # Number is forced to Double ok($t->_Number(undef) == 0) ; ok($t->_Number(0) == 0) ; ok($t->_Number($val) == $val) ; ok($t->_Number("-$val") == -$val) ; ok(! $t->_boolean(undef)) ; ok(! $t->_boolean(0)) ; ok(! $t->_boolean("")) ; ok($t->_boolean("true")) ; ok($t->_boolean(1)) ; ok(! $t->_Boolean(undef)) ; ok(! $t->_Boolean(0)) ; ok(! $t->_Boolean("")) ; ok($t->_Boolean("true")) ; ok($t->_Boolean(1)) ; ok($t->_char(undef), "\0") ; ok($t->_char(0), "0") ; ok($t->_char("1"), '1') ; eval {$t->_char("10")} ; ok($@, qr/Can't convert/) ; #' ok($t->_Character(undef), "\0") ; ok($t->_Character(0), "0") ; ok($t->_Character("1"), '1') ; eval {$t->_Character("10")} ; ok($@, qr/Can't convert/) ; #' ok($t->_String(undef), undef) ; ok($t->_String(0), "0") ; ok($t->_String("string"), 'string') ; my $str = "\r\n&&&\r\n\ntre gfd gf$$ b F D&a;t% R f &p;vf\r\r" ; ok($t->_String($str), $str) ; ok($t->_StringBuffer(undef), undef) ; ok($t->_StringBuffer(0), "0") ; ok($t->_StringBuffer("stringbuffer"), 'stringbuffer') ; # Test if scalars can pass as java.lang.Object. # They should be converted to strings. ok($t->_Object(undef), undef) ; ok($t->_Object(0), "0") ; ok($t->_Object(666) == 666) ; ok($t->_Object("object"), 'object') ; } ok($t->__get_private()->{proto}->ObjectCount(), 1) ; __END__ __Java__ class types2 { public types2(){ } public byte _byte(byte b){ return (byte)(b + (byte)1) ; } public Byte _Byte(Byte b){ return b ; } public short _short(short s){ return (short)(s + (short)1) ; } public Short _Short(Short s){ return s ; } public int _int(int i){ return i + 1 ; } public Integer _Integer(Integer i){ return i ; } public long _long(long l){ return l + 1 ; } public Long _Long(Long l){ return l ; } public float _float(float f){ return f + 1 ; } public Float _Float(Float f){ return f ; } public double _double(double d){ return d + 1 ; } public Double _Double(Double d){ return d ; } public Number _Number(Number n){ return n ; } public boolean _boolean(boolean b){ return b ; } public Boolean _Boolean(Boolean b){ return b ; } public char _char(char c){ return c ; } public Character _Character(Character c){ return c ; } public String _String(String s){ return s ; } public StringBuffer _StringBuffer(StringBuffer sb){ return sb ; } public Object _Object(Object o){ return o ; } } Inline-Java-0.67/t/10_6_shared_sim.t0000644000175000017500000000177714202030173016770 0ustar osboxesosboxespackage t10 ; use strict ; use Test ; BEGIN { # Leave previous server enough time to die... sleep(1) ; if ($ENV{PERL_INLINE_JAVA_JNI}){ plan(tests => 0) ; exit ; } else{ plan(tests => 7) ; } } use Inline ( Java => 't/shared.java', SHARED_JVM => 1, PORT => 17893, NAME => 't10_6', ); { my $t = new t10::t10() ; ok($t->{i}++, 5) ; ok(! Inline::Java::i_am_JVM_owner()) ; } my $JVM1 = Inline::Java::__get_JVM() ; $JVM1->{destroyed} = 1 ; Inline::Java::__clear_JVM() ; Inline->bind( Java => 't/shared.java', SHARED_JVM => 1, PORT => 17893, NAME => 't10_6', ) ; { my $t = new t10::t10() ; ok($t->{i}++, 6) ; ok(! Inline::Java::i_am_JVM_owner()) ; } my $JVM2 = Inline::Java::__get_JVM() ; $JVM2->{destroyed} = 1 ; Inline::Java::__clear_JVM() ; Inline->bind( Java => 't/shared.java', SHARED_JVM => 1, PORT => 17893, NAME => 't10_6', ) ; { my $t = new t10::t10() ; ok($t->{i}, 7) ; ok(! Inline::Java::i_am_JVM_owner()) ; Inline::Java::capture_JVM() ; ok(Inline::Java::i_am_JVM_owner()) ; } Inline-Java-0.67/t/05_arrays.t0000644000175000017500000001242014202030173015715 0ustar osboxesosboxesuse strict ; use Test ; use Inline( Java => 'DATA' ) ; use Inline::Java qw(cast); BEGIN { plan(tests => 55) ; } my $t = new types5() ; { ok(++($t->_byte([12, 34, 56])->[0]) == 124) ; ok(eq_array($t->_Byte([12, 34, 56]), [12, 34, 56])) ; ok(++($t->_short([12, 34, 56])->[0]) == 124) ; ok(eq_array($t->_Short([12, 34, 56]), [12, 34, 56])) ; ok(++($t->_int([12, 34, 56])->[0]) == 124) ; ok(eq_array($t->_Integer([12, 34, 56]), [12, 34, 56])) ; ok(++($t->_long([12, 34, 56])->[0]) == 124) ; ok(eq_array($t->_Long([12, 34, 56]), [12, 34, 56])) ; ok(++($t->_float([12.34, 5.6, 7])->[0]) == 124.456) ; ok(eq_array($t->_Float([12.34, 5.6, 7]), [12.34, 5.6, 7])) ; ok(++($t->_double([12.34, 5.6, 7])->[0]) == 124.456) ; ok(eq_array($t->_Double([12.34, 5.6, 7]), [12.34, 5.6, 7])) ; ok($t->_boolean([1, 0, "tree"])->[0]) ; ok($t->_Boolean([1, 0])->[0]) ; ok(! $t->_Boolean([1, 0])->[1]) ; ok($t->_char(['a', 'b', 'c'])->[0], "A") ; ok(eq_array($t->_Character(['a', 'b', 'c']), ['a', 'b', 'c'], 1)) ; my $a = $t->_String(["bla", "ble", "bli"]) ; ok($a->[0], "STRING") ; $a->[1] = "wazoo" ; ok($a->[1], "wazoo") ; ok($t->_StringBuffer(["bla", "ble", "bli"])->[0], "STRINGBUFFER") ; ok($t->_Object(undef), undef) ; $a = $t->_Object([1, "two", $t]) ; ok($a->[0], "1") ; ok($a->[1], "two") ; my $a2 = cast('types5', $a->[2]); ok(UNIVERSAL::isa($a2, "main::types5")) ; ok($a2->{data}->[1], "a") ; $a2->{data} = ["1", "2"] ; ok($a2->{data}->[1], 2) ; $a->[0]++ ; ok($a->[0], "2") ; $a->[1] = "three" ; ok($a->[1], "three") ; $a->[2] = "string" ; ok($a->[2], "string") ; $a->[0] = $t ; ok(UNIVERSAL::isa(cast('types5', $a->[0]), "main::types5")) ; # Try some multidimensional arrays. $a = $t->_StringString([ ["00", "01"], ["10", "11"] ]) ; # Try some incomplete multidimensional arrays. $a = $t->_StringString([ [undef, "01", "02"], [undef, "11"], undef, ]) ; ok($a->[1]->[0], undef) ; my $b = $a->[1] ; ok($t->_String($b)->[0], "STRING") ; # Arrays of other arrays $a = $t->_StringString([ $a->[0], ]) ; ok($a->[0]->[2], "02") ; # This is one of the things that won't work. # Try passing an array as an Object. eval {$t->_o(["a", "b", "c"])} ; ok($@, qr/Can't create Java array/) ; ok($t->_o(Inline::Java::coerce( "java.lang.Object", ["a", "b", "c"], "[Ljava.lang.String;"))->[0], "a") ; $t->{o} = Inline::Java::coerce( "java.lang.Object", ["a", "b", "c"], "[Ljava.lang.String;") ; ok($t->{o}->[0], "a") ; $t->{o} = $t->{i} ; ok($t->{o}->[0], "1") ; # Mixed types eval {$t->_int(["3", "3456", "cat"])} ; ok($@, qr/Can't convert/) ; ok($t->_Object(["3", "3456", "cat"])->[2], 'cat') ; # Badly constructed array eval {$t->_int(["3", [], "cat"])} ; ok($@, qr/Java array contains mixed types/) ; eval {$t->_StringString([["3"], "string"])} ; ok($@, qr/Java array contains mixed types/) ; # Invalid operations on arrays. eval {@{$b} = ()} ; ok($@, qr/Operation CLEAR/) ; eval {pop @{$b}} ; ok($@, qr/Operation POP/) ; eval {shift @{$b}} ; ok($@, qr/Operation SHIFT/) ; eval {splice(@{$b}, 0, 1)} ; ok($@, qr/Operation SPLICE/) ; eval {$b->[10] = 5} ; ok($@, qr/out of bounds/) ; # Cool stuff on arrays $a = $t->_byte([12, 34, 56]) ; ok(scalar(@{$a}), 3) ; foreach my $e (@{$a}){ ok($e =~ /^(123|34|56)$/) ; } # Zero length arrays $a = $t->_Byte([]) ; ok(scalar(@$a), 0) ; $a = $t->_StringString([[], []]) ; ok(scalar(@{$a}), 2) ; ok(scalar(@{$a->[0]}), 0) ; ok(scalar(@{$a->[1]}), 0) ; } ok($t->__get_private()->{proto}->ObjectCount(), 1) ; sub eq_array { my $a1 = shift ; my $a2 = shift ; my $eq = shift || 0 ; if (scalar(@{$a1}) != scalar(@{$a2})){ return 0 ; } my $ok = 1 ; for (0..$#{$a1}){ if ($eq){ $ok = ($a1->[$_] eq $a2->[$_]) ; } else{ $ok = ($a1->[$_] == $a2->[$_]) ; } last unless $ok ; } return $ok ; } __END__ __Java__ class types5 { public Object o ; public int i[] = {1, 2, 3} ; public String data[] = {"d", "a", "t", "a"} ; public types5(){ } public byte[] _byte(byte b[]){ b[0] = (byte)123 ; return b ; } public Byte[] _Byte(Byte b[]){ return b ; } public short[] _short(short s[]){ s[0] = (short)123 ; return s ; } public Short[] _Short(Short s[]){ return s ; } public int[] _int(int i[]){ i[0] = 123 ; return i ; } public Integer[] _Integer(Integer i[]){ return i ; } public long[] _long(long l[]){ l[0] = 123 ; return l ; } public Long[] _Long(Long l[]){ return l ; } public float[] _float(float f[]){ f[0] = (float)123.456 ; return f ; } public Float[] _Float(Float f[]){ return f ; } public double[] _double(double d[]){ d[0] = 123.456 ; return d ; } public Double[] _Double(Double d[]){ return d ; } public boolean[] _boolean(boolean b[]){ b[0] = true ; return b ; } public Boolean[] _Boolean(Boolean b[]){ return b ; } public char[] _char(char c[]){ c[0] = 'A' ; return c ; } public Character[] _Character(Character c[]){ return c ; } public String[] _String(String s[]){ s[0] = "STRING" ; return s ; } public String[][] _StringString(String s[][]){ return s ; } public StringBuffer[] _StringBuffer(StringBuffer sb[]){ sb[0] = new StringBuffer("STRINGBUFFER") ; return sb ; } public Object[] _Object(Object o[]){ return o ; } public Object _o(Object o){ return o ; } } Inline-Java-0.67/t/02_primitives_1_4.t0000755000175000017500000000155114202030173017255 0ustar osboxesosboxesuse strict ; use Test ; package t02_14 ; use Inline( Java => qq | class t02_14 { public static boolean got14(){ try { Class c = Class.forName("java.lang.CharSequence") ; } catch (ClassNotFoundException cnfe){ return false ; } return true ; } } |, NAME => 't02_14', ) ; package main ; BEGIN { my $got14 = t02_14::t02_14->got14() ; if (! $got14){ plan(tests => 0) ; exit(0) ; } plan(tests => 4) ; } use Inline( Java => 'DATA', ) ; my $t = new types2_1() ; { ok($t->_CharSequence(undef), undef) ; ok($t->_CharSequence(0), "0") ; ok($t->_CharSequence("charsequence"), "charsequence") ; } ok($t->__get_private()->{proto}->ObjectCount(), 1) ; __END__ __Java__ class types2_1 { public types2_1(){ } public CharSequence _CharSequence(CharSequence c){ return c ; } } Inline-Java-0.67/t/types.class0000644000175000017500000000075114202030173016122 0ustar osboxesosboxes-   ()VCodeLineNumberTablefunc()Ljava/lang/String;hm()Ljava/util/HashMap; SourceFile types.java studyjava/util/HashMapkeyvalue t/typesjava/lang/Objectput8(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;!   !*     3YL+W+ Inline-Java-0.67/t/15_native_doubles.t0000755000175000017500000000073614202030173017432 0ustar osboxesosboxesuse strict ; use Test ; use Inline ( Java => 'DATA', NATIVE_DOUBLES => 2, ) ; BEGIN { plan(tests => 3) ; } my $t = new t15() ; { # Here it is hard to test for accuracy, but either it works or it doesn't... ok($t->_Double(0.056200000000000028) > 0.056) ; ok($t->_Double(0.056200000000000028) < 0.057) ; } ok($t->__get_private()->{proto}->ObjectCount(), 1) ; __END__ __Java__ class t15 { public t15(){ } public Double _Double(Double d){ return d ; } } Inline-Java-0.67/t/shared.java0000644000175000017500000000016214202030173016034 0ustar osboxesosboxesclass t10 { static public int i = 5 ; public t10(){ } static synchronized public void incr(){ i++ ; } } Inline-Java-0.67/t/04_members.t0000644000175000017500000000541514202030173016053 0ustar osboxesosboxesuse strict ; use Test::More tests => 28; use Inline( Java => 'DATA', ) ; use Inline::Java qw(cast); my $t = new types4() ; { $t->{_byte} = 123 ; cmp_ok($t->{_byte}, '==', 123) ; $t->{_Byte} = 123 ; cmp_ok($t->{_Byte}, '==', 123) ; $t->{_short} = 123 ; cmp_ok($t->{_short}, '==', 123) ; $t->{_Short} = 123 ; cmp_ok($t->{_Short}, '==', 123) ; $t->{_int} = 123 ; cmp_ok($t->{_int}, '==', 123) ; $t->{_Integer} = 123 ; cmp_ok($t->{_Integer}, '==', 123) ; $t->{_long} = 123 ; cmp_ok($t->{_long}, '==', 123) ; $t->{_Long} = 123 ; cmp_ok($t->{_Long}, '==', 123) ; $t->{_float} = 123.456 ; cmp_ok($t->{_float}, '==', 123.456) ; $t->{_Float} = 123.456 ; cmp_ok($t->{_Float}, '==', 123.456) ; $t->{_double} = 123.456 ; cmp_ok($t->{_double}, '==', 123.456) ; $t->{_Double} = 123.456 ; cmp_ok($t->{_Double}, '==', 123.456) ; $t->{_boolean} = 1 ; ok($t->{_boolean}) ; $t->{_Boolean} = 1 ; ok($t->{_Boolean}) ; $t->{_char} = "a" ; is($t->{_char}, "a") ; $t->{_Character} = "a" ; is($t->{_Character}, "a") ; $t->{_String} = "string" ; is($t->{_String}, "string") ; $t->{_StringBuffer} = "stringbuffer" ; is($t->{_StringBuffer}, "stringbuffer") ; my $obj1 = obj14->new; $t->{_Object} = $obj1 ; is(cast('obj14', $t->{_Object})->get_data(), "obj1") ; $t->{_Object} = "object" ; is($t->{_Object}, "object") ; $t->{_Object} = undef ; is($t->{_Object}, undef) ; $t->{_int} = undef ; cmp_ok($t->{_int}, '==', 0) ; # Receive an unbound object and try to call a member my $unb = $t->get_unbound() ; eval {$unb->{toto} = 1} ; like($@, qr/Can't set member/) ; eval {my $a = $unb->{toto}} ; like($@, qr/Can't get member/) ; # Unexisting member eval {$t->{toto} = 1} ; like($@, qr/No public member/) ; eval {my $a = $t->{toto}} ; like($@, qr/No public member/) ; # Incompatible type eval {$t->{_long} = $obj1} ; like($@, qr/Can't convert/) ; } is($t->__get_private()->{proto}->ObjectCount(), 1) ; __END__ __Java__ import java.util.* ; class obj14 { String data = "obj1" ; public obj14() { } public String get_data(){ return data ; } } class types4 { public byte _byte ; public Byte _Byte ; public short _short ; public Short _Short ; public int _int ; public Integer _Integer ; public long _long ; public Long _Long ; public float _float ; public Float _Float ; public double _double ; public Double _Double ; public boolean _boolean ; public Boolean _Boolean ; public char _char ; public Character _Character ; public String _String ; public StringBuffer _StringBuffer ; public Object _Object ; public types4(){ } public ArrayList get_unbound(){ ArrayList al = new ArrayList<>() ; al.add(0, "al_elem") ; return al ; } public String send_unbound(ArrayList al){ return (String)al.get(0) ; } } Inline-Java-0.67/t/08_study.t0000644000175000017500000000315114202030173015570 0ustar osboxesosboxespackage study ; use strict ; use Test ; use Inline( Java => 'DATA', ) ; # There once was a bug with importing code twice. use Inline( Java => 'STUDY', AUTOSTUDY => 1, STUDY => ['t.types'], CLASSPATH => '.', ) ; use Inline( Java => 'STUDY', AUTOSTUDY => 1, STUDY => ['t.types'], CLASSPATH => '.', ) ; package toto ; use Inline( Java => 'study', AUTOSTUDY => 1, STUDY => ['t.types'], CLASSPATH => '.', ) ; use Inline( Java => 'study', AUTOSTUDY => 1, STUDY => ['t.types'], CLASSPATH => '.', PACKAGE => 'main', ) ; package study ; use Inline::Java qw(study_classes) ; BEGIN { plan(tests => 11) ; } study_classes([ 't.no_const' ]) ; my $t = new study::t::types() ; { ok($t->func(), "study") ; ok($t->hm()->get("key"), "value") ; my $nc = new study::t::no_const() ; ok($nc->{i}, 5) ; my $a = new study::study::a8() ; ok($a->{i}, 50) ; ok($a->truth()) ; ok($a->sa()->[1], 'titi') ; ok($a->sb()->[0]->get('toto'), 'titi') ; ok($a->sb()->[1]->get('error'), undef) ; my $toto_t = new toto::t::types() ; ok(1) ; my $main_t = new t::types() ; ok(1) ; } ok($t->__get_private()->{proto}->ObjectCount(), 1) ; __DATA__ __Java__ // Use a public class package study ; import java.util.* ; public class a8 { public int i = 50 ; public a8(){ } public boolean truth(){ return true ; } public String [] sa(){ String a[] = {"toto", "titi"} ; return a ; } public HashMap [] sb(){ HashMap h1 = new HashMap<>() ; HashMap h2 = new HashMap<>() ; h1.put("toto", "titi") ; h2.put("tata", "tete") ; HashMap a[] = {h1, h2} ; return a ; } } Inline-Java-0.67/t/11_exceptions.t0000755000175000017500000000421114202030173016574 0ustar osboxesosboxesuse strict ; use Test ; use Inline( Java => 'DATA', ) ; use Inline::Java qw(caught) ; BEGIN { # Leave previous server enough time to die... sleep(1) ; plan(tests => 8) ; } my $t = new t9(0) ; { my $msg = '' ; eval { $t->f() ; } ; if ($@){ if (caught("java.io.IOException")){ $msg = $@->getMessage() . "io" ; } elsif (caught("java.lang.Exception")){ $msg = $@->getMessage() ; } else { die $@ ; } } ; ok($msg, "from fio") ; $msg = '' ; eval { $t->f() ; } ; if ($@){ if (caught("java.lang.Throwable")){ $msg = $@->getMessage() ; } elsif (caught("java.io.IOException")){ $msg = $@->getMessage() . "io" ; } else { die $@ ; } } ok($msg, "from f") ; $msg = '' ; eval { die("not e\n") ; } ; if ($@){ if (caught("java.lang.Exception")){ $msg = $@->getMessage() ; } else { $msg = $@ ; } } ok($msg, "not e\n") ; my $e = $t->f2() ; ok($e->getMessage(), "from f2") ; $msg = '' ; eval { my $t2 = new t9(1) ; } ; if ($@){ if (caught("java.lang.Exception")){ $msg = $@->getMessage() ; } else{ die $@ ; } } ok($msg, "from const") ; # Undeclared exception, java.lang.NullPointerException $msg = '' ; eval { my $t2 = new t9(0) ; $t2->len(undef) ; } ; if ($@){ if (caught("java.lang.NullPointerException")){ $msg = "null" ; } else { die $@ ; } } ok($msg, "null") ; # Undeclared exception, java.lang.NullPointerException $msg = '' ; eval { my $t2 = new t9(0) ; $t2->len(undef) ; } ; if ($@){ if (caught("java.lang.IOException")){ $msg = "io" ; } elsif (caught("java.lang.Exception")){ $msg = "null" ; } else{ die $@ ; } } ok($msg, "null") ; # Make sure the last exception is not lying around... $@ = undef ; } ok($t->__get_private()->{proto}->ObjectCount(), 1) ; __END__ __Java__ import java.io.* ; class t9 { public t9(boolean t) throws Exception { if (t){ throw new Exception("from const") ; } } public String f() throws IOException { throw new IOException("from f") ; } public IOException f2() { return new IOException("from f2") ; } public int len(String s) { return s.length() ; } } Inline-Java-0.67/t/99_end.t0000644000175000017500000000024014202030173015174 0ustar osboxesosboxesuse strict ; use Test ; BEGIN { plan(tests => 1) ; } use Inline ( Java => 'STUDY', ) ; Inline::Java::capture_JVM() ; ok(Inline::Java::i_am_JVM_owner()) ; Inline-Java-0.67/t/01_init.t0000644000175000017500000000174714202030173015365 0ustar osboxesosboxesuse strict ; use Test ; BEGIN { $main::cp = $ENV{CLASSPATH} || "" ; plan(tests => 1) ; } use Inline ( Java => 'DATA', ) ; my $ij = $types1::INLINE ; $ij = $types1::INLINE ; # Stupid warning... my $jdk = $ij->get_java_config("J2SDK") ; my $ver = types1->version() ; my $maxMemory = types1->maxMemory() ; print STDERR "\nPerl version is $]\n" ; print STDERR "Inline version is $Inline::VERSION\n" ; print STDERR "Inline::Java version is $Inline::Java::VERSION\n" ; print STDERR "J2SDK version is $ver, from $jdk\n" ; print STDERR "Max memory is $maxMemory\n" ; print STDERR "CLASSPATH is $main::cp\n" ; if ($ENV{PERL_INLINE_JAVA_EMBEDDED_JNI}){ print STDERR "Using JNI extension (embedded).\n" ; } elsif ($ENV{PERL_INLINE_JAVA_JNI}){ print STDERR "Using JNI extension.\n" ; } ok(1) ; __END__ __Java__ class types1 { static public String version(){ return System.getProperty("java.version") ; } static public long maxMemory(){ return Runtime.getRuntime().maxMemory(); } } Inline-Java-0.67/t/10_1_shared_alone.t0000755000175000017500000000064214202030173017262 0ustar osboxesosboxesuse strict ; use Test ; BEGIN { if ($ENV{PERL_INLINE_JAVA_JNI}){ plan(tests => 0) ; exit ; } else{ plan(tests => 4) ; } } use Inline ( Java => 't/shared.java', SHARED_JVM => 1, PORT => 17891 ) ; my $t = new t10() ; { ok($t->{i}, 5) ; ok(! Inline::Java::i_am_JVM_owner()) ; Inline::Java::capture_JVM() ; ok(Inline::Java::i_am_JVM_owner()) ; } ok($t->__get_private()->{proto}->ObjectCount(), 1) ; Inline-Java-0.67/t/09_usages.t0000755000175000017500000000167314202030173015722 0ustar osboxesosboxesuse strict ; use Test ; BEGIN { plan(tests => 6) ; } package t09::p1 ; use Inline( Java => qq | class t09p1 { public static String name = "p1" ; public t09p1(){ } public static String get_prop(int n){ return System.getProperty("prop" + n) ; } } |, NAME => 't09::p1', EXTRA_JAVA_ARGS => '-Dprop1="c:\program files" -Dprop3=42', ) ; package t09::p2 ; use Inline( Java => qq | class t09p2 { public static String name = "p2" ; } |, NAME => 't09::p2', ) ; package t09::p3 ; Inline->bind( Java => qq | class t09p3 { public static String name = "p3" ; } |, NAME => 't09::p3', ) ; package main ; my $t = new t09::p1::t09p1() ; { ok($t->{name}, "p1") ; ok($t->get_prop(1), 'c:\program files') ; ok($t->get_prop(3), 42) ; ok($t09::p2::t09p2::name . $t09::p3::t09p3::name, "p2p3") ; ok($t09::p2::t09p2::name . $t09::p3::t09p3::name, "p2p3") ; } ok($t->__get_private()->{proto}->ObjectCount(), 1) ; Inline-Java-0.67/t/10_5_shared_fork.t0000755000175000017500000000175214202030173017134 0ustar osboxesosboxespackage t10 ; use strict ; use Test ; BEGIN { # Leave previous server enough time to die... sleep(1) ; require Inline::Java::Portable ; if ($ENV{PERL_INLINE_JAVA_JNI}){ plan(tests => 0) ; exit ; } elsif (! Inline::Java::Portable::portable('GOT_FORK')){ plan(tests => 0) ; exit ; } else{ $t10::nb = 5 ; plan(tests => $t10::nb + 3) ; } } use Inline ( Java => 't/shared.java', SHARED_JVM => 1, PORT => 17892, NAME => 't10', ) ; $t10::t10::i = 0 ; my $nb = $t10::nb ; my $sum = (($nb) * ($nb + 1)) / 2 ; for (my $i = 0 ; $i < $nb ; $i++){ if (! fork()){ do_child($i) ; } } # Wait for kids to finish for (my $i = 0 ; $i < $nb ; $i++){ wait() ; ok(1) ; } ok($t10::t10::i, $sum) ; # Bring down the JVM ok(! Inline::Java::i_am_JVM_owner()) ; Inline::Java::capture_JVM() ; ok(Inline::Java::i_am_JVM_owner()) ; sub do_child { my $i = shift ; Inline::Java::reconnect_JVM() ; my $t = new t10::t10() ; for (my $j = 0 ; $j <= $i ; $j++){ $t->incr() ; } exit ; } Inline-Java-0.67/t/00-report-prereqs.t0000644000175000017500000001350614202030173017325 0ustar osboxesosboxes#!perl use strict; use warnings; # This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.020 # THEN modified with more info by Ed J for PDL project use Test::More tests => 1; use ExtUtils::MakeMaker; use File::Spec; # from $version::LAX my $lax_version_re = qr/(?: undef | (?: (?:[0-9]+) (?: \. | (?:\.[0-9]+) (?:_[0-9]+)? )? | (?:\.[0-9]+) (?:_[0-9]+)? ) | (?: v (?:[0-9]+) (?: (?:\.[0-9]+)+ (?:_[0-9]+)? )? | (?:[0-9]+)? (?:\.[0-9]+){2,} (?:_[0-9]+)? ) )/x; # hide optional CPAN::Meta modules from prereq scanner # and check if they are available my $cpan_meta = "CPAN::Meta"; my $cpan_meta_pre = "CPAN::Meta::Prereqs"; my $HAS_CPAN_META = eval "require $cpan_meta; $cpan_meta->VERSION('2.120900')" && eval "require $cpan_meta_pre"; ## no critic # Verify requirements? my $DO_VERIFY_PREREQS = 1; sub _max { my $max = shift; $max = ( $_ > $max ) ? $_ : $max for @_; return $max; } sub _merge_prereqs { my ($collector, $prereqs) = @_; # CPAN::Meta::Prereqs object if (ref $collector eq $cpan_meta_pre) { return $collector->with_merged_prereqs( CPAN::Meta::Prereqs->new( $prereqs ) ); } # Raw hashrefs for my $phase ( keys %$prereqs ) { for my $type ( keys %{ $prereqs->{$phase} } ) { for my $module ( keys %{ $prereqs->{$phase}{$type} } ) { $collector->{$phase}{$type}{$module} = $prereqs->{$phase}{$type}{$module}; } } } return $collector; } my @include = qw( ); my @exclude = qw( ); # Add static prereqs to the included modules list my $static_prereqs = do 't/00-report-prereqs.dd'; # Merge all prereqs (either with ::Prereqs or a hashref) my $full_prereqs = _merge_prereqs( ( $HAS_CPAN_META ? $cpan_meta_pre->new : {} ), $static_prereqs ); # Add dynamic prereqs to the included modules list (if we can) my ($source) = grep { -f } 'MYMETA.json', 'MYMETA.yml'; if ( $source && $HAS_CPAN_META ) { if ( my $meta = eval { CPAN::Meta->load_file($source) } ) { $full_prereqs = _merge_prereqs($full_prereqs, $meta->prereqs); } } else { $source = 'static metadata'; } my @full_reports; my @dep_errors; my $req_hash = $HAS_CPAN_META ? $full_prereqs->as_string_hash : $full_prereqs; # Add static includes into a fake section for my $mod (@include) { $req_hash->{other}{modules}{$mod} = 0; } for my $phase ( qw(configure build test runtime develop other) ) { next unless $req_hash->{$phase}; next if ($phase eq 'develop' and not $ENV{AUTHOR_TESTING}); for my $type ( qw(requires recommends suggests conflicts modules) ) { next unless $req_hash->{$phase}{$type}; my $title = ucfirst($phase).' '.ucfirst($type); my @reports = [qw/Module Want Have Where Howbig/]; for my $mod ( sort keys %{ $req_hash->{$phase}{$type} } ) { next if $mod eq 'perl'; next if grep { $_ eq $mod } @exclude; my $file = $mod; $file =~ s{::}{/}g; $file .= ".pm"; my ($prefix) = grep { -e File::Spec->catfile($_, $file) } @INC; my $want = $req_hash->{$phase}{$type}{$mod}; $want = "undef" unless defined $want; $want = "any" if !$want && $want == 0; my $req_string = $want eq 'any' ? 'any version required' : "version '$want' required"; if ($prefix) { my $filename = File::Spec->catfile($prefix, $file); my $have = MM->parse_version( $filename ); $have = "undef" unless defined $have; push @reports, [$mod, $want, $have, $prefix, (-s $filename)]; if ( $DO_VERIFY_PREREQS && $HAS_CPAN_META && $type eq 'requires' ) { if ( $have !~ /\A$lax_version_re\z/ ) { push @dep_errors, "$mod version '$have' cannot be parsed ($req_string)"; } elsif ( ! $full_prereqs->requirements_for( $phase, $type )->accepts_module( $mod => $have ) ) { push @dep_errors, "$mod version '$have' is not in required range '$want'"; } } } else { push @reports, [$mod, $want, "missing", '', 0]; if ( $DO_VERIFY_PREREQS && $type eq 'requires' ) { push @dep_errors, "$mod is not installed ($req_string)"; } } } if ( @reports ) { push @full_reports, "=== $title ===\n\n"; my $ml = _max( map { length $_->[0] } @reports ); my $wl = _max( map { length $_->[1] } @reports ); my $hl = _max( map { length $_->[2] } @reports ); my $ll = _max( map { length $_->[3] } @reports ); # location my $sl = _max( map { length $_->[4] } @reports ); # size if ($type eq 'modules') { splice @reports, 1, 0, ["-" x $ml, "", "-" x $hl, "-" x $ll, "-" x $sl]; push @full_reports, map { sprintf(" %*s %*s\n", -$ml, $_->[0], $hl, $_->[2]) } @reports; } else { splice @reports, 1, 0, ["-" x $ml, "-" x $wl, "-" x $hl, "-" x $ll, "-" x $sl]; push @full_reports, map { sprintf(" %*s %*s %*s %*s %*s\n", -$ml, $_->[0], $wl, $_->[1], $hl, $_->[2], -$ll, $_->[3], $sl, $_->[4]) } @reports; } push @full_reports, "\n"; } } } if ( @full_reports ) { diag "\nVersions for all modules listed in $source (including optional ones):\n\n", @full_reports; } if ( @dep_errors ) { diag join("\n", "\n*** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ***\n", "The following REQUIRED prerequisites were not satisfied:\n", @dep_errors, "\n" ); } pass; # vim: ts=4 sts=4 sw=4 et: Inline-Java-0.67/t/06_static.t0000644000175000017500000000257614202030173015717 0ustar osboxesosboxesuse strict ; use Test ; use Inline( Java => 'DATA', ) ; BEGIN { plan(tests => 10) ; } # Methods ok(p06::types6->get("key"), undef) ; my $t = new p06::types6("key", "value") ; { ok($t->get("key"), "value") ; # Members ok($p06::types6::i == 5) ; $p06::types6::i = 7 ; ok($t->{i} == 7) ; my $t2 = new p06::types6("key2", "value2") ; my $hm = $p06::types6::hm ; $p06::types6::hm = undef ; ok(p06::types6->get($hm, "key2"), "value2") ; $p06::types6::hm = $hm ; ok($t2->get("key2"), "value2") ; # Calling an instance method without an object reference eval {p06::types6->set()} ; ok($@, qr/must be called from an object reference/) ; # Put in back like before... $p06::types6::i = 5 ; ok($p06::types6::i == 5) ; my $tt = new p06::types6("key", undef) ; ok($tt->get("key"), undef) ; } # Since $types::hm was returned to the Perl space, it was registered in the object # HashMap. ok($t->__get_private()->{proto}->ObjectCount(), 2) ; __END__ __Java__ // package test package p06 ; import java.util.* ; public class types6 { public static int i = 5 ; public static HashMap hm = new HashMap<>() ; public types6(String k, String v){ hm.put(k, v) ; } public static String get(String k){ return (String)hm.get(k) ; } public static String get(HashMap h, String k){ return (String)h.get(k) ; } public String set(){ return "set" ; } } Inline-Java-0.67/t/12_1_callbacks.t0000755000175000017500000002100414202030173016552 0ustar osboxesosboxesuse strict ; use Test::More tests => 37; use Inline ( Java => 'DATA', STUDY => ['org.perl.inline.java.InlineJavaPerlCaller'], STARTUP_DELAY => 20, EXTRA_JAVA_ARGS => '-Xmx256m', ) ; use Inline::Java qw(cast caught) ; use Data::Dumper; my $mtc_cnt = 0 ; my $mtc_mode = 0 ; my $t = new t15() ; { eval { is($t->add(5, 6), 11) ; is($t->add_via_perl(5, 6), 11) ; my $a = $t->incr_via_perl([7, 6, 5]) ; is($a->[1], 7) ; $a = $t->incr_via_perl_ctx($a) ; is($a->[1], 8) ; is($t->mul(5, 6), 30) ; is($t->mul_via_perl(5, 6), 30) ; is($t->silly_mul(3, 2), 6) ; is($t->silly_mul_via_perl(3, 2), 6) ; is(add_via_java(3, 4), 7) ; is($t->add_via_perl_via_java(3, 4), 7) ; is($t->silly_mul_via_perl_via_java(10, 9), 90) ; is(t15->add_via_perl_via_java_t($t, 6, 9), 15) ; is($t->cat_via_perl("Inline", "Java"), "InlineJava") ; is($t->perl_static(), 'main->static') ; is(twister(20, 0, 0), "return perl twister") ; is($t->twister(20, 0, 0), "return java twister") ; eval {twister(20, 0, 1)} ; like($@, qr/^throw perl twister/) ; my $msg = '' ; eval {$t->twister(20, 0, 1)} ; if ($@) { if (caught('t15$OwnException')){ $msg = $@->getMessage() ; } else{ $msg = $@ ; } } is($msg, "throw java twister") or diag Dumper $msg; eval {$t->bug()} ; like($@, qr/^bug/) ; is(cast('t15', $t->perlt())->add(5, 6), 11) ; eval {$t->perldummy()} ; like($@, qr/Can't propagate non-/) ; #' $t->mtc_callbacks(20) ; $t->StartCallbackLoop() ; is($mtc_cnt, 20) ; $mtc_cnt = -30 ; $t->mtc_callbacks2(50) ; $t->StartCallbackLoop() ; is($mtc_cnt, 20) ; $mtc_cnt = 0 ; $mtc_mode = 1 ; $t->mtc_callbacks2(20) ; $t->StartCallbackLoop() ; is($mtc_cnt, 20) ; $mtc_cnt = 0 ; $mtc_mode = 2 ; $t->mtc_callbacks2(20) ; $t->OpenCallbackStream() ; while (($mtc_cnt < 20)&&($t->WaitForCallback(-1) > 0)){ $t->ProcessNextCallback() ; } is($mtc_cnt, 20) ; $mtc_cnt = 0 ; $mtc_mode = 2 ; $t->mtc_callbacks2(10) ; while ($t->WaitForCallback(3.1416) > 0){ cmp_ok($t->WaitForCallback(0), '>=', 1) ; $t->ProcessNextCallback() ; } is($mtc_cnt, 10) ; # Unfortunately we can't test this because the Thread.run method doesn't allow us # to throw any exceptions... # $t->mtc_callbacks_error() ; } ; if ($@){ if (caught("java.lang.Throwable")){ $@->printStackTrace() ; die("Caught Java Exception") ; } else{ die $@ ; } } } is($t->__get_private()->{proto}->ObjectCount(), 1) ; sub add { my $i = shift ; my $j = shift ; return $i + $j ; } sub incr { my $ija = shift ; for (my $i = 0 ; $i < $ija->length() ; $i++){ $ija->[$i]++ ; } return wantarray ? @{$ija} : $ija ; } sub mul { my $i = shift ; my $j = shift ; return $i * $j ; } sub cat { my $i = shift ; my $j = shift ; return $i . $j ; } sub add_via_java { my $i = shift ; my $j = shift ; return $t->add($i, $j) ; } sub add_via_java_t { my $_t = shift ; my $i = shift ; my $j = shift ; return $_t->add($i, $j) ; } sub twister { my $max = shift ; my $cnt = shift ; my $explode = shift ; if ($cnt == $max){ if ($explode){ die("throw perl twister") ; } else{ return "return perl twister" ; } } else{ return $t->twister($max, $cnt+1, $explode) ; } } sub t { return $t ; } sub dummy { die(bless({}, "Inline::Java::dummy")) ; } sub mt_callback { my $pc = shift ; $mtc_cnt++ ; if ($mtc_cnt >= 20){ if ($mtc_mode == 0){ $pc->StopCallbackLoop() ; } elsif ($mtc_mode == 1){ my $o = new org::perl::inline::java::InlineJavaPerlCaller() ; $o->StopCallbackLoop() ; } } } sub static_method { my $class = shift ; return 'main->static' ; } __END__ __Java__ import java.io.* ; import org.perl.inline.java.* ; class t15 extends InlineJavaPerlCaller { class OwnException extends Exception { OwnException(String msg){ super(msg) ; } } class OwnThread extends Thread { InlineJavaPerlCaller pc = null ; boolean error = false ; OwnThread(InlineJavaPerlCaller _pc, int nb, boolean err){ super("CALLBACK-TEST-THREAD-#" + nb) ; pc = _pc ; error = err ; } public void run(){ try { if (! error){ pc.CallPerlSub("main::mt_callback", new Object [] {pc}) ; } else { new InlineJavaPerlCaller() ; } } catch (InlineJavaException ie){ ie.printStackTrace() ; } catch (InlineJavaPerlException ipe){ ipe.printStackTrace() ; } } } public t15() throws InlineJavaException { } public int add(int a, int b){ return a + b ; } public int mul(int a, int b){ return a * b ; } public int silly_mul(int a, int b){ int ret = 0 ; for (int i = 0 ; i < b ; i++){ ret = add(ret, a) ; } return a * b ; } public int silly_mul_via_perl(int a, int b) throws InlineJavaException, InlineJavaPerlException { int ret = 0 ; for (int i = 0 ; i < b ; i++){ ret = add_via_perl(ret, a) ; } return ret ; } public int add_via_perl(int a, int b) throws InlineJavaException, InlineJavaPerlException { String val = (String)CallPerlSub("main::add", new Object [] {Integer.valueOf(a), Integer.valueOf(b)}) ; return Integer.valueOf(val).intValue() ; } public int [] incr_via_perl(int a[]) throws InlineJavaException, InlineJavaPerlException { int [] r = (int [])CallPerlSub("main::incr", new Object [] {a}, a.getClass()) ; return r ; } public int [] incr_via_perl_ctx(int a[]) throws InlineJavaException, InlineJavaPerlException { int [] r = (int [])CallPerlSub("@main::incr", new Object [] {a}, a.getClass()) ; return r ; } public void death_via_perl() throws InlineJavaException, InlineJavaPerlException { InlineJavaPerlCaller c = new InlineJavaPerlCaller() ; c.CallPerlSub("main::death", null) ; } public void except() throws InlineJavaException, InlineJavaPerlException { throw new InlineJavaPerlException("test") ; } public int mul_via_perl(int a, int b) throws InlineJavaException, InlineJavaPerlException { String val = (String)CallPerlSub("main::mul", new Object [] {Integer.valueOf(a), Integer.valueOf(b)}) ; return Integer.parseInt(val) ; } public int add_via_perl_via_java(int a, int b) throws InlineJavaException, InlineJavaPerlException { String val = (String)CallPerlSub("main::add_via_java", new Object [] {Integer.valueOf(a), Integer.valueOf(b)}) ; return Integer.parseInt(val); } static public int add_via_perl_via_java_t(t15 t, int a, int b) throws InlineJavaException, InlineJavaPerlException { InlineJavaPerlCaller c = new InlineJavaPerlCaller() ; String val = (String)c.CallPerlSub("main::add_via_java_t", new Object [] {t, Integer.valueOf(a), Integer.valueOf(b)}) ; return Integer.parseInt(val); } public int silly_mul_via_perl_via_java(int a, int b) throws InlineJavaException, InlineJavaPerlException { int ret = 0 ; for (int i = 0 ; i < b ; i++){ String val = (String)CallPerlSub("add_via_java", new Object [] {Integer.valueOf(ret), Integer.valueOf(a)}) ; ret = Integer.parseInt(val); } return ret ; } public String cat_via_perl(String a, String b) throws InlineJavaException, InlineJavaPerlException { String val = (String)CallPerlSub("cat", new Object [] {a, b}) ; return val ; } public String twister(int max, int cnt, int explode) throws InlineJavaException, InlineJavaPerlException, OwnException { if (cnt == max){ if (explode > 0){ throw new OwnException("throw java twister") ; } else{ return "return java twister" ; } } else{ return (String)CallPerlSub("twister", new Object [] {Integer.valueOf(max), Integer.valueOf(cnt+1), Integer.valueOf(explode)}) ; } } public void bug() throws InlineJavaException { throw new InlineJavaException("bug") ; } public Object perlt() throws InlineJavaException, InlineJavaPerlException, OwnException { return CallPerlSub("t", null) ; } public Object perl_static() throws InlineJavaException, InlineJavaPerlException, OwnException { return CallPerlStaticMethod("main", "static_method", null) ; } public Object perldummy() throws InlineJavaException, InlineJavaPerlException, OwnException { return CallPerlSub("dummy", null) ; } public void mtc_callbacks(int n){ for (int i = 0 ; i < n ; i++){ OwnThread t = new OwnThread(this, i, false) ; t.start() ; } } public void mtc_callbacks2(int n) throws InlineJavaException, InlineJavaPerlException { for (int i = 0 ; i < n ; i++){ InlineJavaPerlCaller pc = new InlineJavaPerlCaller() ; OwnThread t = new OwnThread(pc, i, false) ; t.start() ; } } public void mtc_callbacks_error(){ OwnThread t = new OwnThread(this, 0, true) ; t.start() ; } } Inline-Java-0.67/t/16_subclass.t0000644000175000017500000000103114202040402016225 0ustar osboxesosboxesuse Test::More; use strict; use warnings; { package Hi3; use strict; use warnings; use Config; use File::Spec; BEGIN { $ENV{CLASSPATH} = join $Config{path_sep}, grep defined, $ENV{CLASSPATH}, File::Spec->catfile(qw(t t16subclass.jar)); } use Inline Java => 'STUDY', STUDY => ['t16subclass']; sub new { my $class = shift; # print "class name is $class \n"; my $a = shift; my $b = shift; return Hi3::t16subclass->t16subclass($a, $b); } } my $Higher1 = Hi3->new(5,10); is $Higher1->printValues(), "a = 5\nb = 10"; done_testing; Inline-Java-0.67/TODO0000644000175000017500000000035014202030173014147 0ustar osboxesosboxesCODE: - Localize $@ where required - Finish PerlInterpreter test suite - Finish PerlHandle stuff and document DOCUMENTATION: - Document new Callback Interface - Document InlineJavaPerlObject when finished TEST: - Alpha - Cygwin Inline-Java-0.67/CHANGES0000644000175000017500000002324114202042136014460 0ustar osboxesosboxes0.67 2022-02-12 - remove support for Win95/98/ME - append to CLASSPATH in test not set (#10, #11) - thanks @jlberner 0.66 Fri Apr 6 01:26:50 BST 2018 - Fix build on Cygwin [RT#119307] - thanks @mperry2! 0.65 Tue Apr 3 22:10:55 BST 2018 - put glob in better place to dodge wildcard problems on Win32 gmake 4.2.1 - use registry on Win32 to find JAVA_HOME if not in env - support old and apparently-new JDK locations on OSX [RT#116917] 0.64 Tue Mar 20 15:00:39 GMT 2018 - apply Debian spelling patch 0.63 Tue Feb 13 05:52:42 GMT 2018 - fix JDK 7 problem with "<>" type on HashMap 0.62 Tue Feb 13 05:37:24 GMT 2018 - zap (very) long-deprecated CallPerl interface - type-constrain get*Constructor, all HashMap, ArrayList - build always -Xlint:unchecked - now only JDK7+ - reorganise repo a bit, zap obsolete tests - author-test all doc code examples - fix giving "STUDY" as source case-insensitive - increase maxMemory for t/12_1_callbacks.t - t/01_init.t show maxMemory 0.61 Sat Feb 10 05:01:23 GMT 2018 - manifest test and fix - no ask about JNI on build - tidy up repo, use lib dir, zap dup tests - support Java 9 - CI tests for Java 7-9 - remove pointless dep on Inline::C - update tests to work in parallel - rework java-build to avoid parallel-build fail 0.60 Tue Jan 30 18:53:01 GMT 2018 - apply Debian reproducible-build patch - Added license meta name. (thanks @manwar) 0.59 Mon Jan 29 07:02:52 GMT 2018 - zap no_index line - put . in Makefile.PL @INC for perl 5.26+ 0.58 Sat Nov 29 09:18:45 2014 +0000 - add no_index metadata 0.57 Sat Nov 29 07:09:57 2014 +0000 - Fix some language issues in the manual page. 0.56 Fri Nov 21 15:35:10 2014 +0000 - Remove unnecessary imports - Minor XS bug-fix 0.55 Fri Nov 14 14:54:12 2014 +0000 - tests restored from 0.53 0.540 Tue Sep 9 02:55:18 2014 +0100 - Update doc for case-insensitive args to Inline. - Update metadata - git repo, Inline version. 0.53_90 Tue Aug 19 07:32:57 2014 -0400 - Added AUTOSTUDY to PerlInterpreter - Applied patch by Max Vohlen to fix JNI bug - Applied patch by Charles Brabec to allow wildcards in CLASSPATH 0.53 Sun Jan 9 08:15:06 EST 2011 - Removed PerlNatives extension from the build because it is unmaintained and broken. It can still be enabled manually using the BUILD_PERL_NATIVES build configuration option. - Improved automatic casting. - Fix with get_source_dir() using the DEBUGGER option. Thanks to Paul Frantz for the fix. - Other minor bug and doc fixes. 0.52 Sun Dec 17 20:46:51 EST 2006 - Fixed JNI on cygwin (many thanks to Eric Rybski for the patch) - Improved installation. 'make java' is now performed automatically. - Fixed problems with disappearing exceptions by localizing $@. - Other minor bug fixes 0.51 Tue May 23 20:40:07 EDT 2006 - Several major speed optimizations. - Introduction of support for I/O mapping between Perl and Java (Inline::Java::Handle) - Applied patches by Andrew Bruno and Tim Bunce for MAC OSX - JNI fix for system property passing (thanks to Brian Gugliemetti and Jason Stelzer) - Added NATIVE_DOUBLES configuration option to avoid loss of precision when passing double values between Perl and Java - New interface for processing callbacks from java to perl. - Added support for java.lang.CharSequence as a primitive type. Any Perl scalar passed as a java.lang.CharSequence will instantiate a java.lang.String on the Java side - Added BUILD_JNI, BUILD_PERL_NATIVES, BUILD_PERL_INTERPRETER and JVM_LIB_TYPE build configuration options to help with automated builds - Added BIND configuration option. See docs for details. Note: The Java JVM server noe listens on localhost by default (instead of 0.0.0.0). - Other minor bug fixes 0.50 Mon Jan 31 20:14:43 EST 2005 - Added HOST configuration option to access JVM server remotely - Fixed bug with paths in Cygwin - Fixed bug with regexp that was badly interpreted under the debugger - Extended InlineJavaClassLoader from current thread ClassLoader to enable it to work properly under Tomcat - Include patch by Ihab Awad that allows running the JVM server inside Tomcat - Fixed bug with longs over 32 bits in length and loosened boundary checking in numeric values since it was not portable - Fixed bug (found by Dean Thayer) with socket not closed properly in Java - Other minor bug fixes 0.49 - Added PerlInterpreter: require/eval Perl code directly from Java - Reworked type casting: changes are NOT backwards compatible :( - Callbacks can now be called in list context using "@function_name" - Renamed PerlNatives stuff - Added external command line tool to start/stop a SHARED_JVM server - Applied JNI memory leak patch by Jeff Janes - Removed exports from Inline::Java::Portable - Split and updated documentation 0.47 Sat Feb 14 10:00:00 EST 2004 - Fixed bugs in portability code and added HPUX, AIX and Solaris specifics - Tweaked CLASSPATH directory order - Changed port numbers for SHARED_JVM tests in order to avoid clashes with running installations - Made PerlNatives optional 0.46 Web Feb 04 20:00:00 EST 2004 - Fixed Natives.xs to work with ExtUtils::ParseXS 0.45 Fri Jan 30 20:00:00 EST 2004 - Fixed Makefile.PL arguments that were getting lost - Fixed deprecated require call - Fixed support for symbolic links in J2SDK directory - Basic support for J2SDK 1.5 - Added new experimental feature: PerlNatives 0.44 Sun Nov 23 15:47:06 EST 2003 - Callbacks from multiple threads are now supported - Refactored (again...) studying/.jdat/cache stuff - Added PRIVATE mode for use with SHARED_JVM - Added DEBUGGER mode that launches jdb - Fixed memory leak in JNI code (patch submitted by Dave Blob) 0.43 Tue Oct 14 13:18:25 EDT 2003 - Restored $VERSION in each .pm file - Inline::Java now formerly requires Perl 5.6 0.42 Fri Sep 5 13:18:25 EDT 2003 - Fixed more CLASSPATH issues. CLASSPATH now works like this: * CLASSPATH environment variable is global * CLASSPATH configuration option is local to the user class loader - Added method cache to increase performance and decrease reflection API calls - Altered and documented the study_classes() function - Added EXTRA_JAVA_ARGS and EXTRA_JAVAC_ARGS config options 0.41 Mon Jul 14 13:18:25 EDT 2003 - Fixed CLASSPATH bug - Possibly (!) fixed test suite problems under heavy load 0.40 Fri Apr 11 11:00:00 EST 2003 - Patch by Doug MacEachern to allow running under servlet engines. - Patch by John Kinsley for handling empty arrays. - Custom ClassLoader allows for better isolation of user code and dynamic 'CLASSPATH' (multiple sections/clients are now totally independant). - Core Java code is now compiled separately (at install time) instead of with the user code (for each script). This dramatically improves build time. - Default port number changed to 0 (next available port number). This allows many multiple users to run concurrently without clashes. Note: The default port on systems where this feature is not available has remained 7890. Note: The default port for SHARED_JVM mode is now 7891. - SHARED_JVM mode now calls release_JVM() automatically. - UTF8 support - User code can now be a public class and (optionally) inside a package. - Callback classes have changed. Note: These classes are now in the org.perl.inline.java package. Note: PerlException has been renamed InlineJavaPerlException. Note: If you presently use callbacks, your code may now no longer compile. You will need to apply the changes listed above to fix it. - study_classes now returns the package in which the studied classes have been put. - Many bug fixes and documentation corrections. 0.33 Mon Jun 17 13:50:14 EDT 2002 - Improved and more flexible debug output - Auto loading of thread libraries under Solaris - Basic support for J2SDK 1.4 - Other minor bug fixes 0.32 Sat Apr 6 11:45:06 EST 2002 - Restored compatibility with perl 5.005_03 - Other minor bug fixes 0.31 Mon Feb 4 15:45:06 EDT 2002 - Exception handling (Perl can 'catch' Java exceptions) - Callbacks to Perl from Java - More complete test suite - Improved documentation and related examples - Improved installation script and directions - Other minor bug fixes 0.30 Mon Sep 17 15:45:06 EDT 2001 - JVM server is now multi-threaded - Added 'SHARED_JVM' option for mod_perl support - Beefed up test suite 0.23 Thu Aug 30 08:41:11 EDT 2001 - Added support for multiple Inline sections using a special notation in the CLASSPATH. - Added the 'fix' Makefile.PL option au automatically fix the Makefile for Win95/98/Me. 0.22 Fri Jun 1 13:31:35 EDT 2001 - Fixed up Inline::Java to work with Inline 0.41 - Added support for java.lang.Number as a primitive numeric type. Any Perl scalar passed as a java.lang.Number will instantiate a java.lang.Double on the Java side. 0.21 Tue May 8 11:32:28 EDT 2001 - Added 'studying' of external Java classes - Added support for default no-arg constructors for public classes - Caching for class information - Added error message stating that Inline::Java doesn't currently support multiple sections 0.20 Sat Apr 14 23:00:00 EDT 2001 - Added optional JNI extension. - Added support for arrays. - Added support for public member variables. - Added support for public static member variables. - Added type casting. 0.01 Thu Feb 15 14:01:25 EST 2001 - Created Inline::Java. Inline-Java-0.67/META.yml0000644000175000017500000000130214202042236014731 0ustar osboxesosboxes--- abstract: 'Write Perl classes in Java.' author: - 'Patrick LeBoutillier ' build_requires: ExtUtils::MakeMaker: '7.30' configure_requires: ExtUtils::MakeMaker: '7.30' File::Which: '0' dynamic_config: 1 generated_by: 'ExtUtils::MakeMaker version 7.44, CPAN::Meta::Converter version 2.150010' license: artistic_2 meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Inline-Java no_index: directory: - t - inc requires: Inline: '0.68' MIME::Base64: '0' Test: '1.13' perl: '5.008' resources: repository: https://github.com/ingydotnet/Inline-Java version: '0.67' x_serialization_backend: 'CPAN::Meta::YAML version 0.018' Inline-Java-0.67/Java/0000755000175000017500000000000014202042236014345 5ustar osboxesosboxesInline-Java-0.67/Java/PerlInterpreter/0000755000175000017500000000000014202042236017473 5ustar osboxesosboxesInline-Java-0.67/Java/PerlInterpreter/PerlInterpreter.pm0000644000175000017500000000040514202030173023153 0ustar osboxesosboxespackage Inline::Java::PerlInterpreter ; use strict ; use Inline::Java ; $Inline::Java::PerlInterpreter::VERSION = '0.52' ; use Inline ( Java => 'STUDY', STUDY => [], AUTOSTUDY => 1, EMBEDDED_JNI => 1, NAME => 'Inline::Java::PerlInterpreter', ) ; 1 ; Inline-Java-0.67/Java/PerlInterpreter/PerlInterpreter.pod0000644000175000017500000000566514202030173023336 0ustar osboxesosboxes=head1 NAME Inline::Java::PerlInterpreter - Call Perl directly from Java using Inline::Java. =head1 SYNOPSIS =for comment import org.perl.inline.java.* ; class HelpMePerl { static private InlineJavaPerlInterpreter pi = null ; public HelpMePerl() throws InlineJavaException { } static private boolean matches(String target, String pattern) throws InlineJavaPerlException, InlineJavaException { Boolean b = (Boolean)pi.eval("'" + target + "' =~ /" + pattern + "/", Boolean.class) ; return b.booleanValue() ; } public static void main(String args[]) throws InlineJavaPerlException, InlineJavaException { pi = InlineJavaPerlInterpreter.create() ; String target = "aaabbbccc" ; String pattern = "ab+" ; boolean ret = matches(target, pattern) ; System.out.println( target + (ret ? " matches " : " doesn't match ") + pattern) ; pi.destroy() ; } } =for comment =head1 DESCRIPTION WARNING: C is still experimental. The C Java class allows you to load a Perl interpreter directly from Java. You can then perform regular callbacks to call into Perl. Z<> =head1 USING THE org.perl.inline.java.InlineJavaPerlInterpreter CLASS B Before using C, you must have installed C as well as the JNI extension. Additionally, the PerlInterpreter extension must also have been installed. B To be able to use the C class, you must use the jar file provided by C. You can easily locate this jar file using the following command: % perl -MInline::Java=jar You must then add this jar file to your CLASSPATH as you would any jar file. B C itself extends C. See L for information on the callback API. Besides that API, C provides only 2 other public methods: =over 4 =item public InlineJavaPerlInterpreter create() throws InlineJavaPerlException, InlineJavaException Creates a new org.perl.inline.java.InlineJavaPerlInterpreter object. This class in a singleton. =item public void destroy() Destroys the Perl interpreter. =back =head1 SEE ALSO L, L, L. Z<> =head1 AUTHOR Patrick LeBoutillier is the author of Inline::Java. Z<> =head1 COPYRIGHT Copyright (c) 2001-2004, Patrick LeBoutillier. All Rights Reserved. This module is free software. It may be used, redistributed and/or modified under the terms of the Perl Artistic License. See http://www.perl.com/perl/misc/Artistic.html for more details. =cut Inline-Java-0.67/Java/PerlInterpreter/t/0000755000175000017500000000000014202042236017736 5ustar osboxesosboxesInline-Java-0.67/Java/PerlInterpreter/t/Tests.pl0000644000175000017500000000033314202030173021371 0ustar osboxesosboxespackage main ; use strict ; sub whats_your_name { return "perl" ; } sub sum_array_list { my $a = shift ; my $sum = 0 ; for (my $i = 0 ; $i < $a->size() ; $i++){ $sum += $a->get($i) ; } return $sum ; } 1 ; Inline-Java-0.67/Java/PerlInterpreter/t/02_perl_interpreter.t0000644000175000017500000000705514202030173024015 0ustar osboxesosboxesuse strict ; use Test ; use File::Spec ; use Config ; BEGIN { if ($^O eq 'cygwin'){ # Stand-alone Java interpreter cannot load Cygwin DLL directly plan(tests => 0) ; exit ; } plan(tests => 13) ; } use Inline ( Java => 'DATA', NAME => 'Tests' ) ; use Inline::Java::Portable ; ok(1) ; my $inline = $org::perl::inline::java::InlineJavaPerlInterpreterTests::INLINE ; $inline = $org::perl::inline::java::InlineJavaPerlInterpreterTests::INLINE ; # stupid warning... my $install_dir = File::Spec->catdir($inline->get_api('install_lib'), 'auto', $inline->get_api('modpname')) ; require Inline::Java->find_default_j2sdk() ; my $server_jar = Inline::Java::Portable::get_server_jar() ; run_java($install_dir, $server_jar) ; ################################################# sub run_java { my @cps = @_ ; $ENV{CLASSPATH} = Inline::Java::Portable::make_classpath(@cps) ; Inline::Java::debug(1, "CLASSPATH is $ENV{CLASSPATH}\n") ; my $java = File::Spec->catfile( Inline::Java::get_default_j2sdk(), Inline::Java::Portable::portable("J2SDK_BIN"), 'java' . Inline::Java::Portable::portable("EXE_EXTENSION")) ; my $debug = $ENV{PERL_INLINE_JAVA_DEBUG} || 0 ; my $cmd = Inline::Java::Portable::portable("SUB_FIX_CMD_QUOTES", "\"$java\" " . "org.perl.inline.java.InlineJavaPerlInterpreterTests $debug") ; Inline::Java::debug(1, "Command is $cmd\n") ; open(CMD, "$cmd|") or die("Can't execute $cmd: $!") ; while (){ print $_ ; } } __END__ __Java__ package org.perl.inline.java ; import java.util.* ; class InlineJavaPerlInterpreterTests implements Runnable { private static int cnt = 2 ; private static InlineJavaPerlInterpreter pi = null ; private static int nb_callbacks_to_run = 5 ; private static int nb_callbacks_run = 0 ; private InlineJavaPerlInterpreterTests() throws InlineJavaException, InlineJavaPerlException { } private synchronized static void ok(Object o1, Object o2){ if (o1.equals(o2)){ String comment = " # " + o1 + " == " + o2 ; System.out.println("ok " + cnt + comment) ; } else { String comment = " # " + o1 + " != " + o2 ; System.out.println("nok " + cnt + comment) ; } cnt++ ; } public void run(){ try { String name = (String)pi.CallPerlSub("whats_your_name", null, String.class) ; ok(name, "perl") ; nb_callbacks_run++ ; if (nb_callbacks_run == nb_callbacks_to_run){ pi.StopCallbackLoop() ; } } catch (Exception e){ e.printStackTrace() ; System.exit(1) ; } } public static void main(String args[]){ try { int debug = 0 ; if (args.length > 0){ debug = Integer.parseInt(args[0]) ; InlineJavaUtils.set_debug(debug) ; } InlineJavaPerlInterpreter.init("test") ; pi = InlineJavaPerlInterpreter.create() ; pi.require("t/Tests.pl") ; ok("1", "1") ; pi.require("Carp") ; ok("1", "1") ; Integer sum = (Integer)pi.eval("34 + 56", Integer.class) ; ok(sum, Integer.valueOf(90)) ; String name = (String)pi.CallPerlSub("whats_your_name", null, String.class) ; ok(name, "perl") ; for (int i = 1 ; i <= nb_callbacks_to_run ; i++){ Thread t = new Thread(new InlineJavaPerlInterpreterTests()) ; t.start() ; } pi.StartCallbackLoop(); ArrayList a = new ArrayList<>() ; for (int i = 0 ; i < 100 ; i++){ a.add(Integer.valueOf(i * 2)) ; } sum = (Integer)pi.CallPerlSub("sum_array_list", new Object [] {a}, Integer.class) ; ok(sum, Integer.valueOf(9900)) ; pi.destroy() ; ok("1", "1") ; } catch (Exception e){ e.printStackTrace() ; System.exit(1) ; } ok("1", "1") ; } } Inline-Java-0.67/Java/PerlInterpreter/PerlInterpreter.xs0000644000175000017500000000421714202030173023176 0ustar osboxesosboxes#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #ifdef __CYGWIN__ #include "w32api/basetyps.h" #endif /* Include the JNI header file */ #include "jni.h" /* The PerlInterpreter handle */ PerlInterpreter *interp = NULL ; /* XS initialisation stuff */ void boot_DynaLoader(pTHX_ CV* cv) ; static void xs_init(pTHX){ char *file = __FILE__ ; dXSUB_SYS ; newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file) ; } void throw_ijp(JNIEnv *env, char *msg){ jclass ije ; ije = (*(env))->FindClass(env, "org/perl/inline/java/InlineJavaPerlException") ; if ((*(env))->ExceptionCheck(env)){ (*(env))->ExceptionDescribe(env) ; (*(env))->ExceptionClear(env) ; (*(env))->FatalError(env, "Can't find class InlineJavaPerlException: exiting...") ; } (*(env))->ThrowNew(env, ije, msg) ; } JNIEXPORT void JNICALL Java_org_perl_inline_java_InlineJavaPerlInterpreter_construct(JNIEnv *env, jclass cls){ char *args[] = {"inline-java", "-e1"} ; char **envdup = NULL ; #ifdef PERL_PARSE_ENV_DUP int envl = 0 ; int i = 0 ; /* This will leak, but it's a one shot... */ for (i = 0 ; environ[i] != NULL ; i++){ envl++ ; } envdup = (char **)calloc(envl + 1, sizeof(char *)) ; for (i = 0 ; i < envl ; i++){ envdup[i] = strdup(environ[i]) ; } #endif interp = perl_alloc() ; perl_construct(interp) ; perl_parse(interp, xs_init, 2, args, envdup) ; perl_run(interp) ; } JNIEXPORT void JNICALL Java_org_perl_inline_java_InlineJavaPerlInterpreter_destruct(JNIEnv *env, jclass cls){ if (interp != NULL){ perl_destruct(interp) ; perl_free(interp) ; interp = NULL ; } } JNIEXPORT void JNICALL Java_org_perl_inline_java_InlineJavaPerlInterpreter_evalNoReturn(JNIEnv *env, jclass cls, jstring code){ SV *sv = NULL ; char *pcode = NULL ; pcode = (char *)((*(env))->GetStringUTFChars(env, code, NULL)) ; sv = sv_2mortal(newSVpv(pcode, 0)) ; /* sv = eval_pv(pcode, FALSE) ; */ eval_sv(sv, G_EVAL|G_KEEPERR) ; (*(env))->ReleaseStringUTFChars(env, code, pcode) ; if (SvTRUE(ERRSV)){ STRLEN n_a ; throw_ijp(env, SvPV(ERRSV, n_a)) ; } } MODULE = Inline::Java::PerlInterpreter PACKAGE = Inline::Java::PerlInterpreter PROTOTYPES: DISABLE Inline-Java-0.67/Java/PerlInterpreter/Makefile.PL0000644000175000017500000000132214202030173021440 0ustar osboxesosboxesuse ExtUtils::MakeMaker ; use ExtUtils::Embed ; use Config ; use strict ; require "../../lib/Inline/Java/Portable.pm" ; my $ccopts = ccopts() ; chomp($ccopts) ; my $ldopts = ldopts() ; chomp($ldopts) ; my $pre = Inline::Java::Portable::portable("PRE_WHOLE_ARCHIVE") ; my $post = Inline::Java::Portable::portable("POST_WHOLE_ARCHIVE") ; my $dupenv = Inline::Java::Portable::portable("PERL_PARSE_DUP_ENV") ; WriteMakefile( NAME => 'Inline::Java::PerlInterpreter', VERSION_FROM => 'PerlInterpreter.pm', CCFLAGS => "$ccopts $dupenv", LDDLFLAGS => "$pre $ldopts $post $Config{lddlflags}", INC => join(' ', @main::I), dynamic_lib => Inline::Java::Portable::portable("dynamic_lib"), # CCFLAGS => '-D_REENTRANT', ) ; Inline-Java-0.67/Java/typemap0000644000175000017500000000052214202030173015743 0ustar osboxesosboxesTYPEMAP InlineJavaJNIVM * T_PTROBJ_IJVM OUTPUT T_PTROBJ_IJVM sv_setref_pv($arg, \"Inline::Java::JNI\", (void *)$var) ; INPUT T_PTROBJ_IJVM if (sv_derived_from($arg, \"Inline::Java::JNI\")) { $var = ($type)SvIV((SV*)SvRV($arg)) ; } else{ if (SvOK($arg)){ croak(\"$var is not of type Inline::Java::JNI\") ; } } Inline-Java-0.67/Java/PerlNatives/0000755000175000017500000000000014202042236016601 5ustar osboxesosboxesInline-Java-0.67/Java/PerlNatives/PerlNatives.pod0000644000175000017500000000674414202030173021551 0ustar osboxesosboxes=head1 NAME Inline::Java::PerlNatives - Map Java native methods to Perl functions. =head1 SYNOPSIS =for comment use Inline Java => <<'END' ; import org.perl.inline.java.* ; class Pod_PN extends InlineJavaPerlNatives { public Pod_PN() throws InlineJavaException { } native public String hello() ; } END package Pod_PN ; sub hello { return "hi!" ; } package main ; my $b = new Pod_PN() ; print($b->hello() . "\n") ; # prints hi! =for comment =head1 DESCRIPTION WARNING: C is still experimental. C allows you to define your callbacks as native Java methods that are automatically linked to Perl subroutines. You implement the Perl subroutine directly in the package in which C binds your class. You can do this by making your Java code extend the C class. Note: PerlNatives requires J2SDK version >= 1.4 Z<> =head1 USING THE org.perl.inline.java.InlineJavaPerlNatives CLASS Let's revisit an example from the L documentation: =for comment use Inline Java => <<'END' ; import java.util.* ; import org.perl.inline.java.* ; import javax.swing.* ; import java.awt.event.* ; class Pod_Button_PN extends InlineJavaPerlNatives implements ActionListener { public Pod_Button_PN() throws InlineJavaException { JFrame frame = new JFrame("Pod_Button") ; frame.setSize(100,100) ; JButton button = new JButton("Click Me!") ; frame.getContentPane().add(button) ; button.addActionListener(this) ; frame.show() ; } public void actionPerformed(ActionEvent e){ button_pressed() ; } native public void button_pressed() ; } END package Pod_Button_PN ; sub button_pressed { print('click!' . "\n") ; # prints click! $main::b->StopCallbackLoop() ; } package main ; $main::b = new Pod_Button_PN() ; $main::b->StartCallbackLoop() ; =for comment Extending InlineJavaPerlNatives tells C that all native methods declared in that class should be linked to Perl subroutines implemented in the approriate package. You can then call these methods from Java just like regular methods. You can even call them from Perl if they are public. Z<> =head1 BUGS AND DEFICIENCIES C has a few limits that one must be aware of: =over 4 =item 1 You cannot declare 2 native methods with the same name in a class (even if they have different signatures). =item 2 Native methods can have arguments of any type, but they must return either void or an Object (use wrappers like Integer and Double to return primitive types). =item 3 Even if you do not declare them, InlineJavaException and InlineJavaPerlException exceptions (as well as others) may be thrown from within the native methods =back =head1 SEE ALSO L, L, L. Z<> =head1 AUTHOR Patrick LeBoutillier is the author of Inline::Java. Z<> =head1 COPYRIGHT Copyright (c) 2001-2004, Patrick LeBoutillier. All Rights Reserved. This module is free software. It may be used, redistributed and/or modified under the terms of the Perl Artistic License. See http://www.perl.com/perl/misc/Artistic.html for more details. =cut Inline-Java-0.67/Java/PerlNatives/t/0000755000175000017500000000000014202042236017044 5ustar osboxesosboxesInline-Java-0.67/Java/PerlNatives/t/02_perl_natives.t0000644000175000017500000000355514202030173022232 0ustar osboxesosboxesuse strict ; use Test ; BEGIN { plan(tests => 5) ; } use Inline::Java qw(caught) ; use Inline ( Java => 'DATA', ) ; eval { t121->init() ; my $t = new t121() ; ok($t->types_stub(1, 2, 3, 4, 5, 6, 1, 2, "1000"), 1024) ; ok($t->array_stub([34, 56], ["toto", "789"]), 789 + 34) ; my $t2 = new t1212() ; ok($t2->types_stub(1, 2, 3, 4, 5, 6, 1, 2, "1000"), 1024) ; ok($t->callback_stub(), "toto") ; ok($t->__get_private()->{proto}->ObjectCount(), 2) ; } ; if ($@){ if (caught("java.lang.Throwable")){ $@->printStackTrace() ; die("Caught Java Exception") ; } else{ die $@ ; } } ################################## package t121 ; sub types { my $this = shift ; my $sum = 0 ; map {$sum += $_} @_ ; return $sum ; } sub array { my $this = shift ; my $i = shift ; my $str = shift ; return $i->[0] + $str->[1] ; } sub callback { my $this = shift ; return $this->get_name() ; } package main ; __DATA__ __Java__ import org.perl.inline.java.* ; class t121 extends InlineJavaPerlNatives { static public boolean got14(){ return System.getProperty("java.version").startsWith("1.4") ; } public t121() throws InlineJavaException { } static public void init() throws InlineJavaException { init("test") ; } public String types_stub(byte b, short s, int i, long j, float f, double d, boolean x, char c, String str){ return types(b, s, i, j, f, d, x, c, str) ; } public native String types(byte b, short s, int i, long j, float f, double d, boolean x, char c, String str) ; public String array_stub(int i[], String str[]){ return array(i, str) ; } private native String array(int i[], String str[]) ; public String callback_stub(){ return callback() ; } public native String callback() ; public String get_name(){ return "toto" ; } } ; class t1212 extends t121 { public t1212() throws InlineJavaException { } } ; Inline-Java-0.67/Java/PerlNatives/PerlNatives.xs0000644000175000017500000001276214202030173021416 0ustar osboxesosboxes#include "EXTERN.h" #include "perl.h" #include "XSUB.h" /* #include "stdlib.h" #include "string.h" #include "stdio.h" #include "stdarg.h" */ #ifdef __CYGWIN__ #include "w32api/basetyps.h" #endif /* Include the JNI header file */ #include "jni.h" void throw_ije(JNIEnv *env, char *msg){ jclass ije ; ije = (*(env))->FindClass(env, "org/perl/inline/java/InlineJavaException") ; if ((*(env))->ExceptionCheck(env)){ (*(env))->ExceptionDescribe(env) ; (*(env))->ExceptionClear(env) ; (*(env))->FatalError(env, "Can't find class InlineJavaException: exiting...") ; } (*(env))->ThrowNew(env, ije, msg) ; } /* Here we simply check if an exception is pending an re-throw it */ int check_exception_from_java(JNIEnv *env){ jthrowable exc ; int ret = 0 ; exc = (*(env))->ExceptionOccurred(env) ; if (exc != NULL){ /* (*(env))->ExceptionDescribe(env) ; */ (*(env))->ExceptionClear(env) ; if ((*(env))->Throw(env, exc)){ (*(env))->FatalError(env, "Throw of InlineJava*Exception failed: exiting...") ; } ret = 1 ; } return ret ; } jobject create_primitive_object(JNIEnv *env, char f, char *cls_name, jvalue val){ jclass arg_cls ; jmethodID mid ; jobject ret = NULL ; char sign[64] ; arg_cls = (*(env))->FindClass(env, cls_name) ; if (check_exception_from_java(env)){ return NULL ; } sprintf(sign, "(%c)V", f) ; mid = (*(env))->GetMethodID(env, arg_cls, "", sign) ; if (check_exception_from_java(env)){ return NULL ; } ret = (*(env))->NewObjectA(env, arg_cls, mid, &val) ; if (check_exception_from_java(env)){ return NULL ; } return ret ; } jobject extract_va_arg(JNIEnv *env, va_list *list, char f){ jobject ret = NULL ; jvalue val ; /* A bit of voodoo going on for J and F, but the rest I think is pretty kosher (on a 32 bit machine at least...) */ switch(f){ case 'B': val.b = (jbyte)va_arg(*list, int) ; ret = create_primitive_object(env, f, "java/lang/Byte", val) ; break ; case 'S': val.s = (jshort)va_arg(*list, int) ; ret = create_primitive_object(env, f, "java/lang/Short", val) ; break ; case 'I': val.i = (jint)va_arg(*list, int) ; ret = create_primitive_object(env, f, "java/lang/Integer", val) ; break ; case 'J': val.d = (jdouble)va_arg(*list, double) ; ret = create_primitive_object(env, f, "java/lang/Long", val) ; break ; case 'F': /* Seems float is not properly promoted to double... */ val.i = (jint)va_arg(*list, int) ; ret = create_primitive_object(env, f, "java/lang/Float", val) ; break ; case 'D': val.d = (jdouble)va_arg(*list, double) ; ret = create_primitive_object(env, f, "java/lang/Double", val) ; break ; case 'Z': val.z = (jboolean)va_arg(*list, int) ; ret = create_primitive_object(env, f, "java/lang/Boolean", val) ; break ; case 'C': val.c = (jchar)va_arg(*list, int) ; ret = create_primitive_object(env, f, "java/lang/Character", val) ; break ; } return ret ; } /* This is the generic native function that callback java to call the proper perl method. */ jobject JNICALL generic_perl_native(JNIEnv *env, jobject obj, ...){ va_list list ; jclass cls ; jmethodID mid ; jstring jfmt ; char *fmt ; int fmt_len ; jclass obj_cls ; jobjectArray obj_array ; jobject arg ; int i ; jobject ret = NULL ; cls = (*(env))->GetObjectClass(env, obj) ; mid = (*(env))->GetMethodID(env, cls, "LookupMethod", "()Ljava/lang/String;") ; if (check_exception_from_java(env)){ return NULL ; } /* Call obj.LookupMethod to get the format string */ jfmt = (*(env))->CallObjectMethod(env, obj, mid) ; if (check_exception_from_java(env)){ return NULL ; } fmt = (char *)((*(env))->GetStringUTFChars(env, jfmt, NULL)) ; fmt_len = strlen(fmt) ; obj_cls = (*(env))->FindClass(env, "java/lang/Object") ; if (check_exception_from_java(env)){ return NULL ; } obj_array = (*(env))->NewObjectArray(env, fmt_len, obj_cls, NULL) ; if (check_exception_from_java(env)){ return NULL ; } (*(env))->SetObjectArrayElement(env, obj_array, 0, obj) ; if (check_exception_from_java(env)){ return NULL ; } va_start(list, obj) ; for (i = 1 ; i < fmt_len ; i++){ if (fmt[i] != 'L'){ arg = extract_va_arg(env, &list, fmt[i]) ; if (arg == NULL){ return NULL ; } } else{ arg = (jobject)va_arg(list, jobject) ; } (*(env))->SetObjectArrayElement(env, obj_array, i, arg) ; if (check_exception_from_java(env)){ return NULL ; } } va_end(list) ; /* Call obj.InvokePerlMethod and grab the returned object and return it */ mid = (*(env))->GetMethodID(env, cls, "InvokePerlMethod", "([Ljava/lang/Object;)Ljava/lang/Object;") ; if (check_exception_from_java(env)){ return NULL ; } ret = (*(env))->CallObjectMethod(env, obj, mid, obj_array) ; if (check_exception_from_java(env)){ return NULL ; } return ret ; } /* This function is used to register the specified native method and associate it with our magic method that trap and redirects all the Perl native calls. */ JNIEXPORT void JNICALL Java_org_perl_inline_java_InlineJavaPerlNatives_RegisterMethod(JNIEnv *env, jobject obj, jclass cls, jstring name, jstring signature){ JNINativeMethod nm ; /* Register the function */ nm.name = (char *)((*(env))->GetStringUTFChars(env, name, NULL)) ; nm.signature = (char *)((*(env))->GetStringUTFChars(env, signature, NULL)) ; nm.fnPtr = generic_perl_native ; (*(env))->RegisterNatives(env, cls, &nm, 1) ; (*(env))->ReleaseStringUTFChars(env, name, nm.name) ; (*(env))->ReleaseStringUTFChars(env, signature, nm.signature) ; if (check_exception_from_java(env)){ return ; } } Inline-Java-0.67/Java/PerlNatives/Makefile.PL0000644000175000017500000000053314202030173020551 0ustar osboxesosboxesuse ExtUtils::MakeMaker ; use strict ; require "../../lib/Inline/Java/Portable.pm" ; WriteMakefile( NAME => 'Inline::Java::PerlNatives', VERSION_FROM => 'PerlNatives.pm', INC => join(' ', @main::I), LIBS => [join(' ', @main::L) . " -ljvm"], dynamic_lib => Inline::Java::Portable::portable("dynamic_lib"), # CCFLAGS => '-D_REENTRANT', ) ; Inline-Java-0.67/Java/PerlNatives/PerlNatives.pm0000644000175000017500000000014714202030173021372 0ustar osboxesosboxespackage Inline::Java::PerlNatives ; use strict ; $Inline::Java::PerlNatives::VERSION = '0.52' ; 1 ; Inline-Java-0.67/Java/sources/0000755000175000017500000000000014202042236016030 5ustar osboxesosboxesInline-Java-0.67/Java/sources/org/0000755000175000017500000000000014202042236016617 5ustar osboxesosboxesInline-Java-0.67/Java/sources/org/perl/0000755000175000017500000000000014202042236017561 5ustar osboxesosboxesInline-Java-0.67/Java/sources/org/perl/inline/0000755000175000017500000000000014202042236021037 5ustar osboxesosboxesInline-Java-0.67/Java/sources/org/perl/inline/java/0000755000175000017500000000000014202042236021760 5ustar osboxesosboxesInline-Java-0.67/Java/sources/org/perl/inline/java/InlineJavaArray.java0000644000175000017500000000543614202030173025647 0ustar osboxesosboxespackage org.perl.inline.java ; import java.util.* ; import java.lang.reflect.Array ; class InlineJavaArray { private InlineJavaClass ijc ; InlineJavaArray(InlineJavaClass _ijc){ ijc = _ijc ; } Object CreateArray(Class c, StringTokenizer st) throws InlineJavaException { StringBuffer sb = new StringBuffer(st.nextToken()) ; sb.replace(0, 1, "") ; sb.replace(sb.length() - 1, sb.length(), "") ; StringTokenizer st2 = new StringTokenizer(sb.toString(), ",") ; ArrayList al = new ArrayList<>() ; while (st2.hasMoreTokens()){ al.add(al.size(), st2.nextToken()) ; } int size = al.size() ; int dims[] = new int[size] ; for (int i = 0 ; i < size ; i++){ dims[i] = Integer.parseInt((String)al.get(i)) ; InlineJavaUtils.debug(4, "array dimension: " + (String)al.get(i)) ; } Object array = null ; try { array = Array.newInstance(c, dims) ; ArrayList args = new ArrayList<>() ; while (st.hasMoreTokens()){ args.add(args.size(), st.nextToken()) ; } // Now we need to fill it. Since we have an arbitrary number // of dimensions, we can do this recursively. PopulateArray(array, c, dims, args) ; } catch (IllegalArgumentException e){ throw new InlineJavaException("Arguments to array constructor for class " + c.getName() + " are incompatible: " + e.getMessage()) ; } return array ; } void PopulateArray (Object array, Class elem, int dims[], ArrayList args) throws InlineJavaException { if (dims.length > 1){ int nb_args = args.size() ; int nb_sub_dims = dims[0] ; int nb_args_per_sub_dim = nb_args / nb_sub_dims ; int sub_dims[] = new int[dims.length - 1] ; for (int i = 1 ; i < dims.length ; i++){ sub_dims[i - 1] = dims[i] ; } for (int i = 0 ; i < nb_sub_dims ; i++){ // We want the args from i*nb_args_per_sub_dim -> ArrayList sub_args = new ArrayList<>() ; for (int j = (i * nb_args_per_sub_dim) ; j < ((i + 1) * nb_args_per_sub_dim) ; j++){ sub_args.add(sub_args.size(), (String)args.get(j)) ; } PopulateArray(((Object [])array)[i], elem, sub_dims, sub_args) ; } } else{ String msg = "In creation of array of " + elem.getName() + ": " ; try { for (int i = 0 ; i < dims[0] ; i++){ String arg = (String)args.get(i) ; Object o = ijc.CastArgument(elem, arg) ; Array.set(array, i, o) ; if (o != null){ InlineJavaUtils.debug(4, "setting array element " + String.valueOf(i) + " to " + o.toString()) ; } else{ InlineJavaUtils.debug(4, "setting array element " + String.valueOf(i) + " to " + o) ; } } } catch (InlineJavaCastException e){ throw new InlineJavaCastException(msg + e.getMessage()) ; } catch (InlineJavaException e){ throw new InlineJavaException(msg + e.getMessage()) ; } } } } Inline-Java-0.67/Java/sources/org/perl/inline/java/InlineJavaPerlCaller.java0000644000175000017500000001657214202030173026621 0ustar osboxesosboxespackage org.perl.inline.java ; import java.util.* ; import java.io.* ; /* Callback to Perl... */ public class InlineJavaPerlCaller { private InlineJavaServer ijs = InlineJavaServer.GetInstance() ; private Thread creator = null ; static private Map thread_callback_queues = Collections.synchronizedMap(new HashMap()) ; static private ResourceBundle resources = null ; static private boolean inited = false ; /* Only thread that communicate with Perl are allowed to create PerlCallers because this is where we get the thread that needs to be notified when the callbacks come in. */ public InlineJavaPerlCaller() throws InlineJavaException { init() ; Thread t = Thread.currentThread() ; if (ijs.IsThreadPerlContact(t)){ creator = t ; } else{ throw new InlineJavaException("InlineJavaPerlCaller objects can only be created by threads that communicate directly with Perl") ; } } synchronized static protected void init() throws InlineJavaException { if (! inited){ try { resources = ResourceBundle.getBundle("InlineJava") ; inited = true ; } catch (MissingResourceException mre){ throw new InlineJavaException("Error loading InlineJava.properties: " + mre.getMessage()) ; } } } static protected ResourceBundle GetBundle(){ return resources ; } /* New interface */ public Object CallPerlSub(String sub, Object args[]) throws InlineJavaException, InlineJavaPerlException { return CallPerlSub(sub, args, null) ; } /* New interface */ public Object CallPerlSub(String sub, Object args[], Class cast) throws InlineJavaException, InlineJavaPerlException { InlineJavaCallback ijc = new InlineJavaCallback( (String)null, sub, args, cast) ; return CallPerl(ijc) ; } /* New interface */ public Object CallPerlMethod(InlineJavaPerlObject obj, String method, Object args[]) throws InlineJavaException, InlineJavaPerlException { return CallPerlMethod(obj, method, args, null) ; } /* New interface */ public Object CallPerlMethod(InlineJavaPerlObject obj, String method, Object args[], Class cast) throws InlineJavaException, InlineJavaPerlException { InlineJavaCallback ijc = new InlineJavaCallback( obj, method, args, cast) ; return CallPerl(ijc) ; } /* New interface */ public Object CallPerlStaticMethod(String pkg, String method, Object args[]) throws InlineJavaException, InlineJavaPerlException { return CallPerlStaticMethod(pkg, method, args, null) ; } /* New interface */ public Object CallPerlStaticMethod(String pkg, String method, Object args[], Class cast) throws InlineJavaException, InlineJavaPerlException { InlineJavaCallback ijc = new InlineJavaCallback( pkg, method, args, cast) ; return CallPerl(ijc) ; } public Object eval(String code) throws InlineJavaPerlException, InlineJavaException { return eval(code, null) ; } public Object eval(String code, Class cast) throws InlineJavaPerlException, InlineJavaException { return CallPerlSub("Inline::Java::Callback::java_eval", new Object [] {code}, cast) ; } public Object require(String module_or_file) throws InlineJavaPerlException, InlineJavaException { return CallPerlSub("Inline::Java::Callback::java_require", new Object [] {module_or_file}) ; } public Object require_file(String file) throws InlineJavaPerlException, InlineJavaException { return CallPerlSub("Inline::Java::Callback::java_require", new Object [] {file, Boolean.TRUE}) ; } public Object require_module(String module) throws InlineJavaPerlException, InlineJavaException { return CallPerlSub("Inline::Java::Callback::java_require", new Object [] {module, Boolean.FALSE}) ; } private Object CallPerl(InlineJavaCallback ijc) throws InlineJavaException, InlineJavaPerlException { Thread t = Thread.currentThread() ; if (t == creator){ ijc.Process() ; return ijc.GetResponse() ; } else { // Enqueue the callback into the creator thread's queue and notify it // that there is some work for him. ijc.ClearResponse() ; InlineJavaCallbackQueue q = GetQueue(creator) ; InlineJavaUtils.debug(3, "enqueing callback for processing for " + creator.getName() + " in " + t.getName() + "...") ; q.EnqueueCallback(ijc) ; InlineJavaUtils.debug(3, "notifying that a callback request is available for " + creator.getName() + " in " + t.getName()) ; // Now we must wait until the callback is processed and get back the result... return ijc.WaitForResponse(t) ; } } public void OpenCallbackStream() throws InlineJavaException { Thread t = Thread.currentThread() ; if (! ijs.IsThreadPerlContact(t)){ throw new InlineJavaException("InlineJavaPerlCaller.OpenCallbackStream() can only be called by threads that communicate directly with Perl") ; } InlineJavaCallbackQueue q = GetQueue(t) ; q.OpenCallbackStream() ; } /* Blocks until either a callback arrives, timeout seconds has passed or the call is interrupted by Interrupt? */ public int WaitForCallback(double timeout) throws InlineJavaException { Thread t = Thread.currentThread() ; if (! ijs.IsThreadPerlContact(t)){ throw new InlineJavaException("InlineJavaPerlCaller.WaitForCallback() can only be called by threads that communicate directly with Perl") ; } InlineJavaCallbackQueue q = GetQueue(t) ; if (timeout == 0.0){ // no wait return q.GetSize() ; } else if (timeout == -1.0){ timeout = 0.0 ; } return q.WaitForCallback(timeout) ; } public boolean ProcessNextCallback() throws InlineJavaException, InlineJavaPerlException { Thread t = Thread.currentThread() ; if (! ijs.IsThreadPerlContact(t)){ throw new InlineJavaException("InlineJavaPerlCaller.ProcessNextCallback() can only be called by threads that communicate directly with Perl") ; } InlineJavaCallbackQueue q = GetQueue(t) ; return q.ProcessNextCallback() ; } public void CloseCallbackStream() throws InlineJavaException { InlineJavaCallbackQueue q = GetQueue(creator) ; q.CloseCallbackStream() ; } public void StartCallbackLoop() throws InlineJavaException, InlineJavaPerlException { Thread t = Thread.currentThread() ; if (! ijs.IsThreadPerlContact(t)){ throw new InlineJavaException("InlineJavaPerlCaller.StartCallbackLoop() can only be called by threads that communicate directly with Perl") ; } InlineJavaCallbackQueue q = GetQueue(t) ; InlineJavaUtils.debug(3, "starting callback loop for " + creator.getName() + " in " + t.getName()) ; q.OpenCallbackStream() ; while (q.IsStreamOpen()){ q.ProcessNextCallback() ; } } public void StopCallbackLoop() throws InlineJavaException { Thread t = Thread.currentThread() ; InlineJavaCallbackQueue q = GetQueue(creator) ; InlineJavaUtils.debug(3, "stopping callback loop for " + creator.getName() + " in " + t.getName()) ; q.CloseCallbackStream() ; } /* Here the prototype accepts Threads because the JNI thread calls this method also. */ static synchronized void AddThread(Thread t){ thread_callback_queues.put(t, new InlineJavaCallbackQueue()) ; } static synchronized void RemoveThread(InlineJavaServerThread t){ thread_callback_queues.remove(t) ; } static private InlineJavaCallbackQueue GetQueue(Thread t) throws InlineJavaException { InlineJavaCallbackQueue q = (InlineJavaCallbackQueue)thread_callback_queues.get(t) ; if (q == null){ throw new InlineJavaException("Can't find thread " + t.getName() + "!") ; } return q ; } } Inline-Java-0.67/Java/sources/org/perl/inline/java/InlineJavaClass.java0000644000175000017500000003421514202030173025633 0ustar osboxesosboxespackage org.perl.inline.java ; import java.util.* ; import java.lang.reflect.* ; class InlineJavaClass { private InlineJavaServer ijs ; private InlineJavaProtocol ijp ; static private HashMap class2jni_code = new HashMap<>() ; static { class2jni_code.put(byte.class, "B") ; class2jni_code.put(short.class, "S") ; class2jni_code.put(int.class, "I") ; class2jni_code.put(long.class, "J") ; class2jni_code.put(float.class, "F") ; class2jni_code.put(double.class, "D") ; class2jni_code.put(boolean.class, "Z") ; class2jni_code.put(char.class, "C") ; class2jni_code.put(void.class, "V") ; } ; static private HashMap class2wrapper = new HashMap<>() ; static { class2wrapper.put(byte.class, java.lang.Byte.class) ; class2wrapper.put(short.class, java.lang.Short.class) ; class2wrapper.put(int.class, java.lang.Integer.class) ; class2wrapper.put(long.class, java.lang.Long.class) ; class2wrapper.put(float.class, java.lang.Float.class) ; class2wrapper.put(double.class, java.lang.Double.class) ; class2wrapper.put(boolean.class, java.lang.Boolean.class) ; class2wrapper.put(char.class, java.lang.Character.class) ; class2wrapper.put(void.class, java.lang.Void.class) ; } ; static private HashMap name2class = new HashMap<>() ; static { name2class.put("byte", byte.class) ; name2class.put("short", short.class) ; name2class.put("int", int.class) ; name2class.put("long", long.class) ; name2class.put("float", float.class) ; name2class.put("double", double.class) ; name2class.put("boolean", boolean.class) ; name2class.put("char", char.class) ; name2class.put("void", void.class) ; name2class.put("B", byte.class) ; name2class.put("S", short.class) ; name2class.put("I", int.class) ; name2class.put("J", long.class) ; name2class.put("F", float.class) ; name2class.put("D", double.class) ; name2class.put("Z", boolean.class) ; name2class.put("C", char.class) ; name2class.put("V", void.class) ; } ; InlineJavaClass(InlineJavaServer _ijs, InlineJavaProtocol _ijp){ ijs = _ijs ; ijp = _ijp ; } /* Makes sure a class exists */ static Class ValidateClass(String name) throws InlineJavaException { Class pc = FindType(name) ; if (pc != null){ return pc ; } try { Class c = Class.forName(name, true, InlineJavaServer.GetInstance().GetUserClassLoader()) ; return c ; } catch (ClassNotFoundException e){ throw new InlineJavaException("Class " + name + " not found") ; } } /* Remove L...; from a class name if it has been extracted from an Array class name. */ static String CleanClassName(String name){ if (name != null){ int l = name.length() ; if ((l > 2)&&(name.charAt(0) == 'L')&&(name.charAt(l - 1) == ';')){ name = name.substring(1, l - 1) ; } } return name ; } static private Class ValidateClassQuiet(String name){ try { return ValidateClass(name) ; } catch (InlineJavaException ije){ return null ; } } /* This is the monster method that determines how to cast arguments */ 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] ; InlineJavaUtils.debug(4, "arg " + String.valueOf(i) + " of signature is " + p.getName()) ; ret[i] = CastArgument(p, (String)args.get(i)) ; } return ret ; } /* This is the monster method that determines how to cast arguments */ Object CastArgument(Class p, String argument) throws InlineJavaException { Object ret = null ; ArrayList tokens = new ArrayList<>() ; StringTokenizer st = new StringTokenizer(argument, ":") ; 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))){ Class ap = p ; if (ap == java.lang.Number.class){ InlineJavaUtils.debug(4, "specializing java.lang.Number to java.lang.Double") ; ap = java.lang.Double.class ; } else if (ap.getName().equals("java.lang.CharSequence")){ InlineJavaUtils.debug(4, "specializing java.lang.CharSequence to java.lang.String") ; ap = java.lang.String.class ; } if (type.equals("undef")){ if (num){ InlineJavaUtils.debug(4, "args is undef -> forcing to " + ap.getName() + " 0") ; ret = ijp.CreateObject(ap, new Object [] {"0"}, new Class [] {String.class}) ; InlineJavaUtils.debug(4, " result is " + ret.toString()) ; } else{ ret = null ; InlineJavaUtils.debug(4, "args is undef -> forcing to " + ap.getName() + " " + ret) ; InlineJavaUtils.debug(4, " result is " + ret) ; } } else if (type.equals("scalar")){ String arg = ijp.Decode((String)tokens.get(1)) ; InlineJavaUtils.debug(4, "args is scalar (" + arg + ") -> forcing to " + ap.getName()) ; try { ret = ijp.CreateObject(ap, new Object [] {arg}, new Class [] {String.class}) ; InlineJavaUtils.debug(4, " result is " + ret.toString()) ; } catch (NumberFormatException e){ throw new InlineJavaCastException("Can't convert " + arg + " to " + ap.getName()) ; } } else if (type.equals("double")){ String arg = ijp.Decode((String)tokens.get(1)) ; // We have native double bytes in arg. long l = 0 ; char c[] = arg.toCharArray() ; for (int i = 0 ; i < 8 ; i++){ l += (((long)c[i]) << (8 * i)) ; } double d = Double.longBitsToDouble(l) ; ret = Double.valueOf(d) ; } else { throw new InlineJavaCastException("Can't convert reference to " + p.getName()) ; } } else if (ClassIsBool(p)){ if (type.equals("undef")){ InlineJavaUtils.debug(4, "args is undef -> forcing to bool false") ; ret = Boolean.FALSE; InlineJavaUtils.debug(4, " result is " + ret.toString()) ; } else if (type.equals("scalar")){ String arg = ijp.Decode((String)tokens.get(1)) ; InlineJavaUtils.debug(4, "args is scalar (" + arg + ") -> forcing to bool") ; if ((arg.equals(""))||(arg.equals("0"))){ arg = "false" ; } else{ arg = "true" ; } ret = Boolean.valueOf(arg) ; InlineJavaUtils.debug(4, " result is " + ret.toString()) ; } else{ throw new InlineJavaCastException("Can't convert reference to " + p.getName()) ; } } else if (ClassIsChar(p)){ if (type.equals("undef")){ InlineJavaUtils.debug(4, "args is undef -> forcing to char '\0'") ; ret = Character.valueOf('\0') ; InlineJavaUtils.debug(4, " result is " + ret.toString()) ; } else if (type.equals("scalar")){ String arg = ijp.Decode((String)tokens.get(1)) ; InlineJavaUtils.debug(4, "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 " + p.getName()) ; } ret = Character.valueOf(c) ; InlineJavaUtils.debug(4, " result is " + ret.toString()) ; } else{ throw new InlineJavaCastException("Can't convert reference to " + p.getName()) ; } } else { InlineJavaUtils.debug(4, "class " + p.getName() + " is reference") ; // We know that what we expect here is a real object if (type.equals("undef")){ InlineJavaUtils.debug(4, "args is undef -> forcing to null") ; ret = null ; } else if (type.equals("scalar")){ // Here if we need a java.lang.Object.class, it's probably // because we can store anything, so we use a String object. if (p == java.lang.Object.class){ String arg = ijp.Decode((String)tokens.get(1)) ; ret = arg ; } else{ throw new InlineJavaCastException("Can't convert primitive type to " + p.getName()) ; } } else if (type.equals("java_object")){ // We need an object and we got an object... InlineJavaUtils.debug(4, "class " + p.getName() + " is reference") ; String c_name = (String)tokens.get(1) ; String objid = (String)tokens.get(2) ; Class c = ValidateClass(c_name) ; if (DoesExtend(c, p) > -1){ InlineJavaUtils.debug(4, " " + c.getName() + " is a kind of " + p.getName()) ; // get the object from the hash table int id = Integer.parseInt(objid) ; Object o = ijs.GetObject(id) ; ret = o ; } else{ throw new InlineJavaCastException("Can't cast a " + c.getName() + " to a " + p.getName()) ; } } else{ InlineJavaUtils.debug(4, "class " + p.getName() + " is reference") ; String pkg = (String)tokens.get(1) ; pkg = pkg.replace('/', ':') ; String objid = (String)tokens.get(2) ; if (DoesExtend(p, org.perl.inline.java.InlineJavaPerlObject.class) > -1){ InlineJavaUtils.debug(4, " Perl object is a kind of " + p.getName()) ; int id = Integer.parseInt(objid) ; ret = new InlineJavaPerlObject(pkg, id) ; } else{ throw new InlineJavaCastException("Can't cast a Perl object to a " + p.getName()) ; } } } return ret ; } /* Returns the number of levels that separate a from b */ static int DoesExtend(Class a, Class b){ return DoesExtend(a, b, 0) ; } static int DoesExtend(Class a, Class b, int level){ InlineJavaUtils.debug(4, "checking if " + a.getName() + " extends " + b.getName()) ; if (a == b){ return level ; } Class parent = a.getSuperclass() ; if (parent != null){ InlineJavaUtils.debug(4, " parent is " + parent.getName()) ; int ret = DoesExtend(parent, b, level + 1) ; if (ret != -1){ return ret ; } } // Maybe b is an interface a implements it? Class inter[] = a.getInterfaces() ; for (int i = 0 ; i < inter.length ; i++){ InlineJavaUtils.debug(4, " interface is " + inter[i].getName()) ; int ret = DoesExtend(inter[i], b, level + 1) ; if (ret != -1){ return ret ; } } return -1 ; } /* Finds the wrapper class for the passed primitive type. */ static Class FindWrapper(Class p){ Class w = (Class)class2wrapper.get(p) ; if (w == null){ w = p ; } return w ; } /* Finds the primitive type class for the passed primitive type name. */ static Class FindType (String name){ return (Class)name2class.get(name) ; } static String FindJNICode(Class p){ if (! Object.class.isAssignableFrom(p)){ return (String)class2jni_code.get(p) ; } else { String name = p.getName().replace('.', '/') ; if (p.isArray()){ return name ; } else{ return "L" + name + ";" ; } } } static boolean ClassIsPrimitive(Class p){ String name = p.getName() ; if ((ClassIsNumeric(p))||(ClassIsString(p))||(ClassIsChar(p))||(ClassIsBool(p))){ InlineJavaUtils.debug(4, "class " + name + " is primitive") ; return true ; } return false ; } /* Determines if class is of numerical type. */ static private HashMap numeric_classes = new HashMap<>() ; static { 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, java.lang.Number.class, byte.class, short.class, int.class, long.class, float.class, double.class, } ; for (int i = 0 ; i < list.length ; i++){ numeric_classes.put(list[i], Boolean.TRUE) ; } } static boolean ClassIsNumeric (Class p){ return (numeric_classes.get(p) != null) ; } static private HashMap double_classes = new HashMap<>(); static { Class [] list = { java.lang.Double.class, double.class, } ; for (int i = 0 ; i < list.length ; i++){ double_classes.put(list[i], Boolean.TRUE) ; } } static boolean ClassIsDouble (Class p){ return (double_classes.get(p) != null) ; } /* Class is String or StringBuffer */ static private HashMap string_classes = new HashMap<>(); static { Class csq = ValidateClassQuiet("java.lang.CharSequence") ; Class [] list = { java.lang.String.class, java.lang.StringBuffer.class, csq } ; for (int i = 0 ; i < list.length ; i++){ string_classes.put(list[i], Boolean.TRUE) ; } } static boolean ClassIsString (Class p){ return (string_classes.get(p) != null) ; } /* Class is Char */ static private HashMap char_classes = new HashMap<>() ; static { Class [] list = { java.lang.Character.class, char.class, } ; for (int i = 0 ; i < list.length ; i++){ char_classes.put(list[i], Boolean.TRUE) ; } } static boolean ClassIsChar (Class p){ return (char_classes.get(p) != null) ; } /* Class is Bool */ static private HashMap bool_classes = new HashMap<>() ; static { Class [] list = { java.lang.Boolean.class, boolean.class, } ; for (int i = 0 ; i < list.length ; i++){ bool_classes.put(list[i], Boolean.TRUE) ; } } static boolean ClassIsBool (Class p){ return (bool_classes.get(p) != null) ; } /* Determines if a class is not of a primitive type or of a wrapper class. */ static boolean ClassIsReference (Class p){ String name = p.getName() ; if (ClassIsPrimitive(p)){ return false ; } InlineJavaUtils.debug(4, "class " + name + " is reference") ; return true ; } static boolean ClassIsArray (Class p){ String name = p.getName() ; if ((name.startsWith("["))&&(ClassIsReference(p))){ InlineJavaUtils.debug(4, "class " + name + " is array") ; return true ; } return false ; } static boolean ClassIsPublic (Class p){ int pub = p.getModifiers() & Modifier.PUBLIC ; if (pub != 0){ return true ; } return false ; } static boolean ClassIsHandle (Class p){ if ((ClassIsReadHandle(p))||(ClassIsWriteHandle(p))){ return true ; } return false ; } static boolean ClassIsReadHandle (Class p){ if ((java.io.Reader.class.isAssignableFrom(p))|| (java.io.InputStream.class.isAssignableFrom(p))){ return true ; } return false ; } static boolean ClassIsWriteHandle (Class p){ if ((java.io.Writer.class.isAssignableFrom(p))|| (java.io.OutputStream.class.isAssignableFrom(p))){ return true ; } return false ; } } Inline-Java-0.67/Java/sources/org/perl/inline/java/InlineJavaServer.java0000644000175000017500000002015214202030173026027 0ustar osboxesosboxespackage org.perl.inline.java ; import java.net.* ; import java.io.* ; import java.util.* ; /* This is the server that will answer all the requests for and on Java objects. */ public class InlineJavaServer { private static InlineJavaServer instance = null ; private String host = null ; private int port = 0 ; private boolean shared_jvm = false ; private boolean priv = false ; private boolean native_doubles = false ; private boolean finished = false ; private ServerSocket server_socket = null ; private InlineJavaUserClassLoader ijucl = null ; private HashMap> thread_objects = new HashMap<>(); private int objid = 1 ; private boolean jni = false ; private Thread creator = null ; private int thread_count = 0 ; // This constructor is used in JNI mode private InlineJavaServer(int debug, boolean _native_doubles){ init(debug, _native_doubles) ; jni = true ; AddThread(creator) ; } // This constructor is used in server mode // Normally one would then call RunMainLoop() /* Note: Consider http://groups.google.com/group/perl.inline/tree/browse_frm/thread/aa7f5ce236f6d576/3db48a308a8175fb?rnum=1&hl=en&q=Congratulations+with+Inline%3A%3AJava+0.51&_done=%2Fgroup%2Fperl.inline%2Fbrowse_frm%2Fthread%2Faa7f5ce236f6d576%2Fd2de9cf38429c09c%3Flnk%3Dst%26q%3DCongratulations+with+Inline%3A%3AJava+0.51%26rnum%3D1%26hl%3Den%26#doc_3db48a308a8175fb before changing this prototype */ public InlineJavaServer(int debug, String _host, int _port, boolean _shared_jvm, boolean _priv, boolean _native_doubles){ init(debug, _native_doubles) ; jni = false ; host = _host ; port = _port ; shared_jvm = _shared_jvm ; priv = _priv ; try { if ((host == null)||(host.equals(""))||(host.equals("ANY"))){ server_socket = new ServerSocket(port) ; } else { server_socket = new ServerSocket(port, 0, InetAddress.getByName(host)) ; } } catch (IOException e){ InlineJavaUtils.Fatal("Can't open server socket on port " + String.valueOf(port) + ": " + e.getMessage()) ; } } public void RunMainLoop(){ while (! finished){ try { String name = "IJST-#" + thread_count++ ; InlineJavaServerThread ijt = new InlineJavaServerThread(name, this, server_socket.accept(), (priv ? new InlineJavaUserClassLoader() : ijucl)) ; ijt.start() ; if (! shared_jvm){ try { ijt.join() ; } catch (InterruptedException e){ } break ; } } catch (IOException e){ if (! finished){ System.err.println("Main Loop IO Error: " + e.getMessage()) ; System.err.flush() ; } } } } private synchronized void init(int debug, boolean _native_doubles){ instance = this ; creator = Thread.currentThread() ; InlineJavaUtils.set_debug(debug) ; native_doubles = _native_doubles ; ijucl = new InlineJavaUserClassLoader() ; } static InlineJavaServer GetInstance(){ if (instance == null){ InlineJavaUtils.Fatal("No instance of InlineJavaServer has been created!") ; } return instance ; } InlineJavaUserClassLoader GetUserClassLoader(){ Thread t = Thread.currentThread() ; if (t instanceof InlineJavaServerThread){ return ((InlineJavaServerThread)t).GetUserClassLoader() ; } else { return ijucl ; } } String GetType(){ return (shared_jvm ? "shared" : "private") ; } boolean GetNativeDoubles(){ return native_doubles ; } boolean IsJNI(){ return jni ; } /* Since this function is also called from the JNI XS extension, it's best if it doesn't throw any exceptions. */ String ProcessCommand(String cmd) { return ProcessCommand(cmd, true) ; } String ProcessCommand(String cmd, boolean addlf) { InlineJavaUtils.debug(3, "packet recv is " + cmd) ; String resp = null ; if (cmd != null){ InlineJavaProtocol ijp = new InlineJavaProtocol(this, cmd) ; try { ijp.Do() ; InlineJavaUtils.debug(3, "packet sent is " + ijp.GetResponse()) ; resp = ijp.GetResponse() ; } catch (InlineJavaException e){ // Encode the error in default encoding since we don't want any // Exceptions thrown here... String err = "error scalar:" + ijp.EncodeFromByteArray(e.getMessage().getBytes()) ; InlineJavaUtils.debug(3, "packet sent is " + err) ; resp = err ; } } else{ if (! shared_jvm){ // Probably connection dropped... InlineJavaUtils.debug(1, "lost connection with client in single client mode. Exiting.") ; System.exit(1) ; } else{ InlineJavaUtils.debug(1, "lost connection with client in shared JVM mode.") ; return null ; } } if (addlf){ resp = resp + "\n" ; } return resp ; } /* This method really has no business here, but for historical reasons it will remain here. */ native String jni_callback(String cmd) ; boolean IsThreadPerlContact(Thread t){ if (((jni)&&(t == creator))|| ((! jni)&&(t instanceof InlineJavaServerThread))){ return true ; } return false ; } synchronized Object GetObject(int id) throws InlineJavaException { Object o = null ; HashMap h = (HashMap)thread_objects.get(Thread.currentThread()) ; if (h == null){ throw new InlineJavaException("Can't find thread " + Thread.currentThread().getName() + "!") ; } else{ o = h.get(Integer.valueOf(id)) ; if (o == null){ throw new InlineJavaException("Can't find object " + id + " for thread " +Thread.currentThread().getName()) ; } } return o ; } synchronized int PutObject(Object o) throws InlineJavaException { HashMap h = (HashMap)thread_objects.get(Thread.currentThread()) ; int id = objid ; if (h == null){ throw new InlineJavaException("Can't find thread " + Thread.currentThread().getName() + "!") ; } else{ h.put(Integer.valueOf(objid), o) ; objid++ ; } return id ; } synchronized Object DeleteObject(int id) throws InlineJavaException { Object o = null ; HashMap h = (HashMap)thread_objects.get(Thread.currentThread()) ; if (h == null){ throw new InlineJavaException("Can't find thread " + Thread.currentThread().getName() + "!") ; } else{ o = h.remove(Integer.valueOf(id)) ; if (o == null){ throw new InlineJavaException("Can't find object " + id + " for thread " + Thread.currentThread().getName()) ; } } return o ; } synchronized int ObjectCount() throws InlineJavaException { int i = -1 ; HashMap h = (HashMap)thread_objects.get(Thread.currentThread()) ; if (h == null){ throw new InlineJavaException("Can't find thread " + Thread.currentThread().getName() + "!") ; } else{ i = h.values().size() ; } return i ; } public synchronized void StopMainLoop(){ if (! jni){ try { finished = true ; server_socket.close() ; } catch (IOException e){ System.err.println("Shutdown IO Error: " + e.getMessage()) ; System.err.flush() ; } } } synchronized void Shutdown(){ StopMainLoop() ; System.exit(0) ; } /* Here the prototype accepts Threads because the JNI thread calls this method also. */ synchronized void AddThread(Thread t){ thread_objects.put(t, new HashMap()) ; InlineJavaPerlCaller.AddThread(t) ; } synchronized void RemoveThread(InlineJavaServerThread t){ thread_objects.remove(t) ; InlineJavaPerlCaller.RemoveThread(t) ; } /* Startup */ public static void main(String[] argv){ int debug = Integer.parseInt(argv[0]) ; String host = argv[1] ; int port = Integer.parseInt(argv[2]) ; boolean shared_jvm = Boolean.parseBoolean(argv[3]) ; boolean priv = Boolean.parseBoolean(argv[4]) ; boolean native_doubles = Boolean.parseBoolean(argv[5]) ; InlineJavaServer ijs = new InlineJavaServer(debug, host, port, shared_jvm, priv, native_doubles) ; ijs.RunMainLoop() ; System.exit(0) ; } /* With PerlInterpreter this is called twice, but we don't want to create a new object the second time. */ public static InlineJavaServer jni_main(int debug, boolean native_doubles){ if (instance != null){ InlineJavaUtils.set_debug(debug) ; InlineJavaUtils.debug(1, "recycling InlineJavaServer created by PerlInterpreter") ; return instance ; } else { return new InlineJavaServer(debug, native_doubles) ; } } } Inline-Java-0.67/Java/sources/org/perl/inline/java/InlineJavaThrown.java0000644000175000017500000000024714202030173026045 0ustar osboxesosboxespackage org.perl.inline.java ; class InlineJavaThrown { Throwable t ; InlineJavaThrown(Throwable _t){ t = _t ; } Throwable GetThrowable(){ return t ; } } Inline-Java-0.67/Java/sources/org/perl/inline/java/InlineJavaInvocationTargetException.java0000644000175000017500000000041014202030173031713 0ustar osboxesosboxespackage org.perl.inline.java ; class InlineJavaInvocationTargetException extends InlineJavaException { private Throwable t ; InlineJavaInvocationTargetException(String m, Throwable _t){ super(m) ; t = _t ; } Throwable GetThrowable(){ return t ; } } Inline-Java-0.67/Java/sources/org/perl/inline/java/InlineJavaCastException.java0000644000175000017500000000022214202030173027326 0ustar osboxesosboxespackage org.perl.inline.java ; class InlineJavaCastException extends InlineJavaException { InlineJavaCastException(String m){ super(m) ; } } Inline-Java-0.67/Java/sources/org/perl/inline/java/InlineJavaServerThread.java0000644000175000017500000000242714202030173027164 0ustar osboxesosboxespackage org.perl.inline.java ; import java.io.* ; import java.net.* ; import java.util.* ; class InlineJavaServerThread extends Thread { private InlineJavaServer ijs ; private Socket client ; private BufferedReader br ; private BufferedWriter bw ; private InlineJavaUserClassLoader ijucl ; InlineJavaServerThread(String name, InlineJavaServer _ijs, Socket _client, InlineJavaUserClassLoader _ijucl) throws IOException { super(name) ; client = _client ; ijs = _ijs ; ijucl = _ijucl ; InputStreamReader ir = new InputStreamReader(client.getInputStream()) ; OutputStreamWriter or = new OutputStreamWriter(client.getOutputStream()) ; br = new BufferedReader(ir) ; bw = new BufferedWriter(or) ; } BufferedReader GetReader(){ return br ; } BufferedWriter GetWriter(){ return bw ; } InlineJavaUserClassLoader GetUserClassLoader(){ return ijucl ; } public void run(){ try { ijs.AddThread(this) ; while (true){ String cmd = br.readLine() ; String resp = ijs.ProcessCommand(cmd) ; if (resp != null){ bw.write(resp) ; bw.flush() ; } else { client.close() ; break ; } } } catch (IOException e){ System.err.println("IO error: " + e.getMessage()) ; } finally { ijs.RemoveThread(this) ; } } } Inline-Java-0.67/Java/sources/org/perl/inline/java/InlineJavaCallback.java0000644000175000017500000000737114202030173026265 0ustar osboxesosboxespackage org.perl.inline.java ; import java.util.* ; import java.io.* ; /* Callback to Perl... */ class InlineJavaCallback { private InlineJavaServer ijs = InlineJavaServer.GetInstance() ; private String pkg = null ; private InlineJavaPerlObject obj = null ; private String method = null ; private Object args[] = null ; private Class cast = null ; private Object response = null ; private boolean response_set = false ; InlineJavaCallback(String _pkg, String _method, Object _args[], Class _cast) { this(null, _pkg, _method, _args, _cast) ; } InlineJavaCallback(InlineJavaPerlObject _obj, String _method, Object _args[], Class _cast) { this(_obj, null, _method, _args, _cast) ; if (obj == null){ throw new NullPointerException() ; } } private InlineJavaCallback(InlineJavaPerlObject _obj, String _pkg, String _method, Object _args[], Class _cast) { obj = _obj ; pkg = _pkg ; method = _method ; args = _args ; cast = _cast ; if (method == null){ throw new NullPointerException() ; } if (cast == null){ cast = java.lang.Object.class ; } } private String GetCommand(InlineJavaProtocol ijp) throws InlineJavaException { String via = null ; if (obj != null){ via = "" + obj.GetId() ; } else if (pkg != null){ via = pkg ; } StringBuffer cmdb = new StringBuffer("callback " + via + " " + method + " " + cast.getName()) ; if (args != null){ for (int i = 0 ; i < args.length ; i++){ cmdb.append(" " + ijp.SerializeObject(args[i], null)) ; } } return cmdb.toString() ; } void ClearResponse(){ response = null ; response_set = false ; } Object GetResponse(){ return response ; } synchronized Object WaitForResponse(Thread t){ while (! response_set){ try { InlineJavaUtils.debug(3, "waiting for callback response in " + t.getName() + "...") ; wait() ; } catch (InterruptedException ie){ // Do nothing, return and wait() some more... } } InlineJavaUtils.debug(3, "got callback response") ; Object resp = response ; response = null ; response_set = false ; return resp ; } synchronized void NotifyOfResponse(Thread t){ InlineJavaUtils.debug(3, "notifying that callback has completed in " + t.getName()) ; notify() ; } synchronized void Process() throws InlineJavaException, InlineJavaPerlException { Object ret = null ; try { InlineJavaProtocol ijp = new InlineJavaProtocol(ijs, null) ; String cmd = GetCommand(ijp) ; InlineJavaUtils.debug(2, "callback command: " + cmd) ; Thread t = Thread.currentThread() ; String resp = null ; while (true) { InlineJavaUtils.debug(3, "packet sent (callback) is " + cmd) ; if (! ijs.IsJNI()){ // Client-server mode. InlineJavaServerThread ijt = (InlineJavaServerThread)t ; ijt.GetWriter().write(cmd + "\n") ; ijt.GetWriter().flush() ; resp = ijt.GetReader().readLine() ; } else{ // JNI mode resp = ijs.jni_callback(cmd) ; } InlineJavaUtils.debug(3, "packet recv (callback) is " + resp) ; StringTokenizer st = new StringTokenizer(resp, " ") ; String c = st.nextToken() ; if (c.equals("callback")){ boolean thrown = Boolean.parseBoolean(st.nextToken()) ; String arg = st.nextToken() ; InlineJavaClass ijc = new InlineJavaClass(ijs, ijp) ; ret = ijc.CastArgument(cast, arg) ; if (thrown){ throw new InlineJavaPerlException(ret) ; } break ; } else{ // Pass it on through the regular channel... InlineJavaUtils.debug(3, "packet is not callback response: " + resp) ; cmd = ijs.ProcessCommand(resp, false) ; continue ; } } } catch (IOException e){ throw new InlineJavaException("IO error: " + e.getMessage()) ; } response = ret ; response_set = true ; } } Inline-Java-0.67/Java/sources/org/perl/inline/java/InlineJavaCallbackQueue.java0000644000175000017500000000665214202030173027273 0ustar osboxesosboxespackage org.perl.inline.java ; import java.util.* ; import java.io.* ; /* Queue for callbacks to Perl... */ class InlineJavaCallbackQueue { // private InlineJavaServer ijs = InlineJavaServer.GetInstance() ; private ArrayList queue = new ArrayList<>() ; private boolean wait_interrupted = false ; private boolean stream_opened = false ; InlineJavaCallbackQueue(){ } synchronized void EnqueueCallback(InlineJavaCallback ijc){ queue.add(ijc) ; notify() ; } synchronized private InlineJavaCallback DequeueCallback(){ if (GetSize() > 0){ return (InlineJavaCallback)queue.remove(0) ; } return null ; } synchronized int WaitForCallback(double timeout){ long secs = (long)Math.floor(timeout) ; double rest = timeout - ((double)secs) ; long millis = (long)Math.floor(rest * 1000.0) ; rest = (rest * 1000.0) - ((double)millis) ; int nanos = (int)Math.floor(rest * 1000000.0) ; return WaitForCallback((secs * 1000) + millis, nanos) ; } /* Blocks up to the specified time for the next callback to arrive. Returns -1 if the wait was interrupted voluntarily, 0 on timeout or > 0 if a callback has arrived before the timeout expired. */ synchronized int WaitForCallback(long millis, int nanos){ wait_interrupted = false ; Thread t = Thread.currentThread() ; InlineJavaUtils.debug(3, "waiting for callback request (" + millis + " millis, " + nanos + " nanos) in " + t.getName() + "...") ; if (! stream_opened){ return -1 ; } while ((stream_opened)&&(! wait_interrupted)&&(IsEmpty())){ try { wait(millis, nanos) ; // If we reach this code, it means the either we timed out // or that we were notify()ed. // In the former case, we must break out and return 0. // In the latter case, either the queue will not be empty or // wait_interrupted will be set. We must therefore also break out. break ; } catch (InterruptedException ie){ // Do nothing, return and wait() some more... } } InlineJavaUtils.debug(3, "waiting for callback request finished " + t.getName() + "...") ; if (wait_interrupted){ return -1 ; } else { return GetSize() ; } } /* Waits indefinetely for the next callback to arrive and executes it. Return true on success of false if the wait was interrupted voluntarily. */ synchronized boolean ProcessNextCallback() throws InlineJavaException, InlineJavaPerlException { int rc = WaitForCallback(0, 0) ; if (rc == -1){ // Wait was interrupted return false ; } // DequeueCallback can't return null because we explicetely // waited until a callback was there. Thread t = Thread.currentThread() ; InlineJavaUtils.debug(3, "processing callback request in " + t.getName() + "...") ; InlineJavaCallback ijc = DequeueCallback() ; ijc.Process() ; ijc.NotifyOfResponse(t) ; return true ; } private boolean IsEmpty(){ return (GetSize() == 0) ; } void OpenCallbackStream(){ stream_opened = true ; } synchronized void CloseCallbackStream(){ stream_opened = false ; InterruptWaitForCallback() ; } boolean IsStreamOpen(){ return stream_opened ; } int GetSize(){ return queue.size() ; } synchronized private void InterruptWaitForCallback(){ Thread t = Thread.currentThread() ; InlineJavaUtils.debug(3, "interrupting wait for callback request in " + t.getName() + "...") ; wait_interrupted = true ; notify() ; } } Inline-Java-0.67/Java/sources/org/perl/inline/java/InlineJavaProtocol.java0000644000175000017500000005720214202030173026370 0ustar osboxesosboxespackage org.perl.inline.java ; import java.util.* ; import java.io.* ; import java.lang.reflect.* ; /* This is where most of the work of Inline Java is done. Here determine the request type and then we proceed to serve it. */ class InlineJavaProtocol { private InlineJavaServer ijs ; private InlineJavaClass ijc ; private InlineJavaArray ija ; private String cmd ; private String response = null ; private final String encoding = "UTF-8" ; static private Map member_cache = Collections.synchronizedMap(new HashMap()) ; static private final String report_version = "V2" ; InlineJavaProtocol(InlineJavaServer _ijs, String _cmd) { ijs = _ijs ; ijc = new InlineJavaClass(ijs, this) ; ija = new InlineJavaArray(ijc) ; cmd = _cmd ; } /* Starts the analysis of the command line */ void Do() throws InlineJavaException { StringTokenizer st = new StringTokenizer(cmd, " ") ; String c = st.nextToken() ; if (c.equals("call_method")){ CallJavaMethod(st) ; } else if (c.equals("set_member")){ SetJavaMember(st) ; } else if (c.equals("get_member")){ GetJavaMember(st) ; } else if (c.equals("add_classpath")){ AddClassPath(st) ; } else if (c.equals("server_type")){ ServerType(st) ; } else if (c.equals("report")){ Report(st) ; } else if (c.equals("isa")){ IsA(st) ; } else if (c.equals("create_object")){ CreateJavaObject(st) ; } else if (c.equals("delete_object")){ DeleteJavaObject(st) ; } else if (c.equals("obj_cnt")){ ObjectCount(st) ; } else if (c.equals("cast")){ Cast(st) ; } else if (c.equals("read")){ Read(st) ; } else if (c.equals("make_buffered")){ MakeBuffered(st) ; } else if (c.equals("readline")){ ReadLine(st) ; } else if (c.equals("write")){ Write(st) ; } else if (c.equals("close")){ Close(st) ; } else if (c.equals("die")){ InlineJavaUtils.debug(1, "received a request to die...") ; ijs.Shutdown() ; } else { throw new InlineJavaException("Unknown command " + c) ; } } /* Returns a report on the Java classes, listing all public methods and members */ void Report(StringTokenizer st) throws InlineJavaException { StringBuffer pw = new StringBuffer(report_version + "\n") ; StringTokenizer st2 = new StringTokenizer(st.nextToken(), ":") ; st2.nextToken() ; StringTokenizer st3 = new StringTokenizer(Decode(st2.nextToken()), " ") ; ArrayList class_list = new ArrayList<>() ; while (st3.hasMoreTokens()){ String c = st3.nextToken() ; class_list.add(class_list.size(), c) ; } for (int i = 0 ; i < class_list.size() ; i++){ String name = (String)class_list.get(i) ; Class c = ijc.ValidateClass(name) ; InlineJavaUtils.debug(3, "reporting for " + c) ; Class parent = c.getSuperclass() ; String pname = (parent == null ? "null" : parent.getName()) ; pw.append("class " + c.getName() + " " + pname + "\n") ; Constructor constructors[] = c.getConstructors() ; Method methods[] = c.getMethods() ; Field fields[] = c.getFields() ; boolean pub = ijc.ClassIsPublic(c) ; if (pub){ // If the class is public and has no constructors, // we provide a default no-arg constructors. if (c.getDeclaredConstructors().length == 0){ String noarg_sign = InlineJavaUtils.CreateSignature(new Class [] {}) ; pw.append("constructor " + noarg_sign + "\n") ; } } boolean pn = InlineJavaPerlNatives.class.isAssignableFrom(c) ; for (int j = 0 ; j < constructors.length ; j++){ Constructor x = constructors[j] ; if ((pn)&&(Modifier.isNative(x.getModifiers()))){ continue ; } Class params[] = x.getParameterTypes() ; String sign = InlineJavaUtils.CreateSignature(params) ; Class decl = x.getDeclaringClass() ; pw.append("constructor " + sign + "\n") ; } for (int j = 0 ; j < methods.length ; j++){ Method x = methods[j] ; if ((pn)&&(Modifier.isNative(x.getModifiers()))){ continue ; } String stat = (Modifier.isStatic(x.getModifiers()) ? " static " : " instance ") ; String sign = InlineJavaUtils.CreateSignature(x.getParameterTypes()) ; Class decl = x.getDeclaringClass() ; pw.append("method" + stat + decl.getName() + " " + x.getName() + sign + "\n") ; } for (int j = 0 ; j < fields.length ; j++){ Field x = fields[(InlineJavaUtils.ReverseMembers() ? (fields.length - 1 - j) : j)] ; String stat = (Modifier.isStatic(x.getModifiers()) ? " static " : " instance ") ; Class decl = x.getDeclaringClass() ; Class type = x.getType() ; pw.append("field" + stat + decl.getName() + " " + x.getName() + " " + type.getName() + "\n") ; } } SetResponse(pw.toString()) ; } void AddClassPath(StringTokenizer st) throws InlineJavaException { while (st.hasMoreTokens()){ String path = Decode(st.nextToken()) ; InlineJavaServer.GetInstance().GetUserClassLoader().AddClassPath(path) ; } SetResponse(null) ; } void ServerType(StringTokenizer st) throws InlineJavaException { SetResponse(ijs.GetType()) ; } void IsA(StringTokenizer st) throws InlineJavaException { String class_name = st.nextToken() ; Class c = ijc.ValidateClass(class_name) ; String is_it_a = st.nextToken() ; Class d = ijc.ValidateClass(is_it_a) ; SetResponse(Integer.valueOf(ijc.DoesExtend(c, d))) ; } void ObjectCount(StringTokenizer st) throws InlineJavaException { SetResponse(Integer.valueOf(ijs.ObjectCount())) ; } /* Creates a Java Object with the specified arguments. */ void CreateJavaObject(StringTokenizer st) throws InlineJavaException { String class_name = st.nextToken() ; Class c = ijc.ValidateClass(class_name) ; if (! ijc.ClassIsArray(c)){ ArrayList f = ValidateMethod(true, c, class_name, st) ; Object p[] = (Object [])f.get(1) ; Class clist[] = (Class [])f.get(2) ; try { Object o = CreateObject(c, p, clist) ; SetResponse(o) ; } catch (InlineJavaInvocationTargetException ite){ Throwable t = ite.GetThrowable() ; if (t instanceof InlineJavaException){ InlineJavaException ije = (InlineJavaException)t ; throw ije ; } else{ SetResponse(new InlineJavaThrown(t)) ; } } } else{ // Here we send the type of array we want, but CreateArray // exception the element type. StringBuffer sb = new StringBuffer(class_name) ; // Remove the ['s while (sb.toString().startsWith("[")){ sb.replace(0, 1, "") ; } // remove the L and the ; if (sb.toString().startsWith("L")){ sb.replace(0, 1, "") ; sb.replace(sb.length() - 1, sb.length(), "") ; } Class ec = ijc.ValidateClass(sb.toString()) ; InlineJavaUtils.debug(4, "array elements: " + ec.getName()) ; Object o = ija.CreateArray(ec, st) ; SetResponse(o) ; } } /* Calls a Java method */ void CallJavaMethod(StringTokenizer st) throws InlineJavaException { int id = Integer.parseInt(st.nextToken()) ; String class_name = st.nextToken() ; Object o = null ; if (id > 0){ o = ijs.GetObject(id) ; // Use the class sent by Perl (it might be casted) // class_name = o.getClass().getName() ; } Class c = ijc.ValidateClass(class_name) ; String method = st.nextToken() ; if ((ijc.ClassIsArray(c))&&(method.equals("getLength"))){ int length = Array.getLength(o) ; SetResponse(Integer.valueOf(length)) ; } else{ 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 = InlineJavaServer.GetInstance().GetUserClassLoader().invoke(m, o, p) ; SetResponse(ret, AutoCast(ret, m.getReturnType())) ; } catch (IllegalAccessException e){ throw new InlineJavaException("You are not allowed to invoke method " + name + " in class " + class_name + ": " + e.getMessage()) ; } catch (IllegalArgumentException e){ throw new InlineJavaException("Arguments for method " + name + " in class " + class_name + " are incompatible: " + e.getMessage()) ; } catch (InvocationTargetException e){ Throwable t = e.getTargetException() ; String type = t.getClass().getName() ; String msg = t.getMessage() ; InlineJavaUtils.debug(1, "method " + name + " in class " + class_name + " threw exception " + type + ": " + msg) ; if (t instanceof InlineJavaException){ InlineJavaException ije = (InlineJavaException)t ; throw ije ; } Throwable retval = t; if (t instanceof InlineJavaPerlException){ InlineJavaPerlException ijpe = (InlineJavaPerlException)t; Object eo = ijpe.GetObject(); if (eo instanceof Throwable) { retval = (Throwable)eo; } InlineJavaUtils.debug(2, "InlineJavaPerlException " + retval.toString()) ; } SetResponse(new InlineJavaThrown(retval)) ; } } } /* */ Class AutoCast(Object o, Class want){ if (o == null){ return null ; } Class got = o.getClass() ; if (got.equals(want)){ return null ; } boolean _public = (got.getModifiers() & Modifier.PUBLIC) != 0 ; if ((_public)||(got.getPackage() == null)){ return null ; } InlineJavaUtils.debug(3, "AutoCast: " + got.getName() + " -> " + want.getName()) ; return want ; } /* Returns a new reference to the current object, using the provided subtype */ void Cast(StringTokenizer st) throws InlineJavaException { int id = Integer.parseInt(st.nextToken()) ; String class_name = st.nextToken() ; Object o = ijs.GetObject(id) ; Class c = ijc.ValidateClass(class_name) ; SetResponse(o, c) ; } /* */ void Read(StringTokenizer st) throws InlineJavaException { int id = Integer.parseInt(st.nextToken()) ; int len = Integer.parseInt(st.nextToken()) ; Object o = ijs.GetObject(id) ; Object ret = null ; try { ret = InlineJavaHandle.read(o, len) ; } catch (java.io.IOException e){ ret = new InlineJavaThrown(e) ; } SetResponse(ret) ; } void MakeBuffered(StringTokenizer st) throws InlineJavaException { int id = Integer.parseInt(st.nextToken()) ; Object o = ijs.GetObject(id) ; Object ret = null ; try { ret = InlineJavaHandle.makeBuffered(o) ; if (ret != o){ int buf_id = ijs.PutObject(ret) ; ret = Integer.valueOf(buf_id) ; } else { ret = Integer.valueOf(id) ; } } catch (java.io.IOException e){ ret = new InlineJavaThrown(e) ; } SetResponse(ret) ; } void ReadLine(StringTokenizer st) throws InlineJavaException { int id = Integer.parseInt(st.nextToken()) ; Object o = ijs.GetObject(id) ; Object ret = null ; try { ret = InlineJavaHandle.readLine(o) ; } catch (java.io.IOException e){ ret = new InlineJavaThrown(e) ; } SetResponse(ret) ; } void Write(StringTokenizer st) throws InlineJavaException { int id = Integer.parseInt(st.nextToken()) ; Object arg = ijc.CastArgument(Object.class, st.nextToken()) ; Object o = ijs.GetObject(id) ; Object ret = null ; try { int len = InlineJavaHandle.write(o, arg.toString()) ; ret = Integer.valueOf(len) ; } catch (java.io.IOException e){ ret = new InlineJavaThrown(e) ; } SetResponse(ret) ; } void Close(StringTokenizer st) throws InlineJavaException { int id = Integer.parseInt(st.nextToken()) ; Object o = ijs.GetObject(id) ; Object ret = null ; try { InlineJavaHandle.close(o) ; } catch (java.io.IOException e){ ret = new InlineJavaThrown(e) ; } SetResponse(ret) ; } /* Sets a Java member variable */ void SetJavaMember(StringTokenizer st) throws InlineJavaException { int id = Integer.parseInt(st.nextToken()) ; String class_name = st.nextToken() ; Object o = null ; if (id > 0){ o = ijs.GetObject(id) ; // Use the class sent by Perl (it might be casted) // class_name = o.getClass().getName() ; } Class c = ijc.ValidateClass(class_name) ; String member = st.nextToken() ; if (ijc.ClassIsArray(c)){ int idx = Integer.parseInt(member) ; Class type = ijc.ValidateClass(st.nextToken()) ; String arg = st.nextToken() ; String msg = "For array of type " + c.getName() + ", element " + member + ": " ; try { Object elem = ijc.CastArgument(type, arg) ; InlineJavaServer.GetInstance().GetUserClassLoader().array_set(o, idx, elem) ; SetResponse(null) ; } catch (InlineJavaCastException e){ throw new InlineJavaCastException(msg + e.getMessage()) ; } catch (InlineJavaException e){ throw new InlineJavaException(msg + e.getMessage()) ; } } else{ ArrayList fl = ValidateMember(c, member, st) ; Field f = (Field)fl.get(0) ; String name = f.getName() ; Object p = (Object)fl.get(1) ; try { InlineJavaServer.GetInstance().GetUserClassLoader().set(f, o, p) ; SetResponse(null) ; } catch (IllegalAccessException e){ throw new InlineJavaException("You are not allowed to set member " + name + " in class " + class_name + ": " + e.getMessage()) ; } catch (IllegalArgumentException e){ throw new InlineJavaException("Argument for member " + name + " in class " + class_name + " is incompatible: " + e.getMessage()) ; } } } /* Gets a Java member variable */ void GetJavaMember(StringTokenizer st) throws InlineJavaException { int id = Integer.parseInt(st.nextToken()) ; String class_name = st.nextToken() ; Object o = null ; if (id > 0){ o = ijs.GetObject(id) ; // Use the class sent by Perl (it might be casted) // class_name = o.getClass().getName() ; } Class c = ijc.ValidateClass(class_name) ; String member = st.nextToken() ; if (ijc.ClassIsArray(c)){ int idx = Integer.parseInt(member) ; Object ret = InlineJavaServer.GetInstance().GetUserClassLoader().array_get(o, idx) ; Class eclass = ijc.ValidateClass(ijc.CleanClassName(class_name.substring(1))) ; SetResponse(ret, AutoCast(ret, eclass)) ; } else{ ArrayList fl = ValidateMember(c, member, st) ; Field f = (Field)fl.get(0) ; String name = f.getName() ; try { Object ret = InlineJavaServer.GetInstance().GetUserClassLoader().get(f, o) ; SetResponse(ret, AutoCast(ret, f.getType())) ; } catch (IllegalAccessException e){ throw new InlineJavaException("You are not allowed to set member " + name + " in class " + class_name + ": " + e.getMessage()) ; } catch (IllegalArgumentException e){ throw new InlineJavaException("Argument for member " + name + " in class " + class_name + " is incompatible: " + e.getMessage()) ; } } } /* Deletes a Java object */ void DeleteJavaObject(StringTokenizer st) throws InlineJavaException { int id = Integer.parseInt(st.nextToken()) ; Object o = ijs.DeleteObject(id) ; SetResponse(null) ; } /* Creates a Java Object with the specified arguments. */ Object CreateObject(Class p, Object args[], Class proto[]) throws InlineJavaException { p = ijc.FindWrapper(p) ; String name = p.getName() ; Object ret = null ; try { ret = InlineJavaServer.GetInstance().GetUserClassLoader().create(p, args, proto) ; } catch (NoSuchMethodException e){ throw new InlineJavaException("Constructor for class " + name + " with signature " + InlineJavaUtils.CreateSignature(proto) + " not found: " + e.getMessage()) ; } catch (InstantiationException e){ throw new InlineJavaException("You are not allowed to instantiate object of class " + name + ": " + e.getMessage()) ; } catch (IllegalAccessException e){ throw new InlineJavaException("You are not allowed to instantiate object of class " + name + " using the constructor with signature " + InlineJavaUtils.CreateSignature(proto) + ": " + e.getMessage()) ; } catch (IllegalArgumentException e){ throw new InlineJavaException("Arguments to constructor for class " + name + " with signature " + InlineJavaUtils.CreateSignature(proto) + " are incompatible: " + e.getMessage()) ; } catch (InvocationTargetException e){ Throwable t = e.getTargetException() ; String type = t.getClass().getName() ; String msg = t.getMessage() ; throw new InlineJavaInvocationTargetException( "Constructor for class " + name + " with signature " + InlineJavaUtils.CreateSignature(proto) + " threw exception " + type + ": " + msg, t) ; } return ret ; } /* Makes sure a method exists */ ArrayList ValidateMethod(boolean constructor, Class c, String name, StringTokenizer st) throws InlineJavaException { ArrayList ret = new ArrayList<>() ; // Extract signature String signature = st.nextToken() ; // Extract the arguments ArrayList args = new ArrayList<>() ; while (st.hasMoreTokens()){ args.add(args.size(), st.nextToken()) ; } String key = c.getName() + "." + name + signature ; ArrayList ml = new ArrayList<>() ; Class params[] = null ; Member cached = (Member)member_cache.get(key) ; if (cached != null){ InlineJavaUtils.debug(3, "method was cached") ; ml.add(ml.size(), cached) ; } else{ Member ma[] = (constructor ? (Member [])c.getConstructors() : (Member [])c.getMethods()) ; for (int i = 0 ; i < ma.length ; i++){ Member m = ma[i] ; if (m.getName().equals(name)){ InlineJavaUtils.debug(3, "found a " + name + (constructor ? " constructor" : " method")) ; if (constructor){ params = ((Constructor)m).getParameterTypes() ; } else{ params = ((Method)m).getParameterTypes() ; } // Now we check if the signatures match String sign = InlineJavaUtils.CreateSignature(params, ",") ; InlineJavaUtils.debug(3, sign + " = " + signature + "?") ; if (signature.equals(sign)){ InlineJavaUtils.debug(3, "has matching signature " + sign) ; ml.add(ml.size(), m) ; member_cache.put(key, m) ; break ; } } } } // Now we got a list of matching methods (actually 0 or 1). // We have to figure out which one we will call. if (ml.size() == 0){ // Nothing matched. Maybe we got a default constructor if ((constructor)&&(signature.equals("()"))){ ret.add(0, null) ; ret.add(1, new Object [] {}) ; ret.add(2, new Class [] {}) ; } else{ throw new InlineJavaException( (constructor ? "Constructor " : "Method ") + name + " for class " + c.getName() + " with signature " + signature + " not found") ; } } else if (ml.size() == 1){ // Now we need to force the arguments received to match // the methods signature. Member m = (Member)ml.get(0) ; if (constructor){ params = ((Constructor)m).getParameterTypes() ; } else{ params = ((Method)m).getParameterTypes() ; } String msg = "In method " + name + " of class " + c.getName() + ": " ; try { ret.add(0, m) ; ret.add(1, ijc.CastArguments(params, args)) ; ret.add(2, params) ; } catch (InlineJavaCastException e){ throw new InlineJavaCastException(msg + e.getMessage()) ; } catch (InlineJavaException e){ throw new InlineJavaException(msg + e.getMessage()) ; } } return ret ; } /* Makes sure a member exists */ ArrayList ValidateMember(Class c, String name, StringTokenizer st) throws InlineJavaException { ArrayList ret = new ArrayList<>() ; // Extract member type String type = st.nextToken() ; // Extract the argument String arg = st.nextToken() ; String key = type + " " + c.getName() + "." + name ; ArrayList fl = new ArrayList<>() ; Class param = null ; Member cached = (Member)member_cache.get(key) ; if (cached != null){ InlineJavaUtils.debug(3, "member was cached") ; fl.add(fl.size(), cached) ; } else { Field fa[] = c.getFields() ; for (int i = 0 ; i < fa.length ; i++){ Field f = fa[(InlineJavaUtils.ReverseMembers() ? (fa.length - 1 - i) : i)] ; if (f.getName().equals(name)){ InlineJavaUtils.debug(3, "found a " + name + " member") ; param = f.getType() ; String t = param.getName() ; if (type.equals(t)){ InlineJavaUtils.debug(3, "has matching type " + t) ; fl.add(fl.size(), f) ; } } } } // Now we got a list of matching members. // We have to figure out which one we will call. if (fl.size() == 0){ throw new InlineJavaException( "Member " + name + " of type " + type + " for class " + c.getName() + " not found") ; } else { // Now we need to force the arguments received to match // the methods signature. // If we have more that one, we use the last one, which is the most // specialized Field f = (Field)fl.get(fl.size() - 1) ; member_cache.put(key, f) ; param = f.getType() ; String msg = "For member " + name + " of class " + c.getName() + ": " ; try { ret.add(0, f) ; ret.add(1, ijc.CastArgument(param, arg)) ; ret.add(2, param) ; } catch (InlineJavaCastException e){ throw new InlineJavaCastException(msg + e.getMessage()) ; } catch (InlineJavaException e){ throw new InlineJavaException(msg + e.getMessage()) ; } } return ret ; } /* This sets the response that will be returned to the Perl script */ void SetResponse(Object o) throws InlineJavaException { SetResponse(o, null) ; } void SetResponse(Object o, Class p) throws InlineJavaException { response = "ok " + SerializeObject(o, p) ; } String SerializeObject(Object o, Class p) throws InlineJavaException { Class c = (o == null ? null : o.getClass()) ; if ((c != null)&&(p != null)){ if (ijc.DoesExtend(c, p) < 0){ throw new InlineJavaException("Can't cast a " + c.getName() + " to a " + p.getName()) ; } else{ c = p ; } } if (o == null){ return "undef:" ; } else if ((ijc.ClassIsNumeric(c))||(ijc.ClassIsChar(c))||(ijc.ClassIsString(c))){ if ((ijs.GetNativeDoubles())&&(ijc.ClassIsDouble(c))){ Double d = (Double)o ; long l = Double.doubleToLongBits(d.doubleValue()) ; char ca[] = new char[8] ; for (int i = 0 ; i < 8 ; i++){ ca[i] = (char)((l >> (8 * i)) & 0xFF) ; } return "double:" + Encode(new String(ca)) ; } else { return "scalar:" + Encode(o.toString()) ; } } else if (ijc.ClassIsBool(c)){ String b = o.toString() ; return "scalar:" + Encode((b.equals("true") ? "1" : "0")) ; } else { if (! (o instanceof org.perl.inline.java.InlineJavaPerlObject)){ // Here we need to register the object in order to send // it back to the Perl script. boolean thrown = false ; String type = "object" ; if (o instanceof InlineJavaThrown){ thrown = true ; o = ((InlineJavaThrown)o).GetThrowable() ; c = o.getClass() ; } else if (ijc.ClassIsArray(c)){ type = "array" ; } else if (ijc.ClassIsHandle(c)){ type = "handle" ; } int id = ijs.PutObject(o) ; return "java_" + type + ":" + (thrown ? "1" : "0") + ":" + String.valueOf(id) + ":" + c.getName() ; } else { return "perl_object:" + ((InlineJavaPerlObject)o).GetId() + ":" + ((InlineJavaPerlObject)o).GetPkg() ; } } } byte[] DecodeToByteArray(String s){ return InlineJavaUtils.DecodeBase64(s.toCharArray()) ; } String Decode(String s) throws InlineJavaException { try { if (encoding != null){ return new String(DecodeToByteArray(s), encoding) ; } else { return new String(DecodeToByteArray(s)) ; } } catch (UnsupportedEncodingException e){ throw new InlineJavaException("Unsupported encoding: " + e.getMessage()) ; } } String EncodeFromByteArray(byte bytes[]){ return new String(InlineJavaUtils.EncodeBase64(bytes)) ; } String Encode(String s) throws InlineJavaException { try { if (encoding != null){ return EncodeFromByteArray(s.getBytes(encoding)) ; } else { return EncodeFromByteArray(s.getBytes()) ; } } catch (UnsupportedEncodingException e){ throw new InlineJavaException("Unsupported encoding: " + e.getMessage()) ; } } String GetResponse(){ return response ; } } Inline-Java-0.67/Java/sources/org/perl/inline/java/InlineJavaUserClassLink.java0000644000175000017500000000231514202030173027304 0ustar osboxesosboxesimport java.util.* ; import java.lang.reflect.* ; public class InlineJavaUserClassLink { public InlineJavaUserClassLink(){ } public Object invoke(Method m, Object o, Object p[]) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { return m.invoke(o, p) ; } public Object get(Field f, Object o) throws IllegalAccessException, IllegalArgumentException { return f.get(o) ; } public void set(Field f, Object o, Object p) throws IllegalAccessException, IllegalArgumentException { f.set(o, p) ; } public Object array_get(Object o, Integer idx){ return Array.get(o, idx.intValue()) ; } public void array_set(Object o, Integer idx, Object elem) throws IllegalArgumentException { Array.set(o, idx.intValue(), elem) ; } public Object create(Class p, Object args[], Class proto[]) throws NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { // This will allow usage of the default no-arg constructor if (proto.length == 0){ return p.getDeclaredConstructor().newInstance() ; } else{ Constructor con = (Constructor)p.getConstructor(proto) ; return con.newInstance(args) ; } } } Inline-Java-0.67/Java/sources/org/perl/inline/java/InlineJavaPerlInterpreter.java0000644000175000017500000000662714202030173027722 0ustar osboxesosboxespackage org.perl.inline.java ; import java.util.* ; import java.io.* ; /* InlineJavaPerlInterpreter This singleton class creates a PerlInterpreter object. To this object is bound an instance of InlineJavaServer that will allow communication with Perl. All communication with Perl must be done via InlineJavaPerlCaller in order to insure thread synchronization. Therefore all Perl actions will be implemented via functions in Inline::Java::PerlInterperter so that they can be called via InlineJavaPerlCaller */ public class InlineJavaPerlInterpreter extends InlineJavaPerlCaller { static private boolean inited = false ; static InlineJavaPerlInterpreter instance = null ; static boolean test = false ; static String libperl_so = "" ; protected InlineJavaPerlInterpreter() throws InlineJavaPerlException, InlineJavaException { init() ; InlineJavaUtils.debug(2, "constructing perl interpreter") ; construct() ; InlineJavaUtils.debug(2, "perl interpreter constructed") ; if (! libperl_so.equals("")){ evalNoReturn("require DynaLoader ;") ; evalNoReturn("DynaLoader::dl_load_file(\"" + libperl_so + "\", 0x01) ;") ; } if (test){ evalNoReturn("use blib ;") ; } evalNoReturn("use Inline::Java::PerlInterpreter ;") ; } synchronized static public InlineJavaPerlInterpreter create() throws InlineJavaPerlException, InlineJavaException { if (instance == null){ // Here we create a temporary InlineJavaServer instance in order to be able to instanciate // ourselves. When we create InlineJavaPerlInterpreter, the instance will be overriden. InlineJavaUtils.debug(2, "creating temporary JNI InlineJavaServer") ; InlineJavaServer.jni_main(InlineJavaUtils.get_debug(), false) ; InlineJavaUtils.debug(2, "temporary JNI InlineJavaServer created") ; InlineJavaUtils.debug(2, "creating InlineJavaPerlInterpreter") ; instance = new InlineJavaPerlInterpreter() ; InlineJavaUtils.debug(2, "InlineJavaPerlInterpreter created") ; } return instance ; } synchronized static protected void init() throws InlineJavaException { init("install") ; } synchronized static protected void init(String mode) throws InlineJavaException { InlineJavaPerlCaller.init() ; if (! inited){ test = (mode.equals("test") ? true : false) ; try { String perlinterpreter_so = GetBundle().getString("inline_java_perlinterpreter_so_" + mode) ; File f = new File(perlinterpreter_so) ; if (! f.exists()){ throw new InlineJavaException("Can't initialize PerlInterpreter " + "functionnality: PerlInterpreter extension (" + perlinterpreter_so + ") can't be found") ; } // Load the PerlInterpreter shared object InlineJavaUtils.debug(2, "loading shared library " + perlinterpreter_so) ; System.load(perlinterpreter_so) ; InlineJavaUtils.debug(2, "shared library " + perlinterpreter_so + " loaded") ; libperl_so = GetBundle().getString("inline_java_libperl_so") ; inited = true ; } catch (MissingResourceException mre){ throw new InlineJavaException("Error loading InlineJava.properties resource: " + mre.getMessage()) ; } } } synchronized static private native void construct() ; synchronized static private native void evalNoReturn(String code) throws InlineJavaPerlException ; synchronized static private native void destruct() ; synchronized static public void destroy() { if (instance != null){ destruct() ; instance = null ; } } } Inline-Java-0.67/Java/sources/org/perl/inline/java/InlineJavaException.java0000644000175000017500000000022014202030173026511 0ustar osboxesosboxespackage org.perl.inline.java ; public class InlineJavaException extends Exception { public InlineJavaException(String s) { super(s) ; } } Inline-Java-0.67/Java/sources/org/perl/inline/java/InlineJavaHandle.java0000644000175000017500000000645214202030173025763 0ustar osboxesosboxespackage org.perl.inline.java ; import java.util.* ; import java.io.* ; public class InlineJavaHandle { private static final String charset = "ISO-8859-1" ; static String read(Object o, int len) throws InlineJavaException, IOException { String ret = null ; if (InlineJavaClass.ClassIsReadHandle(o.getClass())){ if (o instanceof java.io.Reader){ char buf[] = new char[len] ; int rc = ((java.io.Reader)o).read(buf) ; if (rc != -1){ ret = new String(buf) ; } } else { byte buf[] = new byte[len] ; int rc = ((java.io.InputStream)o).read(buf) ; if (rc != -1){ ret = new String(buf, charset) ; } } } else { throw new InlineJavaException("Can't read from non-readhandle object (" + o.getClass().getName() + ")") ; } return ret ; } static String readLine(Object o) throws InlineJavaException, IOException { String ret = null ; if (InlineJavaClass.ClassIsReadHandle(o.getClass())){ if (o instanceof java.io.BufferedReader){ ret = ((java.io.BufferedReader)o).readLine() ; } else { throw new InlineJavaException("Can't read line from non-buffered Reader or InputStream") ; } } else { throw new InlineJavaException("Can't read line from non-readhandle object (" + o.getClass().getName() + ")") ; } return ret ; } static Object makeBuffered(Object o) throws InlineJavaException, IOException { Object ret = null ; if (InlineJavaClass.ClassIsReadHandle(o.getClass())){ if (o instanceof java.io.BufferedReader){ ret = (java.io.BufferedReader)o ; } else if (o instanceof java.io.Reader){ ret = new BufferedReader((java.io.Reader)o) ; } else { ret = new BufferedReader(new InputStreamReader((java.io.InputStream)o, charset)) ; } } else if (InlineJavaClass.ClassIsWriteHandle(o.getClass())){ if (o instanceof java.io.BufferedWriter){ ret = (java.io.BufferedWriter)o ; } else if (o instanceof java.io.Writer){ ret = new BufferedWriter((java.io.Writer)o) ; } else { ret = new BufferedWriter(new OutputStreamWriter((java.io.OutputStream)o, charset)) ; } } else { throw new InlineJavaException("Can't make non-handle object buffered (" + o.getClass().getName() + ")") ; } return ret ; } static int write(Object o, String str) throws InlineJavaException, IOException { int ret = -1 ; if (InlineJavaClass.ClassIsWriteHandle(o.getClass())){ if (o instanceof java.io.Writer){ ((java.io.Writer)o).write(str) ; ret = str.length() ; } else { byte b[] = str.getBytes(charset) ; ((java.io.OutputStream)o).write(b) ; ret = b.length ; } } else { throw new InlineJavaException("Can't write to non-writehandle object (" + o.getClass().getName() + ")") ; } return ret ; } static void close(Object o) throws InlineJavaException, IOException { if (InlineJavaClass.ClassIsReadHandle(o.getClass())){ if (o instanceof java.io.Reader){ ((java.io.Reader)o).close() ; } else { ((java.io.InputStream)o).close() ; } } else if (InlineJavaClass.ClassIsWriteHandle(o.getClass())){ if (o instanceof java.io.Writer){ ((java.io.Writer)o).close() ; } else { ((java.io.OutputStream)o).close() ; } } else { throw new InlineJavaException("Can't close non-handle object (" + o.getClass().getName() + ")") ; } } } Inline-Java-0.67/Java/sources/org/perl/inline/java/InlineJavaUtils.java0000644000175000017500000001127614202030173025670 0ustar osboxesosboxespackage org.perl.inline.java ; import java.util.* ; /* Creates a string representing a method signature */ class InlineJavaUtils { private static int debug = 0 ; public synchronized static void set_debug(int d){ debug = d ; } public static int get_debug(){ return debug ; } static String CreateSignature(Class param[]){ return CreateSignature(param, ", ") ; } static String CreateSignature(Class param[], String del){ StringBuffer ret = new StringBuffer() ; for (int i = 0 ; i < param.length ; i++){ if (i > 0){ ret.append(del) ; } ret.append(param[i].getName()) ; } return "(" + ret.toString() + ")" ; } synchronized static void debug(int level, String s) { if ((debug > 0)&&(debug >= level)){ StringBuffer sb = new StringBuffer() ; for (int i = 0 ; i < level ; i++){ sb.append(" ") ; } System.err.println("[java][" + level + "]" + sb.toString() + s) ; System.err.flush() ; } } static void Fatal(String msg){ System.err.println(msg) ; System.err.flush() ; System.exit(1) ; } static boolean ReverseMembers() { String v = System.getProperty("java.version") ; boolean no_rev = ((v.startsWith("1.2"))||(v.startsWith("1.3"))) ; return (! no_rev) ; } /* Base64 stuff. This section conatins code by Christian d'Heureuse that is licended under the LGPL. Used by permission: From: Christian d'Heureuse To: Patrick LeBoutillier Date: Aug 11, 2005 4:45 AM Subject: Re: Base64Coder > I was wondering if you can grant me permission to include your > code in my project. Yes, I grant you permission to include the Base64Coder class in your project. * * A Base64 Encoder/Decoder. * * This class is used to encode and decode data in Base64 format * as described in RFC 1521. * *

* Copyright 2003: Christian d'Heureuse, Inventec Informatik AG, Switzerland.
* License: This is "Open Source" software and released under the GNU/LGPL license. * It is provided "as is" without warranty of any kind. Please contact the author for other licensing arrangements.
* Home page: www.source-code.biz
* *

* Version history:
* 2003-07-22 Christian d'Heureuse (chdh): Module created.
* 2005-08-11 chdh: Lincense changed from GPL to LGPL. * */ // Mapping table from 6-bit nibbles to Base64 characters. private static char[] map1 = new char[64]; static { int i=0; for (char c='A'; c<='Z'; c++) map1[i++] = c; for (char c='a'; c<='z'; c++) map1[i++] = c; for (char c='0'; c<='9'; c++) map1[i++] = c; map1[i++] = '+'; map1[i++] = '/'; } // Mapping table from Base64 characters to 6-bit nibbles. private static byte[] map2 = new byte[128]; static { for (int i=0; i>> 2; int o1 = ((i0 & 3) << 4) | (i1 >>> 4); int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); int o3 = i2 & 0x3F; out[op++] = map1[o0]; out[op++] = map1[o1]; out[op] = op < oDataLen ? map1[o2] : '='; op++; out[op] = op < oDataLen ? map1[o3] : '='; op++; } return out; } public static byte[] DecodeBase64(char[] in){ int iLen = in.length; if (iLen%4 != 0) throw new IllegalArgumentException ("Length of Base64 encoded input string is not a multiple of 4."); while (iLen > 0 && in[iLen-1] == '=') iLen--; int oLen = (iLen*3) / 4; byte[] out = new byte[oLen]; int ip = 0; int op = 0; while (ip < iLen) { int i0 = in[ip++]; int i1 = in[ip++]; int i2 = ip < iLen ? in[ip++] : 'A'; int i3 = ip < iLen ? in[ip++] : 'A'; if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); int b0 = map2[i0]; int b1 = map2[i1]; int b2 = map2[i2]; int b3 = map2[i3]; if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); int o0 = ( b0 <<2) | (b1>>>4); int o1 = ((b1 & 0xf)<<4) | (b2>>>2); int o2 = ((b2 & 3)<<6) | b3; out[op++] = (byte)o0; if (opnew(args) ; */ public InlineJavaPerlObject(String _pkg, Object args[]) throws InlineJavaPerlException, InlineJavaException { pkg = _pkg ; InlineJavaPerlObject stub = (InlineJavaPerlObject)CallPerlStaticMethod(pkg, "new", args, getClass()) ; id = stub.GetId() ; stub.id = 0 ; } /* This is just a stub for already existing objects */ InlineJavaPerlObject(String _pkg, int _id) throws InlineJavaException { pkg = _pkg ; id = _id ; } int GetId(){ return id ; } public String GetPkg(){ return pkg ; } public Object InvokeMethod(String name, Object args[]) throws InlineJavaPerlException, InlineJavaException { return InvokeMethod(name, args, null) ; } public Object InvokeMethod(String name, Object args[], Class cast) throws InlineJavaPerlException, InlineJavaException { return CallPerlMethod(this, name, args, cast) ; } public void Dispose() throws InlineJavaPerlException, InlineJavaException { Dispose(false) ; } protected void Dispose(boolean gc) throws InlineJavaPerlException, InlineJavaException { if (id != 0){ CallPerlSub("Inline::Java::Callback::java_finalize", new Object [] {Integer.valueOf(id), Boolean.valueOf(gc)}) ; } } /* unavoidable due to Perl reference-count behaviour */ @SuppressWarnings("deprecation") protected void finalize() throws Throwable { try { Dispose(true) ; } finally { super.finalize() ; } } } Inline-Java-0.67/Java/sources/org/perl/inline/java/InlineJavaUserClassLoader.java0000644000175000017500000001435114202030173027620 0ustar osboxesosboxespackage org.perl.inline.java ; import java.net.* ; import java.util.* ; import java.io.* ; import java.lang.reflect.* ; /* This is the ClassLoader that loads the users code. It is also used to pass reflection calls to the InlineJavaUserClassLink so that it will execute them. */ class InlineJavaUserClassLoader extends URLClassLoader { private HashMap urls = new HashMap<>() ; private Object link = null ; private Method invoke = null ; private Method get = null ; private Method set = null ; private Method array_get = null ; private Method array_set = null ; private Method create = null ; public InlineJavaUserClassLoader(){ // Added Thread.currentThread().getContextClassLoader() so that the code works // in Tomcat and possibly other embedded environments asa well. super(new URL [] {}, Thread.currentThread().getContextClassLoader()) ; } public void AddClassPath(String path) throws InlineJavaException { try { File p = new File(path) ; URL u = p.toURI().toURL() ; if (urls.get(u) == null){ urls.put(u, "1") ; addURL(u) ; InlineJavaUtils.debug(2, "added " + u + " to classpath") ; } } catch (MalformedURLException e){ throw new InlineJavaException("Can't add invalid classpath entry '" + path + "'") ; } } synchronized private void check_link() throws InlineJavaException { if (link == null){ try { InlineJavaUtils.debug(1, "loading InlineJavaUserClassLink via InlineJavaUserClassLoader") ; Class c = Class.forName("InlineJavaUserClassLink", true, this) ; link = c.getDeclaredConstructor().newInstance() ; invoke = find_method(c, "invoke") ; get = find_method(c, "get") ; set = find_method(c, "set") ; array_get = find_method(c, "array_get") ; array_set = find_method(c, "array_set") ; create = find_method(c, "create") ; } catch (Exception e){ throw new InlineJavaException("InlineJavaUserClassLoader can't load InlineJavaUserClassLink: invalid classpath setup (" + e.getClass().getName() + ": " + e.getMessage() + ")") ; } } } private Method find_method(Class c, String name) throws InlineJavaException { Method ml[] = c.getMethods() ; for (int i = 0 ; i < ml.length ; i++){ if (ml[i].getName().equals(name)){ return ml[i] ; } } throw new InlineJavaException("Can't find method '" + name + "' in class InlineJavaUserClassLink") ; } private Object invoke_via_link(Method m, Object p[]) throws NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InlineJavaException { try { return m.invoke(link, p) ; } catch (IllegalAccessException e){ throw new InlineJavaException("Can't invoke method from class InlineJavaUserClassLink: IllegalAccessException") ; } catch (IllegalArgumentException e){ throw new InlineJavaException("Can't invoke method from class InlineJavaUserClassLink: IllegalArgumentException") ; } catch (InvocationTargetException e){ Throwable t = e.getTargetException() ; if (t instanceof NoSuchMethodException){ throw (NoSuchMethodException)t ; } else if (t instanceof InstantiationException){ throw (InstantiationException)t ; } else if (t instanceof IllegalAccessException){ throw (IllegalAccessException)t ; } if (t instanceof IllegalAccessException){ throw (IllegalAccessException)t ; } else if (t instanceof IllegalArgumentException){ throw (IllegalArgumentException)t ; } else if (t instanceof InvocationTargetException){ throw (InvocationTargetException)t ; } // Not sure if this is really necessary, but... else if (t instanceof RuntimeException){ RuntimeException re = (RuntimeException)t ; throw re ; } else{ // In theory this case is impossible. throw new InlineJavaException("Unexpected exception of type '" + t.getClass().getName() + "': " + t.getMessage()) ; } } } public Object invoke(Method m, Object o, Object p[]) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InlineJavaException { check_link() ; try { return invoke_via_link(invoke, new Object [] {m, o, p}) ; } catch (NoSuchMethodException me){/* Impossible */} catch (InstantiationException ie){/* Impossible */} return null ; } public Object get(Field f, Object o) throws IllegalAccessException, IllegalArgumentException, InlineJavaException { check_link() ; try { return invoke_via_link(get, new Object [] {f, o}) ; } catch (NoSuchMethodException me){/* Impossible */} catch (InstantiationException ie){/* Impossible */} catch (InvocationTargetException e){/* Impossible */} return null ; } public void set(Field f, Object o, Object p) throws IllegalAccessException, IllegalArgumentException, InlineJavaException { check_link() ; try { invoke_via_link(set, new Object [] {f, o, p}) ; } catch (NoSuchMethodException me){/* Impossible */} catch (InstantiationException ie){/* Impossible */} catch (InvocationTargetException e){/* Impossible */} } public Object array_get(Object o, int idx) throws InlineJavaException { check_link() ; try { return invoke_via_link(array_get, new Object [] {o, Integer.valueOf(idx)}) ; } catch (NoSuchMethodException me){/* Impossible */} catch (InstantiationException ie){/* Impossible */} catch (IllegalAccessException iae){/* Impossible */} catch (IllegalArgumentException iae){/* Impossible */} catch (InvocationTargetException e){/* Impossible */} return null ; } public void array_set(Object o, int idx, Object elem) throws IllegalArgumentException, InlineJavaException { check_link() ; try { invoke_via_link(array_set, new Object [] {o, Integer.valueOf(idx), elem}) ; } catch (NoSuchMethodException me){/* Impossible */} catch (InstantiationException ie){/* Impossible */} catch (IllegalAccessException iae){/* Impossible */} catch (InvocationTargetException e){/* Impossible */} } public Object create(Class p, Object args[], Class proto[]) throws NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InlineJavaException { check_link() ; return invoke_via_link(create, new Object [] {p, args, proto}) ; } } Inline-Java-0.67/Java/sources/org/perl/inline/java/InlineJavaPerlException.java0000644000175000017500000000056414202030173027347 0ustar osboxesosboxespackage org.perl.inline.java ; public class InlineJavaPerlException extends Exception { private Object obj ; public InlineJavaPerlException(Object o){ super(o.toString()) ; obj = o ; } public InlineJavaPerlException(String s){ super(s) ; obj = s ; } public Object GetObject(){ return obj ; } public String GetString(){ return (String)obj ; } } Inline-Java-0.67/Java/sources/org/perl/inline/java/InlineJavaPerlNatives.java0000644000175000017500000001752214202030173027024 0ustar osboxesosboxespackage org.perl.inline.java ; import java.lang.reflect.* ; import java.util.* ; import java.io.* ; public class InlineJavaPerlNatives extends InlineJavaPerlCaller { static private boolean inited = false ; static private Map registered_classes = Collections.synchronizedMap(new HashMap()) ; static private Map registered_methods = Collections.synchronizedMap(new HashMap()) ; protected InlineJavaPerlNatives() throws InlineJavaException { init() ; RegisterPerlNatives(this.getClass()) ; } static protected void init() throws InlineJavaException { init("install") ; } synchronized static protected void init(String mode) throws InlineJavaException { InlineJavaPerlCaller.init() ; if (! inited){ try { String perlnatives_so = GetBundle().getString("inline_java_perlnatives_so_" + mode) ; File f = new File(perlnatives_so) ; if (! f.exists()){ throw new InlineJavaException("Can't initialize PerlNatives " + "functionnality: PerlNatives extension (" + perlnatives_so + ") can't be found") ; } try { Class ste_class = Class.forName("java.lang.StackTraceElement") ; } catch (ClassNotFoundException cnfe){ throw new InlineJavaException("Can't initialize PerlNatives " + "functionnality: Java 1.4 or higher required (current is " + System.getProperty("java.version") + ").") ; } // Load the Natives shared object InlineJavaUtils.debug(2, "loading shared library " + perlnatives_so) ; System.load(perlnatives_so) ; inited = true ; } catch (MissingResourceException mre){ throw new InlineJavaException("Error loading InlineJava.properties resource: " + mre.getMessage()) ; } } } // This method actually does the real work of registering the methods. synchronized private void RegisterPerlNatives(Class c) throws InlineJavaException { if (registered_classes.get(c) == null){ InlineJavaUtils.debug(3, "registering natives for class " + c.getName()) ; Constructor constructors[] = c.getDeclaredConstructors() ; Method methods[] = c.getDeclaredMethods() ; registered_classes.put(c, c) ; for (int i = 0 ; i < constructors.length ; i++){ Constructor x = constructors[i] ; if (Modifier.isNative(x.getModifiers())){ RegisterMethod(c, "new", x.getParameterTypes(), c) ; } } for (int i = 0 ; i < methods.length ; i++){ Method x = methods[i] ; if (Modifier.isNative(x.getModifiers())){ RegisterMethod(c, x.getName(), x.getParameterTypes(), x.getReturnType()) ; } } } } private void RegisterMethod(Class c, String mname, Class params[], Class rt) throws InlineJavaException { String cname = c.getName() ; InlineJavaUtils.debug(3, "registering native method " + mname + " for class " + cname) ; // Check return type if ((! Object.class.isAssignableFrom(rt))&&(rt != void.class)){ throw new InlineJavaException("Perl native method " + mname + " of class " + cname + " can only have Object or void return types (not " + rt.getName() + ")") ; } // fmt starts with the return type, which for now is Object only (or void). StringBuffer fmt = new StringBuffer("L") ; StringBuffer sign = new StringBuffer("(") ; for (int i = 0 ; i < params.length ; i++){ String code = InlineJavaClass.FindJNICode(params[i]) ; sign.append(code) ; char ch = code.charAt(0) ; char f = ch ; if (f == '['){ // Arrays are Objects... f = 'L' ; } fmt.append(new String(new char [] {f})) ; } sign.append(")") ; sign.append(InlineJavaClass.FindJNICode(rt)) ; InlineJavaUtils.debug(3, "signature is " + sign) ; InlineJavaUtils.debug(3, "format is " + fmt) ; // For now, no method overloading so no signature necessary String meth = cname + "." + mname ; String prev = (String)registered_methods.get(meth) ; if (prev != null){ throw new InlineJavaException("There already is a native method '" + mname + "' registered for class '" + cname + "'") ; } registered_methods.put(meth, fmt.toString()) ; // call the native method to hook it up RegisterMethod(c, mname, sign.toString()) ; } // This native method will call RegisterNative to hook up the magic // method implementation for the method. native private void RegisterMethod(Class c, String name, String signature) throws InlineJavaException ; // This method will be called from the native side. We need to figure // out who this method is and then look in up in the // registered method list and return the format. private String LookupMethod() throws InlineJavaException { InlineJavaUtils.debug(3, "entering LookupMethod") ; String caller[] = GetNativeCaller() ; String meth = caller[0] + "." + caller[1] ; String fmt = (String)registered_methods.get(meth) ; if (fmt == null){ throw new InlineJavaException("Native method " + meth + " is not registered") ; } InlineJavaUtils.debug(3, "exiting LookupMethod") ; return fmt ; } private Object InvokePerlMethod(Object args[]) throws InlineJavaException, InlineJavaPerlException { InlineJavaUtils.debug(3, "entering InvokePerlMethod") ; String caller[] = GetNativeCaller() ; String pkg = caller[0] ; String method = caller[1] ; // Transform the Java class name into the Perl package name StringTokenizer st = new StringTokenizer(pkg, ".") ; StringBuffer perl_sub = new StringBuffer() ; // Starting with "::" means that the package is relative to the caller package while (st.hasMoreTokens()){ perl_sub.append("::" + st.nextToken()) ; } perl_sub.append("::" + method) ; for (int i = 0 ; i < args.length ; i++){ InlineJavaUtils.debug(3, "InvokePerlMethod argument " + i + " = " + args[i]) ; } Object ret = CallPerlSub(perl_sub.toString(), args) ; InlineJavaUtils.debug(3, "exiting InvokePerlMethod") ; return ret ; } // This method must absolutely be called by a method DIRECTLY called // by generic_perl_native private String[] GetNativeCaller() throws InlineJavaException { InlineJavaUtils.debug(3, "entering GetNativeCaller") ; Class ste_class = null ; try { ste_class = Class.forName("java.lang.StackTraceElement") ; } catch (ClassNotFoundException cnfe){ throw new InlineJavaException("Can't load class java.lang.StackTraceElement") ; } Throwable exec_point = new Throwable() ; try { Method m = exec_point.getClass().getMethod("getStackTrace", new Class [] {}) ; Object stack = m.invoke(exec_point, new Object [] {}) ; if (Array.getLength(stack) <= 2){ throw new InlineJavaException("Improper use of InlineJavaPerlNatives.GetNativeCaller (call stack too short)") ; } Object ste = Array.get(stack, 2) ; m = ste.getClass().getMethod("isNativeMethod", new Class [] {}) ; Boolean is_nm = (Boolean)m.invoke(ste, new Object [] {}) ; if (! is_nm.booleanValue()){ throw new InlineJavaException("Improper use of InlineJavaPerlNatives.GetNativeCaller (caller is not native)") ; } m = ste.getClass().getMethod("getClassName", new Class [] {}) ; String cname = (String)m.invoke(ste, new Object [] {}) ; m = ste.getClass().getMethod("getMethodName", new Class [] {}) ; String mname = (String)m.invoke(ste, new Object [] {}) ; InlineJavaUtils.debug(3, "exiting GetNativeCaller") ; return new String [] {cname, mname} ; } catch (NoSuchMethodException nsme){ throw new InlineJavaException("Error manipulating java.lang.StackTraceElement classes: " + nsme.getMessage()) ; } catch (IllegalAccessException iae){ throw new InlineJavaException("Error manipulating java.lang.StackTraceElement classes: " + iae.getMessage()) ; } catch (InvocationTargetException ite){ // None of the methods invoked throw exceptions, so... throw new InlineJavaException("Exception caught while manipulating java.lang.StackTraceElement classes: " + ite.getTargetException()) ; } } } Inline-Java-0.67/Java/JNI.xs0000644000175000017500000001621514202030173015343 0ustar osboxesosboxes#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #ifdef __CYGWIN__ #include "w32api/basetyps.h" #endif /* Include the JNI header file */ #include "jni.h" /* JNI structure */ typedef struct { JavaVM *jvm ; jclass ijs_class ; jobject ijs ; jmethodID jni_main_mid ; jmethodID process_command_mid ; jint debug ; int embedded ; int native_doubles ; int destroyed ; } InlineJavaJNIVM ; void shutdown_JVM(InlineJavaJNIVM *this){ if ((! this->embedded)&&(! this->destroyed)){ (*(this->jvm))->DestroyJavaVM(this->jvm) ; this->destroyed = 1 ; } } JNIEnv *get_env(InlineJavaJNIVM *this){ JNIEnv *env ; (*(this->jvm))->AttachCurrentThread(this->jvm, ((void **)&env), NULL) ; return env ; } /* This is only used to trap exceptions from Perl. */ void check_exception_from_perl(JNIEnv *env, char *msg){ if ((*(env))->ExceptionCheck(env)){ (*(env))->ExceptionDescribe(env) ; (*(env))->ExceptionClear(env) ; croak("%s", msg) ; } } void throw_ije(JNIEnv *env, char *msg){ jclass ije ; ije = (*(env))->FindClass(env, "org/perl/inline/java/InlineJavaException") ; if ((*(env))->ExceptionCheck(env)){ (*(env))->ExceptionDescribe(env) ; (*(env))->ExceptionClear(env) ; (*(env))->FatalError(env, "Can't find class InlineJavaException: exiting...") ; } (*(env))->ThrowNew(env, ije, msg) ; } jstring JNICALL jni_callback(JNIEnv *env, jobject obj, jstring cmd){ dSP ; jstring resp ; char *c = (char *)((*(env))->GetStringUTFChars(env, cmd, NULL)) ; char *r = NULL ; int count = 0 ; SV *hook = NULL ; char msg[128] ; ENTER ; SAVETMPS ; PUSHMARK(SP) ; XPUSHs(&PL_sv_undef) ; XPUSHs(sv_2mortal(newSVpv(c, 0))) ; PUTBACK ; (*(env))->ReleaseStringUTFChars(env, cmd, c) ; count = perl_call_pv("Inline::Java::Callback::InterceptCallback", G_ARRAY|G_EVAL) ; SPAGAIN ; /* Check the eval */ if (SvTRUE(ERRSV)){ STRLEN n_a ; throw_ije(env, SvPV(ERRSV, n_a)) ; } else{ if (count != 2){ sprintf(msg, "Invalid return value from Inline::Java::Callback::InterceptCallback: %d", count) ; throw_ije(env, msg) ; } } /* The first thing to pop is a reference to the returned object, which we must keep around long enough so that it is not deleted before control gets back to Java. This is because this object may be returned be the callback, and when it gets back to Java it will already be deleted. */ hook = perl_get_sv("Inline::Java::Callback::OBJECT_HOOK", FALSE) ; sv_setsv(hook, POPs) ; r = (char *)POPp ; resp = (*(env))->NewStringUTF(env, r) ; PUTBACK ; FREETMPS ; LEAVE ; return resp ; } /*****************************************************************************/ MODULE = Inline::Java::JNI PACKAGE = Inline::Java::JNI PROTOTYPES: DISABLE InlineJavaJNIVM * new(CLASS, classpath, args, embedded, debug, native_doubles) char * CLASS char * classpath SV * args int embedded int debug int native_doubles PREINIT: JavaVMInitArgs vm_args ; JavaVMOption *options ; JNIEnv *env ; JNINativeMethod nm ; jint res ; char *cp ; int args_len ; int i ; SV ** val = NULL ; STRLEN n_a ; CODE: args = SvRV(args) ; RETVAL = (InlineJavaJNIVM *)safemalloc(sizeof(InlineJavaJNIVM)) ; if (RETVAL == NULL){ croak("Can't create InlineJavaJNIVM") ; } RETVAL->ijs = NULL ; RETVAL->debug = debug ; RETVAL->embedded = embedded ; RETVAL->native_doubles = native_doubles ; RETVAL->destroyed = 0 ; /* Figure out the length of the args array */ args_len = av_len((AV *)args) + 1 ; vm_args.version = JNI_VERSION_1_2 ; options = (JavaVMOption *)malloc((2 + args_len) * sizeof(JavaVMOption)) ; vm_args.options = options ; vm_args.nOptions = 0 ; vm_args.ignoreUnrecognized = JNI_FALSE ; options[vm_args.nOptions++].optionString = ((RETVAL->debug > 5) ? "-verbose" : "-verbose:") ; cp = (char *)malloc((strlen(classpath) + 32) * sizeof(char)) ; sprintf(cp, "-Djava.class.path=%s", classpath) ; options[vm_args.nOptions++].optionString = cp ; for (i = 0 ; i < args_len ; i++){ val = av_fetch((AV *)args, i, 0) ; if (val != NULL){ options[vm_args.nOptions++].optionString = SvPV(*val, n_a) ; } } /* Embedded patch and idea by Doug MacEachern */ if (RETVAL->embedded) { /* We are already inside a JVM */ jint n = 0 ; res = JNI_GetCreatedJavaVMs(&(RETVAL->jvm), 1, &n) ; if (n <= 0) { /* res == 0 even if no JVMs are alive */ res = -1; } if (res < 0) { croak("Can't find any created Java JVMs") ; } env = get_env(RETVAL) ; } else { /* Create the Java VM */ res = JNI_CreateJavaVM(&(RETVAL->jvm), (void **)&(env), &vm_args) ; if (res < 0) { croak("Can't create Java JVM using JNI") ; } } free(options) ; free(cp) ; /* Load the classes that we will use */ RETVAL->ijs_class = (*(env))->FindClass(env, "org/perl/inline/java/InlineJavaServer") ; check_exception_from_perl(env, "Can't find class InlineJavaServer") ; RETVAL->ijs_class = (*(env))->NewGlobalRef(env, RETVAL->ijs_class) ; /* Get the method ids that are needed later */ RETVAL->jni_main_mid = (*(env))->GetStaticMethodID(env, RETVAL->ijs_class, "jni_main", "(IZ)Lorg/perl/inline/java/InlineJavaServer;") ; check_exception_from_perl(env, "Can't find method jni_main in class InlineJavaServer") ; RETVAL->process_command_mid = (*(env))->GetMethodID(env, RETVAL->ijs_class, "ProcessCommand", "(Ljava/lang/String;)Ljava/lang/String;") ; check_exception_from_perl(env, "Can't find method ProcessCommand in class InlineJavaServer") ; /* Register the callback function */ nm.name = "jni_callback" ; nm.signature = "(Ljava/lang/String;)Ljava/lang/String;" ; nm.fnPtr = jni_callback ; (*(env))->RegisterNatives(env, RETVAL->ijs_class, &nm, 1) ; check_exception_from_perl(env, "Can't register method jni_callback in class InlineJavaServer") ; OUTPUT: RETVAL void shutdown(this) InlineJavaJNIVM * this CODE: shutdown_JVM(this) ; void DESTROY(this) InlineJavaJNIVM * this CODE: shutdown_JVM(this) ; safefree(this) ; void create_ijs(this) InlineJavaJNIVM * this PREINIT: JNIEnv *env ; CODE: env = get_env(this) ; this->ijs = (*(env))->CallStaticObjectMethod(env, this->ijs_class, this->jni_main_mid, this->debug, this->native_doubles) ; check_exception_from_perl(env, "Can't call jni_main in class InlineJavaServer") ; this->ijs = (*(env))->NewGlobalRef(env, this->ijs) ; char * process_command(this, data) InlineJavaJNIVM * this char * data PREINIT: JNIEnv *env ; jstring cmd ; jstring resp ; SV *hook = NULL ; CODE: env = get_env(this) ; cmd = (*(env))->NewStringUTF(env, data) ; check_exception_from_perl(env, "Can't create java.lang.String") ; resp = (*(env))->CallObjectMethod(env, this->ijs, this->process_command_mid, cmd) ; /* Thanks Dave Blob for spotting this. This is necessary since this code never really returns to Java It simply calls into Java and comes back. */ (*(env))->DeleteLocalRef(env, cmd); check_exception_from_perl(env, "Can't call ProcessCommand in class InlineJavaServer") ; hook = perl_get_sv("Inline::Java::Callback::OBJECT_HOOK", FALSE) ; sv_setsv(hook, &PL_sv_undef) ; RETVAL = (char *)((*(env))->GetStringUTFChars(env, resp, NULL)) ; OUTPUT: RETVAL CLEANUP: (*(env))->ReleaseStringUTFChars(env, resp, RETVAL) ; (*(env))->DeleteLocalRef(env, resp) ; Inline-Java-0.67/Java/JNI.pm0000644000175000017500000000130514202030173015317 0ustar osboxesosboxespackage Inline::Java::JNI ; @Inline::Java::JNI::ISA = qw(DynaLoader) ; use strict ; $Inline::Java::JNI::VERSION = '0.53_90' ; use DynaLoader ; use Carp ; use File::Basename ; if ($^O eq 'solaris'){ load_lib('-lthread') ; } sub load_lib { my $l = shift ; my $lib = (DynaLoader::dl_findfile($l))[0] ; if ((! $lib)||(! defined(DynaLoader::dl_load_file($lib, 0x01)))){ carp("Couldn't find or load $l.") ; } } # A place to attach the Inline object that is currently in Java land $Inline::Java::JNI::INLINE_HOOK = undef ; eval { Inline::Java::JNI->bootstrap($Inline::Java::JNI::VERSION) ; } ; if ($@){ croak "Can't load JNI module. Did you build it at install time?\nError: $@" ; } 1 ; Inline-Java-0.67/Java/Makefile.PL0000644000175000017500000001771214202030173016324 0ustar osboxesosboxesuse ExtUtils::MakeMaker ; use File::Find ; use strict ; use File::Spec ; # The file we just produced in the parent Makefile.PL require "Inline/Java/default_j2sdk.pl" ; my $build_jni = $main::build_jni ; my $build_perl_natives = $main::build_perl_natives ; my $build_perl_interpreter = $main::build_perl_interpreter ; my $jvm_lib_type = $main::jvm_lib_type ; my $jvm_lib = Inline::Java::Portable::portable('JVM_LIB') ; my $jvm_so = Inline::Java::Portable::portable('JVM_SO') ; my %so_dirs = () ; my @files = ( 'jni.h', 'jni_md.h', $jvm_lib, ) ; if ($jvm_so ne $jvm_lib){ push @files, $jvm_so ; } push @files, 'jvm.cfg' ; my $files = { 'jni.h' => { discard => qr/include-old/, }, 'jni_md.h' => { discard => qr/include-old/, }, $jvm_lib => { }, 'jvm.cfg' => { }, $jvm_so => { }, } ; foreach my $f (@files){ $files->{$f}->{selected} = undef ; $files->{$f}->{choices} = [] ; $files->{$f}->{default_choice} = 1 ; } my $build_jni_by_dflt = Inline::Java::Portable::portable("BUILD_JNI_BY_DFLT") ; if (! defined($build_jni)){ $build_jni = $build_jni_by_dflt; } if ($build_jni){ print "\nBuilding JNI extension.\n\n" ; my $jdk_dir = Inline::Java::get_default_j2sdk() ; my $symlink = Inline::Java::Portable::portable("GOT_SYMLINK") ; find( { wanted => \&search, ($symlink ? (follow_fast => 1, follow_skip => 2) : ()), }, $jdk_dir) ; my $type = FindDefaultVMType() ; if (defined($type)){ my $cnt = 1 ; foreach my $c (@{$files->{$jvm_so}->{choices}}){ if ($c =~ /$type/){ $files->{$jvm_so}->{default_choice} = $cnt ; } $cnt++ ; } } # We no longer need jvm.cfg from now on... pop @files ; my $done = 0 ; foreach my $f (@files){ my $cnt = scalar(@{$files->{$f}->{choices}}) ; if ($cnt == 0){ print "Can't locate file '$f' anywhere under '$jdk_dir'\n" ; $done = 1 ; last ; } elsif ($cnt == 1){ $files->{$f}->{selected} = $files->{$f}->{choices}->[0] ; } else { my $choose = 1 ; if (($f eq $jvm_lib)&&(defined($jvm_lib_type))){ my @matches = grep {/$jvm_lib_type/} @{$files->{$f}->{choices}} ; if (! scalar(@matches)){ print "WARNING: No $f type matching '$jvm_lib_type' found.\n\n" ; } elsif (scalar(@matches) == 1){ print "Automatically selecting '$matches[0]' for $f type.\n\n" ; $files->{$f}->{selected} = $matches[0] ; $choose = 0 ; } } Choose($f) if $choose ; } } if (! $done){ # We have all the required files selected. CleanSoDirs() ; # Cygwin: create gcc-compatible library wrapper for jvm.dll if ($^O eq 'cygwin') { my $lib = File::Spec->catfile(Cwd::cwd, 'libjvm.dll.a') ; my $dll = File::Spec->catfile($files->{$jvm_so}->{selected}, 'jvm.dll') ; print "Creating '$lib' for cygwin.\n\n" ; system("/usr/bin/dlltool --kill-at --dllname jvm.dll --output-lib '$lib' '$dll'") and print "Error attempting to create '$lib'\n" ; } print "Building with:\n" ; map { print " " . File::Spec->catfile($files->{$_}->{selected}, $_) . "\n" ;} @files ; $done = 0 ; if (! $done){ print "\nNote: In order for Inline::Java to use the JNI extension, you will need to\n" . "use the JNI configuration option or set the PERL_INLINE_JAVA_JNI environment\n" . "variable to a true value. You will also need to add the following directories\n" . "to your " . Inline::Java::Portable::portable('SO_LIB_PATH_VAR') . " environment variable:\n" ; @main::SO_DIRS = keys %so_dirs ; map {print " $_\n"; } @main::SO_DIRS ; print "See README.JNI for more information.\n\n" ; @main::I = map { Inline::Java::Portable::portable('SUB_FIX_MAKE_QUOTES', "-I$_") } ($files->{'jni.h'}->{selected}, $files->{'jni_md.h'}->{selected}) ; @main::L = map { Inline::Java::Portable::portable('SUB_FIX_MAKE_QUOTES', "-L$_") } ($files->{$jvm_lib}->{selected}) ; if ($^O eq 'cygwin') { push @main::L, Inline::Java::Portable::portable('SUB_FIX_MAKE_QUOTES', '-L' . Cwd::cwd); } my $DIR = [] ; if (! defined($build_perl_interpreter)){ print < 'Inline::Java::JNI', VERSION_FROM => 'JNI.pm', DIR => $DIR, PMLIBDIRS => [File::Spec->catdir('sources', 'org', 'perl', 'inline', 'java')], INC => join(' ', @main::I), LIBS => [join(' ', @main::L) . " -ljvm"], dynamic_lib => { OTHERLDFLAGS => Inline::Java::Portable::portable('OTHERLDFLAGS') }, # CCFLAGS => '-D_REENTRANT', ) ; } } } else{ print "\n" ; WriteMakefile( NAME => 'Inline::Java::JNI', VERSION_FROM => 'JNI.pm', DIR => [], PMLIBDIRS => [File::Spec->catdir('sources', 'org', 'perl', 'inline', 'java')], XS => {}, C => [] ) ; } ################################################# sub search { my $file = $_ ; my $ext = Inline::Java::Portable::portable('SO_EXT') ; if ($File::Find::dir =~ /jre/){ if ($file =~ /\.$ext$/){ my $dir = File::Spec->canonpath($File::Find::dir) ; $so_dirs{$dir} = 1 ; } } foreach my $f (@files){ if ($file eq $f){ my $re = $files->{$f}->{discard} ; if ((! $re)||($File::Find::dir !~ /$re/)){ push @{$files->{$f}->{choices}}, File::Spec->canonpath($File::Find::dir) ; } last ; } } } sub CleanSoDirs { foreach my $d (keys %so_dirs){ if (-e File::Spec->catfile($d, $jvm_so)){ delete $so_dirs{$d} ; } elsif ($d =~ /plugin/){ delete $so_dirs{$d} ; } elsif ($d =~ /motif/){ delete $so_dirs{$d} ; } elsif ($d =~ /javaws/){ delete $so_dirs{$d} ; } elsif ($d =~ /headless/){ delete $so_dirs{$d} ; } elsif ($d =~ /xawt/){ delete $so_dirs{$d} ; } elsif ($d =~ /_threads/){ if ($d !~ /native_threads/){ delete $so_dirs{$d} ; } } } $so_dirs{$files->{$jvm_so}->{selected}} = 1 ; } sub FindDefaultVMType { my $type = undef ; my $choices = $files->{'jvm.cfg'}->{choices} ; if (scalar(@{$choices})){ my $cfg = File::Spec->catfile($choices->[0], 'jvm.cfg') ; if (open(CFG, "<$cfg")){ while (){ my $line = $_ ; chomp($line) ; $line =~ s/^\s+// ; $line =~ s/\s+$// ; if (! $line){ next ; } elsif ($line =~ /^#/){ next ; } else{ ($type) = split(/\s+/, $line) ; $type =~ s/^-// ; last ; } } close(CFG) ; } } return $type ; } sub Choose { my $f = shift ; my $o = $files->{$f} ; my $cnt = 0 ; my $def = undef ; foreach my $f (@{$o->{choices}}){ $cnt++ ; print "$cnt) $f\n" ; } my $idx = AskSub("Please select from the above list which '$f' to use:", $o->{default_choice}, sub {(($_[0] >= 1)&&($_[0] <= $cnt))}) ; $o->{selected} = $o->{choices}->[int($idx) - 1] ; print "\n" ; } # Gets string from stdin sub Ask { my $ques = shift ; my $def = shift ; return AskSub($ques, $def, undef) ; } # Gets yes/no from stdin sub AskYN { my $ques = shift ; my $def = shift ; my $ans = AskSub($ques, $def, sub {((! $_[0])||($_[0] =~ /^(y|n)$/i))}) ; return (($ans =~ /^y$/i) ? 1 : 0) ; } sub AskSub { my $ques = shift ; my $def = shift ; my $sub = shift ; while (1){ my $ans = prompt($ques, $def) ; if (! $sub){ return $ans ; } elsif ($sub->($ans)){ return $ans ; } } } Inline-Java-0.67/lib/0000755000175000017500000000000014202042236014232 5ustar osboxesosboxesInline-Java-0.67/lib/Inline/0000755000175000017500000000000014202042236015450 5ustar osboxesosboxesInline-Java-0.67/lib/Inline/Java.pm0000644000175000017500000006504114202042136016674 0ustar osboxesosboxespackage Inline::Java; use strict; require 5.006; use base qw(Inline Exporter); # Export the cast function if wanted our @EXPORT_OK = qw(cast coerce study_classes caught jar j2sdk); our $VERSION = '0.67'; # DEBUG is set via the DEBUG config our $DEBUG = 0 unless defined $DEBUG; *DEBUG_STREAM = *STDERR; # Set DEBUG stream use Carp; use Config; use File::Copy; use File::Spec; use Cwd; use Data::Dumper; use Inline::Java::Portable; use Inline::Java::Class; use Inline::Java::Object; use Inline::Java::Array; use Inline::Java::Handle; use Inline::Java::Protocol; use Inline::Java::Callback; # Must be last. use Inline::Java::JVM; # Our default J2SK require Inline::Java->find_default_j2sdk(); # This is set when the script is over. my $DONE = 0; # This is set when at least one JVM is loaded. my $JVM = undef; # This list will store the $o objects... my @INLINES = (); my $report_version = "V2"; # This stuff is to control the termination of the Java Interpreter sub done { my $signal = shift; # To preserve the passed exit code... my $ec = $?; $DONE = 1; if (! $signal){ Inline::Java::debug(1, "killed by natural death."); } else{ Inline::Java::debug(1, "killed by signal SIG$signal."); } shutdown_JVM(); Inline::Java::debug(1, "exiting with $ec"); CORE::exit($ec); exit($ec); } END { if ($DONE < 1){ done(); } } # To export the cast function and others. sub import { my $class = shift; foreach my $a (@_){ if ($a eq 'jar'){ print Inline::Java::Portable::get_server_jar(); exit(); } elsif ($a eq 'j2sdk'){ print Inline::Java->find_default_j2sdk() . " says '" . Inline::Java::get_default_j2sdk() . "'\n"; exit(); } elsif ($a eq 'so_dirs'){ print Inline::Java::Portable::portable('SO_LIB_PATH_VAR') . "=" . join(Inline::Java::Portable::portable('ENV_VAR_PATH_SEP'), Inline::Java::get_default_j2sdk_so_dirs()); exit(); } } $class->export_to_level(1, $class, @_); } ######################## Inline interface ######################## # Register this module as an Inline language support module sub register { return { language => 'Java', aliases => ['JAVA', 'java'], type => 'interpreted', suffix => 'jdat', }; } # Here validate is overridden because some of the config options are needed # at load as well. sub validate { my $o = shift; # This might not print since debug is set further down... Inline::Java::debug(1, "Starting validate."); my $jdk = Inline::Java::get_default_j2sdk(); my $dbg = $Inline::Java::DEBUG; my %opts = @_; $o->set_option('DEBUG', $dbg, 'i', 1, \%opts); $o->set_option('J2SDK', $jdk, 's', 1, \%opts); $o->set_option('CLASSPATH', '', 's', 1, \%opts); $o->set_option('BIND', 'localhost', 's', 1, \%opts); $o->set_option('HOST', 'localhost', 's', 1, \%opts); $o->set_option('PORT', -1, 'i', 1, \%opts); $o->set_option('STARTUP_DELAY', 15, 'i', 1, \%opts); $o->set_option('SHARED_JVM', 0, 'b', 1, \%opts); $o->set_option('START_JVM', 1, 'b', 1, \%opts); $o->set_option('JNI', 0, 'b', 1, \%opts); $o->set_option('EMBEDDED_JNI', 0, 'b', 1, \%opts); $o->set_option('NATIVE_DOUBLES', 0, 'b', 1, \%opts); $o->set_option('WARN_METHOD_SELECT', 0, 'b', 1, \%opts); $o->set_option('STUDY', undef, 'a', 0, \%opts); $o->set_option('AUTOSTUDY', 0, 'b', 1, \%opts); $o->set_option('EXTRA_JAVA_ARGS', '', 's', 1, \%opts); $o->set_option('EXTRA_JAVAC_ARGS', '', 's', 1, \%opts); $o->set_option('DEBUGGER', 0, 'b', 1, \%opts); $o->set_option('PRIVATE', '', 'b', 1, \%opts); $o->set_option('PACKAGE', '', 's', 1, \%opts); my @left_overs = keys(%opts); if (scalar(@left_overs)){ croak "'$left_overs[0]' is not a valid configuration option for Inline::Java"; } # Now for the post processing $Inline::Java::DEBUG = $o->get_java_config('DEBUG'); # Embedded JNI turns on regular JNI if ($o->get_java_config('EMBEDDED_JNI')){ $o->set_java_config('JNI', 1); } if ($o->get_java_config('PORT') == -1){ if ($o->get_java_config('SHARED_JVM')){ $o->set_java_config('PORT', 7891); } else{ $o->set_java_config('PORT', -7890); } } if (($o->get_java_config('JNI'))&&($o->get_java_config('SHARED_JVM'))){ croak("You can't use the 'SHARED_JVM' option in 'JNI' mode"); } if (($o->get_java_config('JNI'))&&($o->get_java_config('DEBUGGER'))){ croak("You can't invoke the Java debugger ('DEBUGGER' option) in 'JNI' mode"); } if ((! $o->get_java_config('SHARED_JVM'))&&(! $o->get_java_config('START_JVM'))){ croak("Disabling the 'START_JVM' option only makes sense in 'SHARED_JVM' mode"); } if ($o->get_java_config('JNI')){ require Inline::Java::JNI; } if ($o->get_java_config('DEBUGGER')){ # Here we want to tweak a few settings to help debugging... Inline::Java::debug(1, "Debugger mode activated"); # Add the -g compile option $o->set_java_config('EXTRA_JAVAC_ARGS', $o->get_java_config('EXTRA_JAVAC_ARGS') . " -g "); # Add the -sourcepath runtime option $o->set_java_config('EXTRA_JAVA_ARGS', $o->get_java_config('EXTRA_JAVA_ARGS') . " -sourcepath " . $o->get_api('build_dir') . Inline::Java::Portable::portable("ENV_VAR_PATH_SEP_CP") . Inline::Java::Portable::get_source_dir() ); } my $study = $o->get_java_config('STUDY'); if ((defined($study))&&(ref($study) ne 'ARRAY')){ croak "Configuration option 'STUDY' must be an array of Java class names"; } Inline::Java::debug(1, "validate done."); } sub set_option { my $o = shift; my $name = shift; my $default = shift; my $type = shift; my $env_or = shift; my $opts = shift; my $desc = shift; if (! exists($o->{ILSM}->{$name})){ my $val = undef; if (($env_or)&&(exists($ENV{"PERL_INLINE_JAVA_$name"}))){ $val = $ENV{"PERL_INLINE_JAVA_$name"}; } elsif (exists($opts->{$name})){ $val = $opts->{$name}; } else{ $val = $default; } if ($type eq 'b'){ if (! defined($val)){ $val = 0; } $val = ($val ? 1 : 0); } elsif ($type eq 'i'){ if ((! defined($val))||($val !~ /\d/)){ $val = 0; } $val = int($val); } $o->set_java_config($name, $val); } delete $opts->{$name}; } sub get_java_config { my $o = shift; my $param = shift; return $o->{ILSM}->{$param}; } sub set_java_config { my $o = shift; my $param = shift; my $value = shift; return $o->{ILSM}->{$param} = $value; } # In theory we shouldn't need to use this, but it seems # it's not all accessible by the API yet. sub get_config { my $o = shift; my $param = shift; return $o->{CONFIG}->{$param}; } sub get_api { my $o = shift; my $param = shift; # Allows us to force a specific package... if (($param eq 'pkg')&&($o->get_config('PACKAGE'))){ return $o->get_config('PACKAGE'); } return $o->{API}->{$param}; } # Parse and compile Java code sub build { my $o = shift; if ($o->get_java_config('built')){ return; } Inline::Java::debug(1, "Starting build."); # Grab and untaint the current directory my $cwd = Cwd::cwd(); if ($o->get_config('UNTAINT')){ ($cwd) = $cwd =~ /(.*)/; } # We must grab this before we change to the build dir because # it could be relative... my $server_jar = Inline::Java::Portable::get_server_jar(); # We need to add all the previous install dirs to the classpath because # they can access each other. my @prev_install_dirs = (); foreach my $in (@INLINES){ push @prev_install_dirs, File::Spec->catdir($in->get_api('install_lib'), 'auto', $in->get_api('modpname')); } my $cp = $ENV{CLASSPATH} || ''; $ENV{CLASSPATH} = Inline::Java::Portable::make_classpath($server_jar, @prev_install_dirs, $o->get_java_config('CLASSPATH')); Inline::Java::debug(2, "classpath: $ENV{CLASSPATH}"); # Create the build dir and go there my $build_dir = $o->get_api('build_dir'); $o->mkpath($build_dir); chdir $build_dir; my $code = $o->get_api('code'); my $pcode = $code; my $study_only = ($code =~ /^(STUDY|SERVER)$/i); my $source = ($study_only ? '' : $o->get_api('modfname') . ".java"); # Parse code to check for public class $pcode =~ s/\\\"//g; $pcode =~ s/\"(.*?)\"//g; $pcode =~ s/\/\*(.*?)\*\///gs; $pcode =~ s/\/\/(.*)$//gm; if ($pcode =~ /public\s+(abstract\s+)?class\s+(\w+)/){ $source = "$2.java"; } my $install_dir = File::Spec->catdir($o->get_api('install_lib'), 'auto', $o->get_api('modpname')); $o->mkpath($install_dir); if ($source){ # Dump the source code... open(Inline::Java::JAVA, ">$source") or croak "Can't open $source: $!"; print Inline::Java::JAVA $code; close(Inline::Java::JAVA); # ... and compile it. my $javac = File::Spec->catfile($o->get_java_config('J2SDK'), Inline::Java::Portable::portable("J2SDK_BIN"), "javac" . Inline::Java::Portable::portable("EXE_EXTENSION")); my $redir = Inline::Java::Portable::portable("IO_REDIR"); my $args = "-deprecation -Xlint:unchecked " . $o->get_java_config('EXTRA_JAVAC_ARGS'); my $pinstall_dir = Inline::Java::Portable::portable("SUB_FIX_JAVA_PATH", $install_dir); my $cmd = Inline::Java::Portable::portable("SUB_FIX_CMD_QUOTES", "\"$javac\" $args -d \"$pinstall_dir\" $source > cmd.out $redir"); if ($o->get_config('UNTAINT')){ ($cmd) = $cmd =~ /(.*)/; } Inline::Java::debug(2, "$cmd"); my $res = system($cmd); my $msg = $o->get_compile_error_msg(); if ($res){ croak $o->compile_error_msg($cmd, $msg); }; if ($msg){ warn("\n$msg\n"); } # When we run the commands, we quote them because in WIN32 you need it if # the programs are in directories which contain spaces. Unfortunately, in # WIN9x, when you quote a command, it masks it's exit value, and 0 is always # returned. Therefore a command failure is not detected. # We need to take care of checking whether there are actually files # to be copied, and if not will exit the script. if (Inline::Java::Portable::portable('COMMAND_COM')){ my @fl = Inline::Java::Portable::find_classes_in_dir($install_dir); if (! scalar(@fl)){ croak "No class files produced. Previous command failed under command.com?"; } foreach my $f (@fl){ if (! (-s $f->{file})){ croak "File $f->{file} has size zero. Previous command failed under command.com?"; } } } } $ENV{CLASSPATH} = $cp; Inline::Java::debug(2, "classpath: $ENV{CLASSPATH}"); # Touch the .jdat file. my $jdat = File::Spec->catfile($install_dir, $o->get_api('modfname') . '.' . $o->get_api('suffix')); if (! open(Inline::Java::TOUCH, ">$jdat")){ croak "Can't create file $jdat"; } close(Inline::Java::TOUCH); # Go back and clean up chdir $cwd; if (($o->get_api('cleanup'))&&(! $o->get_java_config('DEBUGGER'))){ $o->rmpath('', $build_dir); } $o->set_java_config('built', 1); Inline::Java::debug(1, "build done."); } sub get_compile_error_msg { my $o = shift; my $msg = ''; if (open(Inline::Java::CMD, "); close(Inline::Java::CMD); } return $msg; } sub compile_error_msg { my $o = shift; my $cmd = shift; my $error = shift; my $build_dir = $o->get_api('build_dir'); my $lang = $o->get_api('language'); return <get_java_config('loaded')){ return; } Inline::Java::debug(1, "Starting load."); my $install_dir = File::Spec->catdir($o->get_api('install_lib'), 'auto', $o->get_api('modpname')); # If the JVM is not running, we need to start it here. my $cp = $ENV{CLASSPATH} || ''; if (! $JVM){ $ENV{CLASSPATH} = Inline::Java::Portable::make_classpath( Inline::Java::Portable::get_server_jar()); Inline::Java::debug(2, "classpath: $ENV{CLASSPATH}"); $JVM = new Inline::Java::JVM($o); $ENV{CLASSPATH} = $cp; Inline::Java::debug(2, "classpath: $ENV{CLASSPATH}"); my $pc = new Inline::Java::Protocol(undef, $o); $pc->AddClassPath(Inline::Java::Portable::portable("SUB_FIX_JAVA_PATH", Inline::Java::Portable::get_user_jar())); my $st = $pc->ServerType(); if ((($st eq "shared")&&(! $o->get_java_config('SHARED_JVM')))|| (($st eq "private")&&($o->get_java_config('SHARED_JVM')))){ croak "JVM type mismatch on port " . $JVM->{port}; } } $ENV{CLASSPATH} = ''; my @cp = Inline::Java::Portable::make_classpath($install_dir, $o->get_java_config('CLASSPATH')); $ENV{CLASSPATH} = $cp; my $pc = new Inline::Java::Protocol(undef, $o); $pc->AddClassPath(@cp); # Add our Inline object to the list. push @INLINES, $o; $o->set_java_config('id', scalar(@INLINES) - 1); Inline::Java::debug(3, "Inline::Java object id is " . $o->get_java_config('id')); $o->study_module(); if ((defined($o->get_java_config('STUDY')))&&(scalar($o->get_java_config('STUDY')))){ $o->_study($o->get_java_config('STUDY')); } $o->set_java_config('loaded', 1); Inline::Java::debug(1, "load done."); } # This function 'studies' the classes generated by the inlined code. sub study_module { my $o = shift; my $install_dir = File::Spec->catdir($o->get_api('install_lib'), 'auto', $o->get_api('modpname')); my $cache = $o->get_api('modfname') . '.' . $o->get_api('suffix'); my $lines = []; if (! $o->get_java_config('built')){ # Since we didn't build the module, this means that # it was up to date. We can therefore use the data # from the cache. Inline::Java::debug(1, "using jdat cache"); my $p = File::Spec->catfile($install_dir, $cache); my $size = (-s $p) || 0; if ($size > 0){ if (open(Inline::Java::CACHE, "<$p")){ while (){ push @{$lines}, $_; } close(Inline::Java::CACHE); } else{ croak "Can't open $p for reading: $!"; } } } else{ # First thing to do is get the list of classes that comprise the module. # We need the classes that are in the directory or under... my @classes = (); my $cwd = Cwd::cwd(); if ($o->get_config('UNTAINT')){ ($cwd) = $cwd =~ /(.*)/; } # We chdir to the install dir, that makes it easier to figure out # the packages for the classes. chdir($install_dir); my @fl = Inline::Java::Portable::find_classes_in_dir('.'); chdir $cwd; foreach my $f (@fl){ push @classes, $f->{class}; } # Now we ask Java the info about those classes... $lines = $o->report(@classes); # and we update the cache with these results. Inline::Java::debug(1, "updating jdat cache"); my $p = File::Spec->catfile($install_dir, $cache); if (open(Inline::Java::CACHE, ">$p")){ foreach my $l (@{$lines}){ print Inline::Java::CACHE "$l\n"; } close(Inline::Java::CACHE); } else{ croak "Can't open $p file for writing"; } } # Now we read up the symbols and bind them to Perl. $o->bind_jdat($o->load_jdat($lines)); } # This function 'studies' the specified classes and binds them to # Perl. sub _study { my $o = shift; my $classes = shift; my @new_classes = (); foreach my $class (@{$classes}){ $class = Inline::Java::Class::ValidateClass($class); if (! Inline::Java::known_to_perl($o->get_api('pkg'), $class)){ push @new_classes, $class; } } if (! scalar(@new_classes)){ return; } my $lines = $o->report(@new_classes); # Now we read up the symbols and bind them to Perl. $o->bind_jdat($o->load_jdat($lines)); } sub report { my $o = shift; my @classes = @_; my @lines = (); if (scalar(@classes)){ my $pc = new Inline::Java::Protocol(undef, $o); my $resp = $pc->Report(join(" ", @classes)); @lines = split("\n", $resp); } return \@lines; } # Load the jdat code information file. sub load_jdat { my $o = shift; my $lines = shift; Inline::Java::debug_obj($lines); # We need an array here since the same object can have many # study sessions. if (! defined($o->{ILSM}->{data})){ $o->{ILSM}->{data} = []; } my $d = {}; my $data_idx = scalar(@{$o->{ILSM}->{data}}); push @{$o->{ILSM}->{data}}, $d; # The original regexp didn't match anymore under the debugger... # Very strange indeed... # my $re = '[\w.\$\[;]+'; my $re = '.+'; my $idx = 0; my $current_class = undef; if (scalar(@{$lines})){ my $vline = shift @{$lines}; chomp($vline); if ($vline ne $report_version){ croak("Report version mismatch ($vline != $report_version). Delete your '_Inline' and try again."); } } foreach my $line (@{$lines}){ chomp($line); if ($line =~ /^class ($re) ($re)$/){ # We found a class definition my $java_class = $1; my $parent_java_class = $2; $current_class = Inline::Java::java2perl($o->get_api('pkg'), $java_class); $d->{classes}->{$current_class} = {}; $d->{classes}->{$current_class}->{java_class} = $java_class; if ($parent_java_class ne "null"){ $d->{classes}->{$current_class}->{parent_java_class} = $parent_java_class; } $d->{classes}->{$current_class}->{constructors} = {}; $d->{classes}->{$current_class}->{methods} = {}; $d->{classes}->{$current_class}->{fields} = {}; } elsif ($line =~ /^constructor \((.*)\)$/){ my $signature = $1; $d->{classes}->{$current_class}->{constructors}->{$signature} = { SIGNATURE => [split(", ", $signature)], STATIC => 1, IDX => $idx, }; } elsif ($line =~ /^method (\w+) ($re) (\w+)\((.*)\)$/){ my $static = $1; my $declared_in = $2; my $method = $3; my $signature = $4; if (! defined($d->{classes}->{$current_class}->{methods}->{$method})){ $d->{classes}->{$current_class}->{methods}->{$method} = {}; } $d->{classes}->{$current_class}->{methods}->{$method}->{$signature} = { SIGNATURE => [split(", ", $signature)], STATIC => ($static eq "static" ? 1 : 0), IDX => $idx, }; } elsif ($line =~ /^field (\w+) ($re) (\w+) ($re)$/){ my $static = $1; my $declared_in = $2; my $field = $3; my $type = $4; if (! defined($d->{classes}->{$current_class}->{fields}->{$field})){ $d->{classes}->{$current_class}->{fields}->{$field} = {}; } $d->{classes}->{$current_class}->{fields}->{$field}->{$type} = { TYPE => $type, STATIC => ($static eq "static" ? 1 : 0), IDX => $idx, }; } $idx++; } Inline::Java::debug_obj($d); return ($d, $data_idx); } # Binds the classes and the methods to Perl sub bind_jdat { my $o = shift; my $d = shift; my $idx = shift; if (! defined($d->{classes})){ return; } my $inline_idx = $o->get_java_config('id'); my %classes = %{$d->{classes}}; foreach my $class (sort keys %classes) { my $class_name = $class; $class_name =~ s/^(.*):://; my $java_class = $d->{classes}->{$class}->{java_class}; # This parent stuff is needed for PerlNatives (so that you can call PerlNatives methods # from Perl...) my $parent_java_class = $d->{classes}->{$class}->{parent_java_class}; my $parent_module = ''; my $parent_module_declare = ''; if (defined($parent_java_class)){ $parent_module = java2perl($o->get_api('pkg'), $parent_java_class); $parent_module_declare = "\$$parent_module" . "::EXISTS_AS_PARENT = 1;"; $parent_module .= ' '; } if (Inline::Java::known_to_perl($o->get_api('pkg'), $java_class)){ next; } my $colon = ":"; my $dash = "-"; my $ijo = 'Inline::Java::Object'; my $code = <__new( \$JAVA_CLASS, \$INLINE, 0); use Carp; CODE while (my ($field, $types) = each %{$d->{classes}->{$class}->{fields}}){ while (my ($type, $sign) = each %{$types}){ if ($sign->{STATIC}){ $code .= <{classes}->{$class}->{constructors}})){ $code .= <{ILSM}->{data}->[$idx]; my \$signatures = \$d->{classes}->{'$class'}->{constructors}; my (\$proto, \$new_args, \$static) = \$class->__validate_prototype('new', [\@args], \$signatures, \$o); my \$ret = undef; eval { \$ret = \$class->__new(\$JAVA_CLASS, \$o, -1, \$proto, \$new_args); }; croak \$@ if \$@; return \$ret; } sub $class_name { return new(\@_); } CODE } while (my ($method, $sign) = each %{$d->{classes}->{$class}->{methods}}){ $code .= $o->bind_method($idx, $class, $method); } Inline::Java::debug_obj(\$code); # open (Inline::Java::CODE, ">>code") and print CODE $code and close(CODE); # Here it seems that for the eval below to resolve the @INLINES # list properly, it must be used in this function... my $dummy = scalar(@INLINES); eval $code; croak $@ if $@; } } sub bind_method { my $o = shift; my $idx = shift; my $class = shift; my $method = shift; my $static = shift; my $code = <{ILSM}->{data}->[$idx]; my \$signatures = \$d->{classes}->{'$class'}->{methods}->{'$method'}; my (\$proto, \$new_args, \$static) = \$this->__validate_prototype('$method', [\@args], \$signatures, \$o); if ((\$static)&&(! ref(\$this))){ \$this = \$DUMMY_OBJECT; } my \$ret = undef; eval { \$ret = \$this->__get_private()->{proto}->CallJavaMethod('$method', \$proto, \$new_args); }; croak \$@ if \$@; return \$ret; } CODE return $code; } sub get_fields { my $o = shift; my $class = shift; my $fields = {}; my $data_list = $o->{ILSM}->{data}; foreach my $d (@{$data_list}){ if (exists($d->{classes}->{$class})){ while (my ($field, $value) = each %{$d->{classes}->{$class}->{fields}}){ # Here $value is a hash that contains all the different # types available for the field $field $fields->{$field} = $value; } } } return $fields; } # Return a small report about the Java code. sub info { my $o = shift; if (! (($o->{INLINE}->{object_ready})||($o->get_java_config('built')))){ $o->build(); } if (! $o->get_java_config('loaded')){ $o->load(); } my $info = ''; my $data_list = $o->{ILSM}->{data}; foreach my $d (@{$data_list}){ if (! defined($d->{classes})){ next; } my %classes = %{$d->{classes}}; $info .= "The following Java classes have been bound to Perl:\n"; foreach my $class (sort keys %classes) { $info .= "\n class $class:\n"; $info .= " public methods:\n"; while (my ($k, $v) = each %{$d->{classes}->{$class}->{constructors}}){ my $name = $class; $name =~ s/^(.*):://; $info .= " $name($k)\n"; } while (my ($k, $v) = each %{$d->{classes}->{$class}->{methods}}){ while (my ($k2, $v2) = each %{$d->{classes}->{$class}->{methods}->{$k}}){ my $static = ($v2->{STATIC} ? "static " : ""); $info .= " $static$k($k2)\n"; } } $info .= " public member variables:\n"; while (my ($k, $v) = each %{$d->{classes}->{$class}->{fields}}){ while (my ($k2, $v2) = each %{$d->{classes}->{$class}->{fields}->{$k}}){ my $static = ($v2->{STATIC} ? "static " : ""); my $type = $v2->{TYPE}; $info .= " $static$type $k\n"; } } } } return $info; } ######################## General Functions ######################## sub __get_JVM { return $JVM; } # For testing purposes only... sub __clear_JVM { $JVM = undef; } sub shutdown_JVM { if ($JVM){ $JVM->shutdown(); $JVM = undef; } } sub reconnect_JVM { if ($JVM){ $JVM->reconnect(); } } sub capture_JVM { if ($JVM){ $JVM->capture(); } } sub i_am_JVM_owner { if ($JVM){ return $JVM->am_owner(); } } sub release_JVM { if ($JVM){ $JVM->release(); } } sub get_DEBUG { return $Inline::Java::DEBUG; } sub get_DONE { return $DONE; } sub set_DONE { $DONE = 1; } sub __get_INLINES { return \@INLINES; } sub java2perl { my $pkg = shift; my $jclass = shift; $jclass =~ s/[.\$]/::/g; if ((defined($pkg))&&($pkg)){ $jclass = $pkg . "::" . $jclass; } return $jclass; } sub known_to_perl { my $pkg = shift; my $jclass = shift; my $perl_class = java2perl($pkg, $jclass); no strict 'refs'; if (defined(${$perl_class . "::" . "EXISTS"})){ Inline::Java::debug(3, "perl knows about '$jclass' ('$perl_class')"); return 1; } else{ Inline::Java::debug(3, "perl doesn't know about '$jclass' ('$perl_class')"); } return 0; } sub debug { my $level = shift; if (($Inline::Java::DEBUG)&&($Inline::Java::DEBUG >= $level)){ my $x = " " x $level; my $str = join("\n$x", @_); while (chomp($str)) {} print DEBUG_STREAM sprintf("[perl][%s]$x%s\n", $level, $str); } } sub debug_obj { my $obj = shift; my $force = shift || 0; if (($Inline::Java::DEBUG >= 5)||($force)){ debug(5, "Dump:\n" . Dumper($obj)); if (UNIVERSAL::isa($obj, "Inline::Java::Object")){ # Print the guts as well... debug(5, "Private Dump:" . Dumper($obj->__get_private())); } } } sub dump_obj { my $obj = shift; return debug_obj($obj, 1); } ######################## Public Functions ######################## # If we are dealing with a Java object, we simply ask for a new "reference" # with the requested class. sub cast { my $type = shift; my $val = shift; if (! UNIVERSAL::isa($val, "Inline::Java::Object")){ croak("Type casting can only be used on Java objects. Use 'coerce' instead."); } return $val->__cast($type); } # coerce is used to force a specific prototype to be used. sub coerce { my $type = shift; my $val = shift; my $array_type = shift; if (UNIVERSAL::isa($val, "Inline::Java::Object")){ croak("Type coercing can't be used on Java objects. Use 'cast' instead."); } my $o = undef; eval { $o = new Inline::Java::Class::Coerce($type, $val, $array_type); }; croak $@ if $@; return $o; } sub study_classes { my $classes = shift; my $package = shift || caller(); my $o = undef; my %pkgs = (); foreach (@INLINES){ my $i = $_; my $pkg = $i->get_api('pkg') || 'main'; $pkgs{$pkg} = 1; if ($pkg eq $package){ $o = $i; last; } } if (defined($o)){ $o->_study($classes); } else { my $msg = "Can't place studied classes under package '$package' since Inline::Java was not used there. Valid packages are:\n"; foreach my $pkg (keys %pkgs){ $msg .= " $pkg\n"; } croak($msg); } } sub caught { my $class = shift; my $e = $@; $class = Inline::Java::Class::ValidateClass($class); my $ret = 0; if (($e)&&(UNIVERSAL::isa($e, "Inline::Java::Object"))){ my ($msg, $score) = $e->__isa($class); if ($msg){ $ret = 0; } else{ $ret = 1; } } $@ = $e; return $ret; } sub find_default_j2sdk { my $class = shift; return File::Spec->catfile('Inline', 'Java', 'default_j2sdk.pl'); } 1; Inline-Java-0.67/lib/Inline/Java.pod0000644000175000017500000007605414202030173017046 0ustar osboxesosboxes=head1 NAME Inline::Java - Write Perl classes in Java. =head1 SYNOPSIS =for comment use Inline Java => <<'END_OF_JAVA_CODE' ; class Pod_alu { public Pod_alu(){ } public int add(int i, int j){ return i + j ; } public int subtract(int i, int j){ return i - j ; } } END_OF_JAVA_CODE my $alu = new Pod_alu() ; print($alu->add(9, 16) . "\n") ; # prints 25 print($alu->subtract(9, 16) . "\n") ; # prints -7 =for comment =head1 DESCRIPTION The C module allows you to put Java source code directly "inline" in a Perl script or module. A Java compiler is launched and the Java code is compiled. Then Perl asks the Java classes what public methods have been defined. These classes and methods are available to the Perl program as if they had been written in Perl. The process of interrogating the Java classes for public methods occurs the first time you run your Java code. The namespace is cached, and subsequent calls use the cached version. Z<> =head1 JDK COMPATIBILITY As of version 0.62, the minimum JDK supported is JDK 7. This is due to the "diamond operator" C<< <> >> used for generic Cs among others. =head1 USING THE Inline::Java MODULE C is driven by fundamentally the same idea as other C language modules, like C or C. Because Java is both compiled and interpreted, the method of getting your code is different, but overall, using C is very similar to any other C language module. This section will explain the different ways to C Inline::Java. For more details on C, see 'perldoc Inline'. B The most basic form for using C is: use Inline Java => 'Java source code' ; Of course, you can use Perl's "here document" style of quoting to make the code slightly easier to read: use Inline Java => <<'END'; Java source code goes here. END The source code can also be specified as a filename, a subroutine reference (the subroutine should return source code), or an array reference (the array contains lines of source code). This information is detailed in 'perldoc Inline'. In order for C to function properly, it needs to know where to find a Java 2 SDK on your machine. This is done using one of the following techniques: =over 4 =item 1 Set the J2SDK configuration option to the correct directory =item 2 Set the PERL_INLINE_JAVA_J2SDK environment variable to the correct directory =back If none of these are specified, C will use the Java 2 SDK that was specified at install time (see below). =head1 DEFAULT JAVA 2 SDK When C was installed, the path to the Java 2 SDK that was used was stored in a file called default_j2sdk.pl that resides within the C module. You can obtain this path by using the following command: % perl -MInline::Java=j2sdk If you wish to permanently change the default Java 2 SDK that is used by C, edit this file and change the value found there. If you wish use a different Java 2 SDK temporarily, see the J2SDK configuration option described below. Additionally, you can use the following command to get the list of directories that you should put in you shared library path when using the JNI extension: % perl -MInline::Java=so_dirs =head1 CONFIGURATION OPTIONS There are a number of configuration options that dictate the behavior of C: =over 4 =item j2sdk Specifies the path to your Java 2 SDK. Ex: j2sdk => '/my/java/2/sdk/path' Note: This configuration option only has an effect on the first 'use Inline Java' call inside a Perl script, since all other calls make use of the same JVM. =item port Specifies the port number for the server. Default is -1 (next available port number), default for SHARED_JVM mode is 7891. Ex: port => 4567 Note: This configuration option only has an effect on the first 'use Inline Java' call inside a Perl script, since all other calls make use of the same JVM. =item host Specifies the host on which the JVM server is running. This option really only makes sense in SHARED_JVM mode when START_JVM is disabled. Ex: host => 'jvm.server.com' Note: This configuration option only has an effect on the first 'use Inline Java' call inside a Perl script, since all other calls make use of the same JVM. =item bind Specifies the IP address on which the JVM server will be listening. By default the JVM server listens for connections on 'localhost' only. Ex: bind => '192.168.1.1' Ex: bind => '0.0.0.0' Note: This configuration option only has an effect on the first 'use Inline Java' call inside a Perl script, since all other calls make use of the same JVM. =item startup_delay Specifies the maximum number of seconds that the Perl script will try to connect to the Java server. In other words this is the delay that Perl gives to the Java server to start. Default is 15 seconds. Ex: startup_delay => 20 Note: This configuration option only has an effect on the first 'use Inline Java' call inside a Perl script, since all other calls make use of the same JVM. =item classpath Adds the specified CLASSPATH. This CLASSPATH will only be available through the user classloader. To set the CLASSPATH globally (which is most probably what you want to do anyways), use the CLASSPATH environment variable. Ex: classpath => '/my/other/java/classses' =item jni Toggles the execution mode. The default is to use the client/server mode. To use the JNI extension (you must have built it at install time though; see README and README.JNI for more information), set JNI to 1. Ex: jni => 1 Note: This configuration option only has an effect on the first 'use Inline Java' call inside a Perl script, since all other calls make use of the same JVM. =item extra_java_args, extra_javac_args Specify extra command line parameters to be passed to, respectively, the JVM and the Java compiler. Use with caution as some options may alter normal C behavior. Ex: extra_java_args => '-Xmx96m' Note: extra_java_args only has an effect on the first 'use Inline Java' call inside a Perl script, since all other calls make use of the same JVM. =item embedded_jni Same as jni, except C expects the JVM to already be loaded and to have loaded the Perl interpreter that is running the script. This is an advanced feature that should only be need in very specific circumstances. Ex: embedded_jni => 1 Note: This configuration option only has an effect on the first 'use Inline Java' call inside a Perl script, since all other calls make use of the same JVM. Also, the embedded_jni option automatically sets the JNI option. =item shared_jvm This mode enables multiple processes to share the same JVM. It was created mainly in order to be able to use C under mod_perl. Ex: shared_jvm => 1 Note: This configuration option only has an effect on the first 'use Inline Java' call inside a Perl script, since all other calls make use of the same JVM. =item start_jvm When used with shared_jvm, tells C whether to start a new JVM (this is the default) or to expect that one is already running. This option is useful in combination with the command line interface described in the BUGS AND DEFICIENCIES section. Default is 1. Ex: start_jvm => 0 Note: This configuration option only has an effect on the first 'use Inline Java' call inside a Perl script, since all other calls make use of the same JVM. =item private In shared_jvm mode, makes every connection to the JVM use a different classloader so that each connection is isolated from the others. Ex: private => 1 Note: This configuration option only has an effect on the first 'use Inline Java' call inside a Perl script, since all other calls make use of the same JVM. =item debug Enables debugging info. Debugging now uses levels (1 through 5) that (loosely) follow these definitions: 1 = Major program steps 2 = Object creation/destruction 3 = Method/member accesses + packet dumps 4 = Everything else 5 = Data structure dumps Ex: debug => 2 =item debugger Starts jdb (the Java debugger) instead of the regular Java JVM. This option will also cause the Java code to be compiled using the '-g' switch for extra debugging information. EXTRA_JAVA_ARGS can be used use to pass extra options to the debugger. Ex: debugger => 1 =item warn_method_select Throws a warning when C has to 'choose' between different method signatures. The warning states the possible choices and the signature chosen. Ex: warn_method_select => 1 =item study Takes an array of Java classes that you wish to have C learn about so that you can use them inside Perl. Ex: study => ['java.lang.HashMap', 'my.class'] =item autostudy Makes C automatically study unknown classes when it encounters them. Ex: autostudy => 1 =item package Forces C to bind the Java code under the specified package instead of under the current (caller) package. Ex: package => 'main' =item native_doubles Normally, C stringifies floating point numbers when passing them between Perl and Java. In certain cases, this can lead to loss of precision. When native_doubles is set, C will send the actual double bytes in order to preserve precision. Note: This applies only to doubles, not floats. Note: This option may not be portable and may not work properly on some platforms. Ex: native_doubles => 1 =back =head1 ENVIRONMENT VARIABLES Every configuration option listed above, with the exception of STUDY, can be specified using an environment variable named using the following convention: PERL_INLINE_JAVA_