如何在ant中调用javascript

本文详细介绍了如何在Ant构建工具中利用JavaScript执行解密操作,并通过Java函数实现特定的安装配置过滤,以解决在安装过程中遇到的密码展示与数据库验证冲突的问题。此外,文章还探讨了在不同场景下如何优化脚本以兼容不同的操作系统,确保构建过程顺利进行。
在java6中内置了一个javascript的engine:

Rhino is an open-source implementation of JavaScript written entirely in Java. It is typically embedded into Java applications to provide scripting to end users. It is embedded in J2SE 6 as the default Java scripting engine.

[b]应用场景1.[/b]

在工作中, 我遇到了这样一个应用场景. 调用ant时传的属性参数中有连接数据库的密码, 在log中会显示出来, 如果将密码加密, 那么又会报数据库端的验证错误, 说不认这个经过加密的密码. 怎么办, 有两种方法, 一个是用java写自定义的ant task来解密传给ant script的密码. 然后用明文密码来连接数据库. 写java的缺点在于每次都要事先编译好这个ant task. 还有一种方法是在ant script写一个javascript task. 当然javascript可以调用java的解密函数, 这样不用每次运行ant script前都编译task. 具体脚本如下:

<project name="sfamx.cleanupdb" default="cleanup.db.logging">

<dirname property="sfamx.ddl.dir" file="${ant.file.sfamx.ddl.build}"/>

<target name="cleanupall" depends="replace.db.password, cleanup.db.logging"/>

<path id="jdbc.classpath">
<fileset dir="${db.driver.path}" includes="*.jar"/>
</path>

<property name="plaintext.password" value="${plainText}"/>

<target name="replace.db.password">
<script language="javascript">
<classpath>
<!-- for xxx 3.2 -->
<pathelement location="${tibco.home}/components/shared/1.0.0/plugins/com.tibco.security.tibcrypt_2.15.0.009.jar"/>
<pathelement location="${tibco.home}/components/shared/1.0.0/plugins/com.tibco.tpcl.org.slf4j.log4j12_1.6.200.001/slf4j-log4j12-1.5.2.jar"/>
<pathelement location="${tibco.home}/components/shared/1.0.0/plugins/com.tibco.tpcl.org.slf4j.log4j12_1.6.200.001/slf4j-api-1.5.2.jar"/>
<pathelement location="${tibco.home}/components/shared/1.0.0/plugins/com.tibco.tpcl.org.apache.log4j_1.2.400.002/log4j-1.2.15.jar"/>
<!-- for xxx 3.1.5 -->
<pathelement location="${tibco.home}/components/shared/1.0.0/plugins/com.tibco.security.tibcrypt_2.14.300.006.jar"/>
<pathelement location="${tibco.home}/components/shared/1.0.0/plugins/com.tibco.tpcl.org.slf4j.log4j12_1.5.101.001/slf4j-log4j12-1.5.2.jar"/>
<pathelement location="${tibco.home}/components/shared/1.0.0/plugins/com.tibco.tpcl.org.slf4j.log4j12_1.5.101.001/slf4j-api-1.5.2.jar"/>
<pathelement location="${tibco.home}/components/shared/1.0.0/plugins/com.tibco.tpcl.org.apache.log4j_1.2.300.004/log4j-1.2.15.jar"/>
</classpath>
<![CDATA[
importPackage(com.tibco.security);
var encryptedPassword = project.getProperty("admin.db.password");
var decryptedPassword = ObfuscationEngine.decrypt(encryptedPassword);
var plainText = new java.lang.String(decryptedPassword);
project.setProperty("plaintext.password", plainText)
]]>
</script>
</target>

<target name="cleanup.db.logging" depends="replace.db.password"
description="Run ddl to cleanup commonlogging tables in external database for amx administrator">
<sql
driver="${admin.db.driver}"
url="${admin.db.url}"
userid="${admin.db.username}"
password="${plaintext.password}"
print="yes">
<classpath refid="jdbc.classpath"/>
<transaction src="./${db.ddl.path}/drop_commonlogging.ddl"/>
</sql>
</target>
</project>


输出

