混淆技术研究笔记(七)Ant扩展介绍
  ZJE9JAGqQBsi 2023年11月02日 40 0

logo

ant 扩展官方文档:https://ant.apache.org/manual/develop.html

Writing Your Own Task

编写你自己的任务

1. 创建一个XXTask类

创建一个Java类继承org.apache.tools.ant.Task,实际上不继承也可以,定义一个 execute() 方法就可以,例如下面的例子:

public class MyTask {
    public void execute() {
        System.out.println("MyTask");
    }
}

配置到插件中测试:

<plugin>
    <artifactId>maven-antrun-plugin</artifactId>
    <version>1.8</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>run</goal>
            </goals>
            <id>obfuscate</id>
            <configuration>
                <tasks>
                    <property name="runtime_classpath" refid="maven.runtime.classpath"/>
                    <taskdef name="my-task" classname="MyTask" classpath="${runtime_classpath}"/>
                    <my-task/>
                </tasks>
            </configuration>
        </execution>
    </executions>
</plugin>

后续示例只提供 <tasks> 中的内容。 可以在示例的 module-yguard 中的 pom.xml 中测试。

执行 package 打包,部分输出日志如下:

[INFO] --- maven-antrun-plugin:1.8:run (obfuscate) @ module-yguard ---
[WARNING] Parameter tasks is deprecated, use target instead
[INFO] Executing tasks

main:
MyTask
[INFO] Executed tasks

接下来继承 org.apache.tools.ant.Task 试试:

public class MyTask extends org.apache.tools.ant.Task {
    public void execute() {
        System.out.println("MyTask, name: " + getTaskName());
    }
}

执行输出的部分日志如下:

[INFO] --- maven-antrun-plugin:1.8:run (obfuscate) @ module-yguard ---
[WARNING] Parameter tasks is deprecated, use target instead
[INFO] Executing tasks

main:
MyTask, name: my-task
[INFO] Executed tasks

警告中建议将 tasks 改为 target,修改试试:

<target>
    <property name="runtime_classpath" refid="maven.runtime.classpath"/>
    <taskdef name="my-task" classname="MyTask" classpath="${runtime_classpath}"/>
    <my-task/>
</target>

再次运行就没有警告信息了。

2. 给 <my-task> 添加属性

<my-task> 添加属性,例如:

<my-task path="${user.dir}"/>

为了能接收这个属性值,需要在 MyTask 添加对应的 setter 方法, setter 方法必须是采用单个参数public void 方法,修改如下:

import java.io.File;

public class MyTask extends org.apache.tools.ant.Task {
    private File path;

    public void setPath(File path)
    {
        this.path = path;
    }

    public void execute() {
        System.out.println("MyTask, name: " + getTaskName() + ", path: " + path);
    }
}

执行测试输出内容如下:

[INFO] --- maven-antrun-plugin:1.8:run (obfuscate) @ module-yguard ---
[INFO] Executing tasks

main:
MyTask, name: my-task, path: E:\GitHub\yguard-modules-parent
[INFO] Executed tasks

可以看到 Ant 自动把参数转换为 File 类型了,Ant 支持的转换规则如下:

  1. 最常见的 java.lang.String 类型;
  2. boolean类型,支持设置为 true,yes,on,其他值则为 false。这部分的逻辑在 Project 类中,代码如下:
    public static boolean toBoolean(final String s) {
         return ("on".equalsIgnoreCase(s)
                 || "true".equalsIgnoreCase(s)
                 || "yes".equalsIgnoreCase(s));
     }
    
  3. charjava.lang.Character,将传递指定值的第一个字符;
  4. 其他基本类型(int,short,long,float,double,byte);
  5. java.io.File,Ant首先会判断构建文件中给出的值是否代表绝对路径名。如果不是,Ant 会将该值解释为相对于项目的 basedir 的路径名;
  6. org.apache.tools.ant.types.Resource,Ant 会将字符串解析为上面的 java.io.File ,然后作为 org.apache.tools.ant.types.resources.FileResource 传入;
  7. org.apache.tools.ant.types.Path,Ant 将标记化构建文件中指定的值,接受 : 和 ;作为路径分隔符。相对路径名将被解释为相对于项目的 basedir;
  8. java.lang.Class ,Ant 会将构建文件中给出的值解释为 Java 类名,并从系统类加载器加载指定的类;
  9. org.apache.tools.ant.types.EnumeratedAttribute 的子类,会调用子类的 setValue 方法,设置的值必须是抽象方法 String[] getValues() 包含的值,通常用于指定固定选项。
  10. 枚举值,会和枚举的 name 进行匹配。

3. 给 <my-task> 添加文本数据

添加文本数据示例:

<my-task path="${user.dir}" enable="hello">中间的文本</my-task>

