尝试通过Inline :: Java模块将Java内联到Perl中

这是我第一次尝试在Perl中内联Java代码。 我们无法在我们的系统上使用标准SFTP命令。 这是我的力量。 我们有一个名为SFTP.jar的jar文件,可以使用它。 在我之前的前一个人能够让Inline :: Perl工作,但他的实现是草率的,我想清理它。

我正在H:\svn目录上的Windows系统上工作。 我的模块位于H:\svn\FMS3目录下,我在H:\svn\FMS3\Sftp.pm目录下有一个名为SFTP.jarH:\svn\FMS3\Sftp.pm文件。 在H:\svn\FMS3目录下有一个名为Sftp.pm的文件,它定义了一个名为FMS3::Sftp的模块。 (我将所有自定义模块保留在FMS3父模块下)。

我在FMS3::Sftp内联了代码,它看起来像是编译的。 但是,当我尝试执行时,它声称Can't exec JVM: open3: Can't call method "close" on an undefined value at C:/Perl/lib/IPC/Open3.pm line 370

究竟我做错了什么?

FMS3::Sftp模块:

 #! /usr/bin/env perl # Sftp.pm ######################################################################## ######################################################################## # PACKAGE FMS3::Sftp # package FMS3::Sftp; # ######################################################################## ######################################################################## # PERL PRAGMAS # use strict; use warnings; use vars qw($PERL_CLASSPATH); # ######################################################################## ######################################################################## # CONSTANTS # use constant { FTP_SERVER => "10.85.10.190", FTP_USER => "fisaftp", FTP_PASSWORD => "Fisa123456", }; # ######################################################################## ######################################################################## # INITIALIZE # # Set a PERL_CLASSPATH that will include all directories in the # @INC array. Somewhere in this array will be located our JAR file # that we need to include, and of course, this classpath. # # This will be appended to the standard $CLASSPATH environment variable. # BEGIN { use Config; my $cpsep; if ($Config{osname} =~ /^mswin32/i) { $cpsep = ";"; } else { $cpsep = ":"; } $PERL_CLASSPATH = join("/FMS3/Sftp/SFTP.jar$cpsep", @INC); $PERL_CLASSPATH = "$PERL_CLASSPATH/FMS3/Sftp/SFTP.jar"; } # ######################################################################## ######################################################################## # # PERL INLINE JAVA CODE: # use Inline ( Java => 'DATA', J2SDK => $ENV{JAVA_HOME}, CLASSPATH => $PERL_CLASSPATH, STUDY => ["SFTP", "close", "list", "get", "put", "remove"], DEBUG => 4, ); # ######################################################################## ######################################################################## # CONSTRUCTORS # sub new { my $class = shift; my $server = shift; my $user = shift; my $password = shift; if (not $server) { $server = FTP_SERVER; } if (not $user) { $user = FTP_USER; } if (not $password) { $password = FTP_PASSWORD; } my $self = {}; bless($self, $class); eval {$self->{CONNECTION} = new SFTP($server, $user, $password);}; if ($@) { $self->{ERROR} = $@; return; } return $self; } # ######################################################################## ######################################################################## # DESTRUCTOR (Automatic close on losing $self) # sub DESTROY { my $self = shift; $self->{CONNECTION}->close(); return 1; } # ######################################################################## ######################################################################## # List # sub List { my $self = shift; my $location = shift; my @list; eval {@list = $self->{CONNECTION}->list($location);}; if ($@) { $self->{ERROR} = $@; return; } return @list; } # ######################################################################## ######################################################################## # Get # sub Get { my $self = shift; my $file = shift; my $location = shift; eval {$self->{CONNECTION}->get($file, $location);}; if ($@) { $self->{ERROR} = $@; return; } return 1; } # ######################################################################## ######################################################################## # Put # sub Put { my $self = shift; my $file = shift; my $location = shift; my $mode = shift; eval {$self->{CONNECTION}->put($file, $location, $mode);}; if ($@) { $self->{ERROR} = $@; return; } return 1; } # ######################################################################## ######################################################################## # Remove # sub Remove { my $self = shift; my $file = shift; eval {$self->{CONNECTION}->remove($file);}; if ($@) { $self->{ERROR} = $@; return; } return 1; } # ######################################################################## ######################################################################## # Error # sub Error { my $self = shift; return $self->{ERROR}; } # ######################################################################## 1; __DATA__ __Java__ import com.trilead.ssh2.*; import java.io.IOException; import java.util.*; public class SFTP { ConnectionInfo ci; SCPClient sftp=null; SFTPv3Client sftpv3=null; Connection conn=null; public SFTP(String host, String username, String password) { boolean b=false; conn= new Connection(host); try { ci=conn.connect(); b=conn.authenticateWithPassword(username,password); if (!b) { System.out.println("Invalid login."); System.exit(0); } sftp = new SCPClient( conn ); sftpv3 = new SFTPv3Client (conn); } catch (IOException e) { System.out.println("Unable to connect"+": "+e.getMessage()); } } public void close() { conn.close(); } public String[] list (String loc) { Vector v=null; SFTPv3DirectoryEntry x=null; try { v = sftpv3.ls(loc); } catch (IOException e) { System.out.println("Pickup location does not exist, please check!"); String[] value = new String[1]; return value; } String[] s=new String[v.size()]; for (int i=0; i<v.size(); i++) { x = (SFTPv3DirectoryEntry)v.elementAt(i); s[i]=x.filename; } return s; } public void get (String file, String loc) { try{ sftp.get(file,loc); } catch (IOException e) { System.out.println("Unable to download, please check location or file permissions"); } } public void put (String file, String loc, String mode) { try{ sftp.put(file,loc,mode); } catch (IOException e) { System.out.println("Unable to put"+": "+e.getMessage()); } } public void remove (String file) { try{ sftpv3.rm(file); } catch (IOException e) { System.out.println("Unable to remove"+": "+e.getMessage()); } } } 

