2011-04-26 60 views
1

我正在修改一个Ant脚本(目前正在MyEclipse中使用)从命令行工作。我这样做是为了让任何人都可以签出项目并在没有MyEclipse的情况下构建它。我遇到的问题是MyEclipse包含幕后的依赖关系。它通过查看工作区的Ant配置并根据首选项对话框中选定的库编译类路径来实现此目的。长话短说,我需要采取这些依赖关系,并使脚本足够聪明,以便在没有MyEclipse帮助的情况下自行包含它们。Ant可选任务SSHExec和SCP出现问题。类路径问题?

让我头疼的任务是sshexec和scp任务。它们是可选的ant任务,需要运行一个jsch版本。我从MyEclipse的Ant类路径中删除了jsch,并将其添加到项目本身的lib文件夹(lib/dev)中。 MyEclipse立即抱怨说SSHExec类找不到依赖类com.jcraft.jsch.UserInfo,它是jsch-0.1.44.jar的一部分。

我没有看到从构建脚本中为Ant设置类路径的方法。我有以下代码,它将一个path元素添加到脚本中,但我不认为Ant会使用它,除非明确关联到任务或其他元素。

<path id="web-jars"> 
    <fileset dir="${web-lib}"> 
    <include name="**/*.jar" /> 
    </fileset> 
    <fileset dir="${app-lib}"> <!-- this is where jsch resides --> 
    <include name="**/*.jar" /> 
    </fileset> 
</path> 

看来,我需要使用taskdef定义sshexec和scp任务:

<taskdef name="sshexec" classname="org.apache.tools.ant.taskdefs.optional.ssh.SSHExec" 
    classpathref="web-jars"/> 

MyEclipse的抱怨这个,"taskdef A class needed by class org.apache.tools.ant.taskdefs.optional.ssh.SSHExec cannot be found: com/jcraft/jsch/UserInfo"

这显然是在classpathref,网络的罐子。由于这种格式错误或配置错误的taskdef,我无法在脚本中运行任何内容。

+0

问题可以解决此问题 http://stackoverflow.com/a/39976060/3499805 – user3499805 2016-10-11 11:22:03

回答

3

这里的问题是,SSHExec类是从一个本身无法访问web-jars类加载器的类加载器加载的。为taskdef提供这个类路径不会改变这个。每个类只能从它自己的类加载器和任何父类加载器加载类,但是web-jar类加载器不是SSHExec类加载器的父类加载器(可能相反,因为SSHExec似乎可以在这里找到)。

它看起来像这样:

ClassLoader web-jars -------------> application CL -------------> bootstrap CL 

taskdef 
     => look for SSHExec here 
      => look first in parent class loader 
            => look for SSHExec here 
            => look first in parent class loader 
                    => look for SSHExec here 
                    => not found 
            => look in our own classpath 
            => found, load the class 
            => it somehow uses interface UserInfo 
            => look for UserInfo here 
            => look first in parent class loader 
                    => look for UserInfo here 
                    => not found 
            => look in our own classpath 
            => not found, throw exception. 

的VM不知道找的UserInfo(和其他JSch班)在网上罐类加载器。

我想SSHExec任务是在通常的ant类路径中的某处,即由应用程序类加载器加载。然后从ant的类路径中删除SSHExec(或将jsch.jar添加到它)似乎是唯一的解决方案。

+0

谢谢@帕洛埃伯曼。这很有道理。但是,您提到删除SSHExec可能是一个解决方案。如果我从ant classpath(ant/lib)中删除SSHExec(ant-jsch.jar),我需要将它放在其他地方,对吗?我不能简单地删除它,我可以吗?在我看来,会导致Ant在'sshexec'taskdef上失败,因为在类路径中找不到类名。我错过了什么吗? – jinxed 2011-04-28 14:56:14

+1

你应该将它添加到taskdef的'classpath'或'classpathref'中,我想。例如,您可以使用一个新的''定义,引用'web-jars'路径。 – 2011-04-28 22:16:09

0

创建〜/ .ant/lib并在其中复制jsch.jar作为构建初始化的一部分。执行scp/sshexec工作的任何任务都应该依赖于此init目标。

<target name="init"> 
    <property name="user.ant.lib" location="${user.home}/.ant/lib"/> 
    <mkdir dir="${user.ant.lib}"/> 
    <copy todir="${user.ant.lib}"> 
    <fileset dir="${basedir}/build/tools" includes="jsch-*.jar"/> 
    </copy> 
</target> 

<target name="mytarget" depends="init"> 
    <scp todir="[email protected]"><fileset dir="..."/></scp> 
</target> 

在Eclipse中Ant的不幸不会立即拿起这件事,因为它不会在每次执行读取~/.ant/lib;在Eclipse中运行mytarget一次,看着它失败后,然后去: 窗口>首选项>蚂蚁>运行并按恢复默认值 - 这将增加任何。jar文件从~/.ant/lib全球条目部分,你应该很好去。