很显然这种方式和在<my-task>添加子元素是冲突的,这种情况下需要添加 public void addText(String) 方法,代码如下:

import java.io.File;

public class MyTask extends org.apache.tools.ant.Task {
    private File path;
    private boolean enable;
    private String text;

    public void setEnable(boolean enable)
    {
        this.enable = enable;
    }

    public void setPath(File path)
    {
        this.path = path;
    }

    public void addText(String text) {
        this.text = text;
    }

    public void execute() {
        System.out.println("MyTask, name: " + getTaskName() + ", path: " + path + ", enable: " + enable + ", text: " + text);
    }
}

测试输出结果:

[INFO] --- maven-antrun-plugin:1.8:run (obfuscate) @ module-yguard ---
[INFO] Executing tasks

main:
MyTask, name: my-task, path: E:\GitHub\yguard-modules-parent, enable: false, text: 中间的文本
[INFO] Executed tasks

4. 给 <my-task> 添加嵌套元素

例如前面提到的 <patternset> 元素:

<my-task>
    <patternset>
        <include name="org.example.c."/>
        <exclude name="org.example.c.util.FileUtil"/>
    </patternset>
</my-task>

更新 MyTask 代码:

import org.apache.tools.ant.types.PatternSet;

import java.util.ArrayList;
import java.util.List;

public class MyTask extends org.apache.tools.ant.Task
{
  /**
   * The Pattern sets.
   */
  private List<PatternSet> patternSets = new ArrayList(5);

  public void addConfiguredPatternSet(PatternSet ps)
  {
    patternSets.add(ps);
  }

  public void execute()
  {
    patternSets.forEach(ps ->
    {
      String[] includes = ps.getIncludePatterns(getProject());
      String[] excludes = ps.getExcludePatterns(getProject());
      System.out.println("includes: " + String.join(", ", includes));
      System.out.println("excludes: " + String.join(", ", excludes));
    });
  }
}

执行代码输出结果:

[INFO] --- maven-antrun-plugin:1.8:run (obfuscate) @ module-yguard ---
[INFO] Executing tasks

main:
includes: org.example.c.
excludes: org.example.c.util.FileUtil
[INFO] Executed tasks

对于每个嵌套元素,需要编写一个 createaddaddConfigured 方法。 create 方法必须是不带参数并返回 Object 类型的 public 方法。 create 方法的名称必须以 create 开头,后跟元素名称。 add(或 addConfigured)方法必须是一个 public void 方法,该方法采用带有无参数构造函数的 Object 类型的单个参数。 add (addConfigured) 方法的名称必须以 add ( addConfigured ) 开头,后跟元素名称。

也就是上面示例中,支持下面3种写法:

public PatternSet createPatternSet()
{
  PatternSet ps = new PatternSet();
  patternSets.add(ps);
  return ps;
}

public void addPatternSet(PatternSet ps) {
  patternSets.add(ps);
}

public void addConfiguredPatternSet(PatternSet ps)
{
  patternSets.add(ps);
}

这3种写法不能同时存在,具体差异通过 debug 来查看。测试时注释另外两个方法。

4.1 createXxx 方法

在这里插入图片描述 这个方法会创建一个空的 PatternSet 对象,这个对象需要提前添加到 patternSets,否则后续无法获取该值。这里返回该对象后,这个对象会被赋值,在后续执行 execute 时是有值的。

当你嵌套的对象需要复杂的创建方式时,可以采用这种方式,这种方式适合初始化对象。

4.2 addXxx 方法

在这里插入图片描述 可以看到Ant自己实例化了一个PatternSet对象注入进来了,而且此时该对象是空的,还没有被赋值,这种情况下的参数(如这里的PatternSet)需要提供 public 无参数构造方法或将 Project 类作为参数的 public 单参数构造方法

4.3 addConfiguredXxx

在这里插入图片描述 这个方法和上一个类似,但是这里会传入一个配置好的 PatternSet,如果你需要在配置好的对象上进行后续处理,可以使用这个方法,如果想在配置前处理,可以选择前两种方式。

4.4 不要同时使用这3种方法

同时存在时不一定会调用哪一个方法,当你方法中存在逻辑时,就无法保证处理一致。不会像你所想的,先调用 create 创建对象,再通过 add 初始化值,最后调用 addConfigured 方法进行后续处理。

了解这些内容后就可以扩展 Ant 任务了,下一节开始针对 yGuard 进行扩展。

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  2Vtxr3XfwhHq   2024年05月17日   52   0   0 Java
  Tnh5bgG19sRf   2024年05月20日   106   0   0 Java
  8s1LUHPryisj   2024年05月17日   46   0   0 Java
  aRSRdgycpgWt   2024年05月17日   47   0   0 Java
ZJE9JAGqQBsi