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 String[] portletIds = pollerHeader.getPortletIds();
181
182 List<PollerRequest> pollerRequests = new ArrayList<PollerRequest>(
183 portletIds.length);
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 for (String portletId : portletIds) {
217 if (receiveRequestPortletIds.contains(portletId)) {
218 continue;
219 }
220
221 try {
222 PollerRequest pollerRequest = createPollerRequest(
223 request, receiveRequest, pollerHeader, portletId);
224
225 pollerRequests.add(pollerRequest);
226 }
227 catch (Exception e) {
228 _log.error(e, e);
229 }
230 }
231 }
232
233 return pollerRequests;
234 }
235
236 protected JSONObject createPollerResponseHeader(PollerHeader pollerHeader)
237 throws SystemException {
238
239 if (pollerHeader == null) {
240 return null;
241 }
242
243 boolean suspendPolling = false;
244
245 if (pollerHeader.isStartPolling()) {
246 BrowserTrackerLocalServiceUtil.updateBrowserTracker(
247 pollerHeader.getUserId(), pollerHeader.getBrowserKey());
248 }
249 else {
250 BrowserTracker browserTracker =
251 BrowserTrackerLocalServiceUtil.getBrowserTracker(
252 pollerHeader.getUserId(), pollerHeader.getBrowserKey());
253
254 if (browserTracker.getBrowserKey() !=
255 pollerHeader.getBrowserKey()) {
256
257 suspendPolling = true;
258 }
259 }
260
261 JSONObject pollerResponseHeaderJSONObject =
262 JSONFactoryUtil.createJSONObject();
263
264 pollerResponseHeaderJSONObject.put("userId", pollerHeader.getUserId());
265 pollerResponseHeaderJSONObject.put(
266 "initialRequest", pollerHeader.isInitialRequest());
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 companyId = GetterUtil.getLong(
391 String.valueOf(pollerRequestChunk.get("companyId")));
392 String userIdString = GetterUtil.getString(
393 String.valueOf(pollerRequestChunk.get("userId")));
394 long browserKey = GetterUtil.getLong(
395 String.valueOf(pollerRequestChunk.get("browserKey")));
396 String[] portletIds = StringUtil.split(
397 String.valueOf(pollerRequestChunk.get("portletIds")));
398 boolean initialRequest = GetterUtil.getBoolean(
399 String.valueOf(pollerRequestChunk.get("initialRequest")));
400 boolean startPolling = GetterUtil.getBoolean(
401 String.valueOf(pollerRequestChunk.get("startPolling")));
402
403 long userId = getUserId(companyId, userIdString);
404
405 if (userId == 0) {
406 return null;
407 }
408
409 return new PollerHeader(
410 companyId, userId, browserKey, portletIds, initialRequest,
411 startPolling);
412 }
413
414 protected Map<String, Object>[] parsePollerRequestParameters(
415 String pollerRequestString) {
416
417 String fixedPollerRequestString = fixPollerRequestString(
418 pollerRequestString);
419
420 return (Map<String, Object>[])JSONFactoryUtil.deserialize(
421 fixedPollerRequestString);
422 }
423
424 private static final String _ESCAPED_CLOSE_CURLY_BRACE =
425 "[$CLOSE_CURLY_BRACE$]";
426
427 private static final String _ESCAPED_OPEN_CURLY_BRACE =
428 "[$OPEN_CURLY_BRACE$]";
429
430 private static final String _OPEN_HASH_MAP_WRAPPER =
431 "{\"javaClass\":\"java.util.HashMap\",\"map\":{";
432
433 private static final String _PATH_RECEIVE = "/receive";
434
435 private static Log _log = LogFactoryUtil.getLog(
436 PollerRequestHandlerImpl.class);
437
438 private Map<String, PollerSession> _pollerSessions =
439 new HashMap<String, PollerSession>();
440
441 }