为原型 Maven 项目设置动态速度属性

Setting dynamic velocity properties for archetype maven projects

我正在创建原型并希望创建一个广泛可用的项目 属性 包含诸如当前日期和工件 ID 的全小写变体之类的内容。我发现 the following post on Whosebug,这说明了它通常应该如何实现。

我尝试将其添加到原型中-metadata.xml,如下所示:

    ...
    <requiredProperty key="artifactIdLower">
        <defaultValue>${artifactId.toLowerCase()}</defaultValue>
    </requiredProperty>
    <requiredProperty key="ldt">
        <defaultValue>${package.getClass().forName("java.time.LocalDateTime").getMethod("now").invoke(null)}</defaultValue>
    </requiredProperty>
    <requiredProperty key="dtf">
        <defaultValue>${package.getClass().forName("java.time.format.DateTimeFormatter").getMethod("ofPattern", $package.getClass().forName("java.lang.String")).invoke(null, "dd MMM yyyy")}</defaultValue>
    </requiredProperty>
    <requiredProperty key="date">
        <defaultValue>${ldt.format($dtf)}</defaultValue>
    </requiredProperty>
    ...

属性 artifactIdLower 很有用,但 ldtdtfdate 似乎不起作用,给出错误:

Null reference [template 'dtf', line 1, column 1] : ${package.getClass().forName("java.time.format.DateTimeFormatter").getMethod("ofPattern", $package.getClass().forName("java.lang.String")).invoke(null, "dd MMM yyyy")} cannot be resolved.

之后我试图查看这个空引用在链中的何处。我能够将 pkgClass 设置为 $package.getClass()(或 $package.Class),

但在那之后我无法将 $strClass 设置为 $package.getClass().forName("java.lang.String")$pkgClass.forName("java.lang.String")(有趣的是,pkgClassstrClass 都应该是Class 对象)。

这让我想知道在原型内部使用反射是否有限制-metadata.xml。

我的问题是:如何设置可在项目范围内使用的动态生成的 属性 值(如上)?

我不想在我创建的每个文件中都定义这些属性,因为我以后可能想添加更多属性。

编辑: 我试图创建一个包含 #set 指令的 generalproperties.vm 文件。然后,第一行中的每个文件都会使用#parse("generalproperties.vm") 加载该文件。虽然我确实从 pom.xml 文件中获取了要解析的文件,但它的行为并不如我所愿。

以下输入

test
$null
#set( $ldtClass = $package.getClass().forName("java.time.LocalDateTime") )
$ldtClass.Name
$ldtClass.getMethod("now")
#set( $ldtNowMethod = $ldtClass.getMethod("now") )
$ldtNowMethod.Name
#set( $clsLoader = $package.getClass().getClassLoader() )
$clsLoader
#set( $ldtClass2 = $clsLoader.loadClass("java.time.LocalDateTime") )
$ldtClass2.Name
$ldtClass2.getMethod("now")
#set( $ldtNowMethod2 = $ldtClass2.getMethod("now") )
$ldtNowMethod2.Name
#set( $ldt = $ldtNowMethod2.invoke($null) )
$ldt
#set( $dtf = $package.getClass().forName("java.time.format.DateTimeFormatter").getMethod("ofPattern", $package.getClass().forName("java.lang.String")).invoke($null, "yyyy/MM/dd HH:mm:ss") )
$dtf

生成了以下输出:

test
$null
java.time.LocalDateTime
$ldtClass.getMethod("now")
$ldtNowMethod.Name
$clsLoader
$ldtClass2.Name
$ldtClass2.getMethod("now")
$ldtNowMethod2.Name
$ldt
$dtf

前 3 个输出符合预期,但之后我没有得到我想要的结果。如果有人能够解决上述任一问题(使用元数据文件或 generalproperties 文件),将不胜感激。

我能想到的唯一限制是,如果您在 Velocity 配置属性中使用 SecureUberspector 而不是标准的 Uberspector。但是您将无法获得 java.time.LocalDateTime class,所以情况并非如此,除非您使用的是旧的 Velocity 版本。使用 Velocity 1.7,我可以获得对 now() 方法的引用并调用它。

此外,您确定直接 Java 版本工作正常吗?例如,我在 Class.getClassLoader() javadoc 中读到 "some implementations may use null to represent the bootstrap class loader. This method will return null in such implementations if this class was loaded by the bootstrap class loader."

这应该有效:

...
<requiredProperty key="date">
    <defaultValue>${package.getClass().forName("java.time.LocalDateTime").getMethod("now").invoke(null).format($package.Class.forName("java.time.format.DateTimeFormatter").getMethod("ofPattern", $package.Class).invoke(null, "dd MMM yyyy"))}</defaultValue>
</requiredProperty>
...

也许它可以帮助我注意到的人。

当我有类似的事情时:

<requiredProperty key="packageId"></requiredProperty>
<requiredProperty key="packageIdInPathFormat">
    <defaultValue>${package.getClass().getMethod("replace").invoke($packageId, ".", "/")}</defaultValue>
</requiredProperty>

它没有计算 属性 packageIdInPathFormat 中的表达式。

但是当我做了类似的事情时:

<requiredProperty key="packageId"></requiredProperty>

<requiredProperty key="tempPackageId">
   <defaultValue>${packageId}</defaultValue>
</requiredProperty>

<requiredProperty key="packageIdInPathFormat">
   <defaultValue>${tempPackageId.replace(".", "/")}</defaultValue>
</requiredProperty>

表达式已被评估。