pax_global_header00006660000000000000000000000064132615374460014525gustar00rootroot0000000000000052 comment=277ab80dac992ec4c6a63cb97e84a2e4af8b0298 Inline-Java-0.66/000077500000000000000000000000001326153744600135555ustar00rootroot00000000000000Inline-Java-0.66/.gitignore000066400000000000000000000003231326153744600155430ustar00rootroot00000000000000MYMETA.* MANIFEST*.bak Makefile Makefile.old lib/Inline/Java/InlineJavaServer.jar lib/Inline/Java/InlineJavaUser.jar Java/classes/ blib/ java.ts pm_to_blib _Inline/ lib/Inline/Java/default_j2sdk.pl *.bs *.c *.o Inline-Java-0.66/.travis.yml000066400000000000000000000020531326153744600156660ustar00rootroot00000000000000language: java sudo: false jdk: - oraclejdk8 - oraclejdk9 - openjdk7 matrix: include: - jdk: "oraclejdk8" env: AUTHOR_TESTING=1 RELEASE_TESTING=1 - jdk: "oraclejdk8" env: COVERAGE=1 - jdk: "oraclejdk9" env: PERL_INLINE_JAVA_JNI=1 before_install: - git clone git://github.com/travis-perl/helpers ~/travis-perl-helpers - source ~/travis-perl-helpers/init - local-lib cache - perl -V - build-dist - cp MANIFEST.SKIP $BUILD_DIR # so xt/manifest.t can work right - cd $BUILD_DIR # $BUILD_DIR is set by the build-dist command install: - cpan-install --deps # installs prereqs, including recommends - cpan-install --coverage # installs converage prereqs, if enabled before_script: - coverage-setup script: - make - prove -b t/01_init.t # set up config as parallel races and breaks - prove -b -j$(test-jobs) $(test-files) # parallel testing after_success: - coverage-report notifications: irc: channels: - "irc.perl.org#graphql-perl" on_failure: always skip_join: true Inline-Java-0.66/CHANGES000066400000000000000000000232161326153744600145540ustar00rootroot00000000000000Revision history for Perl extension Inline::Java ------------------------------------------------ 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.66/Java/000077500000000000000000000000001326153744600144365ustar00rootroot00000000000000Inline-Java-0.66/Java/JNI.pm000066400000000000000000000013051326153744600154130ustar00rootroot00000000000000package 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.66/Java/JNI.xs000066400000000000000000000162151326153744600154370ustar00rootroot00000000000000#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.66/Java/Makefile.PL000066400000000000000000000177121326153744600164200ustar00rootroot00000000000000use 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.66/Java/PerlInterpreter/000077500000000000000000000000001326153744600175645ustar00rootroot00000000000000Inline-Java-0.66/Java/PerlInterpreter/Makefile.PL000066400000000000000000000013221326153744600215340ustar00rootroot00000000000000use 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.66/Java/PerlInterpreter/PerlInterpreter.pm000066400000000000000000000004051326153744600232470ustar00rootroot00000000000000package 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.66/Java/PerlInterpreter/PerlInterpreter.pod000066400000000000000000000056651326153744600234320ustar00rootroot00000000000000=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.66/Java/PerlInterpreter/PerlInterpreter.xs000066400000000000000000000042171326153744600232720ustar00rootroot00000000000000#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.66/Java/PerlInterpreter/t/000077500000000000000000000000001326153744600200275ustar00rootroot00000000000000Inline-Java-0.66/Java/PerlInterpreter/t/02_perl_interpreter.t000066400000000000000000000070551326153744600241110ustar00rootroot00000000000000use 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.66/Java/PerlInterpreter/t/Tests.pl000066400000000000000000000003331326153744600214650ustar00rootroot00000000000000package 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.66/Java/PerlNatives/000077500000000000000000000000001326153744600166725ustar00rootroot00000000000000Inline-Java-0.66/Java/PerlNatives/Makefile.PL000066400000000000000000000005331326153744600206450ustar00rootroot00000000000000use 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.66/Java/PerlNatives/PerlNatives.pm000066400000000000000000000001471326153744600214660ustar00rootroot00000000000000package Inline::Java::PerlNatives ; use strict ; $Inline::Java::PerlNatives::VERSION = '0.52' ; 1 ; Inline-Java-0.66/Java/PerlNatives/PerlNatives.pod000066400000000000000000000067441326153744600216450ustar00rootroot00000000000000=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.66/Java/PerlNatives/PerlNatives.xs000066400000000000000000000127621326153744600215120ustar00rootroot00000000000000#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.66/Java/PerlNatives/t/000077500000000000000000000000001326153744600171355ustar00rootroot00000000000000Inline-Java-0.66/Java/PerlNatives/t/02_perl_natives.t000066400000000000000000000035551326153744600223260ustar00rootroot00000000000000use 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.66/Java/sources/000077500000000000000000000000001326153744600161215ustar00rootroot00000000000000Inline-Java-0.66/Java/sources/org/000077500000000000000000000000001326153744600167105ustar00rootroot00000000000000Inline-Java-0.66/Java/sources/org/perl/000077500000000000000000000000001326153744600176525ustar00rootroot00000000000000Inline-Java-0.66/Java/sources/org/perl/inline/000077500000000000000000000000001326153744600211305ustar00rootroot00000000000000Inline-Java-0.66/Java/sources/org/perl/inline/java/000077500000000000000000000000001326153744600220515ustar00rootroot00000000000000Inline-Java-0.66/Java/sources/org/perl/inline/java/InlineJavaArray.java000066400000000000000000000054361326153744600257430ustar00rootroot00000000000000package 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.66/Java/sources/org/perl/inline/java/InlineJavaCallback.java000066400000000000000000000073711326153744600263610ustar00rootroot00000000000000package 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.66/Java/sources/org/perl/inline/java/InlineJavaCallbackQueue.java000066400000000000000000000066521326153744600273670ustar00rootroot00000000000000package 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.66/Java/sources/org/perl/inline/java/InlineJavaCastException.java000066400000000000000000000002221326153744600274220ustar00rootroot00000000000000package org.perl.inline.java ; class InlineJavaCastException extends InlineJavaException { InlineJavaCastException(String m){ super(m) ; } } Inline-Java-0.66/Java/sources/org/perl/inline/java/InlineJavaClass.java000066400000000000000000000342151326153744600257270ustar00rootroot00000000000000package 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.66/Java/sources/org/perl/inline/java/InlineJavaException.java000066400000000000000000000002201326153744600266050ustar00rootroot00000000000000package org.perl.inline.java ; public class InlineJavaException extends Exception { public InlineJavaException(String s) { super(s) ; } } Inline-Java-0.66/Java/sources/org/perl/inline/java/InlineJavaHandle.java000066400000000000000000000064521326153744600260570ustar00rootroot00000000000000package 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.66/Java/sources/org/perl/inline/java/InlineJavaInvocationTargetException.java000066400000000000000000000004101326153744600320070ustar00rootroot00000000000000package 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.66/Java/sources/org/perl/inline/java/InlineJavaPerlCaller.java000066400000000000000000000165721326153744600267150ustar00rootroot00000000000000package 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.66/Java/sources/org/perl/inline/java/InlineJavaPerlException.java000066400000000000000000000005641326153744600274430ustar00rootroot00000000000000package 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.66/Java/sources/org/perl/inline/java/InlineJavaPerlInterpreter.java000066400000000000000000000066271326153744600300160ustar00rootroot00000000000000package 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.66/Java/sources/org/perl/inline/java/InlineJavaPerlNatives.java000066400000000000000000000175221326153744600271200ustar00rootroot00000000000000package 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.66/Java/sources/org/perl/inline/java/InlineJavaPerlObject.java000066400000000000000000000031451326153744600267110ustar00rootroot00000000000000package org.perl.inline.java ; /* InlineJavaPerlObject */ public class InlineJavaPerlObject extends InlineJavaPerlCaller { private int id = 0 ; private String pkg = null ; /* Creates a Perl Object by calling pkg->new(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.66/Java/sources/org/perl/inline/java/InlineJavaProtocol.java000066400000000000000000000572021326153744600264640ustar00rootroot00000000000000package 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.66/Java/sources/org/perl/inline/java/InlineJavaServer.java000066400000000000000000000201521326153744600261230ustar00rootroot00000000000000package 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.66/Java/sources/org/perl/inline/java/InlineJavaServerThread.java000066400000000000000000000024271326153744600272600ustar00rootroot00000000000000package 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.66/Java/sources/org/perl/inline/java/InlineJavaThrown.java000066400000000000000000000002471326153744600261410ustar00rootroot00000000000000package org.perl.inline.java ; class InlineJavaThrown { Throwable t ; InlineJavaThrown(Throwable _t){ t = _t ; } Throwable GetThrowable(){ return t ; } } Inline-Java-0.66/Java/sources/org/perl/inline/java/InlineJavaUserClassLink.java000066400000000000000000000023151326153744600274000ustar00rootroot00000000000000import 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.66/Java/sources/org/perl/inline/java/InlineJavaUserClassLoader.java000066400000000000000000000143511326153744600277140ustar00rootroot00000000000000package 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.66/Java/sources/org/perl/inline/java/InlineJavaUtils.java000066400000000000000000000112761326153744600257640ustar00rootroot00000000000000package 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 (opcatfile($jdk_dir, $jdk_bin, $f . $ext)){ my $bf = File::Spec->catfile($jdk_bin, $f . $ext) ; print "Can't locate file '$bf' anywhere under '$jdk_dir'\n" ; } } # Now we have the J2SDK directory and it exists. # We will create the default_j2sdk.pl file that # will contain that value for future use. my $def_jdk = File::Spec->catfile(qw(lib Inline Java default_j2sdk.pl)) ; open(J2SDK, ">$def_jdk") or die("Can't open '$def_jdk' for writing: $!") ; print J2SDK <catfile($jdk_dir, $jdk_bin, 'javac' . $ext) ; my $jar = File::Spec->catfile($jdk_dir, $jdk_bin, 'jar' . $ext) ; my $src_dir = File::Spec->catdir('Java', 'sources', 'org', 'perl', 'inline', 'java') ; my @src = glob File::Spec->catfile($src_dir, '*.java') ; my $obj_dir = File::Spec->catdir('Java', 'classes') ; my $server_arch = File::Spec->catfile(qw(lib Inline Java InlineJavaServer.jar)) ; my $user_arch = File::Spec->catfile(qw(lib Inline Java InlineJavaUser.jar)) ; # Create the object diretory because later we need to put the properties # file inside it. if (! -e $obj_dir){ mkdir($obj_dir) or die("Can't create object directory '$obj_dir': $!") ; } my $INSTALLSITEARCH = '' ; my $INST_ARCHLIB = '' ; sub MY::postamble { my $this = shift ; my $java_src = join(' ', @src, File::Spec->catfile($obj_dir, 'InlineJava.properties')) ; my $make = <{$var} ; while ($val =~ s/\$\((.*?)\)/$mm->{$1}/){} $val =~ s/\\/\\\\/g ; return $val ; } my @subfiles = glob File::Spec->catfile(qw(lib Inline Java *.*)); my $subprefix = File::Spec->catdir(qw(lib Inline)); # Write the Makefile WriteMakefile( NAME => 'Inline::Java', VERSION_FROM => 'lib/Inline/Java.pm', MIN_PERL_VERSION => '5.008', LICENSE => 'artistic_2', DIR => ['Java'], BUILD_REQUIRES => { 'ExtUtils::MakeMaker' => '7.30', }, XSMULTI => 1, CONFIGURE_REQUIRES => { 'ExtUtils::MakeMaker' => '7.30', }, PREREQ_PM => { Inline => 0.68, Test => 1.13, 'MIME::Base64' => 0, }, PM => { 'lib/Inline/Java.pm' => File::Spec->catfile('$(INST_LIBDIR)', 'Java.pm'), 'lib/Inline/Java.pod'=> File::Spec->catfile('$(INST_LIBDIR)', 'Java.pod'), map { my $f = $_; $f =~ s#\Q$subprefix\E#\$(INST_LIBDIR)#; ($_ => $f) } @subfiles, $server_arch, $user_arch, }, clean => {FILES => "$def_jdk _Inline $obj_dir $server_arch $user_arch java.ts"}, ABSTRACT_FROM => 'lib/Inline/Java.pod', # retrieve abstract from module AUTHOR => 'Patrick LeBoutillier ', META_MERGE => { "meta-spec" => { version => 2 }, resources => { repository => { type => 'git', url => 'https://github.com/ingydotnet/Inline-Java', web => 'https://github.com/ingydotnet/Inline-Java', }, }, prereqs => { develop => { requires => { 'Test::CheckManifest' => '0.9', }, }, }, }, ); # Add the so_dirs to the default_j2sdk.pl file. open(J2SDK, ">>$def_jdk") or die("Can't open '$def_jdk' for appending: $!") ; print J2SDK <catfile($INSTALLSITEARCH, @perlnatives_so_parts) ; $install_perlnatives_so = Inline::Java::Portable::portable("SUB_FIX_JAVA_PATH", $install_perlnatives_so) ; $install_perlnatives_so =~ s/\\/\\\\/g ; my $test_perlnatives_so = File::Spec->rel2abs(File::Spec->catfile($INST_ARCHLIB, @perlnatives_so_parts)) ; $test_perlnatives_so = Inline::Java::Portable::portable("SUB_FIX_JAVA_PATH", $test_perlnatives_so) ; $test_perlnatives_so =~ s/\\/\\\\/g ; my @perlinterpreter_so_parts = ("auto", "Inline", "Java", "PerlInterpreter", "PerlInterpreter." . Inline::Java::Portable::portable('SO_EXT')) ; my $install_perlinterpreter_so = File::Spec->catfile($INSTALLSITEARCH, @perlinterpreter_so_parts) ; $install_perlinterpreter_so = Inline::Java::Portable::portable("SUB_FIX_JAVA_PATH", $install_perlinterpreter_so) ; $install_perlinterpreter_so =~ s/\\/\\\\/g ; my $test_perlinterpreter_so = File::Spec->rel2abs(File::Spec->catfile($INST_ARCHLIB, @perlinterpreter_so_parts)) ; $test_perlinterpreter_so = Inline::Java::Portable::portable("SUB_FIX_JAVA_PATH", $test_perlinterpreter_so) ; $test_perlinterpreter_so =~ s/\\/\\\\/g ; my $libperl = $Config{libperl} ; my $dlext = $Config{dlext} ; my $libperl_so = '' ; if ($libperl =~ /\.$dlext$/){ $libperl_so = File::Spec->catfile($Config{installarchlib}, 'CORE', $libperl) ; } my $prop = File::Spec->catfile($obj_dir, 'InlineJava.properties') ; open(PROP, ">$prop") or die("Can't open '$prop' for writing: $!") ; print PROP < ; close(MAKEFILE) ; open(MAKEFILE, ">Makefile") or die "Can't open Makefile for writing" ; foreach my $line (@lines){ if ($line !~ /^\s*((\@\[)|(\]))\s*$/){ print MAKEFILE $line ; } } close(MAKEFILE) ; } Inline-Java-0.66/README000066400000000000000000000061071326153744600144410ustar00rootroot00000000000000INTRODUCTION: Inline::Java - Write Perl classes in Java. Inline::Java lets you write Perl classes in Java. Example: use Inline Java => <<'END'; class JAxH { public JAxH(String x){ System.out.println("Just Another " + x + " Hacker") ; } } END new JAxH('Inline') ; When run, this complete program prints: Just Another Inline Hacker ------------------------------------------------------------------------------- JNI (JAVA NATIVE INTERFACE) EXTENSION: Inline::Java now provides a JNI extension that allows you to load the Java virtual machine as shared object instead of running it as a separate process. See README.JNI for more information on building the JNI extension. ------------------------------------------------------------------------------- INSTALLATION: - This module requires Inline version 0.44 or higher to be installed. - It also requires a version of the Java SDK 1.2 or higher to be installed. You can get the latest Java SDK from Sun Microsystems at http://java.sun.com. Follow the provided instructions in order to install the Java SDK properly. To install Inline::Java do this: % perl Makefile.PL J2SDK=/your/java/dir (see Note 1) % make (see Note 2) % make test (see Note 3, 4) % make install You have to 'make install' before you can run it successfully. Note 1: Under Win95/98/Me, you may need to do 'cd ..' to get back to the your original directory after the command has completed. Also, you may set either the JAVA_HOME or the PERL_INLINE_JAVA_J2SDK environment variable to /your/java/dir instead of using the J2SDK Makefile.PL parameter. Note 2: Use nmake on Win32. Note 3: If you have built the JNI extension and want the test suite to use it, you will need to set the PERL_INLINE_JAVA_JNI environment variable to 1 BEFORE running 'make test'. Note 4: When testing Inline::Java, it's always a good idea to run 'make test' twice. The first time you test the building and loading of a module, the second time you test loading of an already built module. ------------------------------------------------------------------------------- FEATURES FOR THIS VERSION: Inline::Java version 0.52 is a minor upgrade that includes: - 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. See CHANGES for a full change list. ------------------------------------------------------------------------------- INFORMATION: = For more information on Inline::Java, see 'perldoc Inline::Java'. = For information about Inline, see 'perldoc Inline'. = For information on using Java, visit http://java.sun.org. Inline::Java's mailing list is inline@perl.org. To subscribe, send an email to inline-subscribe@perl.org. Please send questions and comments to Patrick LeBoutillier . Copyright (c) 2001-2005, Patrick LeBoutillier. All Rights Reserved. Inline-Java-0.66/README.JNI000066400000000000000000000153271326153744600150640ustar00rootroot00000000000000JNI (JAVA NATIVE INTERFACE) EXTENSION ------------------------------------- Inline::Java now provides a JNI extension that allows you to load the Java virtual machine as shared object instead of running it as a separate process. PLATFORM AVAILABILITY --------------------- The JNI extension is available on all supported platforms. The extension builds properly on all platform, but problems can occur when running it or tweaking maybe necessary on certain platforms. All help is welcome if anyone out there is a JNI expert. The reason why JNI is a bit complex under Linux/Solaris is because of threads. The Java Virtual Machine (libjvm.so) shared object uses native threads when embedded inside another program and that host program (in this case Perl) must link with the same threads library for everything to work properly. Starting with Perl 5.8, this works fine. With previous versions, you may get around rebuilding Perl by setting LD_PRELOAD. The only problems encountered where that when setting LD_PRELOAD before running the test suite, the LD_PRELOAD affects make as well and on Solaris some crashes were seen. Read more on this in the Solaris section below. Note: Make sure the directories listed at the end of the installation procedure are included in your LD_LIBRARY_PATH (PATH on Win32) environment variable. This JNI extension will not load properly the the Java shared objects cannot be located at runtime. OVERVIEW -------- +----------+------------+------------+ | JDK1.3.1 | J2SDK1.4.2 | J2SDK1.5.0 | +-------------+----------+------------+------------+ | Win32 | ok | ok | ok | +-------------+----------+------------+------------+ | cygwin | ok* | ok* | ok* | +-------------+----------+------------+------------+ | Linux RH7.3 | ok* | ok* | ? | +-------------+----------+------------+------------+ | Linux RH9.0 | ok* | ok* | ok | +-------------+----------+------------+------------+ | Soloris 2.8 | ok* | ? | ? | +-------------+----------+------------+------------+ * : Read below WIN32 ----- Java 2 SDK 1.3.1: The JNI extension runs without problems. Java 2 SDK 1.4.2: The JNI extension runs without problems. LINUX ----- Java 2 SDK 1.3.1: The JNI extension runs without problems with this Java 2 SDK, provided that you use Perl >= 5.8.0 or do one of the following: 1- Rebuild perl and add the libpthread library in front of all other libraries (see the 'BUILDING PERL' section below). You should also use your system's malloc (not perl's). This is the recommended solution. 2- Add the proper version of libpthread.so to your LD_PRELOAD environment variable. On my test system this was /lib/i686/libpthread.so.0. This solution seems viable but thread related crashes/hang-ups have been reported on some systems. If make crashes while running the test suite, try running it like this: % for i in `ls t/*.t` ; do perl -Mblib $i; done Also, make sure you use do not use 'classic' VM. This one should only be used with 'green threads', which don't seem to work with JNI. Use either the 'client' or the 'server' VMs. Java 2 SDK 1.4.2: The same as Java 2 SDK 1.3.1 applies. SOLARIS ------- Java 2 SDK 1.3.1: The JNI extension runs without problems with this Java 2 SDK, provided that you use Perl >= 5.8.0 or do one of the following: 1- Rebuild perl and add the libthread library in front of all other libraries (see the 'BUILDING PERL' section below). You should also use gcc and your system's malloc (not perl's). This is the recommended solution. 2- Add the proper version of libthread.so to your LD_PRELOAD environment variable. On my test system this was /lib/libthread.so. This solution seems viable but thread related crashes/hang-ups have been reported on some systems. If make crashes while running the test suite, try running it like this: % for i in `ls t/*.t` ; do perl -Mblib $i; done CYGWIN ------ Java 2 SDK 1.3.1: The JNI extension runs without problems. PerlInterpreter: Compiles but stand-alone (non-JNI initiated) Java interpreter locks up when attempting to load the DLL. This is a known issue with initialization of the cygwin1.dll from a non-cygwin DLL or EXE, which has been "broken" since at least Cygwin 1.5.13. A possible work around might be to build the PerlInterpreter against a native Win32 Perl distribution with '-mno-cygwin' GCC compile flag, although this means you would be using native Perl instead of Cygwin Perl when using PerlInterpreter. Java 2 SDK 1.4.2: The JNI extension runs without problems. PerlInterpreter: The same as Java 2 SDK 1.3.1 applies. PerlNatives: Compiles and runs fine in a JNI-initiated interpreter, but stand-alone (non-JNI initiated) Java interpreter locks up when attempting to load the DLL. This is a known issue with initialization of the cygwin1.dll from a non-cygwin DLL or EXE, which has been "broken" since at least Cygwin 1.5.13. Java 2 SDK 1.5.0: The same as Java 2 SDK 1.4.2 applies. BUILDING PERL ------------- Here's how to rebuild Perl (version < 5.8.0) to get the JNI extension to work properly: - Use all the defaults or whatever makes sense, but no threaded Perl and no interpreter threads, i.e.: Build a threading Perl? [n] n Build Perl for multiplicity? [n] n - When asked what libraries to use, type -lthread (Solaris) or -lpthread (Linux) and tack on whatever the default is at the end, i.e.: What libraries to use? -> [-lnsl -lndbm -lgdbm -ldb -ldl -lm -lc -lcrypt -lutil] -lpthread -lnsl -lndbm -lgdbm -ldb -ldl -lm -lc -lcrypt -lutil (under Linux it's -lpthread, but for Solaris it's -lthread) - Make sure that you do not use perl's own malloc, i.e.: Do you wish to attempt to use the malloc that comes with perl5? -> [n] n RUNNING Inline::Java WITH THE JNI EXTENSION ------------------------------------------- To run Inline::Java with the JNI extension, do one of the following: - set the JNI configuration option to 1 - set the PERL_INLINE_JAVA_JNI environment variable to 1 To run the test suite (make test) with the JNI extension you must use the PERL_INLINE_JAVA_JNI environment variable USING THE 'SHARED_JVM' MODE --------------------------- Inline::Java 0.30 introduced a 'SHARED_JVM' mode that allows many clients to connect to the same Inline::Java Java server. The 'SHARED_JVM' mode is meant to be used with forking processes such as Apache with mod_perl. The 'SHARED_JVM' mode does NOT work along with the JNI mode. In fact the author was not able to successfully fork the Java Virtual Machine under any circumstances. Inline-Java-0.66/TODO000066400000000000000000000003501326153744600142430ustar00rootroot00000000000000CODE: - 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.66/examples/000077500000000000000000000000001326153744600153735ustar00rootroot00000000000000Inline-Java-0.66/examples/cgi/000077500000000000000000000000001326153744600161355ustar00rootroot00000000000000Inline-Java-0.66/examples/cgi/CGI.cgi000077500000000000000000000012441326153744600172270ustar00rootroot00000000000000#!/usr/bin/perl package t::CGI ; use strict ; use CGI ; use CGI::Carp qw(fatalsToBrowser) ; use Inline ( Java => '/home/patrickl/DEV/Inline-Java/t/counter.java', DIRECTORY => '/home/patrickl/DEV/Inline-Java/_Inline_web_test', SHARED_JVM => 1, NAME => 't::CGI', ) ; BEGIN { $t::CGI::cnt = new t::CGI::counter() ; } my $gnb = $t::CGI::cnt->gincr() ; my $nb = $t::CGI::cnt->incr() ; my $q = new CGI() ; print "Content-type: text/html\n\n" ; print $q->start_html() . "Inline-Java " . $Inline::Java::VERSION . "