05/25/12 18:46:55.406 INFO: [ProcessWrapper] Executing: D:\build\fabric\DSEngine\resources\win32\wrappid.exe,D:\build\fabric\DSEngine\work\yangxiaoming-lt-1\antcall.pid,D:/build/fabric/DSEngine/work/yangxiaoming-lt-1/tibcoamx/tibcojre/1.6.0/bin/java,-cp,D:/build/fabric/DSEngine/work/yangxiaoming-lt-1/tibcoamx/tools/lib/antpackage.jar,org.apache.tools.ant.launch.Launcher,-f,D:\build\fabric\DSEngine\work\yangxiaoming-lt-1\scripts\cleanupDDL\cleanupDB.xml,[b]-Dadmin.db.password=#!Panbl6s1FhkBUM70G9T+okR+fv5Nwoq+fYUx+SLzZi8=[/b],-Dadmin.db.url=jdbc:sqlserver://192.168.71.99:1433;databasename=amxdb,-Dadmin.db.username=sa,-Ddb.ddl.path=mssql300,-Ddb.driver.path=D:\build\fabric\DSEngine\work\yangxiaoming-lt-1/fabric/mssql2008_driver,-Dtibco.home=D:/build/fabric/DSEngine/work/yangxiaoming-lt-1/tibcoamx,-Dadmin.db.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver,[b]cleanup.db.logging[/b],
05/25/12 18:46:55.609 INFO: [ProcessWrapper] [STDOUT] Buildfile: D:\build\fabric\DSEngine\work\yangxiaoming-lt-1\scripts\cleanupDDL\cleanupDB.xml
05/25/12 18:46:55.875 INFO: [ProcessWrapper] [STDOUT]
05/25/12 18:46:55.875 INFO: [ProcessWrapper] [STDOUT] replace.db.password:
05/25/12 18:46:55.984 INFO: [ProcessWrapper] [STDOUT] [script] log4j:WARN No appenders could be found for logger (com.tibco.security.TIBCOSecurity).
05/25/12 18:46:55.984 INFO: [ProcessWrapper] [STDOUT] [script] log4j:WARN Please initialize the log4j system properly.
05/25/12 18:46:56.500 INFO: [ProcessWrapper] [STDOUT] [echo] Tibc02008
05/25/12 18:46:56.500 INFO: [ProcessWrapper] [STDOUT]
05/25/12 18:46:56.500 INFO: [ProcessWrapper] [STDOUT] cleanup.db.logging:
05/25/12 18:46:56.687 INFO: [ProcessWrapper] [STDOUT] [sql] Executing resource: D:\build\fabric\DSEngine\work\yangxiaoming-lt-1\scripts\cleanupDDL\mssql300\drop_commonlogging.ddl
05/25/12 18:46:56.687 INFO: [ProcessWrapper] [STDOUT] [sql] 0 rows affected
05/25/12 18:46:56.687 INFO: [ProcessWrapper] [STDOUT] [sql] 1 of 1 SQL statements executed successfully
05/25/12 18:46:56.703 INFO: [ProcessWrapper] [STDOUT]
05/25/12 18:46:56.703 INFO: [ProcessWrapper] [STDOUT] BUILD SUCCESSFUL
05/25/12 18:46:56.703 INFO: [ProcessWrapper] [STDOUT] Total time: 1 second


在ant中使用javascript, 在javascript又调用了java, 所以一定要注意数据的boxing和unboxing. 比如用java的方法返回decryptedPassword 时, 它其实已经被unboxing了, 失去了java的char[]类型, 但内在传递的值是不变的, 所以我们需要对它重新boxing, 让它成为java的String类型, 在boxing他的char[]值同时解码, 获得实际字符串, 也就是明文. 再将它传递给javascript的变量.

换句话说, 有的情况js和java的函数相同, 如果var的类型不明显,javascript引擎不知该调用哪个方法, 建议用var input = new String(strInput)

[b]应用场景2.[/b]

在工作当中我遇到了这样一种情况, 安装时需要选择administration, runime host这样的安装profile, 这两者是交集. 我们的目的是想以administration里的所有assembly names作为exclude的对象, 在安装runtime host时加以过滤. 从而保留runtime host独有的assemblies.

