代码之家  ›  专栏  ›  技术社区  ›  David W.

尝试通过内嵌::Java模块将Java内嵌到perl中

  •  1
  • David W.  · 技术社区  · 14 年前

    这是我第一次尝试在Perl中嵌入Java代码。我们不能在系统上使用标准的sftp命令。这是我力所能及的。我们有一个jar文件,名为sftp.jar,可以使用。在我之前的前一个人可以让inline::perl工作,但是他的实现很草率,我想清理一下。

    我正在使用Windows系统 H:\svn 目录。我的模块在 H:\svn\FMS3 目录,我有一个jar文件 SFTP.jar H:\svn\FMS3\Sftp.pm 目录。有一个文件叫做 Sftp.pm 位于 H:\Svn\FMS3 目录,并定义一个名为 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
    
    2 回复  |  直到 14 年前
        1
  •  3
  •   David W.    14 年前

    可以。我明白了。我做错了几件事:

    • 在学习中,我既有方法又有课堂,但我只应该有课堂。

    错误的

    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);};
    

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

        2
  •  1
  •   salva    14 年前

    尝试net::sftp::foreign,如果将其与plink(putty包中的命令行ssh客户机)一起使用,则不需要任何其他模块即可使其正常工作。