" . "Inline-Java says this page received $gnb hits!
" . "Inline-Java says this CGI ($$) served $nb of those hits." . $q->end_html() ; 1 ; Inline-Java-0.66/examples/cgi/MOD_PERL.pl000066400000000000000000000000601326153744600177270ustar00rootroot00000000000000use lib "/home/patrickl/DEV/Inline-Java" ; 1 ; Inline-Java-0.66/examples/cgi/MOD_PERL.pm000077500000000000000000000014051326153744600177370ustar00rootroot00000000000000#!/usr/bin/perl package t::MOD_PERL ; use strict ; use CGI ; use Inline ( Java => '/home/patrickl/DEV/Inline-Java/t/counter.java', DIRECTORY => '/home/patrickl/DEV/Inline-Java/_Inline_web_test', NAME => 't::MOD_PERL', SHARED_JVM => 1, ) ; use Apache2::RequestRec ; use Apache2::RequestIO ; use Apache2::Const qw(:common) ; my $cnt = new t::MOD_PERL::counter() ; sub handler { my $r = shift ; $r->content_type('text/html') ; my $gnb = $cnt->gincr() ; my $nb = $cnt->incr() ; my $q = new CGI() ; print $q->start_html() . "Inline-Java " . $Inline::Java::VERSION . "

