使用特殊doclet运行Javadoc时模糊的IOException

时间:2012-09-27 23:21:55

标签: java ant javadoc doclet

这个可能是一个特定于doclet实现的问题,但我相信它确实是我在这里处理的JavaDoc配置问题。

我正在尝试让yDoc UML Doclet工作,以便它作为Ant构建的一部分为我的Java应用程序生成UML图。我下载了项目(社区版),并尝试调整他们的build-sample.xml,但无法让它发挥作用。

这是我的项目目录结构:

MyProject/
    src/main/java/
        <All the Java sources I want documented and diagrammed>
    bin/main
        <Compiled binaries of src/main/java/>
    lib/
        styleed.jar
        ydoc.jar
    resources/
        <All the yDoc resources that came with the download>
    umldoclet/
        <Where I want all JavaDocs to go>
    build.xml

这是build.xml

<project name="MyProject" default="ydoc" basedir="." xmlns:ivy="antlib:org.apache.ivy.ant" xmlns:jacoco="antlib:org.jacoco.ant">

    <!-- The "compile" task and all its dependencies omitted for brevity,
         but they all absolutely work 100% and "compile" places compiled
         CLASS files under bin/main. -->

    <target name="ydoc" depends="compile">
        <property name="ydoc.home" value="${basedir}"/>

        <javadoc source="1.5" destdir="./umldoclet" additionalparam="-breakiterator">
            <packageset dir="src/main">
                <include name="java/**"/>
            </packageset>
            <doclet name="ydoc.doclets.YStandard" path="${ydoc.home}/lib/ydoc.jar;${ydoc.home}/resources">
                <param name="-author"/>
                <param name="-generic"/>
                <param name="-umlautogen"/>
                <param name="-filterpath" value="./lib/ydoc.jar"/>
                <param name="-filter" value="ydoc.filters.ExcludeFilter"/>
                <param name="-tag" value="y.precondition"/>
                <param name="-tag" value="y.postcondition"/>
                <param name="-tag" value="y.complexity"/>
                <param name="-tag" value="param"/>
                <param name="-tag" value="return"/>
                <param name="-tag" value="see"/>
                <param name="-tag" value="y.uml"/>
            </doclet>
        </javadoc>
    </target>
</project>

当我运行ydoc任务时,即使在“详细”模式下使用-v参数运行Ant,我看到在Ant控制台中调用[ydoc]任务,然后是读取“Generating Javadoc”的日志语句和从yDoc params回流给我的详细输出中的大约20行,然后是最后的日志消息“Javadoc execution”。然后,以下令人惊讶的模糊IOException

BUILD FAILED
<my-eclipse-home>/MyProject/build.xml:200: Javadoc failed: java.io.IOException: Cannot run program "javadoc": java.io.IOException: error=2, No such file or directory
    at org.apache.tools.ant.taskdefs.Javadoc.execute(Javadoc.java:1765)
    at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291)
    at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:616)
    at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
    at org.apache.tools.ant.Task.perform(Task.java:348)
    at org.apache.tools.ant.Target.execute(Target.java:392)
    at org.apache.tools.ant.Target.performTasks(Target.java:413)
    at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1399)
    at org.apache.tools.ant.Project.executeTarget(Project.java:1368)
    at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
    at org.eclipse.ant.internal.launching.remote.EclipseDefaultExecutor.executeTargets(EclipseDefaultExecutor.java:32)
    at org.apache.tools.ant.Project.executeTargets(Project.java:1251)
    at org.eclipse.ant.internal.launching.remote.InternalAntRunner.run(InternalAntRunner.java:424)
    at org.eclipse.ant.internal.launching.remote.InternalAntRunner.main(InternalAntRunner.java:138)
Caused by: java.io.IOException: Cannot run program "javadoc": java.io.IOException: error=2, No such file or directory
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:475)
    at java.lang.Runtime.exec(Runtime.java:610)
    at org.apache.tools.ant.taskdefs.Execute$Java13CommandLauncher.exec(Execute.java:862)
    at org.apache.tools.ant.taskdefs.Execute.launch(Execute.java:481)
    at org.apache.tools.ant.taskdefs.Execute.execute(Execute.java:495)
    at org.apache.tools.ant.taskdefs.Javadoc.execute(Javadoc.java:1759)
    ... 15 more
Caused by: java.io.IOException: java.io.IOException: error=2, No such file or directory
    at java.lang.UNIXProcess.<init>(UNIXProcess.java:164)
    at java.lang.ProcessImpl.start(ProcessImpl.java:81)
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:468)
    ... 20 more

有没有办法从Ant中获取更多细节?要找出它在异常中引用的文件或目录?以前有没有JavaDoc / yDoc大师遇到过这种情况?我的项目目录结构是否设置不正确,或者与Ant构建要求的不同?我相信我正确设置了doclet/path属性,并使用了正确的路径分隔符(我在Ubuntu Linux上)。对于我的生活,我无法弄清楚从这里去哪里,或者如何在这里诊断潜在的问题!提前谢谢!

修改/更新

