Freemarker 2.3.23能否正确处理varargs?

时间:2017-04-19 19:55:27

标签: java freemarker

这(可怕;不要问;我无法修改数据模型或配置)表达式不起作用:

${statics["java.nio.file.Files"].write(statics["java.nio.file.Paths"].get("/foo/bar.stuff"), statics["java.nio.charset.Charset"].forName("UTF-8").encode(someStringContent).array(), enums["java.nio.file.StandardOpenOption"].WRITE)}

型号代码:

    model.addAttribute("statics", new BeansWrapperBuilder(Configuration.VERSION_2_3_23).build().getStaticModels());
    model.addAttribute("enums", new BeansWrapperBuilder(Configuration.VERSION_2_3_23).build().getEnumModels());

简而言之,它是一种(粗略)方式来获取一些Freemarker字符串内容,将其转换为byte[]数组,并将其写入Freemarker中的/foo/bar.stuff路径。

错误表明Freemarker无法选择正确的varargs方法:

Error executing FreeMarker template
FreeMarker template error:
When trying to call the non-varargs overloads:
No compatible overloaded variation was found; can't convert (unwrap) the 3rd argument to the desired Java type.
The FTL type of the argument values were: extended_hash+string (sun.nio.fs.UnixPath wrapped into f.e.b.StringModel), sequence (byte[] wrapped into f.t.DefaultArrayAdapter$ByteArrayAdapter), extended_hash+string (java.nio.file.StandardOpenOption wrapped into f.e.b.StringModel).
When trying to call the varargs overloads:
Multiple compatible overloaded variations were found with the same priority.
The Java type of the argument values were: sun.nio.fs.UnixPath, byte[], java.nio.file.StandardOpenOption.
The matching overload was searched among these members:
    static java.nio.file.Files.write(java.nio.file.Path, Iterable, java.nio.file.OpenOption...),
    static java.nio.file.Files.write(java.nio.file.Path, Iterable, java.nio.charset.Charset, java.nio.file.OpenOption...),
    static java.nio.file.Files.write(java.nio.file.Path, byte[], java.nio.file.OpenOption...)

我尝试过其他黑客攻击,包括使用java.lang.reflect.Array#newInstance(Class, int)创建一个正确类型的数组,但这没有帮助。

我认为这是不可能的?

3 个答案:

答案 0 :(得分:0)

你可以用自己明确的方法将调用包装到library_sample方法

Files.write()

答案 1 :(得分:0)

我想这将是重载方法选择的一个小故障,它被模拟为100%向后兼容性。因此,您应该将FreeMarker配置的incompatible_improvements设置增加到至少2.3.21以激活修复(或者如果您没有使用object_wrapper设置的默认设置,那么类似的设置您正在创建的ObjectWrapper。但是,你说你无法触及FreeMarker配置......

我在另一个答案中也看到你不能添加自己的静态辅助类......

答案 2 :(得分:0)

假设您的statics模型字段是使用EXPOSE_ALL构建的,您可以更深入地了解反射兔洞:

<#assign class = statics["java.lang.Class"]>
<#assign openOptionClass = class.forName("java.nio.file.OpenOption")>
<#assign filesClass = class.forName("java.nio.file.Files")>
<#assign method = filesClass.getMethod("write", class.forName("java.nio.file.Path"),class.forName("[B"),class.forName("[Ljava.nio.file.OpenOption;"))>
<#assign path = statics["java.nio.file.Paths"].get("/foo/bar.stuff")>
<#assign utf8 = statics["java.nio.charset.Charset"].forName("UTF-8")>
<#assign writeOptions = enums["java.nio.file.StandardOpenOption"].WRITE>
<#assign writeOptionsArray = statics["java.lang.reflect.Array"].newInstance(openOptionClass,1)>
<#assign ignoreThisVoid = statics["java.lang.reflect.Array"].set(writeOptionsArray, 0, writeOptions)>
${method.invoke(null, path, utf8.encode(someStringContent).array(), writeOptionsArray)}

或者您可以尝试PrintWriter(仍然需要EXPOSE_ALL):

<#assign class = statics["java.lang.Class"]>
<#assign fileOutputStreamClass = class.forName("java.io.FileOutputStream")>
<#assign fileOutputStreamConstructor = fileOutputStreamClass.getConstructor(class.forName("java.lang.String"))>
<#assign fileOutputStream = fileOutputStreamConstructor.newInstance("/foo/bar.stuff")>
<#assign ignoreThisVoid = fileOutputStream.write(utf8.encode(someStringContent).array())>