org.exoplatform.commons.notification.template.TemplateUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.exoplatform.commons.notification.template.TemplateUtils.java

Source

/*
 * Copyright (C) 2003-2013 eXo Platform SAS.
 *
 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see<http://www.gnu.org/licenses/>.
 */
package org.exoplatform.commons.notification.template;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.URL;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.exoplatform.commons.api.notification.plugin.config.PluginConfig;
import org.exoplatform.commons.api.notification.plugin.config.TemplateConfig;
import org.exoplatform.commons.api.notification.service.template.TemplateContext;
import org.exoplatform.commons.api.notification.template.Element;
import org.exoplatform.commons.api.notification.template.ElementVisitor;
import org.exoplatform.commons.notification.NotificationUtils;
import org.exoplatform.commons.notification.impl.NotificationContextImpl;
import org.exoplatform.commons.utils.CommonsUtils;
import org.exoplatform.container.configuration.ConfigurationManager;
import org.exoplatform.groovyscript.GroovyTemplate;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.services.resources.ResourceBundleService;
import org.gatein.common.io.IOTools;

public class TemplateUtils {
    private static final Log LOG = ExoLogger.getLogger(TemplateUtils.class);
    private static final String DIGEST_TEMPLATE_KEY = "Digest.{0}.{1}";
    private static final String SIMPLE_TEMPLATE_KEY = "Simple.{0}.{1}";
    private static final Pattern SCRIPT_REMOVE_PATTERN = Pattern
            .compile("<(script|style)[^>]*>[^<]*</(script|style)>", Pattern.CASE_INSENSITIVE);
    private static final Pattern TAGS_REMOVE_PATTERN = Pattern.compile("<[^>]*>", Pattern.CASE_INSENSITIVE);

    private static Map<String, Element> cacheTemplate = new ConcurrentHashMap<String, Element>();

    private static final int MAX_SUBJECT_LENGTH = 50;

    /**
     * Process the Groovy template associate with Template context to generate
     * It will be use for digest mail
     * @param ctx
     * @return
     */
    public static String processGroovy(TemplateContext ctx) {
        Element groovyElement = loadGroovyElement(ctx.getPluginId(), ctx.getLanguage());

        ElementVisitor visitor = new GroovyElementVisitor();
        String content = visitor.with(ctx).visit(groovyElement).out();
        return content;
    }

    /**
     * Generate the Groovy Template
     * @param context The template context
     * @param element The GroovyElemt
     * @param out The Writer to writer template
     * @return
     */
    public static void loadGroovy(TemplateContext context, Element element, Writer out) {

        try {
            String groovyTemplate = element.getTemplate();
            if (groovyTemplate == null) {
                groovyTemplate = loadGroovyTemplate(element.getTemplateConfig().getTemplatePath());
                element.template(groovyTemplate);
            }
            if (groovyTemplate != null && groovyTemplate.length() > 0) {
                GroovyTemplate gTemplate = new GroovyTemplate(groovyTemplate);
                gTemplate.render(out, context);
            }
        } catch (ClassCastException e) {
            throw new IllegalArgumentException("The function only load groovy with GroovyElement type.");
        } catch (Exception e) {
            LOG.warn("Failed to load groovy template of plugin " + context.getPluginId() + "\n" + e.getMessage());
        }
    }

    /**
     * Gets InputStream for groovy template
     * 
     * @param templatePath
     * @return
     * @throws Exception
     */
    private static InputStream getTemplateInputStream(String templatePath) throws Exception {
        try {

            ConfigurationManager configurationManager = CommonsUtils.getService(ConfigurationManager.class);

            String uri = templatePath;
            if (templatePath.indexOf("war") < 0 && templatePath.indexOf("jar") < 0
                    && templatePath.indexOf("classpath") < 0) {
                URL url = null;
                if (templatePath.indexOf("/") == 0) {
                    templatePath = templatePath.substring(1);
                }
                uri = "war:/" + templatePath;
                url = configurationManager.getURL(uri);
                if (url == null) {
                    uri = "jar:/" + templatePath;
                    url = configurationManager.getURL(uri);
                }
            }
            return configurationManager.getInputStream(uri);
        } catch (Exception e) {
            throw new RuntimeException("Error to get notification template " + templatePath, e);
        }
    }

    /**
     * Loads the Groovy template file
     * 
     * @param templatePath
     * @return
     * @throws Exception
     */
    public static String loadGroovyTemplate(String templatePath) throws Exception {
        StringWriter templateText = new StringWriter();
        Reader reader = null;
        try {
            reader = new InputStreamReader(getTemplateInputStream(templatePath));
            IOTools.copy(reader, templateText);
        } catch (Exception e) {
            LOG.debug("Failed to reader template file: " + templatePath, e);
        } finally {
            if (reader != null) {
                reader.close();
            }
        }

        return templateText.toString();
    }

    /**
     * Load the Groovy template element.
     * 
     * @param pluginId The plugin's id
     * @param language The language's id.
     * @return The Groovy element
     */
    public static Element loadGroovyElement(String pluginId, String language) {
        TemplateConfig templateConfig = getTemplateConfig(pluginId);
        return new GroovyElement().language(language).config(templateConfig);
    }

