ant使用总结(四):自定义库

自定义Condition

编写自定义的condition,可以实现自定义的条件判断逻辑,需要实现org.apache.tools.ant.taskdefs.condition.Condition接口,只有一个必须实现的方法就是eval,用于返回条件判断结果。

比如:实现一个用于判断一个字符串是否全部大写的Condition。

步骤:

1.新建Java工程

2.引入ant库

ant相关的jar就在apache-ant-1.9.4\lib目录下。在Java工程中新建一个libs目录,把jar包都拷贝到libs下,选中所有jar,右键Build Path——Add To Build Path,就完成了ant库的引入。

3.自定义Condition条件判断类

package linchaolong.ant.condition;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.taskdefs.condition.Condition;

// 用于判断字符串是否全部是大写
public class UppoerCondition implements Condition{

    private String value;

    // 定义一个setter方法,用于设置value的值
    public void setValue(String value){
        this.value = value;
    }

    //Is this condition true?,条件是否成立的判定方法
    @Override
    public boolean eval() throws BuildException {
        // 如果未设置value属性,抛出异常
        if (value == null) {
            throw new BuildException("value attribute  is not set");
        }
        // 判断字符串是否大写
        return value.toUpperCase().equals(value);
    }
}

4.使用自定义类

<project name="test" default="run">
    <target name="run">
        <!-- 自定义类型 -->
        <typedef
            name="isupper"
            classname="linchaolong.ant.condition.UppoerCondition"
            classpath="./../bin"/><!-- 我这里把工程bin目录添加到类路径 -->

        <!-- 在condition中使用自定义标签 -->
        <condition property="isUpper">
            <isupper value="THIS IS ALL UPPER CASE"/> <!-- 如果条件成立,则定义isUpper属性,而值为true -->
        </condition>

        <!-- 打印属性值 -->
        <echo>result : ${isUpper}</echo>

        <antcall target="result" />
    </target>

    <target name="result" if="${isUpper}">
        <echo>is all uppper</echo>
    </target>
</project>

打印结果:

自定义选择器

FilenameSelector

通过自定义选择器可以实现自定义的文件过滤规则。需要继承org.apache.tools.ant.types.selectors.FilenameSelector,并重写isSelected方法。

示例:

package linchaolong.ant.selector;

import java.io.File;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.types.selectors.FilenameSelector;

// 用于过滤出所有指定后缀的文件的Selector
public class EndWithSelector extends FilenameSelector {

    private String endWith;

    // setter
    public void setEndWith(String endWith) {
        this.endWith = endWith;
    }

    @Override
    public boolean isSelected(File dir, String filename, File file) {
        // 如果未设置endWith属性则抛出异常
        if (endWith == null) {
            throw new BuildException("endWith is not set.");
        }
        return filename.toLowerCase().endsWith(endWith.toLowerCase().trim());
    }
}

使用示例:

<project name="test" default="run">
    <target name="run">
        <!-- 自定义类型 -->
        <typedef
            name="endwithSelector"
            classname="linchaolong.ant.selector.EndWithSelector"
            classpath="./../bin"/><!-- 我这里把工程bin目录添加到类路径 -->

        <!-- 把上层目录下所有.class文件拷贝到to目录下 -->
        <copy todir="to">
           <fileset dir="./../">
              <endwithSelector endWith=".class"/>
           </fileset>
        </copy>
    </target>
</project>

BaseSelectorContainer

BaseSelectorContainer是一个选择器容器,在过滤文件的时候可能需要多个判断条件,这时就需要用到选择器容器了。

BaseSelectorContainereva中有一个vlidate方法,当调用vlidate方法时会调用verifySettings方法,主要用于检查配置是否正确。可以通过定义verifySettings方法检查配置。

示例代码

package linchaolong.ant.selector;
import java.io.File;
import java.util.Enumeration;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.types.selectors.BaseSelectorContainer;
import org.apache.tools.ant.types.selectors.FileSelector;

// 用于过滤出满足指定数量条件的文件的选择器容器
public class MatchCountSelectors extends BaseSelectorContainer {
    private int count = -1;
    private String when;

    public static final String MORE = "more";
    public static final String LESS = "less";
    public static final String EQUAL = "equal";

    // setter
    public void setCount(int count) {
        this.count = count;
    }
    // setter
    public void setWhen(String when){
        this.when = when;
    }

    // 校验配置是否正确
    public void verifySettings() {
        if (count < 0) {
            // 如果配置不正确抛出异常
           throw new BuildException("count attribute should be set");
        }
        if(when == null){
            throw new BuildException("when attribute should be set");
        }
    }

    // 从选择的文件中选择指定数量的文件
    public boolean isSelected(File baseDir, String filename, File file) {
        // 调用validate方法检查配置是否正确
        validate();

        // 迭代所有容器的选择器列表,计算当前文件满足的条件个数
        int countSelected = 0;
        for (Enumeration e = selectorElements(); e.hasMoreElements();) {
            FileSelector s = (FileSelector) e.nextElement();
            if (s.isSelected(baseDir, filename, file)) {
                countSelected++;
            }
        }

        // 判断是否满足指定数量的条件
        if(MORE.equalsIgnoreCase(when)){
            return countSelected > count;
        }else if(EQUAL.equalsIgnoreCase(when)){
            return countSelected == count;
        }
        else if(LESS.equalsIgnoreCase(when)){
            return countSelected < count;
        }else{
            throw new BuildException("when value is not defined");
        }
    }
}

