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