/* * ****************************************************************************** * MontiCore Language Workbench * Copyright (c) 2015, MontiCore, All rights reserved. * * This project is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this project. If not, see <http://www.gnu.org/licenses/>. * ****************************************************************************** */ package de.monticore.generating.templateengine.freemarker; import static com.google.common.base.Strings.isNullOrEmpty; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; import java.lang.reflect.InvocationTargetException; import de.se_rwth.commons.logging.Log; import freemarker.log.Logger; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; /** * Helps to process FreeMarker templates with MontiCore. * * @author (last commit) $Author$ * @version $Revision$, * $Date$ * */ public class FreeMarkerTemplateEngine { public static final String FM_FILE_EXTENSION = ".ftl"; private final Configuration configuration; public FreeMarkerTemplateEngine(Configuration configuration) { this.configuration = Log .errorIfNull( configuration, "0xA4048 Configuration must not be null in FreeMarkerTemplateEngine constructor."); } /** * Loads the template named qualifiedTemplateName from the class path. * * @param qualifiedTemplateName full qualified template name EXCLUDING the * file extension * @return the FreeMarker template or null, if the template is not available */ public Template loadTemplate(String qualifiedTemplateName) { isNullOrEmpty(qualifiedTemplateName); try { // use empty logger to suppress default free marker log behaviour Logger.selectLoggerLibrary(Logger.LIBRARY_NONE); } catch (ClassNotFoundException e1) { // TODO use default logger instead } Template result; try { result = configuration.getTemplate(qualifiedTemplateName); } catch (IOException e) { throw new MontiCoreFreeMarkerException("0xA0560 Unable to load template: " + e.getMessage()); } return result; } /** * Runs the Template engine on the given template and data and writes the * result into the StringBuilder buffer * * @param buffer contains the result * @param data data for the template * @param template the template file * @throws IOException */ public void run(StringBuilder buffer, Object data, Template template) { Log.errorIfNull(template, "0xA0562 The given template must not be null"); Writer w = new StringWriter(); try { template.process(data, w); w.flush(); } catch (TemplateException e) { StringBuilder causedExceptionInfo = new StringBuilder(); if (e.getCause() instanceof MontiCoreFreeMarkerException) { throw (MontiCoreFreeMarkerException)e.getCause(); } Throwable targetException; if (e.getCause() instanceof InvocationTargetException) { targetException = ((InvocationTargetException)e.getCause()).getTargetException(); if (targetException != null) { causedExceptionInfo.append("\n").append(targetException); } } throw new MontiCoreFreeMarkerException("0xA0561 Unable to execute template " + template.getName() + FM_FILE_EXTENSION + " : " + e.getLocalizedMessage() + System.getProperty("line.separator") + "Exception-type: " + e.getCause() + causedExceptionInfo.toString() + System.getProperty("line.separator") + "Caused by " + System.getProperty("line.separator") + e.getFTLInstructionStack(), e.getCause()); } catch (IOException e) { throw new MontiCoreFreeMarkerException("0xA0563 Could read template " + template.getName() + FM_FILE_EXTENSION); } buffer.append(w.toString()); } /** * Loads the template first using the loadTemplate() method then runs the * template engine using the run() method. * * @param qualifiedTemplateName full qualified template name EXCLUDING the * file extension * @param buffer contains the result * @param data data for the template */ public void loadAndRun(String qualifiedTemplateName, StringBuilder buffer, Object data) { Template t = loadTemplate(qualifiedTemplateName); run(buffer, data, t); } }