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

com.liferay.portal.poller.PollerRequestHandlerImpl Maven / Gradle / Ivy

There is a newer version: 7.4.3.112-ga112
Show newest version
/**
 * 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.portal.poller;

import com.liferay.petra.encryptor.Encryptor;
import com.liferay.petra.string.StringPool;
import com.liferay.portal.kernel.json.JSONFactoryUtil;
import com.liferay.portal.kernel.json.JSONObject;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.messaging.DestinationNames;
import com.liferay.portal.kernel.messaging.Message;
import com.liferay.portal.kernel.messaging.MessageBusUtil;
import com.liferay.portal.kernel.messaging.MessageListener;
import com.liferay.portal.kernel.model.BrowserTracker;
import com.liferay.portal.kernel.model.Company;
import com.liferay.portal.kernel.poller.PollerHeader;
import com.liferay.portal.kernel.poller.PollerProcessor;
import com.liferay.portal.kernel.poller.PollerRequest;
import com.liferay.portal.kernel.poller.PollerResponse;
import com.liferay.portal.kernel.service.BrowserTrackerLocalServiceUtil;
import com.liferay.portal.kernel.service.CompanyLocalServiceUtil;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.HttpUtil;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.uuid.PortalUUIDUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

/**
 * @author Michael C. Han
 * @author Brian Wing Shun Chan
 * @author Edward Han
 */
public class PollerRequestHandlerImpl
	implements MessageListener, PollerRequestHandler {

	@Override
	public PollerHeader getPollerHeader(String pollerRequestString) {
		if (Validator.isNull(pollerRequestString)) {
			return null;
		}

		Map[] pollerRequestChunks =
			parsePollerRequestParameters(pollerRequestString);

		return parsePollerRequestHeader(pollerRequestChunks);
	}

	@Override
	public JSONObject processRequest(
			HttpServletRequest request, String pollerRequestString)
		throws Exception {

		if (Validator.isNull(pollerRequestString)) {
			return null;
		}

		Map[] pollerRequestChunks =
			parsePollerRequestParameters(pollerRequestString);

		PollerHeader pollerHeader = parsePollerRequestHeader(
			pollerRequestChunks);

		if (!isValidPollerHeader(pollerHeader)) {
			if (_log.isWarnEnabled()) {
				_log.warn(
					"Invalid poller header for request " + pollerRequestString);
			}

			return null;
		}

		boolean receiveRequest = isReceiveRequest(
			HttpUtil.normalizePath(request.getPathInfo()));

		String pollerSessionId = getPollerSessionId(pollerHeader);

		PollerSession pollerSession = null;

		synchronized (_pollerSessions) {
			pollerSession = _pollerSessions.get(pollerSessionId);

			if ((pollerSession == null) && receiveRequest) {
				pollerSession = new PollerSession(pollerSessionId);

				_pollerSessions.put(pollerSessionId, pollerSession);
			}
		}

		List pollerRequests = createPollerRequests(
			pollerHeader, pollerRequestChunks, receiveRequest);

		executePollerRequests(pollerSession, pollerRequests);

		if (receiveRequest) {
			return createPollerResponseHeader(pollerHeader);
		}

		return null;
	}

	@Override
	public void receive(Message message) {
		Object messagePayload = message.getPayload();

		if (!(messagePayload instanceof PollerResponse)) {
			return;
		}

		PollerResponse pollerResponse = (PollerResponse)messagePayload;

		PollerHeader pollerHeader = pollerResponse.getPollerHeader();

		String pollerSessionId = getPollerSessionId(pollerHeader);

		synchronized (_pollerSessions) {
			PollerSession pollerSession = _pollerSessions.get(pollerSessionId);

			if ((pollerSession != null) &&
				pollerSession.completePortletProcessing(
					pollerResponse.getPortletId(), message.getResponseId())) {

				_pollerSessions.remove(pollerSessionId);
			}
		}
	}

	protected PollerRequest createPollerRequest(
			PollerHeader pollerHeader, String portletId, boolean receiveRequest)
		throws Exception {

		return createPollerRequest(
			pollerHeader, portletId, new HashMap(), null,
			receiveRequest);
	}

	protected PollerRequest createPollerRequest(
			PollerHeader pollerHeader, String portletId,
			Map parameterMap, String chunkId,
			boolean receiveRequest)
		throws Exception {

		PollerProcessor pollerProcessor =
			PollerProcessorUtil.getPollerProcessor(portletId);

		if (pollerProcessor == null) {
			if (_log.isWarnEnabled()) {
				_log.warn(
					"Poller processor not found for portlet " + portletId);
			}

			return null;
		}

		return new PollerRequest(
			pollerHeader, portletId, parameterMap, chunkId, receiveRequest);
	}

	protected List createPollerRequests(
			PollerHeader pollerHeader,
			Map[] pollerRequestChunks, boolean receiveRequest)
		throws Exception {

		Map portletIdsMap = pollerHeader.getPortletIdsMap();

		List pollerRequests = new ArrayList<>(
			portletIdsMap.size());

		Set receiveRequestPortletIds = null;

		if (receiveRequest) {
			receiveRequestPortletIds = new HashSet<>(
				(int)(pollerRequestChunks.length / 0.75) + 1);
		}

		for (int i = 1; i < pollerRequestChunks.length; i++) {
			Map pollerRequestChunk = pollerRequestChunks[i];

			String portletId = (String)pollerRequestChunk.get("portletId");
			Map parameterMap = parseData(pollerRequestChunk);
			String chunkId = (String)pollerRequestChunk.get("chunkId");

			try {
				PollerRequest pollerRequest = createPollerRequest(
					pollerHeader, portletId, parameterMap, chunkId,
					receiveRequest);

				pollerRequests.add(pollerRequest);

				if (receiveRequest) {
					receiveRequestPortletIds.add(portletId);
				}
			}
			catch (Exception e) {
				_log.error(e, e);
			}
		}

		if (receiveRequest) {
			Set portletIds = portletIdsMap.keySet();

			for (String portletId : portletIds) {
				if (receiveRequestPortletIds.contains(portletId)) {
					continue;
				}

				try {
					PollerRequest pollerRequest = createPollerRequest(
						pollerHeader, portletId, receiveRequest);

					pollerRequests.add(pollerRequest);
				}
				catch (Exception e) {
					_log.error(e, e);
				}
			}
		}

		return pollerRequests;
	}

	protected JSONObject createPollerResponseHeader(PollerHeader pollerHeader) {
		if (pollerHeader == null) {
			return null;
		}

		boolean suspendPolling = false;

		if (pollerHeader.isStartPolling()) {
			BrowserTrackerLocalServiceUtil.updateBrowserTracker(
				pollerHeader.getUserId(), pollerHeader.getBrowserKey());
		}
		else {
			BrowserTracker browserTracker =
				BrowserTrackerLocalServiceUtil.getBrowserTracker(
					pollerHeader.getUserId(), pollerHeader.getBrowserKey());

			if (browserTracker.getBrowserKey() !=
					pollerHeader.getBrowserKey()) {

				suspendPolling = true;
			}
		}

		JSONObject pollerResponseHeaderJSONObject =
			JSONFactoryUtil.createJSONObject();

		pollerResponseHeaderJSONObject.put("suspendPolling", suspendPolling);
		pollerResponseHeaderJSONObject.put("userId", pollerHeader.getUserId());

		return pollerResponseHeaderJSONObject;
	}

	protected void executePollerRequests(
		PollerSession pollerSession, List pollerRequests) {

		for (PollerRequest pollerRequest : pollerRequests) {
			if (pollerRequest == null) {
				continue;
			}

			String responseId = null;

			if (pollerRequest.isReceiveRequest()) {
				responseId = PortalUUIDUtil.generate();

				if (!pollerSession.beginPortletProcessing(
						pollerRequest, responseId)) {

					continue;
				}
			}

			Message message = new Message();

			message.setPayload(pollerRequest);

			if (pollerRequest.isReceiveRequest()) {
				message.setResponseId(responseId);

				message.setResponseDestinationName(
					DestinationNames.POLLER_RESPONSE);
			}

			MessageBusUtil.sendMessage(DestinationNames.POLLER, message);
		}
	}

	protected String fixPollerRequestString(String pollerRequestString) {
		if (Validator.isNull(pollerRequestString)) {
			return null;
		}

		return StringUtil.replace(
			pollerRequestString,
			new String[] {
				StringPool.OPEN_CURLY_BRACE, StringPool.CLOSE_CURLY_BRACE,
				_ESCAPED_OPEN_CURLY_BRACE, _ESCAPED_CLOSE_CURLY_BRACE
			},
			new String[] {
				_OPEN_HASH_MAP_WRAPPER, StringPool.DOUBLE_CLOSE_CURLY_BRACE,
				StringPool.OPEN_CURLY_BRACE, StringPool.CLOSE_CURLY_BRACE
			});
	}

	protected String getPollerSessionId(PollerHeader pollerHeader) {
		return String.valueOf(pollerHeader.getUserId());
	}

	protected long getUserId(long companyId, String userIdString) {
		long userId = 0;

		try {
			Company company = CompanyLocalServiceUtil.getCompany(companyId);

			userId = GetterUtil.getLong(
				Encryptor.decrypt(company.getKeyObj(), userIdString));
		}
		catch (Exception e) {
			_log.error(
				StringBundler.concat(
					"Invalid credentials for company id ",
					String.valueOf(companyId), " and user id ", userIdString));
		}

		return userId;
	}

	protected boolean isReceiveRequest(String path) {
		if ((path != null) && path.endsWith(_PATH_RECEIVE)) {
			return true;
		}

		return false;
	}

	protected boolean isValidPollerHeader(PollerHeader pollerHeader) {
		if (pollerHeader == null) {
			return false;
		}

		Map portletIdsMap = pollerHeader.getPortletIdsMap();

		if ((portletIdsMap == null) || portletIdsMap.isEmpty()) {
			return false;
		}

		return true;
	}

	protected Map parseData(
			Map pollerRequestChunk)
		throws Exception {

		Map oldParameterMap =
			(Map)pollerRequestChunk.get("data");

		Map newParameterMap = new HashMap<>();

		if (oldParameterMap == null) {
			return newParameterMap;
		}

		for (Map.Entry entry : oldParameterMap.entrySet()) {
			newParameterMap.put(
				entry.getKey(), String.valueOf(entry.getValue()));
		}

		return newParameterMap;
	}

	protected PollerHeader parsePollerRequestHeader(
		Map[] pollerRequestChunks) {

		if ((pollerRequestChunks == null) || (pollerRequestChunks.length < 1)) {
			return null;
		}

		Map pollerRequestChunk = pollerRequestChunks[0];

		long companyId = GetterUtil.getLong(
			String.valueOf(pollerRequestChunk.get("companyId")));
		String userIdString = GetterUtil.getString(
			String.valueOf(pollerRequestChunk.get("userId")));

		long userId = getUserId(companyId, userIdString);

		if (userId == 0) {
			return null;
		}

		long browserKey = GetterUtil.getLong(
			String.valueOf(pollerRequestChunk.get("browserKey")));
		Map portletIdsMap =
			(Map)pollerRequestChunk.get("portletIdsMap");
		boolean startPolling = GetterUtil.getBoolean(
			String.valueOf(pollerRequestChunk.get("startPolling")));

		return new PollerHeader(
			companyId, userId, browserKey, portletIdsMap, startPolling);
	}

	protected Map[] parsePollerRequestParameters(
		String pollerRequestString) {

		String fixedPollerRequestString = fixPollerRequestString(
			pollerRequestString);

		return (Map[])JSONFactoryUtil.deserialize(
			fixedPollerRequestString);
	}

	private static final String _ESCAPED_CLOSE_CURLY_BRACE =
		"[$CLOSE_CURLY_BRACE$]";

	private static final String _ESCAPED_OPEN_CURLY_BRACE =
		"[$OPEN_CURLY_BRACE$]";

	private static final String _OPEN_HASH_MAP_WRAPPER =
		"{\"javaClass\":\"java.util.HashMap\",\"map\":{";

	private static final String _PATH_RECEIVE = "/receive";

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

	private final Map _pollerSessions = new HashMap<>();

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy