1
22
23 package com.liferay.portal.poller;
24
25 import com.liferay.portal.NoSuchLayoutException;
26 import com.liferay.portal.kernel.json.JSONArray;
27 import com.liferay.portal.kernel.json.JSONFactoryUtil;
28 import com.liferay.portal.kernel.json.JSONObject;
29 import com.liferay.portal.kernel.log.Log;
30 import com.liferay.portal.kernel.log.LogFactoryUtil;
31 import com.liferay.portal.kernel.messaging.DestinationNames;
32 import com.liferay.portal.kernel.poller.PollerHeader;
33 import com.liferay.portal.kernel.poller.PollerProcessor;
34 import com.liferay.portal.kernel.poller.PollerRequest;
35 import com.liferay.portal.kernel.util.ContentTypes;
36 import com.liferay.portal.kernel.util.GetterUtil;
37 import com.liferay.portal.kernel.util.ParamUtil;
38 import com.liferay.portal.kernel.util.StringPool;
39 import com.liferay.portal.kernel.util.StringUtil;
40 import com.liferay.portal.kernel.util.Validator;
41 import com.liferay.portal.model.BrowserTracker;
42 import com.liferay.portal.model.Company;
43 import com.liferay.portal.service.BrowserTrackerLocalServiceUtil;
44 import com.liferay.portal.service.CompanyLocalServiceUtil;
45 import com.liferay.portal.util.PortalUtil;
46 import com.liferay.portal.util.PropsValues;
47 import com.liferay.util.Encryptor;
48 import com.liferay.util.servlet.ServletResponseUtil;
49
50 import java.io.IOException;
51
52 import java.util.HashMap;
53 import java.util.HashSet;
54 import java.util.Map;
55 import java.util.Set;
56
57 import javax.servlet.ServletException;
58 import javax.servlet.http.HttpServlet;
59 import javax.servlet.http.HttpServletRequest;
60 import javax.servlet.http.HttpServletResponse;
61
62
67 public class PollerServlet extends HttpServlet {
68
69 public void service(
70 HttpServletRequest request, HttpServletResponse response)
71 throws IOException, ServletException {
72
73 try {
74 String content = getContent(request);
75
76 if (content == null) {
77 PortalUtil.sendError(
78 HttpServletResponse.SC_NOT_FOUND,
79 new NoSuchLayoutException(), request, response);
80 }
81 else {
82 response.setContentType(ContentTypes.TEXT_PLAIN_UTF8);
83
84 ServletResponseUtil.write(
85 response, content.getBytes(StringPool.UTF8));
86 }
87 }
88 catch (Exception e) {
89 _log.error(e, e);
90
91 PortalUtil.sendError(
92 HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e, request,
93 response);
94 }
95 }
96
97 protected String getContent(HttpServletRequest request) throws Exception {
98 String pollerRequestString = getPollerRequestString(request);
99
100 if (Validator.isNull(pollerRequestString)) {
101 return null;
102 }
103
104 Map<String, Object>[] pollerRequestChunks =
105 (Map<String, Object>[])JSONFactoryUtil.deserialize(
106 pollerRequestString);
107
108 PollerHeader pollerHeader = getPollerHeader(pollerRequestChunks);
109
110 if (pollerHeader == null) {
111 return null;
112 }
113
114 boolean receiveRequest = isReceiveRequest(request);
115
116 JSONArray pollerResponseChunksJSON = null;
117 Set<String> portletIdsWithChunks = null;
118
119 if (receiveRequest) {
120 pollerResponseChunksJSON = JSONFactoryUtil.createJSONArray();
121 portletIdsWithChunks = new HashSet<String>();
122
123 boolean suspendPolling = false;
124
125 if (pollerHeader.isStartPolling()) {
126 BrowserTrackerLocalServiceUtil.updateBrowserTracker(
127 pollerHeader.getUserId(), pollerHeader.getBrowserKey());
128 }
129 else {
130 BrowserTracker browserTracker =
131 BrowserTrackerLocalServiceUtil.getBrowserTracker(
132 pollerHeader.getUserId(), pollerHeader.getBrowserKey());
133
134 if (browserTracker.getBrowserKey() !=
135 pollerHeader.getBrowserKey()) {
136
137 suspendPolling = true;
138 }
139 }
140
141 JSONObject pollerResponseChunkJSON =
142 JSONFactoryUtil.createJSONObject();
143
144 pollerResponseChunkJSON.put("userId", pollerHeader.getUserId());
145 pollerResponseChunkJSON.put(
146 "initialRequest", pollerHeader.isInitialRequest());
147 pollerResponseChunkJSON.put("suspendPolling", suspendPolling);
148
149 pollerResponseChunksJSON.put(pollerResponseChunkJSON);
150 }
151
152 PollerRequestManager pollerRequestManager = new PollerRequestManager(
153 pollerResponseChunksJSON, DestinationNames.POLLER,
154 DestinationNames.POLLER_RESPONSE,
155 PropsValues.POLLER_REQUEST_TIMEOUT);
156
157 for (int i = 1; i < pollerRequestChunks.length; i++) {
158 Map<String, Object> pollerRequestChunk = pollerRequestChunks[i];
159
160 String portletId = (String)pollerRequestChunk.get("portletId");
161 Map<String, String> parameterMap = getData(pollerRequestChunk);
162 String chunkId = (String)pollerRequestChunk.get("chunkId");
163
164 try {
165 PollerRequest pollerRequest = process(
166 portletIdsWithChunks, pollerHeader, portletId, parameterMap,
167 chunkId, receiveRequest);
168
169 pollerRequestManager.addPollerRequest(pollerRequest);
170 }
171 catch (Exception e) {
172 _log.error(e, e);
173 }
174 }
175
176 pollerRequestManager.processRequests();
177
178 if (!receiveRequest) {
179 return StringPool.BLANK;
180 }
181
182 pollerRequestManager.clearRequests();
183
184 for (String portletId : pollerHeader.getPortletIds()) {
185 if (portletIdsWithChunks.contains(portletId)) {
186 continue;
187 }
188
189 try {
190 PollerRequest pollerRequest = process(
191 portletIdsWithChunks, pollerHeader, portletId,
192 new HashMap<String, String>(), null, receiveRequest);
193
194 pollerRequestManager.addPollerRequest(pollerRequest);
195 }
196 catch (Exception e) {
197 _log.error(e, e);
198 }
199 }
200
201 pollerRequestManager.processRequests();
202
203 pollerResponseChunksJSON = pollerRequestManager.getPollerResponse();
204
205 return pollerResponseChunksJSON.toString();
206 }
207
208 protected Map<String, String> getData(
209 Map<String, Object> pollerRequestChunk)
210 throws Exception {
211
212 Map<String, Object> oldParameterMap =
213 (Map<String, Object>)pollerRequestChunk.get("data");
214
215 Map<String, String> newParameterMap = new HashMap<String, String>();
216
217 if (oldParameterMap == null) {
218 return newParameterMap;
219 }
220
221 for (Map.Entry<String, Object> entry : oldParameterMap.entrySet()) {
222 newParameterMap.put(
223 entry.getKey(), String.valueOf(entry.getValue()));
224 }
225
226 return newParameterMap;
227 }
228
229 protected PollerHeader getPollerHeader(
230 Map<String, Object>[] pollerRequestChunks)
231 throws Exception {
232
233 if (pollerRequestChunks.length < 1) {
234 return null;
235 }
236
237 Map<String, Object> pollerRequestChunk = pollerRequestChunks[0];
238
239 long companyId = GetterUtil.getLong(
240 String.valueOf(pollerRequestChunk.get("companyId")));
241 String userIdString = GetterUtil.getString(
242 String.valueOf(pollerRequestChunk.get("userId")));
243 long browserKey = GetterUtil.getLong(
244 String.valueOf(pollerRequestChunk.get("browserKey")));
245 String[] portletIds = StringUtil.split(
246 String.valueOf(pollerRequestChunk.get("portletIds")));
247 boolean initialRequest = GetterUtil.getBoolean(
248 String.valueOf(pollerRequestChunk.get("initialRequest")));
249 boolean startPolling = GetterUtil.getBoolean(
250 String.valueOf(pollerRequestChunk.get("startPolling")));
251
252 long userId = getUserId(companyId, userIdString);
253
254 if (userId == 0) {
255 return null;
256 }
257
258 return new PollerHeader(
259 userId, browserKey, portletIds, initialRequest, startPolling);
260 }
261
262 protected String getPollerRequestString(HttpServletRequest request)
263 throws Exception {
264
265 String pollerRequestString = ParamUtil.getString(
266 request, "pollerRequest");
267
268 if (Validator.isNull(pollerRequestString)) {
269 return null;
270 }
271
272 return StringUtil.replace(
273 pollerRequestString,
274 new String[] {
275 StringPool.OPEN_CURLY_BRACE,
276 StringPool.CLOSE_CURLY_BRACE,
277 _ESCAPED_OPEN_CURLY_BRACE,
278 _ESCAPED_CLOSE_CURLY_BRACE
279 },
280 new String[] {
281 _OPEN_HASH_MAP_WRAPPER,
282 StringPool.DOUBLE_CLOSE_CURLY_BRACE,
283 StringPool.OPEN_CURLY_BRACE,
284 StringPool.CLOSE_CURLY_BRACE
285 });
286 }
287
288 protected long getUserId(long companyId, String userIdString) {
289 long userId = 0;
290
291 try {
292 Company company = CompanyLocalServiceUtil.getCompany(companyId);
293
294 userId = GetterUtil.getLong(
295 Encryptor.decrypt(company.getKeyObj(), userIdString));
296 }
297 catch (Exception e) {
298 _log.error(
299 "Invalid credentials for company id " + companyId +
300 " and user id " + userIdString);
301 }
302
303 return userId;
304 }
305
306 protected boolean isReceiveRequest(HttpServletRequest request)
307 throws Exception {
308
309 String path = GetterUtil.getString(request.getPathInfo());
310
311 if (path.endsWith(_PATH_RECEIVE)) {
312 return true;
313 }
314 else {
315 return false;
316 }
317 }
318
319 protected PollerRequest process(
320 Set<String> portletIdsWithChunks, PollerHeader pollerHeader,
321 String portletId, Map<String, String> parameterMap, String chunkId,
322 boolean receiveRequest)
323 throws Exception {
324
325 PollerProcessor pollerProcessor =
326 PollerProcessorUtil.getPollerProcessor(portletId);
327
328 if (pollerProcessor == null) {
329 _log.error("Poller processor not found for portlet " + portletId);
330
331 return null;
332 }
333
334 PollerRequest pollerRequest = new PollerRequest(
335 pollerHeader, portletId, parameterMap, chunkId, receiveRequest);
336
337 if (receiveRequest) {
338 portletIdsWithChunks.add(portletId);
339 }
340
341 return pollerRequest;
342 }
343
344 private static final String _ESCAPED_CLOSE_CURLY_BRACE =
345 "[$CLOSE_CURLY_BRACE$]";
346
347 private static final String _ESCAPED_OPEN_CURLY_BRACE =
348 "[$OPEN_CURLY_BRACE$]";
349
350 private static final String _OPEN_HASH_MAP_WRAPPER =
351 "{\"javaClass\":\"java.util.HashMap\",\"map\":{";
352
353 private static final String _PATH_RECEIVE = "/receive";
354
355 private static Log _log = LogFactoryUtil.getLog(PollerServlet.class);
356
357 }