使用示例

<project name="test" default="run">
    <target name="run">
        <!-- 自定义类型 -->
        <typedef
            name="matchCountSelectors"
            classname="linchaolong.ant.selector.MatchCountSelectors"
            classpath="./../bin"/><!-- 我这里把工程bin目录添加到类路径 -->

        <copy todir="to">
            <!-- 找出在上层目录下满足以下条件其中2个的所有文件 -->
           <fileset dir="./../">
               <matchCountSelectors count="2" when="more">

                   <!-- 文件中包含selector的文件,忽略大小写 -->
                  <contains text="selector" casesensitive="no"/>

                  <!-- 小于4KB -->
                  <size value="4" units="Ki" when="less"/>

                  <!-- 类型为文件,dir表示目录 -->
                  <type type="file"/>

                  <!-- 可读 -->
                  <readable />

                  <!-- 在2001年1月1日12点后创建的文件 -->
                   <date datetime="01/01/2001 12:00 AM" when="after"/>

               </matchCountSelectors>
           </fileset>
        </copy>
    </target>
</project>

>>点击查看更多选择器

自定义Task

有时ant提供的功能可能不足以满足需求时,我们可以通过继承org.apache.tools.ant.Task编写自己需要的功能,实现public void execute()方法,在execute()方法编写需要执行代码。

在java中通过定义addXXX方法,获取子标签。

示例代码:

package linchaolong.ant.task;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Resource;

// 统计文件个数并把值赋给指定的property
public class TotalFile extends Task {

    private List<FileSet> files = new ArrayList<FileSet>();
    private String name;

    // setter,设置属性名
    public void setName(String name){
        this.name = name;
    }

    // 在java中通过addXXX方法获取子标签
    public void add(FileSet fs) {
        files.add(fs);
    }

    // 检查配置
    public void validitySetting(){
        if (name == null || name.isEmpty()) {
            throw new BuildException("attribute name is empty");
        }
    }

    @Override
    public void execute() throws BuildException {
        super.execute();
        // 检查配置
        validitySetting();

        int total = 0;

        // 统计文件个数
        for (FileSet fs : files) {
            Iterator<Resource> it = fs.iterator();
            while(it.hasNext()){
                it.next();
                ++total;
            }
        }

        // 设置属性值
        getProject().setProperty(name, Integer.toString(total));
    }
}

使用示例:

<project name="test" default="run">
    <target name="run">
        <!-- 自定义类型 -->
        <typedef name="totalFile" classname="linchaolong.ant.task.TotalFile"
            classpath="./../bin" /><!-- 我这里把工程bin目录添加到类路径 -->

        <!-- 统计文件个数 -->
        <totalFile name="total" >
            <fileset dir="./">
                    <!-- 文件中包含selector的文件,忽略大小写 -->
                    <contains text="selector" casesensitive="no" />
                    <!-- 小于4KB -->
                    <size value="4" units="Ki" when="less" />
            </fileset>
            <fileset dir="./../libs">
                    <!-- 类型为文件,dir表示目录 -->
                    <type type="file" />
                    <!-- 可读 -->
                    <readable />
                    <!-- 在2001年1月1日12点后创建的文件 -->
                    <date datetime="01/01/2001 12:00 AM" when="after" />
            </fileset>
        </totalFile>

        <!-- 打印结果 -->
        <echo>total = ${total}</echo>
    </target>
</project>

运行结果:

导出和使用自定义库

一般我们都会把所有class文件打成一个jar,供外部调用。

1.配置关联

比如这里在工程根目录新建了一个tags.cfg文件,内容如下:

#key为tag的名称,value为类的全路径名
#判断字符串是否全部大写
isupper = linchaolong.ant.condition.UpperCondition

#过滤出满足指定条件数量的文件
matchCountSelectors = linchaolong.ant.selector.MatchCountSelectors

#过滤出指定后缀的文件
endwithSelector = linchaolong.ant.selector.EndWithSelector

#统计文件数量
totalFile = linchaolong.ant.task.TotalFile

2.导出jar

选中项目,右键——export——Java——JAR file,选中src目录和配置文件tags.cfg,设置好导出路径,点击finish就ok了。

3.使用自定义库

一般在文件开头的地方先加载扩展库。

    <!-- 使用自定义库 -->
    <typedef resource="tags.cfg"> <!-- 解析tags.cfg并建立关联 -->
        <classpath>
            <pathelement location="./linchaolong_ant.jar" /> <!-- jar文件路径 -->
        </classpath>
    </typedef>

项目地址:https://coding.net/u/linchaolong/p/AntCustomLibrary/git

相关文档

http://ant.apache.org/manual/Types/custom-programming.html

http://ant.apache.org/manual/develop.html#writingowntask

