1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.server;
20
21 import static javax.servlet.RequestDispatcher.ERROR_EXCEPTION;
22 import static javax.servlet.RequestDispatcher.ERROR_MESSAGE;
23 import static javax.servlet.RequestDispatcher.ERROR_STATUS_CODE;
24
25 import java.util.ArrayList;
26 import java.util.List;
27 import java.util.concurrent.TimeUnit;
28 import java.util.concurrent.atomic.AtomicReference;
29
30 import javax.servlet.AsyncListener;
31 import javax.servlet.RequestDispatcher;
32 import javax.servlet.ServletContext;
33 import javax.servlet.ServletResponse;
34 import javax.servlet.UnavailableException;
35
36 import org.eclipse.jetty.http.BadMessageException;
37 import org.eclipse.jetty.http.HttpStatus;
38 import org.eclipse.jetty.server.handler.ContextHandler;
39 import org.eclipse.jetty.server.handler.ContextHandler.Context;
40 import org.eclipse.jetty.util.log.Log;
41 import org.eclipse.jetty.util.log.Logger;
42 import org.eclipse.jetty.util.thread.Locker;
43 import org.eclipse.jetty.util.thread.Scheduler;
44
45
46
47
48 public class HttpChannelState
49 {
50 private static final Logger LOG = Log.getLogger(HttpChannelState.class);
51
52 private final static long DEFAULT_TIMEOUT=Long.getLong("org.eclipse.jetty.server.HttpChannelState.DEFAULT_TIMEOUT",30000L);
53
54
55
56
57 public enum State
58 {
59 IDLE,
60 DISPATCHED,
61 THROWN,
62 ASYNC_WAIT,
63 ASYNC_WOKEN,
64 ASYNC_IO,
65 ASYNC_ERROR,
66 COMPLETING,
67 COMPLETED,
68 UPGRADED
69 }
70
71
72
73
74 public enum Action
75 {
76 DISPATCH,
77 ASYNC_DISPATCH,
78 ERROR_DISPATCH,
79 ASYNC_ERROR,
80 WRITE_CALLBACK,
81 READ_CALLBACK,
82 COMPLETE,
83 TERMINATED,
84 WAIT,
85 }
86
87
88
89
90 public enum Async
91 {
92 NOT_ASYNC,
93 STARTED,
94 DISPATCH,
95 COMPLETE,
96 EXPIRING,
97 EXPIRED,
98 ERRORING,
99 ERRORED
100 }
101
102 private final boolean DEBUG=LOG.isDebugEnabled();
103 private final Locker _locker=new Locker();
104 private final HttpChannel _channel;
105
106 private List<AsyncListener> _asyncListeners;
107 private State _state;
108 private Async _async;
109 private boolean _initial;
110 private boolean _asyncReadPossible;
111 private boolean _asyncReadUnready;
112 private boolean _asyncWrite;
113 private long _timeoutMs=DEFAULT_TIMEOUT;
114 private AsyncContextEvent _event;
115
116 protected HttpChannelState(HttpChannel channel)
117 {
118 _channel=channel;
119 _state=State.IDLE;
120 _async=Async.NOT_ASYNC;
121 _initial=true;
122 }
123
124 public State getState()
125 {
126 try(Locker.Lock lock= _locker.lock())
127 {
128 return _state;
129 }
130 }
131
132 public void addListener(AsyncListener listener)
133 {
134 try(Locker.Lock lock= _locker.lock())
135 {
136 if (_asyncListeners==null)
137 _asyncListeners=new ArrayList<>();
138 _asyncListeners.add(listener);
139 }
140 }
141
142 public void setTimeout(long ms)
143 {
144 try(Locker.Lock lock= _locker.lock())
145 {
146 _timeoutMs=ms;
147 }
148 }
149
150 public long getTimeout()
151 {
152 try(Locker.Lock lock= _locker.lock())
153 {
154 return _timeoutMs;
155 }
156 }
157
158 public AsyncContextEvent getAsyncContextEvent()
159 {
160 try(Locker.Lock lock= _locker.lock())
161 {
162 return _event;
163 }
164 }
165
166 @Override
167 public String toString()
168 {
169 try(Locker.Lock lock= _locker.lock())
170 {
171 return toStringLocked();
172 }
173 }
174
175 public String toStringLocked()
176 {
177 return String.format("%s@%x{s=%s a=%s i=%b r=%s w=%b}",getClass().getSimpleName(),hashCode(),_state,_async,_initial,
178 _asyncReadPossible?(_asyncReadUnready?"PU":"P!U"):(_asyncReadUnready?"!PU":"!P!U"),
179 _asyncWrite);
180 }
181
182
183 private String getStatusStringLocked()
184 {
185 return String.format("s=%s i=%b a=%s",_state,_initial,_async);
186 }
187
188 public String getStatusString()
189 {
190 try(Locker.Lock lock= _locker.lock())
191 {
192 return getStatusStringLocked();
193 }
194 }
195
196
197
198
199 protected Action handling()
200 {
201 try(Locker.Lock lock= _locker.lock())
202 {
203 if(DEBUG)
204 LOG.debug("handling {}",toStringLocked());
205
206 switch(_state)
207 {
208 case IDLE:
209 _initial=true;
210 _state=State.DISPATCHED;
211 return Action.DISPATCH;
212
213 case COMPLETING:
214 case COMPLETED:
215 return Action.TERMINATED;
216
217 case ASYNC_WOKEN:
218 if (_asyncReadPossible)
219 {
220 _state=State.ASYNC_IO;
221 _asyncReadUnready=false;
222 return Action.READ_CALLBACK;
223 }
224
225 if (_asyncWrite)
226 {
227 _state=State.ASYNC_IO;
228 _asyncWrite=false;
229 return Action.WRITE_CALLBACK;
230 }
231
232 switch(_async)
233 {
234 case COMPLETE:
235 _state=State.COMPLETING;
236 return Action.COMPLETE;
237 case DISPATCH:
238 _state=State.DISPATCHED;
239 _async=Async.NOT_ASYNC;
240 return Action.ASYNC_DISPATCH;
241 case EXPIRED:
242 case ERRORED:
243 _state=State.DISPATCHED;
244 _async=Async.NOT_ASYNC;
245 return Action.ERROR_DISPATCH;
246 case STARTED:
247 case EXPIRING:
248 case ERRORING:
249 return Action.WAIT;
250 case NOT_ASYNC:
251 break;
252 default:
253 throw new IllegalStateException(getStatusStringLocked());
254 }
255
256 return Action.WAIT;
257
258 case ASYNC_ERROR:
259 return Action.ASYNC_ERROR;
260
261 case ASYNC_IO:
262 case ASYNC_WAIT:
263 case DISPATCHED:
264 case UPGRADED:
265 default:
266 throw new IllegalStateException(getStatusStringLocked());
267
268 }
269 }
270 }
271
272 public void startAsync(AsyncContextEvent event)
273 {
274 final List<AsyncListener> lastAsyncListeners;
275
276 try(Locker.Lock lock= _locker.lock())
277 {
278 if(DEBUG)
279 LOG.debug("startAsync {}",toStringLocked());
280 if (_state!=State.DISPATCHED || _async!=Async.NOT_ASYNC)
281 throw new IllegalStateException(this.getStatusStringLocked());
282
283 _async=Async.STARTED;
284 _event=event;
285 lastAsyncListeners=_asyncListeners;
286 _asyncListeners=null;
287 }
288
289 if (lastAsyncListeners!=null)
290 {
291 Runnable callback=new Runnable()
292 {
293 @Override
294 public void run()
295 {
296 for (AsyncListener listener : lastAsyncListeners)
297 {
298 try
299 {
300 listener.onStartAsync(event);
301 }
302 catch(Throwable e)
303 {
304
305 LOG.warn(e);
306 }
307 }
308 }
309 @Override
310 public String toString()
311 {
312 return "startAsync";
313 }
314 };
315
316 runInContext(event,callback);
317 }
318 }
319
320
321 public void asyncError(Throwable failure)
322 {
323 AsyncContextEvent event = null;
324 try (Locker.Lock lock= _locker.lock())
325 {
326 switch (_state)
327 {
328 case IDLE:
329 case DISPATCHED:
330 case COMPLETING:
331 case COMPLETED:
332 case UPGRADED:
333 case ASYNC_IO:
334 case ASYNC_WOKEN:
335 case ASYNC_ERROR:
336 {
337 break;
338 }
339 case ASYNC_WAIT:
340 {
341 _event.addThrowable(failure);
342 _state=State.ASYNC_ERROR;
343 event=_event;
344 break;
345 }
346 default:
347 {
348 throw new IllegalStateException(getStatusStringLocked());
349 }
350 }
351 }
352
353 if (event != null)
354 {
355 cancelTimeout(event);
356 runInContext(event, _channel);
357 }
358 }
359
360
361
362
363
364
365
366
367 protected Action unhandle()
368 {
369 Action action;
370 boolean read_interested=false;
371
372 try(Locker.Lock lock= _locker.lock())
373 {
374 if(DEBUG)
375 LOG.debug("unhandle {}",toStringLocked());
376
377 switch(_state)
378 {
379 case COMPLETING:
380 case COMPLETED:
381 return Action.TERMINATED;
382
383 case THROWN:
384 _state=State.DISPATCHED;
385 return Action.ERROR_DISPATCH;
386
387 case DISPATCHED:
388 case ASYNC_IO:
389 case ASYNC_ERROR:
390 break;
391
392 default:
393 throw new IllegalStateException(this.getStatusStringLocked());
394 }
395
396 _initial=false;
397 switch(_async)
398 {
399 case COMPLETE:
400 _state=State.COMPLETING;
401 _async=Async.NOT_ASYNC;
402 action=Action.COMPLETE;
403 break;
404
405 case DISPATCH:
406 _state=State.DISPATCHED;
407 _async=Async.NOT_ASYNC;
408 action=Action.ASYNC_DISPATCH;
409 break;
410
411 case STARTED:
412 if (_asyncReadUnready && _asyncReadPossible)
413 {
414 _state=State.ASYNC_IO;
415 _asyncReadUnready=false;
416 action = Action.READ_CALLBACK;
417 }
418 else if (_asyncWrite)
419 {
420 _asyncWrite=false;
421 _state=State.ASYNC_IO;
422 action=Action.WRITE_CALLBACK;
423 }
424 else
425 {
426 _state=State.ASYNC_WAIT;
427 action=Action.WAIT;
428 if (_asyncReadUnready)
429 read_interested=true;
430 Scheduler scheduler=_channel.getScheduler();
431 if (scheduler!=null && _timeoutMs>0)
432 _event.setTimeoutTask(scheduler.schedule(_event,_timeoutMs,TimeUnit.MILLISECONDS));
433 }
434 break;
435
436 case EXPIRING:
437
438 _state=State.ASYNC_WAIT;
439 action=Action.WAIT;
440 break;
441
442 case EXPIRED:
443
444
445 _state=State.DISPATCHED;
446 _async=Async.NOT_ASYNC;
447 action=Action.ERROR_DISPATCH;
448 break;
449
450 case ERRORED:
451 _state=State.DISPATCHED;
452 _async=Async.NOT_ASYNC;
453 action=Action.ERROR_DISPATCH;
454 break;
455
456 case NOT_ASYNC:
457 _state=State.COMPLETING;
458 action=Action.COMPLETE;
459 break;
460
461 default:
462 _state=State.COMPLETING;
463 action=Action.COMPLETE;
464 break;
465 }
466 }
467
468 if (read_interested)
469 _channel.asyncReadFillInterested();
470
471 return action;
472 }
473
474 public void dispatch(ServletContext context, String path)
475 {
476 boolean dispatch=false;
477 AsyncContextEvent event;
478 try(Locker.Lock lock= _locker.lock())
479 {
480 if(DEBUG)
481 LOG.debug("dispatch {} -> {}",toStringLocked(),path);
482
483 boolean started=false;
484 event=_event;
485 switch(_async)
486 {
487 case STARTED:
488 started=true;
489 break;
490 case EXPIRING:
491 case ERRORING:
492 case ERRORED:
493 break;
494 default:
495 throw new IllegalStateException(this.getStatusStringLocked());
496 }
497 _async=Async.DISPATCH;
498
499 if (context!=null)
500 _event.setDispatchContext(context);
501 if (path!=null)
502 _event.setDispatchPath(path);
503
504 if (started)
505 {
506 switch(_state)
507 {
508 case DISPATCHED:
509 case ASYNC_IO:
510 case ASYNC_WOKEN:
511 break;
512 case ASYNC_WAIT:
513 _state=State.ASYNC_WOKEN;
514 dispatch=true;
515 break;
516 default:
517 LOG.warn("async dispatched when complete {}",this);
518 break;
519 }
520 }
521 }
522
523 cancelTimeout(event);
524 if (dispatch)
525 scheduleDispatch();
526 }
527
528 protected void onTimeout()
529 {
530 final List<AsyncListener> listeners;
531 AsyncContextEvent event;
532 try(Locker.Lock lock= _locker.lock())
533 {
534 if(DEBUG)
535 LOG.debug("onTimeout {}",toStringLocked());
536
537 if (_async!=Async.STARTED)
538 return;
539 _async=Async.EXPIRING;
540 event=_event;
541 listeners=_asyncListeners;
542
543 }
544
545 final AtomicReference<Throwable> error=new AtomicReference<>();
546 if (listeners!=null)
547 {
548 Runnable task=new Runnable()
549 {
550 @Override
551 public void run()
552 {
553 for (AsyncListener listener : listeners)
554 {
555 try
556 {
557 listener.onTimeout(event);
558 }
559 catch(Throwable x)
560 {
561 LOG.warn(x+" while invoking onTimeout listener " + listener);
562 LOG.debug(x);
563 if (error.get()==null)
564 error.set(x);
565 else
566 error.get().addSuppressed(x);
567 }
568 }
569 }
570 @Override
571 public String toString()
572 {
573 return "onTimeout";
574 }
575 };
576
577 runInContext(event,task);
578 }
579
580 Throwable th=error.get();
581 boolean dispatch=false;
582 try(Locker.Lock lock= _locker.lock())
583 {
584 switch(_async)
585 {
586 case EXPIRING:
587 _async=th==null ? Async.EXPIRED : Async.ERRORING;
588 break;
589
590 case COMPLETE:
591 case DISPATCH:
592 if (th!=null)
593 {
594 LOG.ignore(th);
595 th=null;
596 }
597 break;
598
599 default:
600 throw new IllegalStateException();
601 }
602
603 if (_state==State.ASYNC_WAIT)
604 {
605 _state=State.ASYNC_WOKEN;
606 dispatch=true;
607 }
608 }
609
610 if (th!=null)
611 {
612 if (LOG.isDebugEnabled())
613 LOG.debug("Error after async timeout {}",this,th);
614 onError(th);
615 }
616
617 if (dispatch)
618 {
619 if (LOG.isDebugEnabled())
620 LOG.debug("Dispatch after async timeout {}",this);
621 scheduleDispatch();
622 }
623 }
624
625 public void complete()
626 {
627
628
629 boolean handle=false;
630 AsyncContextEvent event;
631 try(Locker.Lock lock= _locker.lock())
632 {
633 if(DEBUG)
634 LOG.debug("complete {}",toStringLocked());
635
636 boolean started=false;
637 event=_event;
638
639 switch(_async)
640 {
641 case STARTED:
642 started=true;
643 break;
644 case EXPIRING:
645 case ERRORING:
646 case ERRORED:
647 break;
648 case COMPLETE:
649 return;
650 default:
651 throw new IllegalStateException(this.getStatusStringLocked());
652 }
653 _async=Async.COMPLETE;
654
655 if (started && _state==State.ASYNC_WAIT)
656 {
657 handle=true;
658 _state=State.ASYNC_WOKEN;
659 }
660 }
661
662 cancelTimeout(event);
663 if (handle)
664 runInContext(event,_channel);
665 }
666
667 public void errorComplete()
668 {
669 try(Locker.Lock lock= _locker.lock())
670 {
671 if(DEBUG)
672 LOG.debug("error complete {}",toStringLocked());
673
674 _async=Async.COMPLETE;
675 _event.setDispatchContext(null);
676 _event.setDispatchPath(null);
677 }
678
679 cancelTimeout();
680 }
681
682 protected void onError(Throwable failure)
683 {
684 final List<AsyncListener> listeners;
685 final AsyncContextEvent event;
686 final Request baseRequest = _channel.getRequest();
687
688 int code=HttpStatus.INTERNAL_SERVER_ERROR_500;
689 String reason=null;
690 if (failure instanceof BadMessageException)
691 {
692 BadMessageException bme = (BadMessageException)failure;
693 code = bme.getCode();
694 reason = bme.getReason();
695 }
696 else if (failure instanceof UnavailableException)
697 {
698 if (((UnavailableException)failure).isPermanent())
699 code = HttpStatus.NOT_FOUND_404;
700 else
701 code = HttpStatus.SERVICE_UNAVAILABLE_503;
702 }
703
704 try(Locker.Lock lock= _locker.lock())
705 {
706 if(DEBUG)
707 LOG.debug("onError {} {}",toStringLocked(),failure);
708
709
710 if(_event!=null)
711 {
712 _event.addThrowable(failure);
713 _event.getSuppliedRequest().setAttribute(ERROR_STATUS_CODE,code);
714 _event.getSuppliedRequest().setAttribute(ERROR_EXCEPTION,failure);
715 _event.getSuppliedRequest().setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE,failure==null?null:failure.getClass());
716
717 _event.getSuppliedRequest().setAttribute(ERROR_MESSAGE,reason!=null?reason:null);
718 }
719 else
720 {
721 Throwable error = (Throwable)baseRequest.getAttribute(ERROR_EXCEPTION);
722 if (error!=null)
723 throw new IllegalStateException("Error already set",error);
724 baseRequest.setAttribute(ERROR_STATUS_CODE,code);
725 baseRequest.setAttribute(ERROR_EXCEPTION,failure);
726 baseRequest.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE,failure==null?null:failure.getClass());
727 baseRequest.setAttribute(ERROR_MESSAGE,reason!=null?reason:null);
728 }
729
730
731 if (_async==Async.NOT_ASYNC)
732 {
733
734 if (_state==State.DISPATCHED)
735 {
736 _state=State.THROWN;
737 return;
738 }
739 throw new IllegalStateException(this.getStatusStringLocked());
740 }
741
742
743 _async=Async.ERRORING;
744 listeners=_asyncListeners;
745 event=_event;
746 }
747
748 if(listeners!=null)
749 {
750 Runnable task=new Runnable()
751 {
752 @Override
753 public void run()
754 {
755 for (AsyncListener listener : listeners)
756 {
757 try
758 {
759 listener.onError(event);
760 }
761 catch (Throwable x)
762 {
763 LOG.warn(x+" while invoking onError listener " + listener);
764 LOG.debug(x);
765 }
766 }
767 }
768
769 @Override
770 public String toString()
771 {
772 return "onError";
773 }
774 };
775 runInContext(event,task);
776 }
777
778 boolean dispatch=false;
779 try(Locker.Lock lock= _locker.lock())
780 {
781 switch(_async)
782 {
783 case ERRORING:
784 {
785
786
787 _async=Async.ERRORED;
788 break;
789 }
790 case DISPATCH:
791 case COMPLETE:
792 {
793
794 break;
795 }
796 default:
797 {
798 throw new IllegalStateException(toString());
799 }
800 }
801
802 if(_state==State.ASYNC_WAIT)
803 {
804 _state=State.ASYNC_WOKEN;
805 dispatch=true;
806 }
807 }
808
809 if(dispatch)
810 {
811 if(LOG.isDebugEnabled())
812 LOG.debug("Dispatch after error {}",this);
813 scheduleDispatch();
814 }
815 }
816
817 protected void onComplete()
818 {
819 final List<AsyncListener> aListeners;
820 final AsyncContextEvent event;
821
822 try(Locker.Lock lock= _locker.lock())
823 {
824 if(DEBUG)
825 LOG.debug("onComplete {}",toStringLocked());
826
827 switch(_state)
828 {
829 case COMPLETING:
830 aListeners=_asyncListeners;
831 event=_event;
832 _state=State.COMPLETED;
833 _async=Async.NOT_ASYNC;
834 break;
835
836 default:
837 throw new IllegalStateException(this.getStatusStringLocked());
838 }
839 }
840
841 if (event!=null)
842 {
843 if (aListeners!=null)
844 {
845 Runnable callback = new Runnable()
846 {
847 @Override
848 public void run()
849 {
850 for (AsyncListener listener : aListeners)
851 {
852 try
853 {
854 listener.onComplete(event);
855 }
856 catch(Throwable e)
857 {
858 LOG.warn(e+" while invoking onComplete listener " + listener);
859 LOG.debug(e);
860 }
861 }
862 }
863 @Override
864 public String toString()
865 {
866 return "onComplete";
867 }
868 };
869
870 runInContext(event,callback);
871 }
872 event.completed();
873 }
874 }
875
876 protected void recycle()
877 {
878 cancelTimeout();
879 try(Locker.Lock lock= _locker.lock())
880 {
881 if(DEBUG)
882 LOG.debug("recycle {}",toStringLocked());
883
884 switch(_state)
885 {
886 case DISPATCHED:
887 case ASYNC_IO:
888 throw new IllegalStateException(getStatusStringLocked());
889 case UPGRADED:
890 return;
891 default:
892 break;
893 }
894 _asyncListeners=null;
895 _state=State.IDLE;
896 _async=Async.NOT_ASYNC;
897 _initial=true;
898 _asyncReadPossible=_asyncReadUnready=false;
899 _asyncWrite=false;
900 _timeoutMs=DEFAULT_TIMEOUT;
901 _event=null;
902 }
903 }
904
905 public void upgrade()
906 {
907 cancelTimeout();
908 try(Locker.Lock lock= _locker.lock())
909 {
910 if(DEBUG)
911 LOG.debug("upgrade {}",toStringLocked());
912
913 switch(_state)
914 {
915 case IDLE:
916 case COMPLETED:
917 break;
918 default:
919 throw new IllegalStateException(getStatusStringLocked());
920 }
921 _asyncListeners=null;
922 _state=State.UPGRADED;
923 _async=Async.NOT_ASYNC;
924 _initial=true;
925 _asyncReadPossible=_asyncReadUnready=false;
926 _asyncWrite=false;
927 _timeoutMs=DEFAULT_TIMEOUT;
928 _event=null;
929 }
930 }
931
932 protected void scheduleDispatch()
933 {
934 _channel.execute(_channel);
935 }
936
937 protected void cancelTimeout()
938 {
939 final AsyncContextEvent event;
940 try(Locker.Lock lock= _locker.lock())
941 {
942 event=_event;
943 }
944 cancelTimeout(event);
945 }
946
947 protected void cancelTimeout(AsyncContextEvent event)
948 {
949 if (event!=null)
950 event.cancelTimeoutTask();
951 }
952
953 public boolean isIdle()
954 {
955 try(Locker.Lock lock= _locker.lock())
956 {
957 return _state==State.IDLE;
958 }
959 }
960
961 public boolean isExpired()
962 {
963 try(Locker.Lock lock= _locker.lock())
964 {
965 return _async==Async.EXPIRED;
966 }
967 }
968
969 public boolean isInitial()
970 {
971 try(Locker.Lock lock= _locker.lock())
972 {
973 return _initial;
974 }
975 }
976
977 public boolean isSuspended()
978 {
979 try(Locker.Lock lock= _locker.lock())
980 {
981 return _state==State.ASYNC_WAIT || _state==State.DISPATCHED && _async==Async.STARTED;
982 }
983 }
984
985 boolean isCompleting()
986 {
987 try(Locker.Lock lock= _locker.lock())
988 {
989 return _state==State.COMPLETING;
990 }
991 }
992
993 boolean isCompleted()
994 {
995 try(Locker.Lock lock= _locker.lock())
996 {
997 return _state == State.COMPLETED;
998 }
999 }
1000
1001 public boolean isAsyncStarted()
1002 {
1003 try(Locker.Lock lock= _locker.lock())
1004 {
1005 if (_state==State.DISPATCHED)
1006 return _async!=Async.NOT_ASYNC;
1007 return _async==Async.STARTED || _async==Async.EXPIRING;
1008 }
1009 }
1010
1011 public boolean isAsyncComplete()
1012 {
1013 try(Locker.Lock lock= _locker.lock())
1014 {
1015 return _async==Async.COMPLETE;
1016 }
1017 }
1018
1019 public boolean isAsync()
1020 {
1021 try(Locker.Lock lock= _locker.lock())
1022 {
1023 return !_initial || _async!=Async.NOT_ASYNC;
1024 }
1025 }
1026
1027 public Request getBaseRequest()
1028 {
1029 return _channel.getRequest();
1030 }
1031
1032 public HttpChannel getHttpChannel()
1033 {
1034 return _channel;
1035 }
1036
1037 public ContextHandler getContextHandler()
1038 {
1039 final AsyncContextEvent event;
1040 try(Locker.Lock lock= _locker.lock())
1041 {
1042 event=_event;
1043 }
1044 return getContextHandler(event);
1045 }
1046
1047 ContextHandler getContextHandler(AsyncContextEvent event)
1048 {
1049 if (event!=null)
1050 {
1051 Context context=((Context)event.getServletContext());
1052 if (context!=null)
1053 return context.getContextHandler();
1054 }
1055 return null;
1056 }
1057
1058 public ServletResponse getServletResponse()
1059 {
1060 final AsyncContextEvent event;
1061 try(Locker.Lock lock= _locker.lock())
1062 {
1063 event=_event;
1064 }
1065 return getServletResponse(event);
1066 }
1067
1068 public ServletResponse getServletResponse(AsyncContextEvent event)
1069 {
1070 if (event!=null && event.getSuppliedResponse()!=null)
1071 return event.getSuppliedResponse();
1072 return _channel.getResponse();
1073 }
1074
1075 void runInContext(AsyncContextEvent event,Runnable runnable)
1076 {
1077 ContextHandler contextHandler = getContextHandler(event);
1078 if (contextHandler==null)
1079 runnable.run();
1080 else
1081 contextHandler.handle(_channel.getRequest(),runnable);
1082 }
1083
1084 public Object getAttribute(String name)
1085 {
1086 return _channel.getRequest().getAttribute(name);
1087 }
1088
1089 public void removeAttribute(String name)
1090 {
1091 _channel.getRequest().removeAttribute(name);
1092 }
1093
1094 public void setAttribute(String name, Object attribute)
1095 {
1096 _channel.getRequest().setAttribute(name,attribute);
1097 }
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107 public void onReadUnready()
1108 {
1109 boolean interested=false;
1110 try(Locker.Lock lock= _locker.lock())
1111 {
1112 if(DEBUG)
1113 LOG.debug("onReadUnready {}",toStringLocked());
1114
1115
1116 if (!_asyncReadUnready)
1117 {
1118 _asyncReadUnready=true;
1119 _asyncReadPossible=false;
1120 if (_state==State.ASYNC_WAIT)
1121 interested=true;
1122 }
1123 }
1124
1125 if (interested)
1126 _channel.asyncReadFillInterested();
1127 }
1128
1129
1130
1131
1132
1133
1134
1135
1136 public boolean onReadPossible()
1137 {
1138 boolean woken=false;
1139 try(Locker.Lock lock= _locker.lock())
1140 {
1141 if(DEBUG)
1142 LOG.debug("onReadPossible {}",toStringLocked());
1143
1144 _asyncReadPossible=true;
1145 if (_state==State.ASYNC_WAIT && _asyncReadUnready)
1146 {
1147 woken=true;
1148 _state=State.ASYNC_WOKEN;
1149 }
1150 }
1151 return woken;
1152 }
1153
1154
1155
1156
1157
1158
1159
1160
1161 public boolean onReadReady()
1162 {
1163 boolean woken=false;
1164 try(Locker.Lock lock= _locker.lock())
1165 {
1166 if(DEBUG)
1167 LOG.debug("onReadReady {}",toStringLocked());
1168
1169 _asyncReadUnready=true;
1170 _asyncReadPossible=true;
1171 if (_state==State.ASYNC_WAIT)
1172 {
1173 woken=true;
1174 _state=State.ASYNC_WOKEN;
1175 }
1176 }
1177 return woken;
1178 }
1179
1180
1181
1182
1183
1184
1185 public boolean onReadEof()
1186 {
1187 boolean woken=false;
1188 try(Locker.Lock lock= _locker.lock())
1189 {
1190 if(DEBUG)
1191 LOG.debug("onReadEof {}",toStringLocked());
1192
1193 if (_state==State.ASYNC_WAIT)
1194 {
1195 _state=State.ASYNC_WOKEN;
1196 _asyncReadUnready=true;
1197 _asyncReadPossible=true;
1198 woken=true;
1199 }
1200 }
1201 return woken;
1202 }
1203
1204
1205 public boolean isReadPossible()
1206 {
1207 try(Locker.Lock lock= _locker.lock())
1208 {
1209 return _asyncReadPossible;
1210 }
1211 }
1212
1213 public boolean onWritePossible()
1214 {
1215 boolean handle=false;
1216
1217 try(Locker.Lock lock= _locker.lock())
1218 {
1219 if(DEBUG)
1220 LOG.debug("onWritePossible {}",toStringLocked());
1221
1222 _asyncWrite=true;
1223 if (_state==State.ASYNC_WAIT)
1224 {
1225 _state=State.ASYNC_WOKEN;
1226 handle=true;
1227 }
1228 }
1229
1230 return handle;
1231 }
1232
1233 }