我有一个名为test.pl的测试程序,如下所示:

 use FMS3::Sftp; my $ftp = FMS3::Sftp->new(); print $ftp->List("."); 

我所要做的就是连接到我们的服务器并执行目录列表。 但是,我在尝试运行test.pl时遇到类路径错误

 [perl][1] validate done. [perl][1] Starting build. [perl][4] portable: ENV_VAR_PATH_SEP_CP for MSWin32 is ';' [perl][4] portable: SUB_FIX_JAVA_PATH => H:\svn for MSWin32 is default 'H:\svn' [perl][4] portable: SUB_FIX_JAVA_PATH => D:\PROGRA~1\IBM\SQLLIB~1\java\db2java.zip for MSWin32 is default 'D:\PROGRA~1\IBM\SQLLIB~1\java\db2java.zip' [perl][4] portable: SUB_FIX_JAVA_PATH => D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc.jar for MSWin32 is default 'D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc.jar' [perl][4] portable: SUB_FIX_JAVA_PATH => D:\PROGRA~1\IBM\SQLLIB~1\java\sqlj.zip for MSWin32 is default 'D:\PROGRA~1\IBM\SQLLIB~1\java\sqlj.zip' [perl][4] portable: SUB_FIX_JAVA_PATH => D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc_license_cu.jar for MSWin32 is default 'D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc_license_cu.jar' [perl][4] portable: SUB_FIX_JAVA_PATH => D:\PROGRA~1\IBM\SQLLIB~1\bin for MSWin32 is default 'D:\PROGRA~1\IBM\SQLLIB~1\bin' [perl][4] portable: SUB_FIX_JAVA_PATH => D:\PROGRA~1\IBM\SQLLIB~1\java\common.jar for MSWin32 is default 'D:\PROGRA~1\IBM\SQLLIB~1\java\common.jar' [perl][4] portable: SUB_FIX_JAVA_PATH => D:\Program Files\Rational\ClearQuest\cqjni.jar for MSWin32 is default 'D:\Program Files\Rational\ClearQuest\cqjni.jar' [perl][4] portable: SUB_FIX_JAVA_PATH => C:\Perl\site\lib\Inline\Java\InlineJavaServer.jar for MSWin32 is default 'C:\Perl\site\lib\Inline\Java\InlineJavaServer.jar' [perl][2] classpath candidate 'C:/Perl/site/lib/FMS3/Sftp/SFTP.jar' scraped [perl][2] classpath candidate 'C:/Perl/lib/FMS3/Sftp/SFTP.jar' scraped [perl][4] portable: SUB_FIX_JAVA_PATH => H:\svn\FMS3\Sftp\SFTP.jar for MSWin32 is default 'H:\svn\FMS3\Sftp\SFTP.jar' [perl][2] classpath: H:\svn;D:\PROGRA~1\IBM\SQLLIB~1\java\db2java.zip;D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc.jar;D:\PROGRA~1\IBM\SQLLIB~1\java\sqlj.zip;D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc_license_cu.jar;D:\PROGRA~1\IBM\SQLLIB~1\bin;D:\PROGRA~1\IBM\SQLLIB~1\java\common.jar;D:\Program Files\Rational\ClearQuest\cqjni.jar;C:\Perl\site\lib\Inline\Java\InlineJavaServer.jar;H:\svn\FMS3\Sftp\SFTP.jar [perl][4] portable: J2SDK_BIN for MSWin32 is 'bin' [perl][4] portable: EXE_EXTENSION for MSWin32 is '.exe' [perl][4] portable: IO_REDIR for MSWin32 is '2>&1' [perl][4] portable: SUB_FIX_JAVA_PATH => H:\svn\_Inline\lib\auto\FMS3\Sftp_7ae5 for MSWin32 is default 'H:\svn\_Inline\lib\auto\FMS3\Sftp_7ae5' [perl][4] portable: SUB_FIX_CMD_QUOTES => "C:\Program Files\Java\jdk1.6.0_17\bin\javac.exe" -deprecation -d "H:\svn\_Inline\lib\auto\FMS3\Sftp_7ae5" SFTP.java > cmd.out 2>&1 for MSWin32 is default '"C:\Program Files\Java\jdk1.6.0_17\bin\javac.exe" -deprecation -d "H:\svn\_Inline\lib\auto\FMS3\Sftp_7ae5" SFTP.java > cmd.out 2>&1' [perl][2] "C:\Program Files\Java\jdk1.6.0_17\bin\javac.exe" -deprecation -d "H:\svn\_Inline\lib\auto\FMS3\Sftp_7ae5" SFTP.java > cmd.out 2>&1 [perl][4] portable: COMMAND_COM for MSWin32 is '0' [perl][2] classpath: .;D:\PROGRA~1\IBM\SQLLIB~1\java\db2java.zip;D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc.jar;D:\PROGRA~1\IBM\SQLLIB~1\java\sqlj.zip;D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc_license_cu.jar;D:\PROGRA~1\IBM\SQLLIB~1\bin;D:\PROGRA~1\IBM\SQLLIB~1\java\common.jar;D:\Program Files\Rational\ClearQuest\cqjni.jar [perl][1] build done. [perl][1] Starting load. [perl][4] portable: ENV_VAR_PATH_SEP_CP for MSWin32 is ';' [perl][4] portable: SUB_FIX_JAVA_PATH => H:\svn for MSWin32 is default 'H:\svn' [perl][4] portable: SUB_FIX_JAVA_PATH => D:\PROGRA~1\IBM\SQLLIB~1\java\db2java.zip for MSWin32 is default 'D:\PROGRA~1\IBM\SQLLIB~1\java\db2java.zip' [perl][4] portable: SUB_FIX_JAVA_PATH => D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc.jar for MSWin32 is default 'D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc.jar' [perl][4] portable: SUB_FIX_JAVA_PATH => D:\PROGRA~1\IBM\SQLLIB~1\java\sqlj.zip for MSWin32 is default 'D:\PROGRA~1\IBM\SQLLIB~1\java\sqlj.zip' [perl][4] portable: SUB_FIX_JAVA_PATH => D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc_license_cu.jar for MSWin32 is default 'D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc_license_cu.jar' [perl][4] portable: SUB_FIX_JAVA_PATH => D:\PROGRA~1\IBM\SQLLIB~1\bin for MSWin32 is default 'D:\PROGRA~1\IBM\SQLLIB~1\bin' [perl][4] portable: SUB_FIX_JAVA_PATH => D:\PROGRA~1\IBM\SQLLIB~1\java\common.jar for MSWin32 is default 'D:\PROGRA~1\IBM\SQLLIB~1\java\common.jar' [perl][4] portable: SUB_FIX_JAVA_PATH => D:\Program Files\Rational\ClearQuest\cqjni.jar for MSWin32 is default 'D:\Program Files\Rational\ClearQuest\cqjni.jar' [perl][4] portable: SUB_FIX_JAVA_PATH => C:\Perl\site\lib\Inline\Java\InlineJavaServer.jar for MSWin32 is default 'C:\Perl\site\lib\Inline\Java\InlineJavaServer.jar' [perl][2] classpath: H:\svn;D:\PROGRA~1\IBM\SQLLIB~1\java\db2java.zip;D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc.jar;D:\PROGRA~1\IBM\SQLLIB~1\java\sqlj.zip;D:\PROGRA~1\IBM\SQLLIB~1\java\db2jcc_license_cu.jar;D:\PROGRA~1\IBM\SQLLIB~1\bin;D:\PROGRA~1\IBM\SQLLIB~1\java\common.jar;D:\Program Files\Rational\ClearQuest\cqjni.jar;C:\Perl\site\lib\Inline\Java\InlineJavaServer.jar [perl][1] starting JVM... [perl][1] client/server mode [perl][4] portable: GOT_NEXT_FREE_PORT for MSWin32 is '0' [perl][4] portable: J2SDK_BIN for MSWin32 is 'bin' [perl][4] portable: EXE_EXTENSION for MSWin32 is '.exe' [perl][4] portable: SUB_FIX_CMD_QUOTES => "C:\Program Files\Java\jdk1.6.0_17\bin\java.exe" org.perl.inline.java.InlineJavaServer 4 localhost 7890 false false false for MSWin32 is default '"C:\Program Files\Java\jdk1.6.0_17\bin\java.exe" org.perl.inline.java.InlineJavaServer 4 localhost 7890 false false false' [perl][2] "C:\Program Files\Java\jdk1.6.0_17\bin\java.exe" org.perl.inline.java.InlineJavaServer 4 localhost 7890 false false false [perl][4] portable: DEV_NULL for MSWin32 is 'nul' [perl][1] JVM owner exiting... Can't exec JVM: open3: Can't call method "close" on an undefined value at C:/Perl/lib/IPC/Open3.pm line 370. at C:/Perl/site/lib/Inline/Java.pm line 484 INIT failed--call queue aborted. [perl][1] killed by natural death. [perl][1] exiting with 22 

