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