eu.esdihumboldt.hale.io.geoserver.template.Templates.java Source code

Java tutorial

Introduction

Here is the source code for eu.esdihumboldt.hale.io.geoserver.template.Templates.java

Source

/*
 * Copyright (c) 2015 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:
 *     Data Harmonisation Panel <http://www.dhpanel.eu>
 */

package eu.esdihumboldt.hale.io.geoserver.template;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;

import com.google.common.io.Files;

/**
 * Singleton class encapsulating a Velocity engine instance.
 * 
 * @author Stefano Costa, GeoSolutions
 */
public class Templates {

    private static Templates instance;

    /**
     * Return the singleton factory instance.
     * 
     * @return the factory instance
     * @throws TemplateException if an error occurs initializing the template
     *             engine
     */
    public static Templates getInstance() throws TemplateException {
        if (instance == null) {
            instance = new Templates();
        }

        return instance;
    }

    private final File tmpDir;
    private final VelocityEngine ve;

    private Templates() throws TemplateException {
        ve = new VelocityEngine();

        tmpDir = Files.createTempDir();
        tmpDir.deleteOnExit();

        ve.setProperty(VelocityEngine.RUNTIME_LOG_LOGSYSTEM_CLASS, "org.apache.velocity.runtime.log.JdkLogChute");
        ve.setProperty(VelocityEngine.RESOURCE_LOADER, "file");
        ve.setProperty("class.resource.loader.description", "Velocity File Resource Loader");
        ve.setProperty("file.resource.loader.class",
                "org.apache.velocity.runtime.resource.loader.FileResourceLoader");
        ve.setProperty("file.resource.loader.path", tmpDir.getAbsolutePath());

        try {
            ve.init();
        } catch (Exception e) {
            throw new TemplateException(e);
        }
    }

    /**
     * Loads the specified template file and merges it with a Velocity context
     * instance created from the provided variables; the final output is
     * returned as an {@link InputStream} instance.
     * 
     * <p>
     * NOTE: due to a problem with Velocity's classpath loader not working in an
     * OSGi context, the template file is first copied to a temp file and then
     * loaded from there. {@link File#deleteOnExit()} is invoked on the temp
     * file <code>File</code> object after the template is merged.
     * </p>
     * 
     * @param templateResource the template to load
     * @param variables the template context
     * @return the result of merging the template with the provided context
     * @throws TemplateException if an error occurs processing the template
     */
    public InputStream loadTemplate(String templateResource, Map<String, Object> variables)
            throws TemplateException {
        VelocityContext vc = new VelocityContext(variables);

        try {
            File templateFile = copyTemplateToFile(templateResource);

            Template template = ve.getTemplate(templateFile.getName(), "UTF-8");

            StringWriter sw = new StringWriter();
            template.merge(vc, sw);

            templateFile.deleteOnExit();

            return new ByteArrayInputStream(sw.toString().getBytes("UTF-8"));
        } catch (Exception e) {
            throw new TemplateException(e);
        }

    }

    private File copyTemplateToFile(String templateResource) throws IOException {
        InputStream templateStream = getClass().getResourceAsStream(templateResource);
        if (templateStream == null) {
            throw new IOException("Template resource not found: " + templateResource);
        }

        File templateFile = new File(tmpDir, createRandomTemplateName(templateResource));
        OutputStream outputStream = null;
        try {
            outputStream = new BufferedOutputStream(new FileOutputStream(templateFile));
            IOUtils.copy(templateStream, outputStream);

            return templateFile;
        } finally {
            closeAndIgnoreException(templateStream);
            closeAndIgnoreException(outputStream);
        }
    }

    private String createRandomTemplateName(String templateResource) {
        return "template" + templateResource.hashCode() + System.currentTimeMillis() + ".vm";
    }

    private void closeAndIgnoreException(InputStream in) {
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
                // ignore
            }
        }
    }

    private void closeAndIgnoreException(OutputStream out) {
        if (out != null) {
            try {
                out.close();
            } catch (IOException e) {
                // ignore
            }
        }
    }
}