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