有没有办法从build.xml中指定本地jsch.jar的位置?
build.xml包含<scp>
和<sshexec>
任务,因此我将jsch.jar和 其他库与build.xml一起提供在同一目录中。有没有办法从build.xml中指定本地jsch.jar的位置?
下面的taskdef:
<taskdef name="scp"
classname="org.apache.tools.ant.taskdefs.optional.ssh.Scp"
classpath="WebContent/WEB-INF/lib/jsch-0.1.43.jar" />
抛出一个错误
A class needed by class org.apache.tools.ant.taskdefs.optional.ssh.Scp
cannot be found: com/jcraft/jsch/UserInfo
我不能修改标准的Ant安装(例如把jsch.jar在蚂蚁的lib目录 或删除蚂蚁jsch。 jar),或添加命令行标志,或者修改系统环境变量等等:脚本必须在不同系统上使用默认Ant 运行。
实际上,我重新张贴在这里最初提出这样的问题: http://ant.1045680.n5.nabble.com/specifying-location-of-an-external-library-within-build-xml-td1344969.html
,但无法获得有关的类加载器的工作答案。
最后,我找到了工作液(用于蚂蚁1.7.1至少)。首先,你必须从ANT_HOME/lib
中删除ant-jsch.jar
,因为Ant抱怨并且感到困惑。再从项目本身的加载库:
<available property="ant-jsch.present" file="${ant.home}/lib/ant-jsch.jar"/>
<fail if="ant-jsch.present" message="Please remove ant-jsch.jar from ANT_HOME/lib see [http://ant.apache.org/faq.html#delegating-classloader]"/>
<path id="jsch.path">
<pathelement location="lib/ant-jsch.jar" />
<pathelement location="lib/jsch-0.1.44.jar" />
</path>
<taskdef name="scp" classname="org.apache.tools.ant.taskdefs.optional.ssh.Scp" classpathref="jsch.path" />
<taskdef name="sshexec" classname="org.apache.tools.ant.taskdefs.optional.ssh.SSHExec" classpathref="jsch.path" />
创建路径引用,然后在你的任务定义使用它:
<path id="ssh.path">
<pathelement location="${lib1.dir}/helloworld.jar"/>
<fileset dir="${lib2.dir}">
<include name="*.jar"/>
</fileset>
</path>
<taskdef name="mytask" classname="org.mytask" classpathref="ssh.path" />
所以,这个问题是旧的,但我设计的另一种方法可以帮助别人。我们可以使用适当的类路径从<java>
任务产生Ant以运行<scp>
。这避免了classpath中泄漏的问题,并没有需要改变的Ant安装以任何方式:
<target name="sendfile">
<!-- file: local file to send -->
<!-- todir: remote directory -->
<java classname="org.apache.tools.ant.launch.Launcher"
fork="true" dir="${basedir}" taskname="ant+scp">
<classpath>
<pathelement location="/where/is/jsch-0.1.49.jar"/>
<pathelement location="${ant.home}/lib/ant-launcher.jar"/>
</classpath>
<arg value="-buildfile"/>
<arg file="${ant.file}"/>
<arg value="-Dfile=${file}"/>
<arg value="-Dtodir=${todir}"/>
<arg value="sendfile.scp"/>
</java>
</target>
<target name="sendfile.scp">
<echo message="Sending ${file} to ${todir}"/>
<property file="/tmp/passwordfile"/>
<scp file="${file}" todir="[email protected]:${todir}"
trust="true" port="22" password="${PASSWORD}"/>
</target>
不需要
的port
参数,但它是这里自定义SSH端口的提醒。密码是存储在
/tmp/passwordfile
上的财产,如
PASSWORD=mysecretpassword
。改变这些以适应您的需求。这里遵循使用示例:
<ant target="sendfile">
<!-- Example: send /etc/os-release file to remote dir /home/myself -->
<property name="file" value="/etc/os-release"/>
<property name="todir" value="/home/myself"/>
</ant>
仅供参考,我发现有用的是重新包装罐的方法,所以他们不冲突 - 你可以使用JarJar这样在蚂蚁做到这一点:
<taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask" classpath="${basedir}/lib/build/jar/jarjar-1.4.jar"/>
<taskdef name="scp" classname="repackaged.scp.org.apache.tools.ant.taskdefs.optional.ssh.Scp" classpath="${basedir}/lib/build/jar/repackaged-scp.jar"/>
<target name="repackage.scp" description="Repackages Ant's optional SCP task and the JSch implementation to avoid conflicting with one on Ant's classpath">
<delete file="${basedir}/lib/build/jar/repackaged-scp.jar" failonerror="false"/>
<jarjar basedir="." jarfile="${basedir}/lib/build/jar/repackaged-scp.jar" includes="nothing">
<zipfileset src="${basedir}/lib/build/jar/ant-jsch-1.9.1.jar"/>
<zipfileset src="${basedir}/lib/build/jar/jsch-0.1.50.jar"/>
<rule pattern="com.jcraft.jsch.**" result="[email protected]"/>
<rule pattern="org.apache.tools.ant.taskdefs.optional.ssh.**" result="[email protected]"/>
</jarjar>
</target>
创建~/.ant/lib
并复制jsch.jar
作为构建初始化的一部分。
<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>
我能够从这里 https://stackoverflow.com/a/858744/3499805 解决这个问题,下面的帖子,然后
<taskdef resource="net/jtools/classloadertask/antlib.xml" classpath="${basedir}/ant-lib/ant-classloadertask.jar" />
<classloader loader="system" classpath="${basedir}/ant-lib/jsch-0.1.54.jar"/>
有一个著名的trick与URLClassLoader
。通过使用它,我们可以让jsch
访问ant-jsch
。
我不知道如何从@ user3499805答案classloadertask
的作品。
<target name="injectJsch" description="inject jsch jar">
<makeurl file="${acdc.java.tools}/lib/jsch-0.1.50.jar" property="jsch.jar.url"/>
<taskdef name="injectJsch"
classname="tools.deployments.ant.InjectJsch"
classpath="${basedir}/jars/ajwf_deploytools.jar"
/>
<injectJsch jarLocation="${jsch.jar.url}"/>
</target>
_
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";
}
看来这是一个普遍的问题,我觉得这是最好的解决办法,除了没有失败,我要先走一步,删除/ lib中/蚂蚁-jsch.jar。如果它帮助其他人,Paulo在他的SO中解释了核心问题[回答相关的SCP问题](http://stackoverflow.com/questions/5796587/problems-with-ant-optional-tasks-sshexec-和-scp-classpath-issue)和[同样的问题出现在junit中,并在这里解释](http://ant.apache.org/faq.html#delegating-classloader) – gMale 2011-08-12 14:29:29
但是这需要修改标准的Ant安装。 – 2016-08-04 08:07:10
我一直在努力解决这个问题几天,这个解决方案是我唯一能够工作的解决方案! – 2017-08-23 14:14:08