com.liferay.journal.transformer.JournalTransformer.java Source code

Java tutorial

Introduction

Here is the source code for com.liferay.journal.transformer.JournalTransformer.java

Source

/**
 * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
 *
 * This library 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 2.1 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.
 */

package com.liferay.journal.transformer;

import com.liferay.dynamic.data.mapping.model.DDMForm;
import com.liferay.dynamic.data.mapping.model.DDMFormField;
import com.liferay.dynamic.data.mapping.model.DDMFormFieldOptions;
import com.liferay.dynamic.data.mapping.model.DDMStructure;
import com.liferay.dynamic.data.mapping.model.LocalizedValue;
import com.liferay.dynamic.data.mapping.service.DDMStructureLocalServiceUtil;
import com.liferay.journal.configuration.JournalServiceConfiguration;
import com.liferay.portal.kernel.io.unsync.UnsyncStringWriter;
import com.liferay.portal.kernel.json.JSONFactoryUtil;
import com.liferay.portal.kernel.json.JSONObject;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.mobile.device.Device;
import com.liferay.portal.kernel.mobile.device.UnknownDevice;
import com.liferay.portal.kernel.model.Company;
import com.liferay.portal.kernel.module.configuration.ConfigurationProviderUtil;
import com.liferay.portal.kernel.portlet.PortletRequestModel;
import com.liferay.portal.kernel.security.auth.CompanyThreadLocal;
import com.liferay.portal.kernel.security.permission.PermissionThreadLocal;
import com.liferay.portal.kernel.service.CompanyLocalServiceUtil;
import com.liferay.portal.kernel.template.StringTemplateResource;
import com.liferay.portal.kernel.template.Template;
import com.liferay.portal.kernel.template.TemplateConstants;
import com.liferay.portal.kernel.template.TemplateManager;
import com.liferay.portal.kernel.template.TemplateManagerUtil;
import com.liferay.portal.kernel.template.TemplateResource;
import com.liferay.portal.kernel.templateparser.TemplateNode;
import com.liferay.portal.kernel.templateparser.TransformException;
import com.liferay.portal.kernel.templateparser.TransformerListener;
import com.liferay.portal.kernel.theme.ThemeDisplay;
import com.liferay.portal.kernel.util.Constants;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.LocaleUtil;
import com.liferay.portal.kernel.util.LocalizationUtil;
import com.liferay.portal.kernel.util.PropertiesUtil;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.xml.Attribute;
import com.liferay.portal.kernel.xml.Document;
import com.liferay.portal.kernel.xml.DocumentException;
import com.liferay.portal.kernel.xml.Element;
import com.liferay.portal.kernel.xml.SAXReaderUtil;
import com.liferay.portal.xsl.XSLTemplateResource;
import com.liferay.portal.xsl.XSLURIResolver;
import com.liferay.taglib.servlet.PipingServletResponse;

import java.io.IOException;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;

/**
 * @author Brian Wing Shun Chan
 * @author Raymond Aug
 * @author Wesley Gong
 * @author Angelo Jefferson
 * @author Hugo Huijser
 * @author Marcellus Tavares
 * @author Juan Fernndez
 * @author Eduardo Garcia
 */
public class JournalTransformer {

    public JournalTransformer(boolean restricted) {
        _restricted = restricted;
    }

    /**
     * @deprecated As of 4.0.0, replaced by {@link #JournalTransformer(boolean)}
     */
    @Deprecated
    public JournalTransformer(String errorTemplatePropertyKey, boolean restricted) {

        this(restricted);
    }

    /**
     * @deprecated As of 4.0.0, replaced by {@link #JournalTransformer(boolean)}
     */
    @Deprecated
    public JournalTransformer(String transformerListenerPropertyKey, String errorTemplatePropertyKey,
            boolean restricted) {

        this(restricted);
    }

    public String transform(ThemeDisplay themeDisplay, Map<String, Object> contextObjects,
            Map<String, String> tokens, String viewMode, String languageId, Document document,
            PortletRequestModel portletRequestModel, String script, String langType, boolean propagateException)
            throws Exception {

        return doTransform(themeDisplay, contextObjects, tokens, viewMode, languageId, document,
                portletRequestModel, script, langType, propagateException);
    }

