2009-07-30 6 views
1

Я использовал FreeMarker на некоторое время, но есть одна яркая часть функциональности, которая либо отсутствует, либо я просто не могу понять (я надеюсь, что последний!). Если вы передадите cfg.getTemplate() абсолютный путь, он просто не работает. Я знаю, что вы можете указать каталог шаблонов, но я не могу этого сделать, мой прецедент может обрабатывать файлы в любом каталоге. Есть ли способ установить FreeMarker для отображения абсолютных путей так, как ожидал любой пользователь?Использование Абсолютного Пути с FreeMarker

ответ

6

Мне пришлось использовать абсолютный путь, потому что шаблоны происходят в скрипте Ant, а шаблоны находятся в файловой системе и обнаружены с помощью набора файлов Ant. Я предполагаю, что это довольно уникальные требования ...

Во всяком случае, для потомков (до тех пор, как SO вверх), вот решение, которое работает:

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. 
    } 

} 

и инициализация:

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, который не позволит вам получать шаблоны извне «базового» каталога (который по умолчанию взят из системного свойства user.dir, поэтому это ваш домашний каталог). Что вы можете сделать, это:

  1. Явное создать FileTemplateLoader с BASEDIR установлен в вашей самой верхней директории из-под которой вы будете получать шаблоны (вы могли бы теоретически установить его с корнем, чтобы использовать абсолютные пути, но это ОЧЕНЬ ПЛОХАЯ ВЕЩЬ © с точки зрения безопасности).
  2. Напишите свой собственный загрузчик шаблонов, который будет иметь абсолютный путь, но затем убедитесь, что шаблон все еще находится внутри вашей папки с шаблонами. Если вы это сделаете, позаботьтесь о сравнении путей канонических файлов.
  3. Пересмотреть свой подход. Вам действительно нужны абсолютные пути для шаблонов?
+0

Спасибо за ответ. В итоге я просто менял каталог шаблонов каждый раз, но создание пользовательского FileTemplateLoader было бы более правильным способом справиться с этим. Я, конечно, понимаю, почему это будет дырой в безопасности, если вы используете его для создания веб-страниц, но если он работает в обычном режиме, мне кажется, что стандартные разрешения linux должны быть достаточно хорошей профилактической мерой, нет? – dimo414

+0

До тех пор, пока ваши разрешения настроены адекватно, да, вы должны быть в порядке. Я все еще не могу представить, почему вы использовали бы абсолютный путь, хотя ... похоже, что вы хотите либо сохранить шаблон в какой-то общей (не root) папке, либо, если они настраиваются для пользователя, где-то относительно пользовательский дом. Но я уверен, что у вас есть ваши причины - удачи в реализации. – ChssPly76

2

на самом деле это удалить начало «/», так что вам нужно, чтобы добавить его в

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

проблема с принятое решение состоит в том, что имя пути уничтожается в FreeMarker до использования TemplateLoader. См 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()); 
Смежные вопросы