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                    _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                            long classNameId = 0;
113    
114                            if (contextObjects != null) {
115                                    for (String key : contextObjects.keySet()) {
116                                            template.put(key, contextObjects.get(key));
117                                    }
118    
119                                    classNameId = GetterUtil.getLong(
120                                            contextObjects.get(TemplateConstants.CLASS_NAME_ID));
121                            }
122    
123                            template.put("company", getCompany(themeDisplay, companyId));
124                            template.put("companyId", companyId);
125                            template.put("device", getDevice(themeDisplay));
126    
127                            String templatesPath = getTemplatesPath(
128                                    companyId, scopeGroupId, classNameId);
129    
130                            template.put(
131                                    "permissionChecker",
132                                    PermissionThreadLocal.getPermissionChecker());
133                            template.put(
134                                    "randomNamespace",
135                                    StringUtil.randomId() + StringPool.UNDERLINE);
136                            template.put("scopeGroupId", scopeGroupId);
137                            template.put("siteGroupId", siteGroupId);
138                            template.put("templatesPath", templatesPath);
139    
140                            // Deprecated variables
141    
142                            template.put("groupId", scopeGroupId);
143                            template.put("journalTemplatesPath", templatesPath);
144    
145                            mergeTemplate(template, unsyncStringWriter, false);
146                    }
147                    catch (Exception e) {
148                            throw new TransformException("Unhandled exception", e);
149                    }
150    
151                    return unsyncStringWriter.toString();
152            }
153    
154            protected Company getCompany(ThemeDisplay themeDisplay, long companyId)
155                    throws Exception {
156    
157                    if (themeDisplay != null) {
158                            return themeDisplay.getCompany();
159                    }
160    
161                    return CompanyLocalServiceUtil.getCompany(companyId);
162            }
163    
164            protected Device getDevice(ThemeDisplay themeDisplay) {
165                    if (themeDisplay != null) {
166                            return themeDisplay.getDevice();
167                    }
168    
169                    return UnknownDevice.getInstance();
170            }
171    
172            protected String getErrorTemplateId(
173                    String errorTemplatePropertyKey, String langType) {
174    
175                    return PropsUtil.get(errorTemplatePropertyKey, new Filter(langType));
176            }
177    
178            protected TemplateResource getErrorTemplateResource(String langType) {
179                    try {
180                            Class<?> clazz = getClass();
181    
182                            ClassLoader classLoader = clazz.getClassLoader();
183    
184                            String errorTemplateId = errorTemplateIds.get(langType);
185    
186                            URL url = classLoader.getResource(errorTemplateId);
187    
188                            return new URLTemplateResource(errorTemplateId, url);
189                    }
190                    catch (Exception e) {
191                    }
192    
193                    return null;
194            }
195    
196            protected Template getTemplate(
197                            String templateId, String script, String langType)
198                    throws Exception {
199    
200                    TemplateResource templateResource = new StringTemplateResource(
201                            templateId, script);
202    
203                    TemplateResource errorTemplateResource = getErrorTemplateResource(
204                            langType);
205    
206                    return TemplateManagerUtil.getTemplate(
207                            langType, templateResource, errorTemplateResource, _restricted);
208            }
209    
210            protected String getTemplateId(
211                    String templateId, long companyId, long companyGroupId, long groupId) {
212    
213                    StringBundler sb = new StringBundler(5);
214    
215                    sb.append(companyId);
216                    sb.append(StringPool.POUND);
217    
218                    if (companyGroupId > 0) {
219                            sb.append(companyGroupId);
220                    }
221                    else {
222                            sb.append(groupId);
223                    }
224    
225                    sb.append(StringPool.POUND);
226                    sb.append(templateId);
227    
228                    return sb.toString();
229            }
230    
231            protected String getTemplatesPath(
232                    long companyId, long groupId, long classNameId) {
233    
234                    StringBundler sb = new StringBundler(7);
235    
236                    sb.append(TemplateConstants.TEMPLATE_SEPARATOR);
237                    sb.append(StringPool.SLASH);
238                    sb.append(companyId);
239                    sb.append(StringPool.SLASH);
240                    sb.append(groupId);
241                    sb.append(StringPool.SLASH);
242                    sb.append(classNameId);
243    
244                    return sb.toString();
245            }
246    
247            protected void mergeTemplate(
248                            Template template, UnsyncStringWriter unsyncStringWriter,
249                            boolean propagateException)
250                    throws Exception {
251    
252                    if (propagateException) {
253                            template.doProcessTemplate(unsyncStringWriter);
254                    }
255                    else {
256                            template.processTemplate(unsyncStringWriter);
257                    }
258            }
259    
260            protected void prepareTemplate(ThemeDisplay themeDisplay, Template template)
261                    throws Exception {
262    
263                    if (themeDisplay == null) {
264                            return;
265                    }
266    
267                    template.prepare(themeDisplay.getRequest());
268            }
269    
270            protected void setErrorTemplateIds(String errorTemplatePropertyKey) {
271                    Set<String> langTypes = TemplateManagerUtil.getTemplateManagerNames();
272    
273                    for (String langType : langTypes) {
274                            String errorTemplateId = getErrorTemplateId(
275                                    errorTemplatePropertyKey, langType);
276    
277                            if (Validator.isNotNull(errorTemplateId)) {
278                                    errorTemplateIds.put(langType, errorTemplateId);
279                            }
280                    }
281            }
282    
283            protected void setTransformerListeners(
284                    String transformerListenerPropertyKey, ClassLoader classLoader) {
285    
286                    Set<String> transformerListenerClassNames = SetUtil.fromArray(
287                            PropsUtil.getArray(transformerListenerPropertyKey));
288    
289                    for (String transformerListenerClassName :
290                                    transformerListenerClassNames) {
291    
292                            try {
293                                    if (_log.isDebugEnabled()) {
294                                            _log.debug(
295                                                    "Instantiating transformer listener " +
296                                                            transformerListenerClassName);
297                                    }
298    
299                                    TransformerListener transformerListener =
300                                            (TransformerListener)InstanceFactory.newInstance(
301                                                    classLoader, transformerListenerClassName);
302    
303                                    transformerListeners.add(transformerListener);
304                            }
305                            catch (Exception e) {
306                                    _log.error(e, e);
307                            }
308                    }
309            }
310    
311            protected final Map<String, String> errorTemplateIds = new HashMap<>();
312            protected final Set<TransformerListener> transformerListeners =
313                    new HashSet<>();
314    
315            private static final Log _log = LogFactoryUtil.getLog(Transformer.class);
316    
317            private final boolean _restricted;
318    
319    }