<target name="gen-zip-excludes">
<path id="my.path">
<dirset dir="${installation.root}/components/shared/1.0.0/features" includes="*">
<depth max="1"/>
</dirset>
<dirset dir="${installation.root}/components/shared/1.0.0/plugins" includes="*">
<depth max="1"/>
</dirset>
<fileset dir="${installation.root}/components/shared/1.0.0/plugins" includes="*.jar"/>
</path>
<pathconvert targetos="unix" property="zip.excludes" refid="my.path" pathsep="${file.separator}**,">
</pathconvert>
</target>
...
...
<scriptdef name="bwsefilter" language="javascript">
<attribute name="text" />
<attribute name="pluginspath" />
<attribute name="featurespath" />
<attribute name="property" />
<![CDATA[
var text = new java.lang.String(attributes.get("text"));
var path1 = new java.lang.String(attributes.get("pluginspath"));
var path2 = new java.lang.String(attributes.get("featurespath"));
var replaced = text.replaceAll(path1,"**").replaceAll(path2, "**");
project.setProperty(attributes.get("property"), replaced);
]]>
</scriptdef>

<target name="bwse.distribution.filter">
<bwsefilter text="${zip.excludes}" pluginspath="${installation.root}/components/shared/1.0.0/features" featurespath="${installation.root}/components/shared/1.0.0/plugins" property="file.excludes"/>
</target>
...
...
<target name="bwse.distribution.package" depends="bwse.distribution.clean">
<zip destfile="${bwse.distribution.name}">
<zipfileset dir="${installation.root}/" includes="bwse/"/>
<zipfileset dir="${installation.root}/components" prefix="components" excludes="${file.excludes}"/>
<zipfileset dir="${temp.dir}/" includes="grid-library.xml"/>
<zipfileset dir="${temp.dir}/" includes="*.properties"/>
<zipfileset dir="${download.root}/${bwse.installer.name}" includes="TIB_bwse_${bwse.installer.version}_license.pdf"/>
</zip>
<delete includeemptydirs="true">
<fileset dir="${temp.dir}/"/>
</delete>
</target>


[b]注意以下问题[/b]

[b]1.[/b]在这段脚本中:
    <pathconvert targetos="unix" property="zip.excludes" refid="my.path" pathsep="${file.separator}**,">


初看可能会疑惑, targetos为什么标称unix呢? 其实是想和后面的pluginspath="${installation.root}/components/shared/1.0.0/features" featurespath="${installation.root}/components/shared/1.0.0/plugins" 兼容, 如果是没有targetos, 默认的情况下就会根据所在的平台自己判断, 如果在windows上, ${file.separator}就会成为'\', 这样与后面的没办法匹配, 也就过滤失败. 其实ant或者直接说java里都用'/'作为文件分隔符, 即使pluginspath和featurespath里用的是'\'也一样会失败的.

还有人可能会有疑问, pathsep的分隔符为什么要用'${file.separator}**,',而不是',' 原因是我们收集的文件集合里有的是文件夹, 有的是文件, 文件夹必须用'**/文件夹/**过滤', 文件用'**/文件', 而文件用'**/文件/**'也没有问题, 为了把两者都一次性过滤, 所以都用'**/文件或文件夹/**'来过滤.

[b]2.[/b] 在<![CDATA[]]>中, 我们可以用javascript和java代码来完成自定义task, 但js和java混用的话,函数又类似的时候可能会混淆编译器. 所以建议要么用javascript, 要么用java的函数, 用java之前最好把js的字符串用new java.lang.String();转化一下, 比如var text = new java.lang.String(attributes.get("text"));


具体可以参考下这篇文章:
[url]https://developer.mozilla.org/zh_tw/Core_JavaScript_1.5_%E6%95%99%E5%AD%B8/LiveConnect_%E6%A6%82%E8%A6%81/%E8%B3%87%E6%96%99%E9%A1%9E%E5%9E%8B%E7%9A%84%E8%BD%89%E6%8F%9B/%E5%BE%9E_JavaScript_%E5%88%B0_Java_%E7%9A%84%E8%BD%89%E6%8F%9B[/url]


补充:

To do more interesting things with Ant, you have access to properties, targets, and references. For an explanation of properties, targets, and references, refer to the ant manual

project.getProperty(string propertyName);
project.getUserProperty(string propertyName);
project.getTarget(string targetId);
project.getReference(string refereceId);

project is a shortcut for getProject(), which returns the project object.
self returns the script task itself for logging and other task specific utilities.
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值