| 1 20 package org.enhydra.barracuda.core.event; 21 22 import java.io.*; 23 import java.lang.reflect.*; 24 import java.util.*; 25 import javax.servlet.*; 26 import javax.servlet.http.*; 27 28 import org.apache.log4j.*; 29 30 import org.enhydra.barracuda.core.comp.scripting.*; 31 import org.enhydra.barracuda.core.event.events.*; 32 import org.enhydra.barracuda.core.helper.servlet.*; 33 import org.enhydra.barracuda.core.view.*; 34 import org.enhydra.barracuda.plankton.*; 35 import org.enhydra.barracuda.plankton.data.*; 36 import org.enhydra.barracuda.plankton.exceptions.*; 37 import org.enhydra.barracuda.plankton.http.URLRewriter; 38 import org.enhydra.barracuda.plankton.http.ServletUtil; 39 40 80 public class ApplicationGateway extends HttpServlet implements EventGateway { 81 82 private static final Class CLASS = ApplicationGateway.class; 83 private static final Logger logger = Logger.getLogger(CLASS); 84 private static final Logger orLogger = Logger.getLogger(CLASS.getName()+"_ORStackTrace"); 85 86 public static boolean USE_EVENT_POOLING = true; public static boolean RESPOND_WITH_404 = false; public static RequestWrapper REQUEST_WRAPPER = null; public static ResponseWrapper RESPONSE_WRAPPER = null; public static String LR_OVERRIDE_KEY = "$lr_override"; public static int LR_DEBUG = 0; 95 private static final String APPLICATION_ASSEMBLER = "ApplicationAssembler"; 97 private static final String ASSEMBLY_DESCRIPTOR = "AssemblyDescriptor"; 98 private static final String SAX_PARSER = "SAXParser"; 99 100 public static final String HTTP_SERVLET_REQUEST = CLASS+".HttpServletRequest"; public static final String HTTP_SERVLET_RESPONSE = CLASS+".HttpServletResponse"; public static final String THREAD_POOL = CLASS+".ThreadPool"; 105 public static final String TARGET_EVENT_NAME = CLASS+".TargetEventName"; public static final String EXTERNAL_CONTEXT_OBJ_NAME = CLASS+".ExternalContextObjName"; 109 110 public static final String LONG_RUNNING_ID = "$lrid"; 113 114 115 116 117 118 119 120 private EventBroker masterEventBroker = null; 122 private EventPool masterEventPool = null; 123 private static long uid = System.currentTimeMillis(); 124 private static final String LONG_RUNNING_RESPONSE_INDICATOR = "$is_lr_resp"; protected EventGateway eventGateway = (EventGateway) Classes.newInstance(A_Classes.DEFAULT_EVENT_GATEWAY); protected List gateways = null; 127 protected boolean virgin = true; 129 130 131 134 public ApplicationGateway() { 135 logger.info("Instantiating "+this); 136 } 137 138 139 144 public void initializeLocal() { 145 } 146 147 158 public final void initializeLocal(ServletConfig iconfig) throws ServletException { 159 } 160 161 165 public void destroyLocal() { 166 } 167 168 175 public EventBroker getNewEventBrokerInstance() { 176 if (logger.isDebugEnabled()) logger.debug("instantiating DefaultEventBroker"); 177 return new DefaultEventBroker(getDispatcherFactory(), getEventExtension()); 178 } 179 180 187 194 196 203 public DispatchQueue getNewDispatchQueueInstance() { 204 if (logger.isDebugEnabled()) logger.debug("instantiating DefaultDispatchQueue"); 205 return new DefaultDispatchQueue(true); 206 } 207 208 215 public DispatcherFactory getDispatcherFactory() { 216 if (logger.isDebugEnabled()) logger.debug("instantiating DefaultDispatcherFactory"); 217 return new DefaultDispatcherFactory(); 218 } 219 220 228 public String getEventExtension() { 229 return ".event"; 230 } 231 232 256 public void handleDefault(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 257 handleDefaultExt(req, resp, null); 258 } 259 260 286 public void handleDefaultExt(HttpServletRequest req, HttpServletResponse resp, Object externalContextObj) throws ServletException, IOException { 287 String ourl = req.getRequestURL().toString(); 288 String oqstr = req.getQueryString(); 289 long bmillis = 0; 290 long smillis = 0; 291 long emillis = 0; 292 if (virgin) { 293 if (logger.isInfoEnabled()) { 294 logger.info("\n\n\n\n\n\n"+ 295 "=======================================\n"+ 296 "ApplicationGateway servlet was reloaded\n"+ 297 "======================================="); 298 } 299 virgin = false; 300 } 301 if (logger.isInfoEnabled()) bmillis = System.currentTimeMillis(); 302 if (logger.isInfoEnabled()) { 303 logger.info("\n\n\n"+ 304 "--------------------------------------------------------------------------\n"+ 305 "Handling incoming HTTP request: "+ourl+(oqstr!=null ? "?"+oqstr : "")+"\n"+ 306 "--------------------------------------------------------------------------"); 307 } 308 BaseEvent event = null; 309 310 311 EventBroker eventBroker = getEventBroker(); 314 EventPool eventPool = getEventPool(); 315 ViewCapabilities vc = new ViewCapabilities(req, resp); 316 DefaultEventContext context = null; 317 HttpServletResponse oresp = null; 318 DeferredResponseWrapper dresp = null; 319 String uri = req.getRequestURI(); 322 String lrid = req.getParameter(LONG_RUNNING_ID); 323 boolean lrOverride = ("true".equalsIgnoreCase(req.getParameter(LR_OVERRIDE_KEY))); 324 boolean useEventPool = USE_EVENT_POOLING; 325 boolean eventCameFromPool = false; 326 boolean allowEventAliasing = true; String target = null; 328 329 try { 330 ObjectRepository.setupSessionRepository(req); 333 334 335 336 if (lrid!=null && !lrOverride) { 339 ObjectRepository session = ObjectRepository.getSessionRepository(); 341 ObjectRepository softSession = ObjectRepository.getSoftSessionRepository(); 342 dresp = (DeferredResponseWrapper) session.getState(lrid); 343 344 345 if (dresp==null) { 347 if (logger.isInfoEnabled()) logger.info("DeferredResponseWrapper missing from session - continuing as if $lrid=null (pass ??)"); 348 ((BarracudaServletRequestWrapper) req).removeParameter(LONG_RUNNING_ID); 349 String lridstr = LONG_RUNNING_ID+"="+lrid; 350 oqstr = StringUtil.replace(oqstr, lridstr, ""); 351 oqstr = StringUtil.replace(oqstr, "?"+lridstr, ""); 352 lrid = null; 353 354 BarracudaServletRequestWrapper breq = (BarracudaServletRequestWrapper) req; 358 Map pmap = (Map) softSession.getState(ourl); 359 if (pmap!=null) { 360 if (logger.isInfoEnabled()) logger.info("Restoring params from previous POST"); 361 Iterator it = pmap.entrySet().iterator(); 362 while (it.hasNext()) { 363 Map.Entry me = (Map.Entry) it.next(); 364 String key = (String ) me.getKey(); 365 if (key.equals(LONG_RUNNING_ID)) continue; 366 String [] vals = (String []) me.getValue(); 367 for (int i=0; i<vals.length; i++) { 368 String val = vals[i]; 369 String oval = breq.getParameter(key); 370 if (val==oval || (val!=null && val.equals(oval))) continue; breq.addParameter(key, val); 372 } 373 } 374 breq.setMethod("POST"); 375 } 376 377 } else if (dresp.isCommitted()) { 379 try { 380 Integer error = (Integer ) session.getState(lrid+"_error"); 382 if (error!=null) { 383 resp.sendError(error.intValue()); 384 return; 385 } 386 387 Exception dexcp = (Exception ) session.getState(lrid+"_exception"); 389 if (dexcp!=null) { 390 if (logger.isInfoEnabled()) logger.info("Throwing a deferred EventException (pass 3)"); 391 if (dexcp instanceof EventException) throw (EventException) dexcp; 392 else if (dexcp instanceof ServletException) throw (ServletException) dexcp; 393 else if (dexcp instanceof IOException) throw (IOException) dexcp; 394 else if (dexcp instanceof RuntimeException ) throw (RuntimeException ) dexcp; 395 else { 396 logger.warn("found unexpected exception in session:"+dexcp); 397 } 398 } 399 400 if (logger.isInfoEnabled()) logger.info("Actually rendering completed response from DeferredResponseWrapper (pass 3)"); 402 dresp.actuallySendResponse(resp); 403 return; 404 } finally { 405 session.removeState(lrid+"*"); 406 dresp = null; 407 } 408 409 } else { 411 if (logger.isInfoEnabled()) logger.info("Writing response to DeferredResponseWrapper in session (pass 2)"); 412 413 oresp = resp; 415 resp = dresp; 416 dresp.setUnderlyingResponse(oresp); 417 418 BarracudaServletRequestWrapper breq = (BarracudaServletRequestWrapper) req; 421 Map pmap = (Map) session.getState(lrid+"_params"); 422 Iterator it = pmap.entrySet().iterator(); 423 while (it.hasNext()) { 424 Map.Entry me = (Map.Entry) it.next(); 425 String key = (String ) me.getKey(); 426 String [] vals = (String []) me.getValue(); 427 for (int i=0; i<vals.length; i++) { 428 String val = vals[i]; 429 String oval = breq.getParameter(key); 430 if (val==oval || (val!=null && val.equals(oval))) continue; breq.addParameter(key, val); 432 } 433 } 434 session.removeState(lrid+"_params"); 435 436 if ("POST".equalsIgnoreCase((String ) session.getState(lrid+"_orig_method"))) { 439 softSession.putState(ourl, req.getParameterMap()); 440 } else { 441 softSession.removeState(ourl); 442 } 443 } 444 } 445 447 448 449 450 451 452 ObjectRepository lor = ObjectRepository.getLocalRepository(); lor.putState(HTTP_SERVLET_REQUEST, req); lor.putState(HTTP_SERVLET_RESPONSE, resp); 457 target = req.getServletPath(); 459 if (logger.isDebugEnabled()) { 460 logger.debug("Incoming URI:"+req.getRequestURI()); 461 logger.debug("ServletPath:"+target); 462 ServletUtil.showHeader(req, logger); } 465 if (logger.isInfoEnabled()) ServletUtil.showParams(req, logger); 467 if (null==target || target.length()==0) { 469 target = req.getRequestURI(); 470 if (logger.isDebugEnabled()) logger.debug("Setting target to request URI: " + target); 471 } 472 473 if (target!=null) { 475 int spos = target.lastIndexOf("/"); 476 if (spos>-1) target = target.substring(spos+1); 477 } 478 if (target!=null) { 480 int spos = target.lastIndexOf("\\"); 481 if (spos>-1) target = target.substring(spos+1); 482 } 483 484 String ext = eventBroker.getEventExtension(); 486 String eventName = target; 487 if (eventName.endsWith(ext)) { 488 eventName = target.substring(0, target.length()-ext.length()); 489 if (logger.isDebugEnabled()) logger.debug("Target Event:"+eventName); 490 } 491 492 if (allowEventAliasing) try { 494 String fullEventName = eventBroker.matchEventClass(eventName); 495 if (fullEventName!=null) { 496 eventName = fullEventName; 497 if (logger.isDebugEnabled()) logger.debug("Fully qualified Event:"+eventName); 498 } 499 } catch (InvalidClassException e) {} 500 501 if (logger.isDebugEnabled()) logger.debug("Creating Event"); 504 try { 505 Class cl = Classes.getClass(eventName); 509 if (useEventPool) try { 511 if (logger.isDebugEnabled()) logger.debug("Checking out event from event pool"); 512 event = eventPool.checkoutEvent(cl); 513 eventCameFromPool = true; 514 } catch (NoAvailableEventsException e) { 515 if (logger.isDebugEnabled()) logger.debug("No available events in pool"); 516 } 517 518 if (event==null) { 521 if (logger.isDebugEnabled()) logger.debug("Creating a new event from scratch"); 522 event = (BaseEvent) cl.newInstance(); } 524 525 } catch (Exception e) { 526 if (RESPOND_WITH_404) { 532 533 if (oresp!=null && dresp!=null) { 537 ObjectRepository session = ObjectRepository.getSessionRepository(); 538 session.putState(lrid+"_error", new Integer (HttpServletResponse.SC_NOT_FOUND)); 539 } else { 540 logger.warn("Class "+eventName+" not found...Responding with 404 error"); 541 resp.sendError(HttpServletResponse.SC_NOT_FOUND); 542 } 543 return; 544 } else { 546 logger.error("Class "+eventName+" not found...Creating a generic HttpRequestEvent"); 547 event = new HttpRequestEvent(); 548 } 549 } 551 552 if (!(event instanceof HttpRequestEvent)) event = new HttpRequestEvent(); 557 558 559 560 561 562 563 564 if (event instanceof LongRunning && !lrOverride) { 567 568 if (!(req instanceof BarracudaServletRequestWrapper)) throw new EventException("LongRunning support not enabled - you must use a req wrapper that implements BarracudaServletRequestWrapper"); 571 if (!(resp instanceof BarracudaServletResponseWrapper)) throw new EventException("LongRunning support not enabled - you must use a resp wrapper that implements BarracudaServletResponseWrapper"); 572 573 if (lrid==null) { 576 if (logger.isInfoEnabled()) logger.info("Redirecting for CheckLongRunningEvent (pass 1)"); 577 578 ObjectRepository session = ObjectRepository.getSessionRepository(); 581 lrid = getUID(); 582 session.putState(lrid, new DeferredResponseWrapper()); 583 session.putState(lrid+"_params", new HashMap(req.getParameterMap())); 584 session.putState(lrid+"_orig_url", ourl+(oqstr!=null ? "?"+oqstr : "")); 585 session.putState(lrid+"_orig_method", req.getMethod()); 586 session.putState(lrid+"_event", event); 587 588 ClientSideRedirectException rdException = new ClientSideRedirectException(new CheckLongRunningEvent()); 590 String rdURL = URLRewriter.encodeRedirectURL(req, resp, rdException.getRedirectURL()+"?"+LongRunningEventGateway.LRG_ID+"="+lrid); 591 rdURL = ScriptDetector.prepareRedirectURL(rdURL, vc); 592 if (logger.isInfoEnabled()) logger.info("rdURL: "+rdURL); 593 594 String lrURL = ourl+(oqstr!=null ? "?"+oqstr : "")+(oqstr!=null ? "&" : "?")+LONG_RUNNING_ID+"="+lrid; 596 if (logger.isInfoEnabled()) logger.info("lrURL: "+lrURL); 597 598 resp.setContentType("text/html"); 600 StringBuffer sb = new StringBuffer (500); 601 sb.append("<html>"); 602 sb.append(" <head>"); 603 sb.append(" <title>Redirecting...</title>"); 604 sb.append(" </head>"); 605 sb.append(" <script language=\"javascript\">"); 606 sb.append(" var pageFullyLoaded = false;"); 607 sb.append(" function handleComplete() {"); 608 sb.append(" if (!pageFullyLoaded) {"); 609 sb.append(" window.top.location.replace('CancelLongRunningEvent.event?"+LongRunningEventGateway.LRG_ID+"="+lrid+"');"); 610 sb.append(" alert('In the future, please press the Cancel button to properly stop a long running process');"); 611 sb.append(" }"); 612 sb.append(" }"); 613 sb.append(" </script>"); 614 if (LR_DEBUG==1) { sb.append(" <frameset rows=\"100%,200\">"); 616 sb.append(" <frame SRC=\""+rdURL+"\">"); 617 sb.append(" <frame SRC=\""+lrURL+"\">"); 618 sb.append(" </frameset>"); 619 } else if (LR_DEBUG==2) { sb.append(" <frameset rows=\"100%,200\">"); 621 sb.append(" <frame SRC=\"foo.html\" >"); 622 sb.append(" <frame SRC=\""+lrURL+"\">"); 623 sb.append(" </frameset>"); 624 } else { sb.append(" <frameset rows=\"100%,1\" onload=\"handleComplete();\">"); 626 sb.append(" <frame SRC=\""+rdURL+"\" frameborder=\"0\" noresize>"); 627 sb.append(" <frame SRC=\""+lrURL+"\" frameborder=\"0\" noresize>"); 628 sb.append(" </frameset>"); 629 } 630 sb.append(" </frameset>"); 631 sb.append("</html>"); 632 String content = sb.toString(); 633 Writer wr = resp.getWriter(); 634 wr.write(content); 635 wr.close(); 636 resp.flushBuffer(); 637 638 return; 640 641 } else { 644 LongRunning lr = (LongRunning) event; 645 lr.reset(); 646 dresp.setLongRunning(lr); 647 dresp.setLongRunningThread(Thread.currentThread()); 648 } 649 } 650 652 653 654 655 656 657 658 event.setSource(this); 660 event.setHandled(false); 661 662 String [] ids = req.getParameterValues(BaseEvent.EVENT_ID); 668 if (logger.isDebugEnabled()) logger.debug("Looking for event listener ids:"+ids); 669 if (ids!=null) { 670 for (int i=0, max=ids.length; i<max; i++) { 671 String id = ids[i]; 672 if (logger.isDebugEnabled()) logger.debug("Target EventID:"+id); 673 if (allowEventAliasing) try { 674 id = eventBroker.matchListenerID(ids[i]); 675 if (logger.isDebugEnabled()) logger.debug("Fully qualified EventID:"+id); 676 } catch (InvalidClassException e) {} 677 event.addListenerID(id); 678 } 679 } 680 681 if (logger.isDebugEnabled()) logger.debug("Dispatching event:"+event+" to broker:"+eventBroker); 683 DispatchQueue eventQueue = getNewDispatchQueueInstance(); 684 HttpResponseEvent defaultResponseEvent = new HttpResponseEvent(); 685 defaultResponseEvent.setSource(event); 686 eventQueue.addEvent(event); 687 context = new DefaultEventContext(eventQueue, vc, this.getServletConfig(), req, resp, defaultResponseEvent); 688 context.putState(TARGET_EVENT_NAME, eventName); 689 if (null!=externalContextObj) { 690 context.putState(EXTERNAL_CONTEXT_OBJ_NAME, externalContextObj); 691 } 692 if (logger.isInfoEnabled()) smillis = System.currentTimeMillis(); 693 eventBroker.dispatchEvent(context); 694 if (logger.isInfoEnabled()) emillis = System.currentTimeMillis(); 695 if (logger.isInfoEnabled()) logger.info("Dispatching complete! (handled in "+(emillis-smillis)+" of "+(emillis-bmillis)+" millis)"); 696 697 698 } catch (ClientSideRedirectException re) { 699 if (context!=null) { 701 if (logger.isDebugEnabled()) logger.debug("Saving context"); 702 context.persistContext(re); 703 } 704 705 String url = URLRewriter.encodeRedirectURL(req, resp, re.getRedirectURL()); 707 url = ScriptDetector.prepareRedirectURL(url, vc); if (logger.isInfoEnabled()) logger.info("ClientSideRedirectException...redirecting to "+url); 709 resp.sendRedirect(url); 710 711 } catch (EventException e) { 712 if (logger.isInfoEnabled()) logger.debug("got EventException: "+e); 715 if (oresp!=null && dresp!=null) { 716 if (dresp.isInterrupted()) return; 717 ObjectRepository session = ObjectRepository.getSessionRepository(); 718 session.putState(lrid+"_exception"
|