6262import javax .servlet .http .HttpServletRequest ;
6363import javax .servlet .http .HttpServletResponse ;
6464import org .eclipse .jetty .ee8 .nested .ContextHandler ;
65- import org .eclipse .jetty .ee8 .nested .HandlerWrapper ;
66- import org .eclipse .jetty .ee8 .nested .HttpChannel ;
6765import org .eclipse .jetty .ee8 .nested .Request ;
66+ import org .eclipse .jetty .ee8 .nested .ScopedHandler ;
6867import org .eclipse .jetty .ee8 .servlet .ServletHolder ;
6968import org .eclipse .jetty .ee8 .webapp .Configuration ;
7069import org .eclipse .jetty .ee8 .webapp .JettyWebXmlConfiguration ;
@@ -354,7 +353,6 @@ protected void connectContainer() throws Exception {
354353 0 ,
355354 Runtime .getRuntime ().availableProcessors (),
356355 new HttpConnectionFactory (configuration ));
357- connector .addBean (new CompletionListener ());
358356 connector .setHost (address );
359357 connector .setPort (port );
360358 // Linux keeps the port blocked after shutdown if we don't disable this.
@@ -597,7 +595,7 @@ private File determineAppRoot() throws IOException {
597595 * com.google.apphosting.api.ApiProxy.Environment} which is stored as a request Attribute and then
598596 * set/cleared on a ThreadLocal by the ContextScopeListener {@link ThreadLocal}.
599597 */
600- private class ApiProxyHandler extends HandlerWrapper {
598+ private class ApiProxyHandler extends ScopedHandler {
601599 @ SuppressWarnings ("hiding" ) // Hides AbstractContainerService.appEngineWebXml
602600 private final AppEngineWebXml appEngineWebXml ;
603601
@@ -606,7 +604,103 @@ public ApiProxyHandler(AppEngineWebXml appEngineWebXml) {
606604 }
607605
608606 @ Override
609- public void handle (String target , Request baseRequest , HttpServletRequest request , HttpServletResponse response ) throws IOException , ServletException {
607+ public void doHandle (
608+ String target ,
609+ Request baseRequest ,
610+ HttpServletRequest request ,
611+ HttpServletResponse response )
612+ throws IOException , ServletException {
613+ nextHandle (target , baseRequest , request , response );
614+ }
615+
616+ @ Override
617+ public void doScope (
618+ String target ,
619+ Request baseRequest ,
620+ HttpServletRequest request ,
621+ HttpServletResponse response )
622+ throws IOException , ServletException {
623+
624+ org .eclipse .jetty .server .Request .addCompletionListener (
625+ baseRequest .getCoreRequest (),
626+ t -> {
627+ try {
628+ // a special hook with direct access to the container instance
629+ // we invoke this only after the normal request processing,
630+ // in order to generate a valid response
631+ if (request .getRequestURI ().startsWith (AH_URL_RELOAD )) {
632+ try {
633+ reloadWebApp ();
634+ log .info ("Reloaded the webapp context: " + request .getParameter ("info" ));
635+ } catch (Exception ex ) {
636+ log .log (Level .WARNING , "Failed to reload the current webapp context." , ex );
637+ }
638+ }
639+ } finally {
640+
641+ LocalEnvironment env =
642+ (LocalEnvironment ) request .getAttribute (LocalEnvironment .class .getName ());
643+ if (env != null ) {
644+ environments .remove (env );
645+
646+ // Acquire all of the semaphores back, which will block if any are outstanding.
647+ Semaphore semaphore =
648+ (Semaphore ) env .getAttributes ().get (LocalEnvironment .API_CALL_SEMAPHORE );
649+ try {
650+ System .err .println ("=========== acquire semaphore ===========" );
651+ semaphore .acquire (MAX_SIMULTANEOUS_API_CALLS );
652+ } catch (InterruptedException ex ) {
653+ Thread .currentThread ().interrupt ();
654+ log .log (
655+ Level .WARNING , "Interrupted while waiting for API calls to complete:" , ex );
656+ }
657+
658+ try {
659+ ApiProxy .setEnvironmentForCurrentThread (env );
660+
661+ // Invoke all of the registered RequestEndListeners.
662+ env .callRequestEndListeners ();
663+
664+ if (apiProxyDelegate instanceof ApiProxyLocal ) {
665+ // If apiProxyDelegate is not instanceof ApiProxyLocal, we are presumably
666+ // running in
667+ // the devappserver2 environment, where the master web server in Python will
668+ // take care
669+ // of logging requests.
670+ ApiProxyLocal apiProxyLocal = (ApiProxyLocal ) apiProxyDelegate ;
671+ String appId = env .getAppId ();
672+ String versionId = env .getVersionId ();
673+ String requestId = DevLogHandler .getRequestId ();
674+
675+ LocalLogService logService =
676+ (LocalLogService ) apiProxyLocal .getService (LocalLogService .PACKAGE );
677+
678+ @ SuppressWarnings ("NowMillis" )
679+ long nowMillis = System .currentTimeMillis ();
680+ logService .addRequestInfo (
681+ appId ,
682+ versionId ,
683+ requestId ,
684+ request .getRemoteAddr (),
685+ request .getRemoteUser (),
686+ baseRequest .getTimeStamp () * 1000 ,
687+ nowMillis * 1000 ,
688+ request .getMethod (),
689+ request .getRequestURI (),
690+ request .getProtocol (),
691+ request .getHeader ("User-Agent" ),
692+ true ,
693+ response .getStatus (),
694+ request .getHeader ("Referrer" ));
695+ logService .clearResponseSize ();
696+ }
697+ } finally {
698+ ApiProxy .clearEnvironmentForCurrentThread ();
699+ }
700+ }
701+ }
702+ });
703+
610704 if (baseRequest .getDispatcherType () == DispatcherType .REQUEST ) {
611705 Semaphore semaphore = new Semaphore (MAX_SIMULTANEOUS_API_CALLS );
612706
@@ -631,87 +725,9 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques
631725 // this and so the Environment has not yet been created.
632726 ApiProxy .Environment oldEnv = enterScope (request );
633727 try {
634- super .handle (target , baseRequest , request , response );
635- }
636- finally {
637- exitScope (oldEnv );
638- }
639- }
640- }
641-
642- private class CompletionListener implements HttpChannel .Listener {
643- @ Override
644- public void onComplete (Request request ) {
645- try {
646- // a special hook with direct access to the container instance
647- // we invoke this only after the normal request processing,
648- // in order to generate a valid response
649- if (request .getRequestURI ().startsWith (AH_URL_RELOAD )) {
650- try {
651- reloadWebApp ();
652- log .info ("Reloaded the webapp context: " + request .getParameter ("info" ));
653- } catch (Exception ex ) {
654- log .log (Level .WARNING , "Failed to reload the current webapp context." , ex );
655- }
656- }
728+ super .doScope (target , baseRequest , request , response );
657729 } finally {
658-
659- LocalEnvironment env =
660- (LocalEnvironment ) request .getAttribute (LocalEnvironment .class .getName ());
661- if (env != null ) {
662- environments .remove (env );
663-
664- // Acquire all of the semaphores back, which will block if any are outstanding.
665- Semaphore semaphore =
666- (Semaphore ) env .getAttributes ().get (LocalEnvironment .API_CALL_SEMAPHORE );
667- try {
668- semaphore .acquire (MAX_SIMULTANEOUS_API_CALLS );
669- } catch (InterruptedException ex ) {
670- Thread .currentThread ().interrupt ();
671- log .log (Level .WARNING , "Interrupted while waiting for API calls to complete:" , ex );
672- }
673-
674- try {
675- ApiProxy .setEnvironmentForCurrentThread (env );
676-
677- // Invoke all of the registered RequestEndListeners.
678- env .callRequestEndListeners ();
679-
680- if (apiProxyDelegate instanceof ApiProxyLocal ) {
681- // If apiProxyDelegate is not instanceof ApiProxyLocal, we are presumably running in
682- // the devappserver2 environment, where the master web server in Python will take care
683- // of logging requests.
684- ApiProxyLocal apiProxyLocal = (ApiProxyLocal ) apiProxyDelegate ;
685- String appId = env .getAppId ();
686- String versionId = env .getVersionId ();
687- String requestId = DevLogHandler .getRequestId ();
688-
689- LocalLogService logService =
690- (LocalLogService ) apiProxyLocal .getService (LocalLogService .PACKAGE );
691-
692- @ SuppressWarnings ("NowMillis" )
693- long nowMillis = System .currentTimeMillis ();
694- logService .addRequestInfo (
695- appId ,
696- versionId ,
697- requestId ,
698- request .getRemoteAddr (),
699- request .getRemoteUser (),
700- request .getTimeStamp () * 1000 ,
701- nowMillis * 1000 ,
702- request .getMethod (),
703- request .getRequestURI (),
704- request .getProtocol (),
705- request .getHeader ("User-Agent" ),
706- true ,
707- request .getResponse ().getStatus (),
708- request .getHeader ("Referrer" ));
709- logService .clearResponseSize ();
710- }
711- } finally {
712- ApiProxy .clearEnvironmentForCurrentThread ();
713- }
714- }
730+ exitScope (oldEnv );
715731 }
716732 }
717733 }
0 commit comments