001
014
015 package com.liferay.portal.poller;
016
017 import com.liferay.portal.kernel.exception.SystemException;
018 import com.liferay.portal.kernel.json.JSONFactoryUtil;
019 import com.liferay.portal.kernel.json.JSONObject;
020 import com.liferay.portal.kernel.log.Log;
021 import com.liferay.portal.kernel.log.LogFactoryUtil;
022 import com.liferay.portal.kernel.messaging.DestinationNames;
023 import com.liferay.portal.kernel.messaging.Message;
024 import com.liferay.portal.kernel.messaging.MessageBusUtil;
025 import com.liferay.portal.kernel.messaging.MessageListener;
026 import com.liferay.portal.kernel.poller.DefaultPollerResponse;
027 import com.liferay.portal.kernel.poller.PollerHeader;
028 import com.liferay.portal.kernel.poller.PollerProcessor;
029 import com.liferay.portal.kernel.poller.PollerRequest;
030 import com.liferay.portal.kernel.poller.PollerResponse;
031 import com.liferay.portal.kernel.util.GetterUtil;
032 import com.liferay.portal.kernel.util.StringPool;
033 import com.liferay.portal.kernel.util.StringUtil;
034 import com.liferay.portal.kernel.util.Validator;
035 import com.liferay.portal.kernel.uuid.PortalUUIDUtil;
036 import com.liferay.portal.model.BrowserTracker;
037 import com.liferay.portal.model.Company;
038 import com.liferay.portal.service.BrowserTrackerLocalServiceUtil;
039 import com.liferay.portal.service.CompanyLocalServiceUtil;
040 import com.liferay.util.Encryptor;
041
042 import java.util.ArrayList;
043 import java.util.HashMap;
044 import java.util.HashSet;
045 import java.util.List;
046 import java.util.Map;
047 import java.util.Set;
048
049 import javax.servlet.http.HttpServletRequest;
050
051
056 public class PollerRequestHandlerImpl
057 implements PollerRequestHandler, MessageListener {
058
059 public PollerHeader getPollerHeader(String pollerRequestString) {
060 if (Validator.isNull(pollerRequestString)) {
061 return null;
062 }
063
064 Map<String, Object>[] pollerRequestChunks =
065 parsePollerRequestParameters(pollerRequestString);
066
067 return parsePollerRequestHeader(pollerRequestChunks);
068 }
069
070 public JSONObject processRequest(
071 HttpServletRequest request, String pollerRequestString)
072 throws Exception {
073
074 if (Validator.isNull(pollerRequestString)) {
075 return null;
076 }
077
078 Map<String, Object>[] pollerRequestChunks =
079 parsePollerRequestParameters(pollerRequestString);
080
081 PollerHeader pollerHeader = parsePollerRequestHeader(
082 pollerRequestChunks);
083
084 if (!isValidPollerHeader(pollerHeader)) {
085 if (_log.isWarnEnabled()) {
086 _log.warn(
087 "Invalid poller header for request " +
088 pollerRequestString);
089 }
090
091 return null;
092 }
093
094 boolean receiveRequest = isReceiveRequest(request.getPathInfo());
095
096 String pollerSessionId = getPollerSessionId(pollerHeader);
097
098 PollerSession pollerSession = null;
099
100 synchronized (_pollerSessions) {
101 pollerSession = _pollerSessions.get(pollerSessionId);
102
103 if ((pollerSession == null) && receiveRequest) {
104 pollerSession = new PollerSession(pollerSessionId);
105
106 _pollerSessions.put(pollerSessionId, pollerSession);
107 }
108 }
109
110 List<PollerRequest> pollerRequests = createPollerRequests(
111 request, pollerHeader, pollerRequestChunks, receiveRequest);
112
113 executePollerRequests(pollerSession, pollerRequests);
114
115 if (receiveRequest) {
116 return createPollerResponseHeader(pollerHeader);
117 }
118 else {
119 return null;
120 }
121 }
122
123 public void receive(Message message) {
124 Object messagePayload = message.getPayload();
125
126 if (!(messagePayload instanceof PollerResponse)) {
127 return;
128 }
129
130 PollerResponse pollerResponse = (PollerResponse)messagePayload;
131
132 PollerHeader pollerHeader = pollerResponse.getPollerHeader();
133
134 String pollerSessionId = getPollerSessionId(pollerHeader);
135
136 synchronized (_pollerSessions) {
137 PollerSession pollerSession = _pollerSessions.get(pollerSessionId);
138
139 if ((pollerSession != null) &&
140 pollerSession.completePortletProcessing(
141 pollerResponse.getPortletId(), message.getResponseId())) {
142
143 _pollerSessions.remove(pollerSessionId);
144 }
145 }
146 }
147
148 protected PollerRequest createPollerRequest(
149 HttpServletRequest request, boolean receiveRequest,
150 PollerHeader pollerHeader, String portletId)
151 throws Exception {
152
153 return createPollerRequest(
154 request, receiveRequest, pollerHeader, portletId,
155 new HashMap<String, String>(), null);
156 }
157
158 protected PollerRequest createPollerRequest(
159 HttpServletRequest request, boolean receiveRequest,
160 PollerHeader pollerHeader, String portletId,
161 Map<String, String> parameterMap, String chunkId)
162 throws Exception {
163
164 PollerProcessor pollerProcessor =
165 PollerProcessorUtil.getPollerProcessor(portletId);
166
167 if (pollerProcessor == null) {
168 if (_log.isWarnEnabled()) {
169 _log.warn(
170 "Poller processor not found for portlet " + portletId);
171 }
172
173 return null;
174 }
175
176 return new PollerRequest(
177 request, pollerHeader, portletId, parameterMap, chunkId,
178 receiveRequest);
179 }
180
181 protected List<PollerRequest> createPollerRequests(
182 HttpServletRequest request, PollerHeader pollerHeader,
183 Map<String, Object>[] pollerRequestChunks, boolean receiveRequest)
184 throws Exception {
185
186 Map<String, Boolean> portletIdsMap = pollerHeader.getPortletIdsMap();
187
188 List<PollerRequest> pollerRequests = new ArrayList<PollerRequest>(
189 portletIdsMap.size());
190
191 Set<String> receiveRequestPortletIds = null;
192
193 if (receiveRequest) {
194 receiveRequestPortletIds = new HashSet<String>(
195 (int)(pollerRequestChunks.length / 0.75) + 1);
196 }
197
198 for (int i = 1; i < pollerRequestChunks.length; i++) {
199 Map<String, Object> pollerRequestChunk = pollerRequestChunks[i];
200
201 String portletId = (String)pollerRequestChunk.get("portletId");
202 Map<String, String> parameterMap = parseData(pollerRequestChunk);
203 String chunkId = (String)pollerRequestChunk.get("chunkId");
204
205 try {
206 PollerRequest pollerRequest = createPollerRequest(
207 request, receiveRequest, pollerHeader, portletId,
208 parameterMap, chunkId);
209
210 pollerRequests.add(pollerRequest);
211
212 if (receiveRequest) {
213 receiveRequestPortletIds.add(portletId);
214 }
215 }
216 catch (Exception e) {
217 _log.error(e, e);
218 }
219 }
220
221 if (receiveRequest) {
222 Set<String> portletIds = portletIdsMap.keySet();
223
224 for (String portletId : portletIds) {
225 if (receiveRequestPortletIds.contains(portletId)) {
226 continue;
227 }
228
229 try {
230 PollerRequest pollerRequest = createPollerRequest(
231 request, receiveRequest, pollerHeader, portletId);
232
233 pollerRequests.add(pollerRequest);
234 }
235 catch (Exception e) {
236 _log.error(e, e);
237 }
238 }
239 }
240
241 return pollerRequests;
242 }
243
244 protected JSONObject createPollerResponseHeader(PollerHeader pollerHeader)
245 throws SystemException {
246
247 if (pollerHeader == null) {
248 return null;
249 }
250
251 boolean suspendPolling = false;
252
253 if (pollerHeader.isStartPolling()) {
254 BrowserTrackerLocalServiceUtil.updateBrowserTracker(
255 pollerHeader.getUserId(), pollerHeader.getBrowserKey());
256 }
257 else {
258 BrowserTracker browserTracker =
259 BrowserTrackerLocalServiceUtil.getBrowserTracker(
260 pollerHeader.getUserId(), pollerHeader.getBrowserKey());
261
262 if (browserTracker.getBrowserKey() !=
263 pollerHeader.getBrowserKey()) {
264
265 suspendPolling = true;
266 }
267 }
268
269 JSONObject pollerResponseHeaderJSONObject =
270 JSONFactoryUtil.createJSONObject();
271
272 pollerResponseHeaderJSONObject.put("userId", pollerHeader.getUserId());
273 pollerResponseHeaderJSONObject.put("suspendPolling", suspendPolling);
274
275 return pollerResponseHeaderJSONObject;
276 }
277
278 protected void executePollerRequests(
279 PollerSession pollerSession, List<PollerRequest> pollerRequests) {
280
281 for (PollerRequest pollerRequest : pollerRequests) {
282 PollerRequestResponsePair pollerRequestResponsePair =
283 new PollerRequestResponsePair(pollerRequest);
284
285 String responseId = null;
286
287 if (pollerRequest.isReceiveRequest()) {
288 responseId = PortalUUIDUtil.generate();
289
290 PollerResponse pollerResponse = new DefaultPollerResponse(
291 pollerRequest.getPollerHeader(),
292 pollerRequest.getPortletId(), pollerRequest.getChunkId());
293
294 pollerRequestResponsePair.setPollerResponse(pollerResponse);
295
296 if (!pollerSession.beginPortletProcessing(
297 pollerRequestResponsePair, responseId)) {
298
299 continue;
300 }
301 }
302
303 Message message = new Message();
304
305 message.setPayload(pollerRequestResponsePair);
306
307 if (pollerRequest.isReceiveRequest()) {
308 message.setResponseId(responseId);
309
310 message.setResponseDestinationName(
311 DestinationNames.POLLER_RESPONSE);
312 }
313
314 MessageBusUtil.sendMessage(DestinationNames.POLLER, message);
315 }
316 }
317
318 protected String fixPollerRequestString(String pollerRequestString) {
319 if (Validator.isNull(pollerRequestString)) {
320 return null;
321 }
322
323 return StringUtil.replace(
324 pollerRequestString,
325 new String[] {
326 StringPool.OPEN_CURLY_BRACE, StringPool.CLOSE_CURLY_BRACE,
327 _ESCAPED_OPEN_CURLY_BRACE, _ESCAPED_CLOSE_CURLY_BRACE
328 },
329 new String[] {
330 _OPEN_HASH_MAP_WRAPPER, StringPool.DOUBLE_CLOSE_CURLY_BRACE,
331 StringPool.OPEN_CURLY_BRACE, StringPool.CLOSE_CURLY_BRACE
332 });
333 }
334
335 protected String getPollerSessionId(PollerHeader pollerHeader) {
336 return String.valueOf(pollerHeader.getUserId());
337 }
338
339 protected long getUserId(long companyId, String userIdString) {
340 long userId = 0;
341
342 try {
343 Company company = CompanyLocalServiceUtil.getCompany(companyId);
344
345 userId = GetterUtil.getLong(
346 Encryptor.decrypt(company.getKeyObj(), userIdString));
347 }
348 catch (Exception e) {
349 _log.error(
350 "Invalid credentials for company id " + companyId +
351 " and user id " + userIdString);
352 }
353
354 return userId;
355 }
356
357 protected boolean isReceiveRequest(String path) {
358 if ((path != null) && path.endsWith(_PATH_RECEIVE)) {
359 return true;
360 }
361 else {
362 return false;
363 }
364 }
365
366 protected boolean isValidPollerHeader(PollerHeader pollerHeader) {
367 if (pollerHeader == null) {
368 return false;
369 }
370
371 Map<String, Boolean> portletIdsMap = pollerHeader.getPortletIdsMap();
372
373 if ((portletIdsMap == null) || portletIdsMap.isEmpty()) {
374 return false;
375 }
376
377 return true;
378 }
379
380 protected Map<String, String> parseData(
381 Map<String, Object> pollerRequestChunk)
382 throws Exception {
383
384 Map<String, Object> oldParameterMap =
385 (Map<String, Object>)pollerRequestChunk.get("data");
386
387 Map<String, String> newParameterMap = new HashMap<String, String>();
388
389 if (oldParameterMap == null) {
390 return newParameterMap;
391 }
392
393 for (Map.Entry<String, Object> entry : oldParameterMap.entrySet()) {
394 newParameterMap.put(
395 entry.getKey(), String.valueOf(entry.getValue()));
396 }
397
398 return newParameterMap;
399 }
400
401 protected PollerHeader parsePollerRequestHeader(
402 Map<String, Object>[] pollerRequestChunks) {
403
404 if ((pollerRequestChunks == null) || (pollerRequestChunks.length < 1)) {
405 return null;
406 }
407
408 Map<String, Object> pollerRequestChunk = pollerRequestChunks[0];
409
410 long browserKey = GetterUtil.getLong(
411 String.valueOf(pollerRequestChunk.get("browserKey")));
412 long companyId = GetterUtil.getLong(
413 String.valueOf(pollerRequestChunk.get("companyId")));
414 Map<String, Boolean> portletIdsMap =
415 (Map<String, Boolean>)pollerRequestChunk.get("portletIdsMap");
416 boolean startPolling = GetterUtil.getBoolean(
417 String.valueOf(pollerRequestChunk.get("startPolling")));
418 String userIdString = GetterUtil.getString(
419 String.valueOf(pollerRequestChunk.get("userId")));
420
421 long userId = getUserId(companyId, userIdString);
422
423 if (userId == 0) {
424 return null;
425 }
426
427 return new PollerHeader(
428 companyId, userId, browserKey, portletIdsMap, startPolling);
429 }
430
431 protected Map<String, Object>[] parsePollerRequestParameters(
432 String pollerRequestString) {
433
434 String fixedPollerRequestString = fixPollerRequestString(
435 pollerRequestString);
436
437 return (Map<String, Object>[])JSONFactoryUtil.deserialize(
438 fixedPollerRequestString);
439 }
440
441 private static final String _ESCAPED_CLOSE_CURLY_BRACE =
442 "[$CLOSE_CURLY_BRACE$]";
443
444 private static final String _ESCAPED_OPEN_CURLY_BRACE =
445 "[$OPEN_CURLY_BRACE$]";
446
447 private static final String _OPEN_HASH_MAP_WRAPPER =
448 "{\"javaClass\":\"java.util.HashMap\",\"map\":{";
449
450 private static final String _PATH_RECEIVE = "/receive";
451
452 private static Log _log = LogFactoryUtil.getLog(
453 PollerRequestHandlerImpl.class);
454
455 private Map<String, PollerSession> _pollerSessions =
456 new HashMap<String, PollerSession>();
457
458 }