    public String transform(ThemeDisplay themeDisplay, Map<String, String> tokens, String viewMode,
            String languageId, Document document, PortletRequestModel portletRequestModel, String script,
            String langType) throws Exception {

        return doTransform(themeDisplay, null, tokens, viewMode, languageId, document, portletRequestModel, script,
                langType, false);
    }

    public String transform(ThemeDisplay themeDisplay, Map<String, String> tokens, String viewMode,
            String languageId, Document document, PortletRequestModel portletRequestModel, String script,
            String langType, boolean propagateException) throws Exception {

        return doTransform(themeDisplay, null, tokens, viewMode, languageId, document, portletRequestModel, script,
                langType, propagateException);
    }

    protected String doTransform(ThemeDisplay themeDisplay, Map<String, Object> contextObjects,
            Map<String, String> tokens, String viewMode, String languageId, Document document,
            PortletRequestModel portletRequestModel, String script, String langType, boolean propagateException)
            throws Exception {

        // Setup listeners

        if (_log.isDebugEnabled()) {
            _log.debug("Language " + languageId);
        }

        if (Validator.isNull(viewMode)) {
            viewMode = Constants.VIEW;
        }

        if (_logTokens.isDebugEnabled()) {
            String tokensString = PropertiesUtil.list(tokens);

            _logTokens.debug(tokensString);
        }

        if (_logTransformBefore.isDebugEnabled()) {
            _logTransformBefore.debug(document);
        }

        List<TransformerListener> transformerListeners = JournalTransformerListenerRegistryUtil
                .getTransformerListeners();

        for (TransformerListener transformerListener : transformerListeners) {

            // Modify XML

            if (_logXmlBeforeListener.isDebugEnabled()) {
                _logXmlBeforeListener.debug(document);
            }

            if (transformerListener != null) {
                document = transformerListener.onXml(document, languageId, tokens);

                if (_logXmlAfterListener.isDebugEnabled()) {
                    _logXmlAfterListener.debug(document);
                }
            }

            // Modify script

            if (_logScriptBeforeListener.isDebugEnabled()) {
                _logScriptBeforeListener.debug(script);
            }

            if (transformerListener != null) {
                script = transformerListener.onScript(script, document, languageId, tokens);

                if (_logScriptAfterListener.isDebugEnabled()) {
                    _logScriptAfterListener.debug(script);
                }
            }
        }

        // Transform

        String output = null;

        if (Validator.isNull(langType)) {
            output = LocalizationUtil.getLocalization(document.asXML(), languageId);
        } else {
            long companyId = 0;
            long companyGroupId = 0;
            long articleGroupId = 0;
            long classNameId = 0;

            if (tokens != null) {
                companyId = GetterUtil.getLong(tokens.get("company_id"));
                companyGroupId = GetterUtil.getLong(tokens.get("company_group_id"));
                articleGroupId = GetterUtil.getLong(tokens.get("article_group_id"));
                classNameId = GetterUtil.getLong(tokens.get(TemplateConstants.CLASS_NAME_ID));
            }

            long scopeGroupId = 0;
            long siteGroupId = 0;

            if (themeDisplay != null) {
                companyId = themeDisplay.getCompanyId();
                companyGroupId = themeDisplay.getCompanyGroupId();
                scopeGroupId = themeDisplay.getScopeGroupId();
                siteGroupId = themeDisplay.getSiteGroupId();
            }

            String templateId = tokens.get("template_id");

            templateId = getTemplateId(templateId, companyId, companyGroupId, articleGroupId);

            Template template = getTemplate(templateId, tokens, languageId, document, script, langType);

            if (contextObjects != null) {
                template.putAll(contextObjects);
            }

            UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter();

            try {
                if (document != null) {
                    Element rootElement = document.getRootElement();

                    List<TemplateNode> templateNodes = getTemplateNodes(themeDisplay, rootElement,
                            Long.valueOf(tokens.get("ddm_structure_id")));

                    if (templateNodes != null) {
                        for (TemplateNode templateNode : templateNodes) {
                            template.put(templateNode.getName(), templateNode);
                        }
                    }

                    if (portletRequestModel != null) {
                        template.put("request", portletRequestModel.toMap());

                        if (langType.equals(TemplateConstants.LANG_TYPE_XSL)) {
                            Document requestDocument = SAXReaderUtil.read(portletRequestModel.toXML());

                            Element requestElement = requestDocument.getRootElement();

                            template.put("xmlRequest", requestElement.asXML());
                        }
                    } else {
                        Element requestElement = rootElement.element("request");

                        template.put("request", insertRequestVariables(requestElement));

                        if (langType.equals(TemplateConstants.LANG_TYPE_XSL)) {
                            template.put("xmlRequest", requestElement.asXML());
                        }
                    }
                }

                template.put("articleGroupId", articleGroupId);
                template.put("company", getCompany(themeDisplay, companyId));
                template.put("companyId", companyId);
                template.put("device", getDevice(themeDisplay));

                String templatesPath = getTemplatesPath(companyId, articleGroupId, classNameId);

                Locale locale = LocaleUtil.fromLanguageId(languageId);

                template.put("locale", locale);

                template.put("permissionChecker", PermissionThreadLocal.getPermissionChecker());
                template.put("randomNamespace", StringUtil.randomId() + StringPool.UNDERLINE);
                template.put("scopeGroupId", scopeGroupId);
                template.put("siteGroupId", siteGroupId);
                template.put("templatesPath", templatesPath);
                template.put("viewMode", viewMode);

                if (themeDisplay != null) {
                    TemplateManager templateManager = TemplateManagerUtil.getTemplateManager(langType);

                    HttpServletRequest request = themeDisplay.getRequest();

                    templateManager.addTaglibSupport(template, request, themeDisplay.getResponse());
                    templateManager.addTaglibTheme(template, "taglibLiferay", request,
                            new PipingServletResponse(themeDisplay.getResponse(), unsyncStringWriter));
                }

                // Deprecated variables

                template.put("groupId", articleGroupId);
                template.put("journalTemplatesPath", templatesPath);

                mergeTemplate(template, unsyncStringWriter, propagateException);
            } catch (Exception e) {
                if (e instanceof DocumentException) {
                    throw new TransformException("Unable to read XML document", e);
                } else if (e instanceof IOException) {
                    throw new TransformException("Error reading template", e);
                } else if (e instanceof TransformException) {
                    throw (TransformException) e;
                } else {
                    throw new TransformException("Unhandled exception", e);
                }
            }

            output = unsyncStringWriter.toString();
        }

        // Postprocess output

        for (TransformerListener transformerListener : transformerListeners) {

            // Modify output

            if (_logOutputBeforeListener.isDebugEnabled()) {
                _logOutputBeforeListener.debug(output);
            }

            output = transformerListener.onOutput(output, languageId, tokens);

            if (_logOutputAfterListener.isDebugEnabled()) {
                _logOutputAfterListener.debug(output);
            }
        }

        if (_logTransfromAfter.isDebugEnabled()) {
            _logTransfromAfter.debug(output);
        }

        return output;
    }