" . "Inline-Java says this page received $gnb hits!
" . "Inline-Java says this MOD_PERL ($$) served $nb of those hits." . $q->end_html() ; return OK ; } 1 ; Inline-Java-0.66/examples/cgi/counter.java000066400000000000000000000003231326153744600204550ustar00rootroot00000000000000class counter { static private int global_i = 0 ; private int i = 0 ; public counter(){ } static public int gincr(){ global_i++ ; return global_i ; } public int incr(){ i++ ; return i ; } } Inline-Java-0.66/examples/shared_jvm_server.pl000066400000000000000000000002171326153744600214400ustar00rootroot00000000000000use strict ; use blib ; use Inline( Java => 'STUDY', SHARED_JVM => 1, ) ; print "Shared JVM server started\n" ; while (1){ sleep(60) ; } Inline-Java-0.66/examples/shared_jvm_test.pl000066400000000000000000000016031326153744600211110ustar00rootroot00000000000000package shared_jvm_test ; use strict ; use blib ; use Inline ( Java => 'DATA', NAME => "shared_jvm_test", SHARED_JVM => 1, ) ; $shared_jvm_test::t::i = 0 ; my $nb = 10 ; my $sum = (($nb) * ($nb + 1)) / 2 ; for (my $i = 0 ; $i < $nb ; $i++){ if (! fork()){ print STDERR "." ; shared_jvm_test::do_child($i) ; } } # Wait for kids to finish for (my $i = 0 ; $i < 5 ; $i++){ sleep(1) ; print STDERR "." ; } print STDERR "\n" ; if ($shared_jvm_test::t::i == $sum){ print STDERR "Test succeeded\n" ; } else{ print STDERR "Test failed ($shared_jvm_test::t::i != $sum)\n" ; } sub do_child { my $i = shift ; Inline::Java::reconnect_JVM() ; my $t = new shared_jvm_test::t() ; my $j = 0 ; for ( ; $j <= $i ; $j++){ $t->incr_i() ; } exit ; } __DATA__ __Java__ import java.util.* ; class t { static public int i = 0 ; public t(){ } public void incr_i(){ i++ ; } } Inline-Java-0.66/examples/swing_callback.pl000066400000000000000000000031571326153744600207010ustar00rootroot00000000000000#!/usr/bin/perl use strict; use warnings; use blib ; use Inline Java => "DATA" ; package EventHandler ; sub new { my $class = shift ; my $max = shift ; return bless({max => $max, nb => 0}, $class) ; } sub button_pressed { my $this = shift ; my $button = shift ; $this->{nb}++ ; print "Button Pressed $this->{nb} times (from perl)\n" ; if ($this->{nb} > $this->{max}){ $button->StopCallbackLoop() ; } return $this->{nb} ; } my $button = MyButton->new(new EventHandler(10)); $button->StartCallbackLoop() ; print "loop done\n" ; package main ; __DATA__ __Java__ import java.util.*; import org.perl.inline.java.*; import javax.swing.*; import java.awt.event.*; public class MyButton extends InlineJavaPerlCaller implements ActionListener { InlineJavaPerlObject po = null ; public MyButton(InlineJavaPerlObject _po) throws InlineJavaException { po = _po ; // create frame JFrame frame = new JFrame("MyButton"); frame.setSize(200,200); // create button JButton button = new JButton("Click Me!"); frame.getContentPane().add(button); // tell the button that when it's clicked, report it to // this class. button.addActionListener(this); // all done, everything added, just show it frame.show(); } public void actionPerformed(ActionEvent e) { try { String cnt = (String)CallPerlMethod(po, "button_pressed", new Object [] {this}); System.out.println("Button Pressed " + cnt + " times (from java)") ; } catch (InlineJavaPerlException pe) { } catch (InlineJavaException pe) { pe.printStackTrace() ;} } } Inline-Java-0.66/examples/swing_gui_test.pl000066400000000000000000000011111326153744600207540ustar00rootroot00000000000000use strict ; use blib ; use Inline ( Java => 'DATA', STUDY => [ 'javax.swing.JFrame', 'javax.swing.JPanel', ], ) ; my $f = HelloJava1->get_frame("HelloJava1") ; $f->setSize(140, 100) ; $f->getContentPane()->add(new HelloJava1()) ; $f->setVisible(1) ; ; __END__ __Java__ class HelloJava1 extends javax.swing.JComponent { public HelloJava1() { } public void paintComponent(java.awt.Graphics g) { g.drawString("Hello from Java!", 17, 40) ; } public static javax.swing.JFrame get_frame(String name) { return new javax.swing.JFrame(name) ; } } Inline-Java-0.66/lib/000077500000000000000000000000001326153744600143235ustar00rootroot00000000000000Inline-Java-0.66/lib/Inline/000077500000000000000000000000001326153744600155415ustar00rootroot00000000000000Inline-Java-0.66/lib/Inline/Java.pm000066400000000000000000000650411326153744600167660ustar00rootroot00000000000000package 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.66'; # 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.66/lib/Inline/Java.pod000066400000000000000000000760541326153744600171420ustar00rootroot00000000000000=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_