1 16 package org.directwebremoting.dwrp; 17 18 import java.io.IOException ; 19 import java.io.PrintWriter ; 20 import java.util.Map ; 21 22 import javax.servlet.http.HttpServletRequest ; 23 import javax.servlet.http.HttpServletResponse ; 24 25 import org.directwebremoting.WebContext; 26 import org.directwebremoting.WebContextFactory; 27 import org.directwebremoting.extend.ConverterManager; 28 import org.directwebremoting.extend.EnginePrivate; 29 import org.directwebremoting.extend.Handler; 30 import org.directwebremoting.extend.PageNormalizer; 31 import org.directwebremoting.extend.RealScriptSession; 32 import org.directwebremoting.extend.ScriptConduit; 33 import org.directwebremoting.extend.ScriptSessionManager; 34 import org.directwebremoting.extend.ServerLoadMonitor; 35 import org.directwebremoting.extend.WaitController; 36 import org.directwebremoting.util.Continuation; 37 import org.directwebremoting.util.Logger; 38 import org.directwebremoting.util.Messages; 39 import org.directwebremoting.util.MimeConstants; 40 41 49 public class PollHandler implements Handler 50 { 51 54 public PollHandler(boolean plain) 55 { 56 this.plain = plain; 57 } 58 59 62 public void handle(HttpServletRequest request, HttpServletResponse response) throws IOException 63 { 64 WebContext webContext = WebContextFactory.get(); 67 68 boolean isGet = request.getMethod().equals("GET"); 69 Map parameters = (Map ) request.getAttribute(ATTRIBUTE_PARAMETERS); 70 if (parameters == null) 71 { 72 try 73 { 74 if (isGet) 75 { 76 parameters = ParseUtil.parseGet(request); 77 } 78 else 79 { 80 parameters = ParseUtil.parsePost(request); 81 } 82 request.setAttribute(ATTRIBUTE_PARAMETERS, parameters); 83 } 84 catch (Exception ex) 85 { 86 String script = EnginePrivate.getRemoteHandleBatchExceptionScript(null, ex); 88 sendErrorScript(response, script); 89 return; 90 } 91 } 92 93 String batchId = extractParameter(request, parameters, ATTRIBUTE_CALL_ID, ProtocolConstants.INBOUND_KEY_BATCHID); 94 String scriptId = extractParameter(request, parameters, ATTRIBUTE_SESSION_ID, ProtocolConstants.INBOUND_KEY_SCRIPT_SESSIONID); 95 String page = extractParameter(request, parameters, ATTRIBUTE_PAGE, ProtocolConstants.INBOUND_KEY_PAGE); 96 String prString = extractParameter(request, parameters, ATTRIBUTE_PARTIAL_RESPONSE, ProtocolConstants.INBOUND_KEY_PARTIAL_RESPONSE); 97 int partialResponse = Integer.valueOf(prString).intValue(); 98 99 if (!activeReverseAjaxEnabled) 101 { 102 log.error("Polling and Comet are disabled. To enable them set the init-param activeReverseAjaxEnabled to true. See http://getahead.org/dwr/server/servlet for more."); 103 String script = EnginePrivate.getRemotePollCometDisabledScript(batchId); 104 sendErrorScript(response, script); 105 return; 106 } 107 108 if (!allowGetForSafariButMakeForgeryEasier && isGet) 109 { 110 String script = EnginePrivate.getRemoteHandleBatchExceptionScript(batchId, new SecurityException ("GET Disallowed")); 112 sendErrorScript(response, script); 113 return; 114 } 115 116 String normalizedPage = pageNormalizer.normalizePage(page); 118 119 webContext.setCurrentPageInformation(normalizedPage, scriptId); 120 RealScriptSession scriptSession = (RealScriptSession) webContext.getScriptSession(); 121 122 long maxConnectedTime = serverLoadMonitor.getConnectedTime(); 123 long endTime = System.currentTimeMillis() + maxConnectedTime; 124 125 if (maxConnectedTime > 0) 129 { 130 notifyThreadsFromSameBrowser(request, scriptId); 131 } 132 133 ScriptConduit notifyConduit = new NotifyOnlyScriptConduit(scriptSession.getScriptLock()); 134 135 boolean canWaitMore = true; 138 if (maxConnectedTime > 0 && !scriptSession.hasWaitingScripts()) 139 { 140 canWaitMore = streamWait(request, notifyConduit, scriptSession, maxConnectedTime); 141 } 142 143 BaseScriptConduit conduit; 144 if (plain) 145 { 146 conduit = new PlainScriptConduit(response, batchId, converterManager); 147 } 148 else 149 { 150 conduit = new HtmlScriptConduit(response, batchId, converterManager); 152 } 153 154 long extraWait = endTime - System.currentTimeMillis(); 156 157 if (maxWaitAfterWrite != -1 && extraWait > maxWaitAfterWrite) 159 { 160 extraWait = maxWaitAfterWrite; 161 } 162 163 if (extraWait <= 0) 165 { 166 canWaitMore = false; 167 } 168 169 if (canWaitMore && partialResponse != PARTIAL_RESPONSE_NO) 170 { 171 streamWait(request, conduit, scriptSession, extraWait); 172 } 173 else 174 { 175 scriptSession.writeScripts(conduit); 176 } 177 178 int timeToNextPoll = serverLoadMonitor.getDisconnectedTime(); 179 180 conduit.close(timeToNextPoll); 181 } 182 183 192 protected boolean streamWait(HttpServletRequest request, ScriptConduit conduit, RealScriptSession scriptSession, long wait) throws IOException 193 { 194 Object lock = scriptSession.getScriptLock(); 195 WaitController controller = new NotifyWaitController(lock); 196 197 try 198 { 199 serverLoadMonitor.threadWaitStarting(controller); 200 if (conduit != null) 201 { 202 scriptSession.addScriptConduit(conduit); 203 } 204 205 synchronized (lock) 206 { 207 Continuation continuation = new Continuation(request); 209 if (continuation.isAvailable()) 210 { 211 if (!sleepWithContinuation(scriptSession, continuation, wait)) 212 { 213 lock.wait(wait); 214 } 215 } 216 else 217 { 218 lock.wait(wait); 219 } 220 221 if (conduit != null) 222 { 223 scriptSession.removeScriptConduit(conduit); 224 } 225 serverLoadMonitor.threadWaitEnding(controller); 226 } 227 } 228 catch (InterruptedException ex) 229 { 230 log.warn("Interupted", ex); 231 232 if (conduit != null) 233 { 234 scriptSession.removeScriptConduit(conduit); 235 } 236 serverLoadMonitor.threadWaitEnding(controller); 237 } 238 239 return !controller.isShutdown(); 240 } 241 242 249 protected boolean sleepWithContinuation(RealScriptSession scriptSession, Continuation continuation, long preStreamWaitTime) 250 { 251 ScriptConduit listener = null; 252 253 try 254 { 255 listener = (ScriptConduit) continuation.getObject(); 257 if (listener == null) 258 { 259 listener = new ResumeContinuationScriptConduit(continuation); 260 continuation.setObject(listener); 261 } 262 scriptSession.addScriptConduit(listener); 263 264 continuation.suspend(preStreamWaitTime); 266 267 scriptSession.removeScriptConduit(listener); 268 } 269 catch (Exception ex) 270 { 271 Continuation.rethrowIfContinuation(ex); 272 273 if (listener != null) 274 { 275 scriptSession.removeScriptConduit(listener); 276 } 277 278 log.warn("Exception", ex); 279 return false; 280 } 281 282 return true; 283 } 284 285 290 protected void notifyThreadsFromSameBrowser(HttpServletRequest request, String scriptId) 291 { 292 String otherScriptSessionId = (String ) request.getSession().getAttribute(ATTRIBUTE_LONGPOLL_SESSION_ID); 295 if (otherScriptSessionId != null) 296 { 297 RealScriptSession previousSession = scriptSessionManager.getScriptSession(otherScriptSessionId); 298 Object lock = previousSession.getScriptLock(); 299 300 synchronized (lock) 302 { 303 lock.notifyAll(); 304 } 305 } 306 307 request.getSession().setAttribute(ATTRIBUTE_LONGPOLL_SESSION_ID, scriptId); 308 } 309 310 320 protected String extractParameter(HttpServletRequest request, Map parameters, String attrName, String paramName) 321 { 322 String id = (String ) request.getAttribute(attrName); 323 324 if (id == null) 325 { 326 id = (String ) parameters.remove(paramName); 327 request.setAttribute(attrName, id); 328 } 329 330 if (id == null) 331 { 332 throw new IllegalArgumentException (Messages.getString("PollHandler.MissingParameter", paramName)); 333 } 334 335 return id; 336 } 337 338 344 protected void sendErrorScript(HttpServletResponse response, String script) throws IOException 345 { 346 PrintWriter out = response.getWriter(); 347 if (plain) 348 { 349 response.setContentType(MimeConstants.MIME_PLAIN); 350 } 351 else 352 { 353 response.setContentType(MimeConstants.MIME_HTML); 354 } 355 356 out.println(ProtocolConstants.SCRIPT_START_MARKER); 357 out.println(script); 358 out.println(ProtocolConstants.SCRIPT_END_MARKER); 359 } 360 361 365 public void setConverterManager(ConverterManager converterManager) 366 { 367 this.converterManager = converterManager; 368 } 369 370 374 public void setServerLoadMonitor(ServerLoadMonitor serverLoadMonitor) 375 { 376 this.serverLoadMonitor = serverLoadMonitor; 377 } 378 379 383 public void setPageNormalizer(PageNormalizer pageNormalizer) 384 { 385 this.pageNormalizer = pageNormalizer; 386 } 387 388 391 public void setScriptSessionManager(ScriptSessionManager scriptSessionManager) 392 { 393 this.scriptSessionManager = scriptSessionManager; 394 } 395 396 401 public void setPollAndCometEnabled(boolean pollAndCometEnabled) 402 { 403 this.activeReverseAjaxEnabled = pollAndCometEnabled; 404 } 405 406 410 public void setActiveReverseAjaxEnabled(boolean activeReverseAjaxEnabled) 411 { 412 this.activeReverseAjaxEnabled = activeReverseAjaxEnabled; 413 } 414 415 418 public void setAllowGetForSafariButMakeForgeryEasier(boolean allowGetForSafariButMakeForgeryEasier) 419 { 420 this.allowGetForSafariButMakeForgeryEasier = allowGetForSafariButMakeForgeryEasier; 421 } 422 423 429 public void setMaxWaitAfterWrite(int maxWaitAfterWrite) 430 { 431 this.maxWaitAfterWrite = maxWaitAfterWrite; 432 } 433 434 437 protected boolean activeReverseAjaxEnabled = false; 438 439 442 protected boolean allowGetForSafariButMakeForgeryEasier = false; 443 444 449 protected int maxWaitAfterWrite = -1; 450 451 454 protected boolean plain; 455 456 459 protected PageNormalizer pageNormalizer; 460 461 464 protected ServerLoadMonitor serverLoadMonitor = null; 465 466 469 protected ConverterManager converterManager = null; 470 471 474 protected ScriptSessionManager scriptSessionManager = null; 475 476 479 public static final String ATTRIBUTE_PARAMETERS = "org.directwebremoting.dwrp.parameters"; 480 481 484 public static final String ATTRIBUTE_CALL_ID = "org.directwebremoting.dwrp.callId"; 485 486 489 public static final String ATTRIBUTE_SESSION_ID = "org.directwebremoting.dwrp.sessionId"; 490 491 494 public static final String ATTRIBUTE_PAGE = "org.directwebremoting.dwrp.page"; 495 496 499 public static final String ATTRIBUTE_PARTIAL_RESPONSE = "org.directwebremoting.dwrp.partialResponse"; 500 501 504 public static final String ATTRIBUTE_LONGPOLL_SESSION_ID = "org.directwebremoting.dwrp.longPollSessionId"; 505 506 509 protected static final int PARTIAL_RESPONSE_NO = 0; 510 511 514 protected static final int PARTIAL_RESPONSE_YES = 1; 515 516 520 protected static final int PARTIAL_RESPONSE_FLUSH = 2; 521 522 525 private static final Logger log = Logger.getLogger(PollHandler.class); 526 } 527 | Popular Tags |