001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.templateparser;
016    
017    import com.liferay.portal.kernel.configuration.Filter;
018    import com.liferay.portal.kernel.io.unsync.UnsyncStringWriter;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.mobile.device.Device;
022    import com.liferay.portal.kernel.mobile.device.UnknownDevice;
023    import com.liferay.portal.kernel.template.StringTemplateResource;
024    import com.liferay.portal.kernel.template.Template;
025    import com.liferay.portal.kernel.template.TemplateConstants;
026    import com.liferay.portal.kernel.template.TemplateManagerUtil;
027    import com.liferay.portal.kernel.template.TemplateResource;
028    import com.liferay.portal.kernel.template.URLTemplateResource;
029    import com.liferay.portal.kernel.templateparser.TransformException;
030    import com.liferay.portal.kernel.templateparser.TransformerListener;
031    import com.liferay.portal.kernel.util.GetterUtil;
032    import com.liferay.portal.kernel.util.InstanceFactory;
033    import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
034    import com.liferay.portal.kernel.util.SetUtil;
035    import com.liferay.portal.kernel.util.StringBundler;
036    import com.liferay.portal.kernel.util.StringPool;
037    import com.liferay.portal.kernel.util.StringUtil;
038    import com.liferay.portal.kernel.util.Validator;
039    import com.liferay.portal.model.Company;
040    import com.liferay.portal.security.permission.PermissionThreadLocal;
041    import com.liferay.portal.service.CompanyLocalServiceUtil;
042    import com.liferay.portal.theme.ThemeDisplay;
043    import com.liferay.portal.util.PropsUtil;
044    
045    import java.net.URL;
046    
047    import java.util.HashMap;
048    import java.util.HashSet;
049    import java.util.Map;
050    import java.util.Set;
051    
052    /**
053     * @author Brian Wing Shun Chan
054     * @author Raymond Aug??
055     * @author Wesley Gong
056     * @author Angelo Jefferson
057     * @author Hugo Huijser
058     * @author Marcellus Tavares
059     * @author Juan Fern??ndez
060     */
061    public class Transformer {
062    
063            public Transformer(String errorTemplatePropertyKey, boolean restricted) {
064                    Set<String> langTypes = TemplateManagerUtil.getSupportedLanguageTypes(
065                            errorTemplatePropertyKey);
066    
067                    for (String langType : langTypes) {
068                            String errorTemplateId = PropsUtil.get(
069                                    errorTemplatePropertyKey, new Filter(langType));
070    
071                            if (Validator.isNotNull(errorTemplateId)) {
072                                    _errorTemplateIds.put(langType, errorTemplateId);
073                            }
074                    }
075    
076                    _restricted = restricted;
077            }
078    
079            public Transformer(
080                    String transformerListenerPropertyKey, String errorTemplatePropertyKey,
081                    boolean restricted) {
082    
083                    this(errorTemplatePropertyKey, restricted);
084    
085                    ClassLoader classLoader = PortalClassLoaderUtil.getClassLoader();
086    
087                    Set<String> transformerListenerClassNames = SetUtil.fromArray(
088                            PropsUtil.getArray(transformerListenerPropertyKey));
089    
090                    for (String transformerListenerClassName :
091                                    transformerListenerClassNames) {
092    
093                            try {
094                                    if (_log.isDebugEnabled()) {
095                                            _log.debug(
096                                                    "Instantiating transformer listener " +
097                                                            transformerListenerClassName);
098                                    }
099    
100                                    TransformerListener transformerListener =
101                                            (TransformerListener)InstanceFactory.newInstance(
102                                                    classLoader, transformerListenerClassName);
103    
104                                    _transformerListeners.add(transformerListener);
105                            }
106                            catch (Exception e) {
107                                    _log.error(e, e);
108                            }
109                    }
110            }
111    
112            public String transform(
113                            ThemeDisplay themeDisplay, Map<String, Object> contextObjects,
114                            String script, String langType,
115                            UnsyncStringWriter unsyncStringWriter)
116                    throws Exception {
117    
118                    if (Validator.isNull(langType)) {
119                            return null;
120                    }
121    
122                    long companyId = 0;
123                    long companyGroupId = 0;
124                    long scopeGroupId = 0;
125                    long siteGroupId = 0;
126    
127                    if (themeDisplay != null) {
128                            companyId = themeDisplay.getCompanyId();
129                            companyGroupId = themeDisplay.getCompanyGroupId();
130                            scopeGroupId = themeDisplay.getScopeGroupId();
131                            siteGroupId = themeDisplay.getSiteGroupId();
132                    }
133    
134                    String templateId = String.valueOf(contextObjects.get("template_id"));
135    
136                    templateId = getTemplateId(
137                            templateId, companyId, companyGroupId, scopeGroupId);
138    
139                    Template template = getTemplate(templateId, script, langType);
140    
141                    try {
142                            prepareTemplate(themeDisplay, template);
143    
144                            long classNameId = 0;
145    
146                            if (contextObjects != null) {
147                                    for (String key : contextObjects.keySet()) {
148                                            template.put(key, contextObjects.get(key));
149                                    }
150    
151                                    classNameId = GetterUtil.getLong(
152                                            contextObjects.get(TemplateConstants.CLASS_NAME_ID));
153                            }
154    
155                            template.put("company", getCompany(themeDisplay, companyId));
156                            template.put("companyId", companyId);
157                            template.put("device", getDevice(themeDisplay));
158    
159                            String templatesPath = getTemplatesPath(
160                                    companyId, scopeGroupId, classNameId);
161    
162                            template.put(
163                                    "permissionChecker",
164                                    PermissionThreadLocal.getPermissionChecker());
165                            template.put(
166                                    "randomNamespace",
167                                    StringUtil.randomId() + StringPool.UNDERLINE);
168                            template.put("scopeGroupId", scopeGroupId);
169                            template.put("siteGroupId", siteGroupId);
170                            template.put("templatesPath", templatesPath);
171    
172                            // Deprecated variables
173    
174                            template.put("groupId", scopeGroupId);
175                            template.put("journalTemplatesPath", templatesPath);
176    
177                            mergeTemplate(template, unsyncStringWriter, false);
178                    }
179                    catch (Exception e) {
180                            throw new TransformException("Unhandled exception", e);
181                    }
182    
183                    return unsyncStringWriter.toString();
184            }
185    
186            protected Company getCompany(ThemeDisplay themeDisplay, long companyId)
187                    throws Exception {
188    
189                    if (themeDisplay != null) {
190                            return themeDisplay.getCompany();
191                    }
192    
193                    return CompanyLocalServiceUtil.getCompany(companyId);
194            }
195    
196            protected Device getDevice(ThemeDisplay themeDisplay) {
197                    if (themeDisplay != null) {
198                            return themeDisplay.getDevice();
199                    }
200    
201                    return UnknownDevice.getInstance();
202            }
203    
204            protected TemplateResource getErrorTemplateResource(String langType) {
205                    try {
206                            Class<?> clazz = getClass();
207    
208                            ClassLoader classLoader = clazz.getClassLoader();
209    
210                            String errorTemplateId = _errorTemplateIds.get(langType);
211    
212                            URL url = classLoader.getResource(errorTemplateId);
213    
214                            return new URLTemplateResource(errorTemplateId, url);
215                    }
216                    catch (Exception e) {
217                    }
218    
219                    return null;
220            }
221    
222            protected Template getTemplate(
223                            String templateId, String script, String langType)
224                    throws Exception {
225    
226                    TemplateResource templateResource = new StringTemplateResource(
227                            templateId, script);
228    
229                    TemplateResource errorTemplateResource = getErrorTemplateResource(
230                            langType);
231    
232                    return TemplateManagerUtil.getTemplate(
233                            langType, templateResource, errorTemplateResource, _restricted);
234            }
235    
236            protected String getTemplateId(
237                    String templateId, long companyId, long companyGroupId, long groupId) {
238    
239                    StringBundler sb = new StringBundler(5);
240    
241                    sb.append(companyId);
242                    sb.append(StringPool.POUND);
243    
244                    if (companyGroupId > 0) {
245                            sb.append(companyGroupId);
246                    }
247                    else {
248                            sb.append(groupId);
249                    }
250    
251                    sb.append(StringPool.POUND);
252                    sb.append(templateId);
253    
254                    return sb.toString();
255            }
256    
257            protected String getTemplatesPath(
258                    long companyId, long groupId, long classNameId) {
259    
260                    StringBundler sb = new StringBundler(7);
261    
262                    sb.append(TemplateConstants.TEMPLATE_SEPARATOR);
263                    sb.append(StringPool.SLASH);
264                    sb.append(companyId);
265                    sb.append(StringPool.SLASH);
266                    sb.append(groupId);
267                    sb.append(StringPool.SLASH);
268                    sb.append(classNameId);
269    
270                    return sb.toString();
271            }
272    
273            protected void mergeTemplate(
274                            Template template, UnsyncStringWriter unsyncStringWriter,
275                            boolean propagateException)
276                    throws Exception {
277    
278                    if (propagateException) {
279                            template.doProcessTemplate(unsyncStringWriter);
280                    }
281                    else {
282                            template.processTemplate(unsyncStringWriter);
283                    }
284            }
285    
286            protected void prepareTemplate(ThemeDisplay themeDisplay, Template template)
287                    throws Exception {
288    
289                    if (themeDisplay == null) {
290                            return;
291                    }
292    
293                    template.prepare(themeDisplay.getRequest());
294            }
295    
296            private static final Log _log = LogFactoryUtil.getLog(Transformer.class);
297    
298            private final Map<String, String> _errorTemplateIds = new HashMap<>();
299            private final boolean _restricted;
300            private final Set<TransformerListener> _transformerListeners =
301                    new HashSet<>();
302    
303    }