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.model.Company;
024    import com.liferay.portal.kernel.security.permission.PermissionThreadLocal;
025    import com.liferay.portal.kernel.service.CompanyLocalServiceUtil;
026    import com.liferay.portal.kernel.template.StringTemplateResource;
027    import com.liferay.portal.kernel.template.Template;
028    import com.liferay.portal.kernel.template.TemplateConstants;
029    import com.liferay.portal.kernel.template.TemplateManagerUtil;
030    import com.liferay.portal.kernel.template.TemplateResource;
031    import com.liferay.portal.kernel.template.URLTemplateResource;
032    import com.liferay.portal.kernel.templateparser.TransformException;
033    import com.liferay.portal.kernel.templateparser.TransformerListener;
034    import com.liferay.portal.kernel.theme.ThemeDisplay;
035    import com.liferay.portal.kernel.util.GetterUtil;
036    import com.liferay.portal.kernel.util.InstanceFactory;
037    import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
038    import com.liferay.portal.kernel.util.SetUtil;
039    import com.liferay.portal.kernel.util.StringBundler;
040    import com.liferay.portal.kernel.util.StringPool;
041    import com.liferay.portal.kernel.util.StringUtil;
042    import com.liferay.portal.kernel.util.Validator;
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                    _restricted = restricted;
065    
066                    setErrorTemplateIds(errorTemplatePropertyKey);
067            }
068    
069            public Transformer(
070                    String transformerListenerPropertyKey, String errorTemplatePropertyKey,
071                    boolean restricted) {
072    
073                    this(errorTemplatePropertyKey, restricted);
074    
075                    ClassLoader classLoader = PortalClassLoaderUtil.getClassLoader();
076    
077                    setTransformerListeners(transformerListenerPropertyKey, classLoader);
078            }
079    
080            public String transform(
081                            ThemeDisplay themeDisplay, Map<String, Object> contextObjects,
082                            String script, String langType,
083                            UnsyncStringWriter unsyncStringWriter)
084                    throws Exception {
085    
086                    if (Validator.isNull(langType)) {
087                            return null;
088                    }
089    
090                    long companyId = 0;
091                    long companyGroupId = 0;
092                    long scopeGroupId = 0;
093                    long siteGroupId = 0;
094    
095                    if (themeDisplay != null) {
096                            companyId = themeDisplay.getCompanyId();
097                            companyGroupId = themeDisplay.getCompanyGroupId();
098                            scopeGroupId = themeDisplay.getScopeGroupId();
099                            siteGroupId = themeDisplay.getSiteGroupId();
100                    }
101    
102                    String templateId = String.valueOf(contextObjects.get("template_id"));
103    
104                    templateId = getTemplateId(
105                            templateId, companyId, companyGroupId, scopeGroupId);
106    
107                    Template template = getTemplate(templateId, script, langType);
108    
109                    try {
110                            prepareTemplate(themeDisplay, template);
111    
112                            template.putAll(contextObjects);
113    
114                            long classNameId = GetterUtil.getLong(
115                                    contextObjects.get(TemplateConstants.CLASS_NAME_ID));
116    
117                            template.put("company", getCompany(themeDisplay, companyId));
118                            template.put("companyId", companyId);
119                            template.put("device", getDevice(themeDisplay));
120    
121                            String templatesPath = getTemplatesPath(
122                                    companyId, scopeGroupId, classNameId);
123    
124                            template.put(
125                                    "permissionChecker",
126                                    PermissionThreadLocal.getPermissionChecker());
127                            template.put(
128                                    "randomNamespace",
129                                    StringUtil.randomId() + StringPool.UNDERLINE);
130                            template.put("scopeGroupId", scopeGroupId);
131                            template.put("siteGroupId", siteGroupId);
132                            template.put("templatesPath", templatesPath);
133    
134                            // Deprecated variables
135    
136                            template.put("groupId", scopeGroupId);
137                            template.put("journalTemplatesPath", templatesPath);
138    
139                            mergeTemplate(template, unsyncStringWriter, false);
140                    }
141                    catch (Exception e) {
142                            throw new TransformException("Unhandled exception", e);
143                    }
144    
145                    return unsyncStringWriter.toString();
146            }
147    
148            protected Company getCompany(ThemeDisplay themeDisplay, long companyId)
149                    throws Exception {
150    
151                    if (themeDisplay != null) {
152                            return themeDisplay.getCompany();
153                    }
154    
155                    return CompanyLocalServiceUtil.getCompany(companyId);
156            }
157    
158            protected Device getDevice(ThemeDisplay themeDisplay) {
159                    if (themeDisplay != null) {
160                            return themeDisplay.getDevice();
161                    }
162    
163                    return UnknownDevice.getInstance();
164            }
165    
166            protected String getErrorTemplateId(
167                    String errorTemplatePropertyKey, String langType) {
168    
169                    return PropsUtil.get(errorTemplatePropertyKey, new Filter(langType));
170            }
171    
172            protected TemplateResource getErrorTemplateResource(String langType) {
173                    try {
174                            Class<?> clazz = getClass();
175    
176                            ClassLoader classLoader = clazz.getClassLoader();
177    
178                            String errorTemplateId = errorTemplateIds.get(langType);
179    
180                            URL url = classLoader.getResource(errorTemplateId);
181    
182                            return new URLTemplateResource(errorTemplateId, url);
183                    }
184                    catch (Exception e) {
185                    }
186    
187                    return null;
188            }
189    
190            protected Template getTemplate(
191                            String templateId, String script, String langType)
192                    throws Exception {
193    
194                    TemplateResource templateResource = new StringTemplateResource(
195                            templateId, script);
196    
197                    TemplateResource errorTemplateResource = getErrorTemplateResource(
198                            langType);
199    
200                    return TemplateManagerUtil.getTemplate(
201                            langType, templateResource, errorTemplateResource, _restricted);
202            }
203    
204            protected String getTemplateId(
205                    String templateId, long companyId, long companyGroupId, long groupId) {
206    
207                    StringBundler sb = new StringBundler(5);
208    
209                    sb.append(companyId);
210                    sb.append(StringPool.POUND);
211    
212                    if (companyGroupId > 0) {
213                            sb.append(companyGroupId);
214                    }
215                    else {
216                            sb.append(groupId);
217                    }
218    
219                    sb.append(StringPool.POUND);
220                    sb.append(templateId);
221    
222                    return sb.toString();
223            }
224    
225            protected String getTemplatesPath(
226                    long companyId, long groupId, long classNameId) {
227    
228                    StringBundler sb = new StringBundler(7);
229    
230                    sb.append(TemplateConstants.TEMPLATE_SEPARATOR);
231                    sb.append(StringPool.SLASH);
232                    sb.append(companyId);
233                    sb.append(StringPool.SLASH);
234                    sb.append(groupId);
235                    sb.append(StringPool.SLASH);
236                    sb.append(classNameId);
237    
238                    return sb.toString();
239            }
240    
241            protected void mergeTemplate(
242                            Template template, UnsyncStringWriter unsyncStringWriter,
243                            boolean propagateException)
244                    throws Exception {
245    
246                    if (propagateException) {
247                            template.doProcessTemplate(unsyncStringWriter);
248                    }
249                    else {
250                            template.processTemplate(unsyncStringWriter);
251                    }
252            }
253    
254            protected void prepareTemplate(ThemeDisplay themeDisplay, Template template)
255                    throws Exception {
256    
257                    if (themeDisplay == null) {
258                            return;
259                    }
260    
261                    template.prepare(themeDisplay.getRequest());
262            }
263    
264            protected void setErrorTemplateIds(String errorTemplatePropertyKey) {
265                    Set<String> langTypes = TemplateManagerUtil.getTemplateManagerNames();
266    
267                    for (String langType : langTypes) {
268                            String errorTemplateId = getErrorTemplateId(
269                                    errorTemplatePropertyKey, langType);
270    
271                            if (Validator.isNotNull(errorTemplateId)) {
272                                    errorTemplateIds.put(langType, errorTemplateId);
273                            }
274                    }
275            }
276    
277            protected void setTransformerListeners(
278                    String transformerListenerPropertyKey, ClassLoader classLoader) {
279    
280                    Set<String> transformerListenerClassNames = SetUtil.fromArray(
281                            PropsUtil.getArray(transformerListenerPropertyKey));
282    
283                    for (String transformerListenerClassName :
284                                    transformerListenerClassNames) {
285    
286                            try {
287                                    if (_log.isDebugEnabled()) {
288                                            _log.debug(
289                                                    "Instantiating transformer listener " +
290                                                            transformerListenerClassName);
291                                    }
292    
293                                    TransformerListener transformerListener =
294                                            (TransformerListener)InstanceFactory.newInstance(
295                                                    classLoader, transformerListenerClassName);
296    
297                                    transformerListeners.add(transformerListener);
298                            }
299                            catch (Exception e) {
300                                    _log.error(e, e);
301                            }
302                    }
303            }
304    
305            protected final Map<String, String> errorTemplateIds = new HashMap<>();
306            protected final Set<TransformerListener> transformerListeners =
307                    new HashSet<>();
308    
309            private static final Log _log = LogFactoryUtil.getLog(Transformer.class);
310    
311            private final boolean _restricted;
312    
313    }