All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.liferay.journal.internal.util.JournalContentImpl Maven / Gradle / Ivy

There is a newer version: 7.0.162
Show newest version
/**
 * SPDX-FileCopyrightText: (c) 2000 Liferay, Inc. https://liferay.com
 * SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
 */

package com.liferay.journal.internal.util;

import com.liferay.change.tracking.spi.listener.CTEventListener;
import com.liferay.exportimport.kernel.lar.ExportImportThreadLocal;
import com.liferay.journal.model.JournalArticle;
import com.liferay.journal.model.JournalArticleDisplay;
import com.liferay.journal.service.JournalArticleLocalService;
import com.liferay.journal.util.JournalContent;
import com.liferay.petra.lang.HashUtil;
import com.liferay.petra.string.StringBundler;
import com.liferay.petra.string.StringPool;
import com.liferay.portal.kernel.cache.MultiVMPool;
import com.liferay.portal.kernel.cache.PortalCache;
import com.liferay.portal.kernel.cache.index.IndexEncoder;
import com.liferay.portal.kernel.cache.index.PortalCacheIndexer;
import com.liferay.portal.kernel.change.tracking.CTCollectionThreadLocal;
import com.liferay.portal.kernel.cluster.ClusterExecutorUtil;
import com.liferay.portal.kernel.cluster.ClusterInvokeThreadLocal;
import com.liferay.portal.kernel.cluster.ClusterRequest;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.LayoutSet;
import com.liferay.portal.kernel.portlet.PortletRequestModel;
import com.liferay.portal.kernel.security.permission.ActionKeys;
import com.liferay.portal.kernel.security.permission.resource.ModelResourcePermission;
import com.liferay.portal.kernel.service.ServiceContext;
import com.liferay.portal.kernel.service.ServiceContextThreadLocal;
import com.liferay.portal.kernel.theme.ThemeDisplay;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.MethodHandler;
import com.liferay.portal.kernel.util.MethodKey;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.workflow.WorkflowConstants;

import java.io.Serializable;

import java.util.Date;
import java.util.Objects;

import javax.portlet.RenderRequest;

import org.apache.commons.lang.time.StopWatch;

import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;

/**
 * @author Brian Wing Shun Chan
 * @author Raymond Augé
 * @author Michael Young
 */
@Component(service = JournalContent.class)
public class JournalContentImpl implements JournalContent {

	@Override
	public void clearCache() {
		if (ExportImportThreadLocal.isImportInProcess()) {
			return;
		}

		_portalCache.removeAll();
	}

	@Override
	public void clearCache(
		long groupId, String articleId, String ddmTemplateKey) {

		_clearCache(groupId, articleId, ddmTemplateKey);

		if (ClusterInvokeThreadLocal.isEnabled()) {
			ClusterRequest clusterRequest =
				ClusterRequest.createMulticastRequest(
					new MethodHandler(
						_clearArticleCacheMethodKey, groupId, articleId,
						ddmTemplateKey),
					true);

			clusterRequest.setFireAndForget(true);

			ClusterExecutorUtil.execute(clusterRequest);
		}
	}

	@Override
	public void clearCache(String ddmTemplateKey) {
		_clearCache(ddmTemplateKey);

		if (ClusterInvokeThreadLocal.isEnabled()) {
			ClusterRequest clusterRequest =
				ClusterRequest.createMulticastRequest(
					new MethodHandler(
						_clearTemplateCacheMethodKey, ddmTemplateKey),
					true);

			clusterRequest.setFireAndForget(true);

			ClusterExecutorUtil.execute(clusterRequest);
		}
	}

	@Override
	public String getContent(
		long groupId, String articleId, String viewMode, String languageId) {

		return getContent(
			groupId, articleId, null, viewMode, languageId, null,
			_getDefaultThemeDisplay());
	}

	@Override
	public String getContent(
		long groupId, String articleId, String viewMode, String languageId,
		PortletRequestModel portletRequestModel) {

		return getContent(
			groupId, articleId, null, viewMode, languageId, portletRequestModel,
			_getDefaultThemeDisplay());
	}

	@Override
	public String getContent(
		long groupId, String articleId, String ddmTemplateKey, String viewMode,
		String languageId, PortletRequestModel portletRequestModel) {

		return getContent(
			groupId, articleId, ddmTemplateKey, viewMode, languageId,
			portletRequestModel, _getDefaultThemeDisplay());
	}

	@Override
	public String getContent(
		long groupId, String articleId, String ddmTemplateKey, String viewMode,
		String languageId, PortletRequestModel portletRequestModel,
		ThemeDisplay themeDisplay) {

		JournalArticleDisplay articleDisplay = getDisplay(
			groupId, articleId, ddmTemplateKey, viewMode, languageId, 1,
			portletRequestModel, themeDisplay);

		if (articleDisplay != null) {
			return articleDisplay.getContent();
		}

		return null;
	}

	@Override
	public String getContent(
		long groupId, String articleId, String ddmTemplateKey, String viewMode,
		String languageId, ThemeDisplay themeDisplay) {

		return getContent(
			groupId, articleId, ddmTemplateKey, viewMode, languageId,
			(PortletRequestModel)null, themeDisplay);
	}

	@Override
	public String getContent(
		long groupId, String articleId, String viewMode, String languageId,
		ThemeDisplay themeDisplay) {

		return getContent(
			groupId, articleId, null, viewMode, languageId, themeDisplay);
	}

	@Override
	public JournalArticleDisplay getDisplay(
		JournalArticle article, String ddmTemplateKey, String viewMode,
		String languageId, int page, PortletRequestModel portletRequestModel,
		ThemeDisplay themeDisplay) {

		StopWatch stopWatch = new StopWatch();

		stopWatch.start();

		long groupId = article.getGroupId();
		String articleId = article.getArticleId();
		double version = article.getVersion();

		articleId = StringUtil.toUpperCase(GetterUtil.getString(articleId));
		ddmTemplateKey = StringUtil.toUpperCase(
			GetterUtil.getString(ddmTemplateKey));

		long layoutSetId = 0;
		boolean lifecycleRender = false;
		boolean secure = false;

		if (portletRequestModel != null) {
			lifecycleRender = RenderRequest.RENDER_PHASE.equals(
				portletRequestModel.getLifecycle());
		}

		if (themeDisplay != null) {
			try {
				if (!_journalArticleModelResourcePermission.contains(
						themeDisplay.getPermissionChecker(), article,
						ActionKeys.VIEW)) {

					return null;
				}
			}
			catch (Exception exception) {
				if (_log.isDebugEnabled()) {
					_log.debug(exception);
				}
			}

			LayoutSet layoutSet = themeDisplay.getLayoutSet();

			layoutSetId = layoutSet.getLayoutSetId();

			if (portletRequestModel == null) {
				lifecycleRender = themeDisplay.isLifecycleRender();
			}

			secure = themeDisplay.isSecure();
		}

		if (Validator.isNull(ddmTemplateKey)) {
			ddmTemplateKey = article.getDDMTemplateKey();
		}

		JournalContentKey journalContentKey = new JournalContentKey(
			groupId, articleId, version, ddmTemplateKey, layoutSetId, viewMode,
			languageId, page, secure);

		JournalArticleDisplay articleDisplay = null;

		boolean productionMode = CTCollectionThreadLocal.isProductionMode();

		if (productionMode) {
			articleDisplay = _portalCache.get(journalContentKey);
		}

		if ((articleDisplay == null) || !lifecycleRender) {
			articleDisplay = getArticleDisplay(
				article, ddmTemplateKey, viewMode, languageId, page,
				portletRequestModel, themeDisplay);

			if ((articleDisplay != null) && articleDisplay.isCacheable() &&
				lifecycleRender) {

				try {
					if (productionMode) {
						_portalCache.put(journalContentKey, articleDisplay);
					}
				}
				catch (ClassCastException classCastException) {
					if (_log.isWarnEnabled()) {
						_log.warn(
							"Unable to cache article display",
							classCastException);
					}
				}
			}
		}

		if (_log.isDebugEnabled()) {
			_log.debug(
				StringBundler.concat(
					"getDisplay for {", groupId, ", ", articleId, ", ",
					ddmTemplateKey, ", ", viewMode, ", ", languageId, ", ",
					page, "} takes ", stopWatch.getTime(), " ms"));
		}

		return articleDisplay;
	}

	@Override
	public JournalArticleDisplay getDisplay(
		long groupId, String articleId, double version, String ddmTemplateKey,
		String viewMode, String languageId, int page,
		PortletRequestModel portletRequestModel, ThemeDisplay themeDisplay) {

		try {
			return getDisplay(
				_journalArticleLocalService.getArticle(
					groupId, articleId, version),
				ddmTemplateKey, viewMode, languageId, page, portletRequestModel,
				themeDisplay);
		}
		catch (PortalException portalException) {
			if (_log.isWarnEnabled()) {
				_log.warn(
					StringBundler.concat(
						"Unable to get display for ", groupId, StringPool.BLANK,
						articleId, StringPool.BLANK, languageId),
					portalException);
			}

			return null;
		}
	}

	@Override
	public JournalArticleDisplay getDisplay(
		long groupId, String articleId, String viewMode, String languageId,
		int page, ThemeDisplay themeDisplay) {

		return getDisplay(
			groupId, articleId, null, viewMode, languageId, page,
			(PortletRequestModel)null, themeDisplay);
	}