好的。 我想到了。 我有几件事情错了:

  • 在Study下,我有方法和类,但我只应该有Class。

错误

 use Inline ( Java => 'DATA', J2SDK => $ENV{JAVA_HOME}, CLASSPATH => $PERL_CLASSPATH, STUDY => ["SFTP", "close", "list", "get", "put", "remove"], # DEBUG => 4, ); 

 use Inline ( Java => 'DATA', J2SDK => $ENV{JAVA_HOME}, CLASSPATH => $PERL_CLASSPATH, STUDY => ["SFTP"], # DEBUG => 4, ); 
  • 当我将SFTP对象声明为new ,我必须为它提供完整的Perl命名空间:

错误

 eval {$self->{CONNECTION} = new SFTP($server, $user, $password);}; 

 eval {$self->{CONNECTION} = new FMS3::Sftp::SFTP($server, $user, $password);}; 

你在这样的事情上花了几个小时,放弃了,然后突然间,尘土飞扬的阁楼上的灯光亮了起来。 我是一个相当聪明的人。 将螺丝刀插入带电sockets,在第三次或第四次之后,我会“嘿,也许这不是一个好主意”。

试试Net :: SFTP :: Foreign,如果你将它与plink(PuTTY包中的命令行ssh客户端)一起使用,你将不需要任何其他模块来使它工作。