打开apache-ant-1.9.4/manual/index.html可以查看ant文档,点击左边的Ant API查看API文档。

时间: 2024-10-07 00:11:05

ant使用总结(四):自定义库的相关文章

iOS流布局UICollectionView系列四——自定义FlowLayout进行瀑布流布局

iOS流布局UICollectionView系列四--自定义FlowLayout进行瀑布流布局 一.引言 前几篇博客从UICollectionView的基础应用到设置UICollectionViewFlowLayout更加灵活的进行布局,但都限制在系统为我们准备好的布局框架中,还是有一些局限性,例如,如果我要进行瀑布流似的不定高布局,前面的方法就很难满足我们的需求了,如下: 这种布局无疑在app的应用中更加广泛,商品的展示,书架书目的展示,都会倾向于采用这样的布局方式,当然,通过自定义FlowL

python解决导入自定义库失败: ModuleNotFoundError: No module named &#39;MyLib&#39;

python安装目录:...\python_3_6_1_64bit 新建文件:chenyeubai.pth,写入库所在的绝对路径E:\workSpace\my_code\learn\myLib 安装路径下的.pth文件会在运行时将文件中路径写入path python解决导入自定义库失败: ModuleNotFoundError: No module named 'MyLib' 原文地址:https://www.cnblogs.com/chenyuebai/p/8416706.html

计算机科学基础知识(四)动态库和位置无关代码

一.前言 本文主要描述了动态库以及和动态库有紧密联系的位置无关代码的相关资讯.首先介绍了动态库和位置无关代码的源由,了解这些背景知识有助于理解和学习动态库.随后,我们通过加-fPIC和不加这个编译选项分别编译出两个relocatable object file,看看编译器是如何生成位置无关代码的.最后,我们自己动手编写一个简单的动态库,并解析了一些symbol Visibility.动态符号表等一些相关基本概念. 本文中的描述是基于ARM MCU,GNU/linux平台而言的,本文是个人对动态库

Dart自定义库、系统库和第三方库

/* 前面介绍Dart基础知识的时候基本上都是在一个文件里面编写Dart代码的,但实际开发中不可能这么写,模块化很重要,所以这就需要使用到库的概念. 在Dart中,库的使用时通过import关键字引入的. library指令可以创建一个库,每个Dart文件都是一个库,即使没有使用library指令来指定. Dart中的库主要有三种: 1.我们自定义的库 import 'lib/xxx.dart'; 2.系统内置库 import 'dart:math'; import 'dart:io'; imp

Robotframework之自定义库

前面对RF有了基本的认识, 系统关键字和自定义关键字都已搞定, 那么就可以开始来封装自己的库了. 过程并不复杂, 但是容易被一些小问题卡住, 因此, 仔细一点咯 1. 在python安装目录下的 Lib\site-packages目录下 新建一个目录,目录名就是库名,如NewLibrary 2. 在新建的NewLibrary目录下创建一个python文件,任何合法的文件名即可,扩展名为py.如:myclass.py. 内容如下: #!/usr/bin/env python #-*- coding

自定义库引用时编译出错“collect2: error: ld returned 1 exit status”

想必很多人都遇到过这样的事情,需要写一个共享库,这个库又不能让所有的人都了解里面是怎么实现的,所以只能提供一个库出来供项目使用,可能是处于保密.核心业务的需要,这些都能够理解.笔者也写了一个简单的东西测试了一下,里面还是有不少东西. "collect2: error: ld returned 1 exit status"首先就遇到了这个问题.查了一下,这种错误网上说法也一大堆,起作用的还不多.在android系统里面加的共享库,需要加"namespace android &q

android-gradle-深入浅出四:自定义构建过程之配置manifest

接上一篇 深入浅出Android Gradle构建系统(三:build task) Android Gradle插件提供了大量的DSL来自定义构建过程,这篇blog就来讲解如何在gradle中配置manifest. DSL提供了配置以下Manifest条目的功能: minSdkVersion targetSdkVersion versionCode versionName applicationId (更加方便有效的包名 -- [参考](http://tools.android.com/tech

走进AngularJs(四)自定义指令----(中)

上一篇简单介绍了自定义一个指令的几个简单参数,restrict.template.templateUrl.replace.transclude,这几个理解起来相对容易很多,因为它们只涉及到了表现,而没有涉及行为.这一篇将继续学习ng自定义指令的几个重量级参数,了解了它们之后我们的custom directive将不光能"看",还要能"动".开始~ 理解compile和link 不知大家有没有这样的感觉,自己定义指令的时候跟写jQuery插件有几分相似之处,都是先预先

struts2权威指南学习笔记:struts2引入自定义库

问题: 在jsp页面中添加了s:property标签,然而在页面始终未展示 解决: 经过搜索学习,发现只要添加语句 <%@ taglib prefix="s" uri="/struts-tags"%> 原因: @taglib表明引用标签.类似java中的import语句 prefix="s" 引用的名称在页面可以使用,就像java中生成的一个对象名,以后调用的时候直接使用<s:xxx/>就可以了 uri="/st