/* * Copyright (c) 2012 Data Harmonisation Panel * * All rights reserved. This program and the accompanying materials are made * available under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution. If not, see <http://www.gnu.org/licenses/>. * * Contributors: * HUMBOLDT EU Integrated Project #030962 * Data Harmonisation Panel <http://www.dhpanel.eu> */ package eu.esdihumboldt.hale.doc.util.content; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.InputStream; import java.io.OutputStream; import java.util.Locale; import java.util.concurrent.Callable; import org.apache.commons.io.IOUtils; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import org.eclipse.help.IHelpContentProducer; import com.google.common.io.Files; /** * Help content based on velocity templates. Use * {@link #getContentFromTemplate(String, String, Callable)} in your * {@link #getInputStream(String, String, Locale)} implementation. * * @author Simon Templer */ public abstract class AbstractVelocityContent implements IHelpContentProducer { /** * The velocity engine used for content generation. */ private VelocityEngine ve; /** * The temporary directory where the template is copied to, and the already * generated is stored. */ private File tempDir; /** * Generate content from the template and the given context factory. If * called more than once with the same id, the previously generated content * for that id is returned. * * @param contentId the content id * @param templateId the template id (there may be multiple templates) * @param contextFactory the context factory, is called once or not at all * @return the content input stream to return in * {@link #getInputStream(String, String, Locale)} * @throws Exception if an error occurs creating the content */ protected InputStream getContentFromTemplate(String contentId, String templateId, Callable<VelocityContext> contextFactory) throws Exception { init(templateId); // creates the template file into the temporary directory // if it doesn't already exist File contentFile = new File(tempDir, templateId + "_" + contentId + ".html"); if (!contentFile.exists()) { // get the template context VelocityContext context = contextFactory.call(); // get the template Template template = ve.getTemplate(templateId + ".vm", "UTF-8"); // write to the file FileWriter fw = new FileWriter(contentFile); template.merge(context, fw); fw.close(); contentFile.deleteOnExit(); } return new FileInputStream(contentFile); } /** * Initialize temporary directory and template engine. * * @param templateId the template id (there may be multiple templates) * * @throws Exception if an error occurs during the initialization */ private void init(String templateId) throws Exception { synchronized (this) { // engine initialization if (ve == null) { ve = new VelocityEngine(); // create a temporary directory tempDir = Files.createTempDir(); tempDir.deleteOnExit(); ve.setProperty("file.resource.loader.path", tempDir.getAbsolutePath()); // initialize VelocityEngine ve.init(); } File templateFile = new File(tempDir, templateId + ".vm"); if (!templateFile.exists()) { OutputStream fos = new BufferedOutputStream(new FileOutputStream(templateFile)); InputStream stream = getTemplate(templateId); // copy the InputStream into FileOutputStream IOUtils.copy(stream, fos); stream.close(); fos.close(); templateFile.deleteOnExit(); } } } /** * Get the template content. * * @param templateId the template id (there may be multiple templates) * * @return the template as input stream * @throws Exception if an error occurs retrieving the template */ protected abstract InputStream getTemplate(String templateId) throws Exception; }