001    /**
002     * Copyright (c) 2000-2013 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.portlet.portletdisplaytemplate.util;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.security.pacl.DoPrivileged;
020    import com.liferay.portal.kernel.servlet.GenericServletWrapper;
021    import com.liferay.portal.kernel.servlet.PipingServletResponse;
022    import com.liferay.portal.kernel.template.TemplateConstants;
023    import com.liferay.portal.kernel.template.TemplateContextType;
024    import com.liferay.portal.kernel.template.TemplateVariableGroup;
025    import com.liferay.portal.kernel.util.JavaConstants;
026    import com.liferay.portal.kernel.util.PropsKeys;
027    import com.liferay.portal.kernel.util.Validator;
028    import com.liferay.portal.kernel.util.WebKeys;
029    import com.liferay.portal.model.Group;
030    import com.liferay.portal.service.GroupLocalServiceUtil;
031    import com.liferay.portal.templateparser.Transformer;
032    import com.liferay.portal.theme.ThemeDisplay;
033    import com.liferay.portal.util.PortletKeys;
034    import com.liferay.portlet.PortletURLUtil;
035    import com.liferay.portlet.dynamicdatamapping.NoSuchTemplateException;
036    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
037    import com.liferay.portlet.dynamicdatamapping.service.DDMTemplateLocalServiceUtil;
038    import com.liferay.taglib.util.VelocityTaglib;
039    import com.liferay.taglib.util.VelocityTaglibImpl;
040    import com.liferay.util.freemarker.FreeMarkerTaglibFactoryUtil;
041    
042    import freemarker.ext.servlet.HttpRequestHashModel;
043    import freemarker.ext.servlet.ServletContextHashModel;
044    
045    import freemarker.template.ObjectWrapper;
046    import freemarker.template.TemplateHashModel;
047    
048    import java.util.HashMap;
049    import java.util.LinkedHashMap;
050    import java.util.List;
051    import java.util.Locale;
052    import java.util.Map;
053    
054    import javax.portlet.PortletPreferences;
055    import javax.portlet.PortletURL;
056    import javax.portlet.RenderRequest;
057    import javax.portlet.RenderResponse;
058    
059    import javax.servlet.GenericServlet;
060    import javax.servlet.Servlet;
061    import javax.servlet.ServletContext;
062    import javax.servlet.http.HttpServletRequest;
063    import javax.servlet.http.HttpServletResponse;
064    import javax.servlet.http.HttpSession;
065    import javax.servlet.jsp.PageContext;
066    
067    /**
068     * @author Eduardo Garcia
069     * @author Juan Fernández
070     * @author Brian Wing Shun Chan
071     */
072    @DoPrivileged
073    public class PortletDisplayTemplateImpl implements PortletDisplayTemplate {
074    
075            public DDMTemplate fetchDDMTemplate(long groupId, String displayStyle) {
076                    try {
077                            Group group = GroupLocalServiceUtil.getGroup(groupId);
078    
079                            Group companyGroup = GroupLocalServiceUtil.getCompanyGroup(
080                                    group.getCompanyId());
081    
082                            if (!displayStyle.startsWith("ddmTemplate_")) {
083                                    return null;
084                            }
085    
086                            String uuid = displayStyle.substring(12);
087    
088                            if (Validator.isNull(uuid)) {
089                                    return null;
090                            }
091    
092                            try {
093                                    return
094                                            DDMTemplateLocalServiceUtil.getDDMTemplateByUuidAndGroupId(
095                                                    uuid, groupId);
096                            }
097                            catch (NoSuchTemplateException nste) {
098                            }
099    
100                            try {
101                                    return
102                                            DDMTemplateLocalServiceUtil.getDDMTemplateByUuidAndGroupId(
103                                                    uuid, companyGroup.getGroupId());
104                            }
105                            catch (NoSuchTemplateException nste) {
106                            }
107                    }
108                    catch (Exception e) {
109                            if (_log.isWarnEnabled()) {
110                                    _log.warn(e, e);
111                            }
112                    }
113    
114                    return null;
115            }
116    
117            public long getDDMTemplateGroupId(ThemeDisplay themeDisplay) {
118                    try {
119                            Group scopeGroup = themeDisplay.getScopeGroup();
120    
121                            if (scopeGroup.isLayout()) {
122                                    scopeGroup = scopeGroup.getParentGroup();
123                            }
124    
125                            if (scopeGroup.isStagingGroup()) {
126                                    Group liveGroup = scopeGroup.getLiveGroup();
127    
128                                    if (!liveGroup.isStagedPortlet(
129                                                    PortletKeys.PORTLET_DISPLAY_TEMPLATES)) {
130    
131                                            return liveGroup.getGroupId();
132                                    }
133                            }
134    
135                            return scopeGroup.getGroupId();
136                    }
137                    catch (Exception e) {
138                            if (_log.isWarnEnabled()) {
139                                    _log.warn(e, e);
140                            }
141                    }
142    
143                    return themeDisplay.getScopeGroupId();
144            }
145    
146            public long getPortletDisplayTemplateDDMTemplateId(
147                    ThemeDisplay themeDisplay, String displayStyle) {
148    
149                    long portletDisplayDDMTemplateId = 0;
150    
151                    long portletDisplayDDMTemplateGroupId = getDDMTemplateGroupId(
152                            themeDisplay);
153    
154                    if (displayStyle.startsWith("ddmTemplate_")) {
155                            DDMTemplate portletDisplayDDMTemplate = fetchDDMTemplate(
156                                    portletDisplayDDMTemplateGroupId, displayStyle);
157    
158                            if (portletDisplayDDMTemplate != null) {
159                                    portletDisplayDDMTemplateId =
160                                            portletDisplayDDMTemplate.getTemplateId();
161                            }
162                    }
163    
164                    return portletDisplayDDMTemplateId;
165            }
166    
167            public Map<String, TemplateVariableGroup> getTemplateVariableGroups() {
168                    Map<String, TemplateVariableGroup> templateVariableGroups =
169                            new LinkedHashMap<String, TemplateVariableGroup>();
170    
171                    TemplateVariableGroup fieldsTemplateVariableGroup =
172                            new TemplateVariableGroup("fields");
173    
174                    fieldsTemplateVariableGroup.addCollectionVariable(
175                            "entries", List.class, PortletDisplayTemplateConstants.ENTRIES,
176                            "entries-item", null, "curEntry");
177                    fieldsTemplateVariableGroup.addVariable(
178                            "entry", null, PortletDisplayTemplateConstants.ENTRY);
179    
180                    templateVariableGroups.put("fields", fieldsTemplateVariableGroup);
181    
182                    TemplateVariableGroup generalVariablesTemplateVariableGroup =
183                            new TemplateVariableGroup("general-variables");
184    
185                    generalVariablesTemplateVariableGroup.addVariable(
186                            "current-url", String.class,
187                            PortletDisplayTemplateConstants.CURRENT_URL);
188                    generalVariablesTemplateVariableGroup.addVariable(
189                            "locale", Locale.class, PortletDisplayTemplateConstants.LOCALE);
190                    generalVariablesTemplateVariableGroup.addVariable(
191                            "portlet-preferences", Map.class,
192                            PortletDisplayTemplateConstants.PORTLET_PREFERENCES);
193                    generalVariablesTemplateVariableGroup.addVariable(
194                            "template-id", null,
195                            PortletDisplayTemplateConstants.DDM_TEMPLATE_ID);
196                    generalVariablesTemplateVariableGroup.addVariable(
197                            "theme-display", ThemeDisplay.class,
198                            PortletDisplayTemplateConstants.THEME_DISPLAY);
199    
200                    templateVariableGroups.put(
201                            "general-variables", generalVariablesTemplateVariableGroup);
202    
203                    TemplateVariableGroup utilTemplateVariableGroup =
204                            new TemplateVariableGroup("util");
205    
206                    utilTemplateVariableGroup.addVariable(
207                            "http-request", HttpServletRequest.class,
208                            PortletDisplayTemplateConstants.REQUEST);
209                    utilTemplateVariableGroup.addVariable(
210                            "liferay-taglib", VelocityTaglib.class,
211                            PortletDisplayTemplateConstants.TAGLIB_LIFERAY);
212                    utilTemplateVariableGroup.addVariable(
213                            "render-request", RenderRequest.class,
214                            PortletDisplayTemplateConstants.RENDER_REQUEST);
215                    utilTemplateVariableGroup.addVariable(
216                            "render-response", RenderResponse.class,
217                            PortletDisplayTemplateConstants.RENDER_RESPONSE);
218    
219                    templateVariableGroups.put("util", utilTemplateVariableGroup);
220    
221                    return templateVariableGroups;
222            }
223    
224            public String renderDDMTemplate(
225                            PageContext pageContext, long ddmTemplateId, List<?> entries)
226                    throws Exception {
227    
228                    Map<String, Object> contextObjects = new HashMap<String, Object>();
229    
230                    return renderDDMTemplate(
231                            pageContext, ddmTemplateId, entries, contextObjects);
232            }
233    
234            public String renderDDMTemplate(
235                            PageContext pageContext, long ddmTemplateId, List<?> entries,
236                            Map<String, Object> contextObjects)
237                    throws Exception {
238    
239                    contextObjects.put(
240                            PortletDisplayTemplateConstants.DDM_TEMPLATE_ID, ddmTemplateId);
241                    contextObjects.put(PortletDisplayTemplateConstants.ENTRIES, entries);
242    
243                    if (!entries.isEmpty()) {
244                            contextObjects.put(
245                                    PortletDisplayTemplateConstants.ENTRY, entries.get(0));
246                    }
247    
248                    HttpServletRequest request =
249                            (HttpServletRequest)pageContext.getRequest();
250    
251                    contextObjects.put(
252                            PortletDisplayTemplateConstants.LOCALE, request.getLocale());
253    
254                    contextObjects.put(PortletDisplayTemplateConstants.REQUEST, request);
255    
256                    RenderRequest renderRequest = (RenderRequest)request.getAttribute(
257                            JavaConstants.JAVAX_PORTLET_REQUEST);
258    
259                    contextObjects.put(
260                            PortletDisplayTemplateConstants.RENDER_REQUEST, renderRequest);
261    
262                    RenderResponse renderResponse = (RenderResponse)request.getAttribute(
263                            JavaConstants.JAVAX_PORTLET_RESPONSE);
264    
265                    contextObjects.put(
266                            PortletDisplayTemplateConstants.RENDER_RESPONSE, renderResponse);
267    
268                    PortletURL currentURL = PortletURLUtil.getCurrent(
269                            renderRequest, renderResponse);
270    
271                    contextObjects.put(
272                            PortletDisplayTemplateConstants.CURRENT_URL, currentURL.toString());
273    
274                    ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.getAttribute(
275                            WebKeys.THEME_DISPLAY);
276    
277                    contextObjects.put(
278                            PortletDisplayTemplateConstants.THEME_DISPLAY, themeDisplay);
279    
280                    // Taglibs
281    
282                    DDMTemplate ddmTemplate = DDMTemplateLocalServiceUtil.getTemplate(
283                            ddmTemplateId);
284    
285                    String language = ddmTemplate.getLanguage();
286    
287                    if (language.equals(TemplateConstants.LANG_TYPE_FTL)) {
288                            _addTaglibSupportFTL(contextObjects, pageContext);
289                    }
290                    else if (language.equals(TemplateConstants.LANG_TYPE_VM)) {
291                            _addTaglibSupportVM(contextObjects, pageContext);
292                    }
293    
294                    contextObjects.putAll(_getPortletPreferences(renderRequest));
295    
296                    return _transformer.transform(
297                            themeDisplay, contextObjects, ddmTemplate.getScript(), language);
298            }
299    
300            private void _addTaglibSupportFTL(
301                            Map<String, Object> contextObjects, PageContext pageContext)
302                    throws Exception {
303    
304                    // FreeMarker servlet application
305    
306                    final Servlet servlet = (Servlet)pageContext.getPage();
307    
308                    GenericServlet genericServlet = null;
309    
310                    if (servlet instanceof GenericServlet) {
311                            genericServlet = (GenericServlet)servlet;
312                    }
313                    else {
314                            genericServlet = new GenericServletWrapper(servlet);
315    
316                            genericServlet.init(pageContext.getServletConfig());
317                    }
318    
319                    ServletContextHashModel servletContextHashModel =
320                            new ServletContextHashModel(
321                                    genericServlet, ObjectWrapper.DEFAULT_WRAPPER);
322    
323                    contextObjects.put(
324                            PortletDisplayTemplateConstants.FREEMARKER_SERVLET_APPLICATION,
325                            servletContextHashModel);
326    
327                    // FreeMarker servlet request
328    
329                    HttpServletRequest request =
330                            (HttpServletRequest)pageContext.getRequest();
331                    HttpServletResponse response =
332                            (HttpServletResponse)pageContext.getResponse();
333    
334                    HttpRequestHashModel requestHashModel = new HttpRequestHashModel(
335                            request, response, ObjectWrapper.DEFAULT_WRAPPER);
336    
337                    contextObjects.put(
338                            PortletDisplayTemplateConstants.FREEMARKER_SERVLET_REQUEST,
339                            requestHashModel);
340    
341                    // Taglib Liferay hash
342    
343                    TemplateHashModel taglibLiferayHash =
344                            FreeMarkerTaglibFactoryUtil.createTaglibFactory(
345                                    pageContext.getServletContext());
346    
347                    contextObjects.put(
348                            PortletDisplayTemplateConstants.TAGLIB_LIFERAY_HASH,
349                            taglibLiferayHash);
350            }
351    
352            private void _addTaglibSupportVM(
353                    Map<String, Object> contextObjects, PageContext pageContext) {
354    
355                    contextObjects.put(
356                            PortletDisplayTemplateConstants.TAGLIB_LIFERAY,
357                            _getVelocityTaglib(pageContext));
358            }
359    
360            private Map<String, Object> _getPortletPreferences(
361                    RenderRequest renderRequest) {
362    
363                    Map<String, Object> contextObjects = new HashMap<String, Object>();
364    
365                    PortletPreferences portletPreferences = renderRequest.getPreferences();
366    
367                    Map<String, String[]> map = portletPreferences.getMap();
368    
369                    contextObjects.put(
370                            PortletDisplayTemplateConstants.PORTLET_PREFERENCES, map);
371    
372                    for (Map.Entry<String, String[]> entry : map.entrySet()) {
373                            String[] values = entry.getValue();
374    
375                            if ((values == null) || (values.length == 0)) {
376                                    continue;
377                            }
378    
379                            String value = values[0];
380    
381                            if (value == null) {
382                                    continue;
383                            }
384    
385                            contextObjects.put(entry.getKey(), value);
386                    }
387    
388                    return contextObjects;
389            }
390    
391            private VelocityTaglib _getVelocityTaglib(PageContext pageContext) {
392                    HttpServletRequest request =
393                            (HttpServletRequest)pageContext.getRequest();
394    
395                    HttpSession session = request.getSession();
396    
397                    ServletContext servletContext = session.getServletContext();
398    
399                    HttpServletResponse response =
400                            (HttpServletResponse)pageContext.getResponse();
401    
402                    VelocityTaglib velocityTaglib = new VelocityTaglibImpl(
403                            servletContext, request,
404                            new PipingServletResponse(response, pageContext.getOut()),
405                            pageContext, null);
406    
407                    return velocityTaglib;
408            }
409    
410            private static Log _log = LogFactoryUtil.getLog(
411                    PortletDisplayTemplateImpl.class);
412    
413            private Transformer _transformer = new Transformer(
414                    PropsKeys.DYNAMIC_DATA_LISTS_TRANSFORMER_LISTENER,
415                    PropsKeys.DYNAMIC_DATA_LISTS_ERROR_TEMPLATE,
416                    TemplateContextType.STANDARD);
417    
418    }