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