感谢大家到目前为止的建议。我完全不使用Eclipse(就构建而言,只是从命令行运行Ant;现在这很好。当我这样做时,我得到了一个成功的构建(所以Eclipse至少部分是罪魁祸首)但是,仍然没有yDoc代。

现在,当我使用verbos(-v)选项从终端运行Ant时,这就是我所看到的:

数百个看起来相同但有不同类别的警告:

[javadoc] Constructing Javadoc information...
[javadoc] /<path-to-my-project>/MyProject/src/main/java/com/some/pkg/SomeObject.java:11: package org.springframework.beans.factory.annotation does not exist
[javadoc] import org.springframework.beans.factory.annotation.Autowired;
[javadoc]                                                    ^

在数百个之后,我得到以下输出(我的源代码树中的每个包中都有1个):

[javadoc] javadoc: warning - No source files for package java.com.some.pkg.<whatever>

最后,详细构建输出的最后一部分:

[javadoc] Valid license file found.
[javadoc] Registered Filter ydoc.filters.ExcludeFilter ...
[javadoc] Registered Taglet for tag @y.complexity ...
[javadoc] Registered Taglet for tag @y.precondition ...
[javadoc] Registered Taglet for tag @y.postcondition ...
[javadoc] Registered Taglet for tag @y.author ...
[javadoc] 1 error
[javadoc] 109 warnings
[javadoc] javadoc: error - No public or protected classes found to document.

BUILD SUCCESSFUL
Total time: 6 seconds

此外,如果它正确执行,它应该将所有JavaDoc放在我的项目根目录中的uml-doclet/目录下。它没有这样的东西!

所以看起来还有更多的事情发生了:

  1. JavaDoc无法看到我的第三方依赖项(例如Spring,Camel等);因此列出了数百个警告
  2. 找不到我的任何资料来源
  3. 再次,赏金给任何可以帮助我实现这一目标的人。再次感谢您的帮助!

3 个答案:

答案 0 :(得分:3)

看起来ant无法找到javadoc二进制文件。我不认为ant使用定义的PATH来查找javadoc二进制文件(文档说它使用的是与ant相同的JDK)。

我会尝试的一些事情是:

  • 可执行文件属性添加到任务中,指向javadoc二进制文件(我不是说这是一个正确的解决方案,但如果它有效,则表示该位置存在问题蚂蚁默认看的地方。)
  • 确保您的JAVA_HOME和PATH指向JDK而不是JRE
  • 确保您的JAVA_HOME指向PATH指向的相同Java安装。

答案 1 :(得分:3)

如果您使用-verbose -debug执行ant,您将看到以下这些行:

Setting project property: ydoc.home -> /var/tmp/ydoc-test
  [javadoc] scanning /var/tmp/ydoc-test/src/main for packages.
dirset: Setup scanner in dir /var/tmp/ydoc-test/src/main with patternSet{ includes: [java/**] excludes: [] }
  [javadoc] Generating Javadoc
  [javadoc] Executing '/usr/lib/jvm/java-7-openjdk-amd64/bin/javadoc' with arguments:
  [...]

或者你会看到这些行:

Setting project property: ydoc.home -> /var/tmp/ydoc-test
  [javadoc] scanning /var/tmp/ydoc-test/src/main for packages.
dirset: Setup scanner in dir /var/tmp/ydoc-test/src/main with patternSet{ includes: [java/**] excludes: [] }
  [javadoc] Generating Javadoc
  [javadoc] Executing 'javadoc' with arguments:

在第一种情况下,Eclipse / Ant找到了一个有效的javadoc命令,并在行[javadoc] Executing >FULL_PATHNAME_TO_JAVADOC>中告诉您。在第二种情况下,它只讨论javadoc没有任何路径名,调试输出将在稍后显示您的例外。

我认为你的案子是第二个,但请检查一下!

如果Eclipse / Ant不知道javadoc的位置,那么首先应该通过将Eclipse从等式中简化来简化:使用命令行并检查输入这些命令不会导致“命令”找不到“消息:

java
javac
javadoc

我假设第一个是OK(毕竟你可以运行Eclipse,如堆栈跟踪中所示)。如果找不到第二个和第三个命令,则表示您尚未在计算机上安装JDK但只安装了JRE。安装一个并重新启动Eclipse。

另一方面,如果找到javacjavadoc没有找到,那么您的JDK就会被破坏。

如果找到javacjavadoc,那么Eclipse根本就不知道它。但在返回Eclipse之前,在命令shell中键入最后一个命令:

readlink -m $(which javadoc)/../..

请记住readlink给你的路径。

在Eclipse goto“Window - &gt; Preferences - &gt; Java - &gt; Installed JREs”中。在列表中选择带复选复选框的条目,然后按“编辑”。如果“JRE home”行与路径readlink给出的不一样,那么很可能您的Eclipse被配置为仅使用本地JRE而不是您安装的JDK。

如果是这种情况,则取消“编辑”对话框,按“添加”,选择“标准VM”并输入readlink给你的路径。在正确进入该路径之后,Eclipse应该为您填写其他字段,因此您只需说“OK”即可。返回“已安装的JRE”列表,勾选新项目。

之后,javadoc任务本身应该开始。

修改

但是你需要做一些调整:

第一:在这部分:

       <packageset dir="src/main">
            <include name="java/**"/>
        </packageset>

您正在混合源directoy和包部件。它应该是:

       <packageset dir="src/main/java">
       </packageset>

同样javadoc喜欢访问引用的类。因此,您应该将相同的类路径添加到用于编译代码的javadoc。因此,请在<classpath>之后添加适当的</packageset>部分。这将照顾“包xyz不存在”的警告。

答案 2 :(得分:0)

我会在build.xml中更改这些行:

<packageset dir="src/main/java">
    <include name="**" />
</packageset>