/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.portlet.display.template.internal; import com.liferay.dynamic.data.mapping.exception.NoSuchTemplateException; import com.liferay.dynamic.data.mapping.model.DDMTemplate; import com.liferay.dynamic.data.mapping.service.DDMTemplateLocalService; import com.liferay.portal.kernel.bean.ClassLoaderBeanHandler; import com.liferay.portal.kernel.exception.PortalException; import com.liferay.portal.kernel.io.unsync.UnsyncStringWriter; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.model.Group; import com.liferay.portal.kernel.portlet.PortletURLUtil; import com.liferay.portal.kernel.portletdisplaytemplate.BasePortletDisplayTemplateHandler; import com.liferay.portal.kernel.security.pacl.DoPrivileged; import com.liferay.portal.kernel.service.GroupLocalService; import com.liferay.portal.kernel.template.TemplateConstants; import com.liferay.portal.kernel.template.TemplateHandler; import com.liferay.portal.kernel.template.TemplateHandlerRegistryUtil; import com.liferay.portal.kernel.template.TemplateManager; import com.liferay.portal.kernel.template.TemplateManagerUtil; import com.liferay.portal.kernel.template.TemplateVariableGroup; import com.liferay.portal.kernel.theme.ThemeDisplay; import com.liferay.portal.kernel.util.ArrayUtil; import com.liferay.portal.kernel.util.JavaConstants; import com.liferay.portal.kernel.util.PortletKeys; import com.liferay.portal.kernel.util.PropsKeys; import com.liferay.portal.kernel.util.ProxyUtil; import com.liferay.portal.kernel.util.Validator; import com.liferay.portal.kernel.util.WebKeys; import com.liferay.portal.templateparser.Transformer; import com.liferay.portlet.display.template.PortletDisplayTemplate; import com.liferay.portlet.display.template.PortletDisplayTemplateConstants; import com.liferay.taglib.servlet.PipingServletResponse; import com.liferay.taglib.util.VelocityTaglib; import java.lang.reflect.InvocationHandler; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; import javax.portlet.PortletPreferences; import javax.portlet.PortletURL; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; /** * @author Eduardo Garcia * @author Juan Fernández * @author Brian Wing Shun Chan * @author Raymond Augé * @author Leonardo Barros */ @Component(immediate = true) @DoPrivileged public class PortletDisplayTemplateImpl implements PortletDisplayTemplate { @Override public DDMTemplate fetchDDMTemplate(long groupId, String displayStyle) { try { Group group = _groupLocalService.getGroup(groupId); Group companyGroup = _groupLocalService.getCompanyGroup( group.getCompanyId()); String uuid = getDDMTemplateKey(displayStyle); if (Validator.isNull(uuid)) { return null; } try { return _ddmTemplateLocalService.getDDMTemplateByUuidAndGroupId( uuid, groupId); } catch (PortalException pe) { // LPS-52675 if (_log.isDebugEnabled()) { _log.debug(pe, pe); } } try { return _ddmTemplateLocalService.getDDMTemplateByUuidAndGroupId( uuid, companyGroup.getGroupId()); } catch (NoSuchTemplateException nste) { } } catch (Exception e) { if (_log.isWarnEnabled()) { _log.warn(e, e); } } return null; } @Override public long getDDMTemplateGroupId(long groupId) { Group group = _groupLocalService.fetchGroup(groupId); if (group == null) { return groupId; } try { if (group.isLayout()) { group = group.getParentGroup(); } if (group.isStagingGroup()) { Group liveGroup = group.getLiveGroup(); if (!liveGroup.isStagedPortlet( PortletKeys.PORTLET_DISPLAY_TEMPLATE)) { return liveGroup.getGroupId(); } } return group.getGroupId(); } catch (Exception e) { if (_log.isWarnEnabled()) { _log.warn(e, e); } } return groupId; } @Override public String getDDMTemplateKey(String displayStyle) { if (!displayStyle.startsWith(DISPLAY_STYLE_PREFIX)) { return null; } return displayStyle.substring(DISPLAY_STYLE_PREFIX.length()); } /** * @deprecated As of 2.0.0 */ @Deprecated @Override public String getDDMTemplateUuid(String displayStyle) { return getDDMTemplateKey(displayStyle); } @Override public DDMTemplate getDefaultPortletDisplayTemplateDDMTemplate( long groupId, long classNameId) { TemplateHandler templateHandler = TemplateHandlerRegistryUtil.getTemplateHandler(classNameId); if ((templateHandler == null) || (templateHandler.getDefaultTemplateKey() == null)) { return null; } return getPortletDisplayTemplateDDMTemplate( groupId, classNameId, getDisplayStyle(templateHandler.getDefaultTemplateKey())); } @Override public String getDisplayStyle(String ddmTemplateKey) { return DISPLAY_STYLE_PREFIX + ddmTemplateKey; } @Override public DDMTemplate getPortletDisplayTemplateDDMTemplate( long groupId, long classNameId, String displayStyle) { return getPortletDisplayTemplateDDMTemplate( groupId, classNameId, displayStyle, false); } @Override public DDMTemplate getPortletDisplayTemplateDDMTemplate( long groupId, long classNameId, String displayStyle, boolean useDefault) { long portletDisplayDDMTemplateGroupId = getDDMTemplateGroupId(groupId); DDMTemplate portletDisplayDDMTemplate = null; if (displayStyle.startsWith(DISPLAY_STYLE_PREFIX)) { String ddmTemplateKey = getDDMTemplateKey(displayStyle); if (Validator.isNotNull(ddmTemplateKey)) { try { portletDisplayDDMTemplate = _ddmTemplateLocalService.fetchTemplate( portletDisplayDDMTemplateGroupId, classNameId, ddmTemplateKey, true); } catch (PortalException pe) { // LPS-52675 if (_log.isDebugEnabled()) { _log.debug(pe, pe); } } } } if ((portletDisplayDDMTemplate == null) && useDefault) { portletDisplayDDMTemplate = getDefaultPortletDisplayTemplateDDMTemplate( groupId, classNameId); } return portletDisplayDDMTemplate; } /** * @deprecated As of 2.0.0 */ @Deprecated @Override public long getPortletDisplayTemplateDDMTemplateId( long groupId, String displayStyle) { long portletDisplayDDMTemplateId = 0; long portletDisplayDDMTemplateGroupId = getDDMTemplateGroupId(groupId); if (displayStyle.startsWith(DISPLAY_STYLE_PREFIX)) { DDMTemplate portletDisplayDDMTemplate = fetchDDMTemplate( portletDisplayDDMTemplateGroupId, displayStyle); if (portletDisplayDDMTemplate != null) { portletDisplayDDMTemplateId = portletDisplayDDMTemplate.getTemplateId(); } } return portletDisplayDDMTemplateId; } @Override public List<TemplateHandler> getPortletDisplayTemplateHandlers() { List<TemplateHandler> templateHandlers = TemplateHandlerRegistryUtil.getTemplateHandlers(); List<TemplateHandler> portletDisplayTemplateHandlers = new ArrayList<>(); for (TemplateHandler templateHandler : templateHandlers) { if (templateHandler instanceof BasePortletDisplayTemplateHandler) { portletDisplayTemplateHandlers.add(templateHandler); } else if (ProxyUtil.isProxyClass(templateHandler.getClass())) { InvocationHandler invocationHandler = ProxyUtil.getInvocationHandler(templateHandler); if (invocationHandler instanceof ClassLoaderBeanHandler) { ClassLoaderBeanHandler classLoaderBeanHandler = (ClassLoaderBeanHandler)invocationHandler; Object bean = classLoaderBeanHandler.getBean(); if (bean instanceof BasePortletDisplayTemplateHandler) { portletDisplayTemplateHandlers.add(templateHandler); } } } } return portletDisplayTemplateHandlers; } @Override public Map<String, TemplateVariableGroup> getTemplateVariableGroups( String language) { Map<String, TemplateVariableGroup> templateVariableGroups = new LinkedHashMap<>(); TemplateVariableGroup fieldsTemplateVariableGroup = new TemplateVariableGroup("fields"); fieldsTemplateVariableGroup.addCollectionVariable( "entries", List.class, PortletDisplayTemplateConstants.ENTRIES, "entries-item", null, "curEntry", null); fieldsTemplateVariableGroup.addVariable( "entry", null, PortletDisplayTemplateConstants.ENTRY); templateVariableGroups.put("fields", fieldsTemplateVariableGroup); TemplateVariableGroup generalVariablesTemplateVariableGroup = new TemplateVariableGroup("general-variables"); generalVariablesTemplateVariableGroup.addVariable( "current-url", String.class, PortletDisplayTemplateConstants.CURRENT_URL); generalVariablesTemplateVariableGroup.addVariable( "locale", Locale.class, PortletDisplayTemplateConstants.LOCALE); generalVariablesTemplateVariableGroup.addVariable( "portlet-preferences", Map.class, PortletDisplayTemplateConstants.PORTLET_PREFERENCES); generalVariablesTemplateVariableGroup.addVariable( "template-id", null, PortletDisplayTemplateConstants.TEMPLATE_ID); generalVariablesTemplateVariableGroup.addVariable( "theme-display", ThemeDisplay.class, PortletDisplayTemplateConstants.THEME_DISPLAY); templateVariableGroups.put( "general-variables", generalVariablesTemplateVariableGroup); TemplateVariableGroup utilTemplateVariableGroup = new TemplateVariableGroup("util"); utilTemplateVariableGroup.addVariable( "http-request", HttpServletRequest.class, PortletDisplayTemplateConstants.REQUEST); if (language.equals(TemplateConstants.LANG_TYPE_VM)) { utilTemplateVariableGroup.addVariable( "liferay-taglib", VelocityTaglib.class, PortletDisplayTemplateConstants.TAGLIB_LIFERAY); } utilTemplateVariableGroup.addVariable( "render-request", RenderRequest.class, PortletDisplayTemplateConstants.RENDER_REQUEST); utilTemplateVariableGroup.addVariable( "render-response", RenderResponse.class, PortletDisplayTemplateConstants.RENDER_RESPONSE); templateVariableGroups.put("util", utilTemplateVariableGroup); return templateVariableGroups; } @Override public String renderDDMTemplate( HttpServletRequest request, HttpServletResponse response, DDMTemplate ddmTemplate, List<?> entries) throws Exception { Map<String, Object> contextObjects = new HashMap<>(); return renderDDMTemplate( request, response, ddmTemplate, entries, contextObjects); } @Override public String renderDDMTemplate( HttpServletRequest request, HttpServletResponse response, DDMTemplate ddmTemplate, List<?> entries, Map<String, Object> contextObjects) throws Exception { Transformer transformer = TransformerHolder.getTransformer(); contextObjects.put( PortletDisplayTemplateConstants.TEMPLATE_ID, ddmTemplate.getTemplateId()); contextObjects.put(PortletDisplayTemplateConstants.ENTRIES, entries); if (!entries.isEmpty()) { contextObjects.put( PortletDisplayTemplateConstants.ENTRY, entries.get(0)); } contextObjects.put( PortletDisplayTemplateConstants.LOCALE, request.getLocale()); RenderRequest renderRequest = (RenderRequest)request.getAttribute( JavaConstants.JAVAX_PORTLET_REQUEST); contextObjects.put( PortletDisplayTemplateConstants.RENDER_REQUEST, renderRequest); RenderResponse renderResponse = (RenderResponse)request.getAttribute( JavaConstants.JAVAX_PORTLET_RESPONSE); contextObjects.put( PortletDisplayTemplateConstants.RENDER_RESPONSE, renderResponse); if ((renderRequest != null) && (renderResponse != null)) { PortletURL currentURL = PortletURLUtil.getCurrent( renderRequest, renderResponse); contextObjects.put( PortletDisplayTemplateConstants.CURRENT_URL, currentURL.toString()); } ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute( WebKeys.THEME_DISPLAY); contextObjects.put( PortletDisplayTemplateConstants.THEME_DISPLAY, themeDisplay); // Custom context objects contextObjects.put( TemplateConstants.CLASS_NAME_ID, ddmTemplate.getClassNameId()); String language = ddmTemplate.getLanguage(); TemplateManager templateManager = TemplateManagerUtil.getTemplateManager(language); TemplateHandler templateHandler = TemplateHandlerRegistryUtil.getTemplateHandler( ddmTemplate.getClassNameId()); templateManager.addContextObjects( contextObjects, templateHandler.getCustomContextObjects()); // Taglibs templateManager.addTaglibSupport(contextObjects, request, response); UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter(); templateManager.addTaglibTheme( contextObjects, "taglibLiferay", request, new PipingServletResponse(response, unsyncStringWriter)); contextObjects.put(TemplateConstants.WRITER, unsyncStringWriter); if (renderRequest != null) { _mergePortletPreferences(renderRequest, contextObjects); } return transformer.transform( themeDisplay, contextObjects, ddmTemplate.getScript(), language, unsyncStringWriter); } @Override public String renderDDMTemplate( HttpServletRequest request, HttpServletResponse response, long ddmTemplateId, List<?> entries) throws Exception { Map<String, Object> contextObjects = new HashMap<>(); return renderDDMTemplate( request, response, ddmTemplateId, entries, contextObjects); } @Override public String renderDDMTemplate( HttpServletRequest request, HttpServletResponse response, long ddmTemplateId, List<?> entries, Map<String, Object> contextObjects) throws Exception { DDMTemplate ddmTemplate = _ddmTemplateLocalService.getTemplate( ddmTemplateId); return renderDDMTemplate( request, response, ddmTemplate, entries, contextObjects); } @Reference(unbind = "-") protected void setDDMTemplateLocalService( DDMTemplateLocalService ddmTemplateLocalService) { _ddmTemplateLocalService = ddmTemplateLocalService; } @Reference(unbind = "-") protected void setGroupLocalService(GroupLocalService groupLocalService) { _groupLocalService = groupLocalService; } private Map<String, Object> _mergePortletPreferences( RenderRequest renderRequest, Map<String, Object> contextObjects) { PortletPreferences portletPreferences = renderRequest.getPreferences(); Map<String, String[]> map = portletPreferences.getMap(); contextObjects.put( PortletDisplayTemplateConstants.PORTLET_PREFERENCES, map); for (Map.Entry<String, String[]> entry : map.entrySet()) { if (contextObjects.containsKey(entry.getKey())) { continue; } String[] values = entry.getValue(); if (ArrayUtil.isEmpty(values)) { continue; } String value = values[0]; if (value == null) { continue; } contextObjects.put(entry.getKey(), value); } return contextObjects; } private static final Log _log = LogFactoryUtil.getLog( PortletDisplayTemplateImpl.class); private DDMTemplateLocalService _ddmTemplateLocalService; private GroupLocalService _groupLocalService; private static class TransformerHolder { public static Transformer getTransformer() { return _transformer; } private static final Transformer _transformer = new Transformer( PropsKeys.PORTLET_DISPLAY_TEMPLATES_ERROR, true); } }