	@Override
	public JournalArticleDisplay getDisplay(
		long groupId, String articleId, String viewMode, String languageId,
		PortletRequestModel portletRequestModel) {

		return getDisplay(
			groupId, articleId, null, viewMode, languageId, 1,
			portletRequestModel, _getDefaultThemeDisplay());
	}

	@Override
	public JournalArticleDisplay getDisplay(
		long groupId, String articleId, String ddmTemplateKey, String viewMode,
		String languageId, int page, PortletRequestModel portletRequestModel,
		ThemeDisplay themeDisplay) {

		JournalArticle article = _journalArticleLocalService.fetchLatestArticle(
			groupId, articleId, WorkflowConstants.STATUS_APPROVED);

		return getDisplay(
			article, ddmTemplateKey, viewMode, languageId, 1,
			portletRequestModel, themeDisplay);
	}

	@Override
	public JournalArticleDisplay getDisplay(
		long groupId, String articleId, String ddmTemplateKey, String viewMode,
		String languageId, PortletRequestModel portletRequestModel) {

		return getDisplay(
			groupId, articleId, ddmTemplateKey, viewMode, languageId, 1,
			portletRequestModel, _getDefaultThemeDisplay());
	}

	@Override
	public JournalArticleDisplay getDisplay(
		long groupId, String articleId, String ddmTemplateKey, String viewMode,
		String languageId, ThemeDisplay themeDisplay) {

		return getDisplay(
			groupId, articleId, ddmTemplateKey, viewMode, languageId, 1,
			(PortletRequestModel)null, themeDisplay);
	}

	@Override
	public JournalArticleDisplay getDisplay(
		long groupId, String articleId, String viewMode, String languageId,
		ThemeDisplay themeDisplay) {

		return getDisplay(
			groupId, articleId, viewMode, languageId, 1, themeDisplay);
	}

	@Activate
	protected void activate(BundleContext bundleContext) {
		_portalCache =
			(PortalCache)
				_multiVMPool.getPortalCache(CACHE_NAME);

		_journalArticlePortalCacheIndexer = new PortalCacheIndexer<>(
			new JournalContentArticleKeyIndexEncoder(), _portalCache);
		_journalTemplatePortalCacheIndexer = new PortalCacheIndexer<>(
			new JournalContentTemplateKeyIndexEncoder(), _portalCache);
		_serviceRegistration = bundleContext.registerService(
			CTEventListener.class,
			new CTEventListener() {

				@Override
				public void onAfterPublish(long ctCollectionId) {
					_portalCache.removeAll();
				}

			},
			null);
	}

	@Deactivate
	protected void deactivate() {
		_multiVMPool.removePortalCache(CACHE_NAME);
		_serviceRegistration.unregister();
	}

	protected JournalArticleDisplay getArticleDisplay(
		JournalArticle article, String ddmTemplateKey, String viewMode,
		String languageId, int page, PortletRequestModel portletRequestModel,
		ThemeDisplay themeDisplay) {

		if (article.getStatus() != WorkflowConstants.STATUS_APPROVED) {
			return null;
		}

		Date date = new Date();

		Date displayDate = article.getDisplayDate();
		Date expirationDate = article.getExpirationDate();

		if (((displayDate != null) && displayDate.after(date)) ||
			((expirationDate != null) && expirationDate.before(date))) {

			return null;
		}

		try {
			return _journalArticleLocalService.getArticleDisplay(
				article, ddmTemplateKey, viewMode, languageId, page,
				portletRequestModel, themeDisplay);
		}
		catch (Exception exception) {
			if (_log.isWarnEnabled()) {
				_log.warn(
					StringBundler.concat(
						"Unable to get display for ", article, StringPool.SPACE,
						languageId),
					exception);
			}

			return null;
		}
	}

	protected JournalArticleDisplay getArticleDisplay(
		long groupId, String articleId, String ddmTemplateKey, String viewMode,
		String languageId, int page, PortletRequestModel portletRequestModel,
		ThemeDisplay themeDisplay) {

		try {
			if (_log.isInfoEnabled()) {
				_log.info(
					StringBundler.concat(
						"Get article display {", groupId, ", ", articleId, ", ",
						ddmTemplateKey, "}"));
			}

			return _journalArticleLocalService.getArticleDisplay(
				groupId, articleId, ddmTemplateKey, viewMode, languageId, page,
				portletRequestModel, themeDisplay);
		}
		catch (Exception exception) {
			if (_log.isWarnEnabled()) {
				_log.warn(
					StringBundler.concat(
						"Unable to get display for ", groupId, StringPool.SPACE,
						articleId, StringPool.SPACE, languageId),
					exception);
			}

			return null;
		}
	}

