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