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