	protected static final String CACHE_NAME = JournalContent.class.getName();

	private static void _clearCache(
		long groupId, String articleId, String ddmTemplateKey) {

		_journalArticlePortalCacheIndexer.removeKeys(
			JournalContentArticleKeyIndexEncoder.encode(
				groupId, articleId, ddmTemplateKey));
	}

	private static void _clearCache(String ddmTemplateKey) {
		_journalTemplatePortalCacheIndexer.removeKeys(ddmTemplateKey);
	}

	private ThemeDisplay _getDefaultThemeDisplay() {
		ServiceContext serviceContext =
			ServiceContextThreadLocal.getServiceContext();

		if (serviceContext == null) {
			return null;
		}

		return serviceContext.getThemeDisplay();
	}

	private static final Log _log = LogFactoryUtil.getLog(
		JournalContentImpl.class);

	private static final MethodKey _clearArticleCacheMethodKey = new MethodKey(
		JournalContentImpl.class, "_clearCache", long.class, String.class,
		String.class);
	private static final MethodKey _clearTemplateCacheMethodKey = new MethodKey(
		JournalContentImpl.class, "_clearCache", String.class);
	private static PortalCacheIndexer
		
			_journalArticlePortalCacheIndexer;
	private static PortalCacheIndexer
		
			_journalTemplatePortalCacheIndexer;
	private static PortalCache
		_portalCache;

	@Reference
	private JournalArticleLocalService _journalArticleLocalService;

	@Reference(
		target = "(model.class.name=com.liferay.journal.model.JournalArticle)"
	)
	private ModelResourcePermission
		_journalArticleModelResourcePermission;

	@Reference
	private MultiVMPool _multiVMPool;

	private ServiceRegistration _serviceRegistration;

	private static class JournalContentArticleKeyIndexEncoder
		implements IndexEncoder {

		public static String encode(
			long groupId, String articleId, String ddmTemplateKey) {

			return StringBundler.concat(
				groupId, StringPool.UNDERLINE, articleId, StringPool.UNDERLINE,
				ddmTemplateKey);
		}

		@Override
		public String encode(JournalContentKey journalContentKey) {
			return encode(
				journalContentKey._groupId, journalContentKey._articleId,
				journalContentKey._ddmTemplateKey);
		}

	}

	private static class JournalContentKey implements Serializable {

		@Override
		public boolean equals(Object object) {
			JournalContentKey journalContentKey = (JournalContentKey)object;

			if ((journalContentKey._groupId == _groupId) &&
				Objects.equals(journalContentKey._articleId, _articleId) &&
				(journalContentKey._version == _version) &&
				Objects.equals(
					journalContentKey._ddmTemplateKey, _ddmTemplateKey) &&
				(journalContentKey._layoutSetId == _layoutSetId) &&
				Objects.equals(journalContentKey._viewMode, _viewMode) &&
				Objects.equals(journalContentKey._languageId, _languageId) &&
				(journalContentKey._page == _page) &&
				(journalContentKey._secure == _secure)) {

				return true;
			}

			return false;
		}

		@Override
		public int hashCode() {
			int hashCode = HashUtil.hash(0, _groupId);

			hashCode = HashUtil.hash(hashCode, _articleId);
			hashCode = HashUtil.hash(hashCode, _version);
			hashCode = HashUtil.hash(hashCode, _ddmTemplateKey);
			hashCode = HashUtil.hash(hashCode, _layoutSetId);
			hashCode = HashUtil.hash(hashCode, _viewMode);
			hashCode = HashUtil.hash(hashCode, _languageId);
			hashCode = HashUtil.hash(hashCode, _page);

			return HashUtil.hash(hashCode, _secure);
		}

		private JournalContentKey(
			long groupId, String articleId, double version,
			String ddmTemplateKey, long layoutSetId, String viewMode,
			String languageId, int page, boolean secure) {

			_groupId = groupId;
			_articleId = articleId;
			_version = version;
			_ddmTemplateKey = ddmTemplateKey;
			_layoutSetId = layoutSetId;
			_viewMode = viewMode;
			_languageId = languageId;
			_page = page;
			_secure = secure;
		}

		private static final long serialVersionUID = 1L;

		private final String _articleId;
		private final String _ddmTemplateKey;
		private final long _groupId;
		private final String _languageId;
		private final long _layoutSetId;
		private final int _page;
		private final boolean _secure;
		private final double _version;
		private final String _viewMode;

	}

	private static class JournalContentTemplateKeyIndexEncoder
		implements IndexEncoder {

		@Override
		public String encode(JournalContentKey journalContentKey) {
			return journalContentKey._ddmTemplateKey;
		}

	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy