带有引用的自定义 Ant 类型导致空类 [英] Custom Ant Types with reference result in empty class

查看:31
本文介绍了带有引用的自定义 Ant 类型导致空类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 Apache Ant 作为工具来处理我必须一遍又一遍地执行的乏味数据收集和计算任务.我已经定义了一些自定义 Ant 任务,它们工作得非常好.

I am using Apache Ant as a tool for tedious data collection and calculation tasks I have to do over and over again. I have defined some custom Ant Tasks and they work really well.

但是,现在我想使用 标签创建新的数据类型.我想在我的 build.xml 的开头定义一些我可以稍后引用的数据,就像我的一个 Java 项目的常规构建文件中的以下示例一样:

However, now I want to create new data-types using the <typedef> tag. I want to define some data in the beginning of my build.xml which I can reference to later, much like the following example from a regular build file from one of my Java projects:

<path id="classpath.build">
    <fileset dir="${dir.lib}">
        <include name="**/*.jar" />
        <exclude name="**/junit*" />
    </fileset>
</path>

所以我创建了一个简单的 HelloWorld 示例,如下所示:

So I created a simple HelloWorld example like follows:

<sampledata data="LOL" id="someid" />

在自定义蚂蚁任务中,我想引用这种数据类型:

and in a custom ant task I would like to refer to this data type:

<customtask dataref="someid" />

这看起来很简单,所以在挖掘 API 文档后我发现我的类必须扩展 org.apache.tools.ant.types.DataType 并且必须有方法 setRefid(org.apache.tools.ant.types.Reference r).

This seems reasonable simple, so after digging in the API docs I found out that my class has to extend org.apache.tools.ant.types.DataType and has to have the method setRefid(org.apache.tools.ant.types.Reference r).

我的自定义 Ant 任务 customtask 对 dataref 属性使用以下代码:

My custom Ant Task customtask uses the following code for the dataref attribute:

public class CustomTask extends Task {

     private SampleData data;

     public void setDataref(Reference r) {
        data = new SampleData(getProject());
        data.setRefid(r);
     }

     public void execute() {
          System.out.println(data.getData());
     }
}

我的 SampleData 实现如下:

And my SampleData implementation is like follows:

public class SampleData extends DataType {

     private String data;

     public SampleData(Project project) {
         setProject(project);
     }

     public void setData(String data) {
         this.data = data;
     }

     public String getData() {
         return this.data;
     }

     public void setRefid(Reference r) {
          super.setRefid(r);
     }

 }

请注意,这都是基于 org.apache.tools.ant.types.Path 的来源,它显示了我想要的行为.

Mind you, this is all based on the sources from org.apache.tools.ant.types.Path which shows the behavior I want.

但是,在使用上面定义的自定义任务创建目标后,输出为 null.所以 SampleData 被实例化,但引用设置不正确.当我调试时,我发现 SampleData 在我的 ant 文件中正确实例化,数据为 LOL,甚至引用设置为 someid.此外,CustomTasksetDataref 方法确实传递了一个名为someid 的引用,所以在setDataref 中它全都出错了> 方法,但我不知道我必须做什么并且缺少手册(或者我遗漏了一个重要部分).

However, after creating a target with the customtask as defined above, the output is null. So SampleData is instantiated but the reference is not set correctly. When I debug I find out that SampleData is correctly instantiated in my ant file with the data LOL and even the refence is set to someid. Also, the CustomTask class setDataref method indeed is passed a Reference named someid, so it all goes wrong in the setDataref method, but I have no clue what I have to do and the manual is lacking (or I am missing an important part).

我感觉我没有完全掌握带有 id 的自定义数据类型的生命周期.

I have the feeling I don't completely grasp the lifecycle of custom datatypes with id's.

编辑 23-11-2012 9:24 :

经过更多的摆弄和查看 org.apache.tools.ant.types.Path 的源代码后,我遵循了那里的一些方法并将我的 SampleData.getData 更改为以下内容:>

After some more fiddling and looking in the source of org.apache.tools.ant.types.Path I followed some of the methods there and changed my SampleData.getData to the following:

public String getData() {
    if(isReference()) {
        return ((SampleData)getCheckedRef()).getData();
    }
    return this.data;
}

我更进一步,但是现在我的 build.xml 中出现以下 Ant 错误:

I am a little bit further, however now I get the following Ant error in my build.xml :

 /home/arjan/dev/so-demo/build.xml:9: someid doesn't denote a SampleData

但是,当我检查 Reference 对象封装的类时,它是正确的类型.我现在对此感到厌烦了.还有什么提示吗?

However when I check the class encapsulated by the Reference object it is the correct type. I am getting pretty fed up by this now. Any more tips?

编辑 23-11-2012 11:46 :

我创建了一个带有清晰测试用例的 Gist.我的 Ant 版本是 1.8.4.希望有人会提出解决方案,因为我已经查看了其他库,如 Sonatype Aether Antlib 并遵循了他们的推理方式.

I created a Gist with a clear testcase. My Ant version is 1.8.4. Hopefully someone will come with a solution, because I've looked in other libraries like Sonatype Aether Antlib and followed their way of reasoning.

getCheckedRef 方法出错,特别是 Ant 源文件 src\main\org\apache\tools\ant\types\DataType.java:250:

It all goes wrong at the getCheckedRef method, specifically in the Ant sourcefile src\main\org\apache\tools\ant\types\DataType.java:250:

if (!(requiredClass.isAssignableFrom(o.getClass()))) {
    log("Class " + o.getClass() + " is not a subclass of " + requiredClass,
            Project.MSG_VERBOSE);
    String msg = ref.getRefId() + " doesn\'t denote a " + dataTypeName;
    throw new BuildException(msg);
}

这是怎么回事?这是我能想到的最简单的测试用例.

What is going on? This is the simples testcase I could come up with.

推荐答案

我相信这可能会解决您的问题,我遇到了类似的错误:

I believe that this might fix your issue, I was running into similar errors:

您的自定义任务和类型缺少 loaderRef 指令.请参阅此处:如果您正在定义与多个共享相同类路径的任务或类型taskdef 或 typedef 任务,对应的类会被不同的 Java ClassLoader 加载.通过不同的类加载器加载的两个同名类从 Java VM 的角度来看不是同一个类,它们不共享静态变量,这些类的实例不能访问私有方法或由定义的实例的属性"另一个班级"同名.它们甚至不属于同一个 Java 包,也不能访问包私有代码.

You are missing the loaderRef directive for your custom task and type. See here: If you are defining tasks or types that share the same classpath with multiple taskdef or typedef tasks, the corresponding classes will be loaded by different Java ClassLoaders. Two classes with the same name loaded via different ClassLoaders are not the same class from the point of view of the Java VM, they don't share static variables and instances of these classes can't access private methods or attributes of instances defined by "the other class" of the same name. They don't even belong to the same Java package and can't access package private code, either.

因此,当您通过 typedef 和 taskdef 定义自定义任务和自定义类型时,请使用 loaderRef 属性 - 只要您的任务和类型定义相同,就可以是任何东西(例如 customTaskLoader).

So when you define your custom task and custom type via typedef and taskdef use the loaderRef attribute - this can be anything (like customTaskLoader) as long as it is the same between your task and type definition.

从那里您可以进一步简化您的代码:

From there you can simplify your code even further:

public class CustomTask extends Task {

 private SampleData data;

 public void execute() {
      System.out.println(data.getData());
 }

}

public class SampleData extends DataType {

 private String data;

 public SampleData(Project project) {
     setProject(project);
 }

 public void setData(String data) {
     this.data = data;
 }

 public String getData() {
     if(isReference()) {
         return ((SampleData)getCheckedRef()).getData();
     }
     return this.data;
 }

}

这篇关于带有引用的自定义 Ant 类型导致空类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