    protected ClassLoader getClassLoader() {
        Class<?> clazz = getClass();

        return clazz.getClassLoader();
    }

    protected Company getCompany(ThemeDisplay themeDisplay, long companyId) throws Exception {

        if (themeDisplay != null) {
            return themeDisplay.getCompany();
        }

        return CompanyLocalServiceUtil.getCompany(companyId);
    }

    protected Device getDevice(ThemeDisplay themeDisplay) {
        if (themeDisplay != null) {
            return themeDisplay.getDevice();
        }

        return UnknownDevice.getInstance();
    }

    protected TemplateResource getErrorTemplateResource(String langType) {
        try {
            long companyId = CompanyThreadLocal.getCompanyId();

            JournalServiceConfiguration journalServiceConfiguration = ConfigurationProviderUtil
                    .getCompanyConfiguration(JournalServiceConfiguration.class, companyId);

            String template = StringPool.BLANK;

            if (langType.equals(TemplateConstants.LANG_TYPE_FTL)) {
                template = journalServiceConfiguration.errorTemplateFTL();
            } else if (langType.equals(TemplateConstants.LANG_TYPE_VM)) {
                template = journalServiceConfiguration.errorTemplateVM();
            } else if (langType.equals(TemplateConstants.LANG_TYPE_XSL)) {
                template = journalServiceConfiguration.errorTemplateXSL();
            } else {
                return null;
            }

            return new StringTemplateResource(langType, template);
        } catch (Exception e) {
        }

        return null;
    }

    protected Template getTemplate(String templateId, Map<String, String> tokens, String languageId,
            Document document, String script, String langType) throws Exception {

        TemplateResource templateResource = null;

        if (langType.equals(TemplateConstants.LANG_TYPE_XSL)) {
            XSLURIResolver xslURIResolver = new JournalXSLURIResolver(tokens, languageId);

            templateResource = new XSLTemplateResource(templateId, script, xslURIResolver, document.asXML());
        } else {
            templateResource = new StringTemplateResource(templateId, script);
        }

        TemplateResource errorTemplateResource = getErrorTemplateResource(langType);

        return TemplateManagerUtil.getTemplate(langType, templateResource, errorTemplateResource, _restricted);
    }

    protected String getTemplateId(String templateId, long companyId, long companyGroupId, long groupId) {

        StringBundler sb = new StringBundler(5);

        sb.append(companyId);
        sb.append(StringPool.POUND);

        if (companyGroupId > 0) {
            sb.append(companyGroupId);
        } else {
            sb.append(groupId);
        }

        sb.append(StringPool.POUND);
        sb.append(templateId);

        return sb.toString();
    }

    protected List<TemplateNode> getTemplateNodes(ThemeDisplay themeDisplay, Element element, long ddmStructureId)
            throws Exception {

        DDMStructure ddmStructure = DDMStructureLocalServiceUtil.getStructure(ddmStructureId);

        DDMForm ddmForm = ddmStructure.getDDMForm();

        Map<String, DDMFormField> ddmFormFieldsMap = ddmForm.getDDMFormFieldsMap(true);

        List<TemplateNode> templateNodes = new ArrayList<>();

        Map<String, TemplateNode> prototypeTemplateNodes = new HashMap<>();

        List<Element> dynamicElementElements = element.elements("dynamic-element");

        for (Element dynamicElementElement : dynamicElementElements) {
            Element dynamicContentElement = dynamicElementElement.element("dynamic-content");

            String data = StringPool.BLANK;

            if (dynamicContentElement != null) {
                data = dynamicContentElement.getText();
            }

            String name = dynamicElementElement.attributeValue("name", StringPool.BLANK);

            if (name.length() == 0) {
                throw new TransformException("Element missing \"name\" attribute");
            }

            String type = dynamicElementElement.attributeValue("type", StringPool.BLANK);

            Map<String, String> attributes = new HashMap<>();

            if (type.equals("image")) {
                JSONObject dataJSONObject = JSONFactoryUtil.createJSONObject(data);

                Iterator<String> itr = dataJSONObject.keys();

                while (itr.hasNext()) {
                    String key = itr.next();

                    String value = dataJSONObject.getString(key);

                    attributes.put(key, value);
                }
            }

            if (dynamicContentElement != null) {
                for (Attribute attribute : dynamicContentElement.attributes()) {
                    attributes.put(attribute.getName(), attribute.getValue());
                }
            }

            TemplateNode templateNode = new TemplateNode(themeDisplay, name, StringUtil.stripCDATA(data), type,
                    attributes);

            if (dynamicElementElement.element("dynamic-element") != null) {
                templateNode.appendChildren(getTemplateNodes(themeDisplay, dynamicElementElement, ddmStructureId));
            } else if ((dynamicContentElement != null) && (dynamicContentElement.element("option") != null)) {

                List<Element> optionElements = dynamicContentElement.elements("option");

                for (Element optionElement : optionElements) {
                    templateNode.appendOption(StringUtil.stripCDATA(optionElement.getText()));
                }
            }

            DDMFormField ddmFormField = ddmFormFieldsMap.get(name);

            if (ddmFormField != null) {
                DDMFormFieldOptions ddmFormFieldOptions = ddmFormField.getDDMFormFieldOptions();

                Map<String, LocalizedValue> options = ddmFormFieldOptions.getOptions();

                for (Entry<String, LocalizedValue> entry : options.entrySet()) {
                    String optionValue = StringUtil.stripCDATA(entry.getKey());

                    LocalizedValue localizedLabel = entry.getValue();

                    String optionLabel = localizedLabel.getString(themeDisplay.getLocale());

                    templateNode.appendOptionMap(optionValue, optionLabel);
                }
            }

            TemplateNode prototypeTemplateNode = prototypeTemplateNodes.get(name);

            if (prototypeTemplateNode == null) {
                prototypeTemplateNode = templateNode;

                prototypeTemplateNodes.put(name, prototypeTemplateNode);

                templateNodes.add(templateNode);
            }

            prototypeTemplateNode.appendSibling(templateNode);
        }

        return templateNodes;
    }

    protected String getTemplatesPath(long companyId, long groupId, long classNameId) {

        StringBundler sb = new StringBundler(7);

        sb.append(TemplateConstants.TEMPLATE_SEPARATOR);
        sb.append(StringPool.SLASH);
        sb.append(companyId);
        sb.append(StringPool.SLASH);
        sb.append(groupId);
        sb.append(StringPool.SLASH);
        sb.append(classNameId);

        return sb.toString();
    }

    protected Map<String, Object> insertRequestVariables(Element element) {
        Map<String, Object> map = new HashMap<>();

        if (element == null) {
            return map;
        }

        for (Element childElement : element.elements()) {
            String name = childElement.getName();

            if (name.equals("attribute")) {
                Element nameElement = childElement.element("name");
                Element valueElement = childElement.element("value");

                map.put(nameElement.getText(), valueElement.getText());
            } else if (name.equals("parameter")) {
                Element nameElement = childElement.element("name");

                List<Element> valueElements = childElement.elements("value");

                if (valueElements.size() == 1) {
                    Element valueElement = valueElements.get(0);

                    map.put(nameElement.getText(), valueElement.getText());
                } else {
                    List<String> values = new ArrayList<>();

                    for (Element valueElement : valueElements) {
                        values.add(valueElement.getText());
                    }

                    map.put(nameElement.getText(), values);
                }
            } else {
                List<Element> elements = childElement.elements();

                if (!elements.isEmpty()) {
                    map.put(name, insertRequestVariables(childElement));
                } else {
                    map.put(name, childElement.getText());
                }
            }
        }

        return map;
    }

    protected void mergeTemplate(Template template, UnsyncStringWriter unsyncStringWriter,
            boolean propagateException) throws Exception {

        if (propagateException) {
            template.doProcessTemplate(unsyncStringWriter);
        } else {
            template.processTemplate(unsyncStringWriter);
        }
    }

    private static final Log _log = LogFactoryUtil.getLog(JournalTransformer.class);

    private static final Log _logOutputAfterListener = LogFactoryUtil
            .getLog(JournalTransformer.class.getName() + ".OutputAfterListener");
    private static final Log _logOutputBeforeListener = LogFactoryUtil
            .getLog(JournalTransformer.class.getName() + ".OutputBeforeListener");
    private static final Log _logScriptAfterListener = LogFactoryUtil
            .getLog(JournalTransformer.class.getName() + ".ScriptAfterListener");
    private static final Log _logScriptBeforeListener = LogFactoryUtil
            .getLog(JournalTransformer.class.getName() + ".ScriptBeforeListener");
    private static final Log _logTokens = LogFactoryUtil.getLog(JournalTransformer.class.getName() + ".Tokens");
    private static final Log _logTransformBefore = LogFactoryUtil
            .getLog(JournalTransformer.class.getName() + ".TransformBefore");
    private static final Log _logTransfromAfter = LogFactoryUtil
            .getLog(JournalTransformer.class.getName() + ".TransformAfter");
    private static final Log _logXmlAfterListener = LogFactoryUtil
            .getLog(JournalTransformer.class.getName() + ".XmlAfterListener");
    private static final Log _logXmlBeforeListener = LogFactoryUtil
            .getLog(JournalTransformer.class.getName() + ".XmlBeforeListener");

    private final Map<String, String> _errorTemplateIds = new HashMap<>();
    private final boolean _restricted;

}