有没有办法从build.xml中指定本地jsch.jar的位置?

build.xml包含任务,因此我将builds中的jsch.jar和其他库提供在同一目录中。

以下taskdef:

  

抛出错误

 A class needed by class org.apache.tools.ant.taskdefs.optional.ssh.Scp cannot be found: com/jcraft/jsch/UserInfo 

我无法修改标准的Ant安装(例如将jsch.jar放在ant lib目录中,或删除ant-jsch.jar),或添加命令行标志,或修改系统环境变量等:脚本必须以默认运行Ant在不同的系统上。

我实际上是在重新提出这里最初提出的问题: http : //ant.1045680.n5.nabble.com/specifying-location-of-an-external-library-within-build-xml-td1344969.html

但是无法得到关于classloader工作的答案。

最后我找到了一个有效的解决方案(至少对Ant 1.7.1)。 首先,你必须从ANT_HOME/lib删除ant-jsch.jar ,因为Ant抱怨它并感到困惑。 然后从项目本身加载库:

         

所以,这个问题已经过时了,但我设计了另一种方法可以帮助别人。 我们可以使用适当的类路径从任务中生成Ant来运行 。 这样可以避免类路径泄漏问题,并且不需要以任何方式更改Ant安装:

                     

不需要port参数,但它在此处作为自定义SSH端口的提醒。 密码是存储在/tmp/passwordfile上的属性,如PASSWORD=mysecretpassword 。 根据您的需要更改这些。 以下是一个用法示例:

      

作为参考,我认为有用的方法是重新包装jar子,因此它们不会发生冲突 – 您可以使用JarJar在Ant中执行此操作,如下所示:

            

我可以通过这里的post来解决这个问题https://stackoverflow.com/a/858744/3499805然后

   

创建路径引用,然后在任务定义中使用它:

        

创建~/.ant/lib并在其中复制jsch.jar作为构建初始化的一部分。

        

URLClassLoader有一个众所周知的技巧 。 通过使用它,我们可以使jsch可以访问ant-jsch

我想知道@ user3499805的答案中的classloadertask是如何工作的。

      

_

 package tools.deployments.ant; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Task; import org.apache.tools.ant.taskdefs.optional.ssh.LogListener; public class InjectJsch extends Task { public void setJarLocation(final String jarLocation) { this.jarLocation = jarLocation; } @Override public void execute() throws BuildException { try { injectJsch(new URL(jarLocation)); } catch (final Exception e) { throw new BuildException(e); } } public static void injectJsch(final URL jarLocation) throws Exception { ClassLoader parent = LogListener.class.getClassLoader(); try { parent.loadClass(TESTCLASS); } catch (final ClassNotFoundException e) { final Method addURLmethod = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); addURLmethod.setAccessible(true); ClassLoader cl; do { cl = parent; if (cl instanceof URLClassLoader) { addURLmethod.invoke(cl, jarLocation); break; } parent = cl.getParent(); } while (parent != cl && parent != null); LogListener.class.getClassLoader().loadClass(TESTCLASS); } } private String jarLocation; private static final String TESTCLASS = "com.jcraft.jsch.UserInfo"; }