    /**
     * Render for Subject template
     * @param ctx
     * @return
     */
    public static String processSubject(TemplateContext ctx) {
        Element subjectElement = null;
        String key = makeTemplateKey(SIMPLE_TEMPLATE_KEY, ctx.getPluginId(), ctx.getLanguage());
        if (cacheTemplate.containsKey(key)) {
            subjectElement = cacheTemplate.get(key);
        } else {
            TemplateConfig templateConfig = getTemplateConfig(ctx.getPluginId());
            subjectElement = NotificationUtils.getSubject(templateConfig, ctx.getPluginId(), ctx.getLanguage())
                    .addNewLine(false);
            cacheTemplate.put(key, subjectElement);
        }

        //The title of activity is escaped on social, then we need to unescape it to process the send email
        String value = (String) ctx.get("ACTIVITY");
        if (value != null) {
            ctx.put("ACTIVITY", StringEscapeUtils.unescapeHtml(value));
        }

        String subject = (String) ctx.get("SUBJECT");
        if (subject != null && subject.length() > 0) {
            ctx.put("SUBJECT", getExcerptSubject(subject));
            return subjectElement.accept(SimpleElementVistior.instance().with(ctx)).out();
        }
        //
        subject = subjectElement.accept(SimpleElementVistior.instance().with(ctx)).out();
        return getExcerptSubject(subject);
    }

    /**
     * Get the excerpt subject of notification mail from origin string
     *  - Just contains plain text
     *  - Limit number of characters
     * @param subject the origin string
     * @return the excerpt of subject
     * @since 4.1.x
     */
    public static String getExcerptSubject(String subject) {
        String newSubject = StringEscapeUtils.unescapeHtml(cleanHtmlTags(subject));
        if (newSubject != null && newSubject.length() > MAX_SUBJECT_LENGTH) {
            newSubject = newSubject.substring(0, MAX_SUBJECT_LENGTH);
            int lastSpace = newSubject.lastIndexOf(" ");
            return ((lastSpace > 0) ? newSubject.substring(0, lastSpace) : newSubject) + "...";
        }

        return newSubject;
    }

    /**
     * Clean all HTML tags on string
     *  
     * @param str the origin string
     * @return The string has not contain HTML tags.
     * @since 4.1.x
     */
    public static String cleanHtmlTags(String str) {
        //
        if (str == null || str.trim().length() == 0) {
            return "";
        }
        // clean multi-lines
        String newSubject = StringUtils.replace(str, "\n", " ");
        // clean script
        newSubject = SCRIPT_REMOVE_PATTERN.matcher(newSubject).replaceAll("");
        // clean tags HTML
        newSubject = TAGS_REMOVE_PATTERN.matcher(newSubject).replaceAll(" ");
        return newSubject.replaceAll("\\s+", " ").trim();
    }

    /**
     * Render for digest template
     * @param ctx
     * @return
     */
    public static String processDigest(TemplateContext ctx) {
        DigestTemplate digest = null;
        String key = makeTemplateKey(DIGEST_TEMPLATE_KEY, ctx.getPluginId(), ctx.getLanguage());
        if (cacheTemplate.containsKey(key)) {
            digest = (DigestTemplate) cacheTemplate.get(key);
        } else {
            TemplateConfig templateConfig = getTemplateConfig(ctx.getPluginId());
            digest = NotificationUtils.getDigest(templateConfig, ctx.getPluginId(), ctx.getLanguage());
            cacheTemplate.put(key, digest);
        }

        return digest.accept(SimpleElementVistior.instance().with(ctx)).out();
    }

    private static String makeTemplateKey(String pattern, String pluginId, String language) {
        return MessageFormat.format(pattern, pluginId, language);
    }

    /**
     * Gets Plugin configuration for specified PluginId
     * @param pluginId
     * @return
     */
    private static TemplateConfig getTemplateConfig(String pluginId) {
        PluginConfig pluginConfig = NotificationContextImpl.cloneInstance().getPluginSettingService()
                .getPluginConfig(pluginId);

        if (pluginConfig == null) {
            throw new IllegalStateException("PluginConfig is NULL with plugId = " + pluginId);
        }

        return pluginConfig.getTemplateConfig();
    }

    /**
     * Gets Resource Bundle value
     * @param key
     * @param locale
     * @param resourcePath
     * @return
     */
    public static String getResourceBundle(String key, Locale locale, String resourcePath) {
        if (key == null || key.trim().length() == 0) {
            return "";
        }
        if (locale == null || locale.getLanguage().isEmpty()) {
            locale = Locale.ENGLISH;
        }

        ResourceBundleService bundleService = CommonsUtils.getService(ResourceBundleService.class);
        ResourceBundle res = bundleService.getResourceBundle(resourcePath, locale);

        if (res == null || res.containsKey(key) == false) {
            LOG.warn("Resource Bundle key not found. " + key + " in source path: " + resourcePath);
            return key;
        }

        return res.getString(key);
    }

}