2009-07-30 34 views
1

私はFreeMarkerを少しずつ使ってきましたが、欠けている機能が1つしかないか、わかりません。 cfg.getTemplate()に絶対パスを渡すと、それは機能しません。私はあなたがテンプレートディレクトリを指定することができますが、私はそれを行う余裕がないことを知っています、私のユースケースは、任意のディレクトリ内のファイルを扱うことができます。どのような方法でも絶対パスをレンダリングするFreeMarkerを設定する方法はありますか?FreeMarkerで絶対パスを使用する

答えて

6

Antスクリプトでテンプレートが実行されていて、テンプレートがファイルシステム上にあり、Antファイルセットで検出されたため、絶対パスを使用する必要がありました。

public class TemplateAbsolutePathLoader implements TemplateLoader { 

    public Object findTemplateSource(String name) throws IOException { 
     File source = new File(name); 
     return source.isFile() ? source : null; 
    } 

    public long getLastModified(Object templateSource) { 
     return ((File) templateSource).lastModified(); 
    } 

    public Reader getReader(Object templateSource, String encoding) 
      throws IOException { 
     if (!(templateSource instanceof File)) { 
      throw new IllegalArgumentException("templateSource is a: " + templateSource.getClass().getName()); 
     } 
     return new InputStreamReader(new FileInputStream((File) templateSource), encoding); 
    } 

    public void closeTemplateSource(Object templateSource) throws IOException { 
     // Do nothing. 
    } 

} 

と初期化は次のとおりです:私は、これらは非常にいくつかのユニークな要件...とにかく

あり、(限りSOアップしている)後世のために、ここで機能するソリューションだと思う

public String generate(File template) { 

    Configuration cfg = new Configuration(); 
    cfg.setTemplateLoader(new TemplateAbsolutePathLoader()); 
    Template tpl = cfg.getTemplate(template.getAbsolutePath()); 

    // ... 
} 
+0

ありがとうございます。私はもはやこのプロジェクトを開発していないので、私はこれをテストすることはできませんが、私は同じ質問を持っている誰もがこれを感謝するだろうと確信しています。 – dimo414

+0

コミュニティが同意しているように私はあなたの答えを受け入れました。 – dimo414

1

FreemarkerはデフォルトでFileTemplateLoaderを使用しています。これは "base"ディレクトリの外からテンプレートを取得することを許可しません(デフォルトでは 'user.dir'システムプロパティから取得されるため、あなたのホームディレクトリです)。あなたにできることは次のとおりです。

  1. 明示的BASEDIRとFileTemplateLoaderを作成するテンプレートを取得することがありますその下からあなたの最上位ディレクトリに設定します(理論的には、絶対パスを使用するためにはルートに設定することができますが、それはですセキュリティの観点からは非常に悪いこと©)。
  2. 絶対パスを使用するテンプレートローダーを作成しますが、テンプレートがテンプレートフォルダ内にあることを確認してください。それを行う場合は、正規のファイルパスを比較するよう注意してください。
  3. あなたのアプローチを再考してください。テンプレートの絶対パスが本当に必要ですか?
+0

おかげでソリューションを使用した方が良いと思います。毎回テンプレートディレクトリを変更するだけでしたが、カスタムFileTemplateLoaderを作成する方がより適切な方法で処理できます。 Webページの生成にセキュリティホールが使用されているのはなぜか分かりますが、通常のユーザーが実行しているプログラムであれば、標準のLinux権限が十分に予防対策になるはずです。 – dimo414

+0

あなたの許可が適切に設定されている限り、そうかもしれません。私はまだあなたが絶対パスを使用する理由を想像することはできません...テンプレートをいくつかの共通の(ルートではない)フォルダの下に置くか、ユーザごとにカスタマイズ可能な場合は、ユーザーの家。しかし、私はあなたの理由があると確信しています - あなたの実装に幸運。 – ChssPly76

2

実際に、それはあなたが

public Object findTemplateSource(String name) throws IOException { 
    File source = new File("/" + name); 
    return source.isFile() ? source : null; 
} 
0

中に問題が発生し、それを再度追加する必要がありますので、「/」先頭を削除TemplateLoaderが使用される前にFreeMarkerでパス名が破棄されているという解決法があります。 TemplateCacheを参照してください:

name = normalizeName(name); 
    if(name == null) { 
     return null; 
    } 
    Template result = null; 
    if (templateLoader != null) { 
     result = getTemplate(templateLoader, name, locale, encoding, parseAsFTL); 
    } 

だから私は例えば提案in this answer

として答えを

 Configuration config = new Configuration(); 
     File templateFile = new File(templateFilename); 
     File templateDir = templateFile.getParentFile(); 
     if (null == templateDir){ 
      templateDir = new File("./"); 
     } 
     config.setDirectoryForTemplateLoading(templateDir); 
     Template template = config.getTemplate(templateFile.getName()); 
関連する問題