@@ -122,21 +122,31 @@ public long transferTo(long position, long count, FileChannel target) throws IOE
122122 return 0 ;
123123 }
124124 try {
125+ final PooledByteBuffer localData = data ;
125126 if (frameDataRemaining == 0 && anyAreSet (state , STATE_LAST_FRAME )) {
126127 synchronized (lock ) {
127128 state |= STATE_RETURNED_MINUS_ONE ;
128129 return -1 ;
129130 }
130- } else if (data != null ) {
131- int old = data .getBuffer ().limit ();
131+ } else if (localData != null ) {
132132 try {
133- if (count < data .getBuffer ().remaining ()) {
134- data .getBuffer ().limit ((int ) (data .getBuffer ().position () + count ));
133+ final int old = localData .getBuffer ().limit ();
134+ try {
135+ if (count < localData .getBuffer ().remaining ()) {
136+ localData .getBuffer ().limit ((int ) (localData .getBuffer ().position () + count ));
137+ }
138+ return target .write (localData .getBuffer (), position );
139+ } finally {
140+ localData .getBuffer ().limit (old );
141+ decrementFrameDataRemaining ();
142+ }
143+ } catch (IllegalStateException e ) {
144+ // NPE should be covered. ISE in case of closed buffer
145+ if (anyAreSet (state , STATE_DONE | STATE_CLOSED | STATE_STREAM_BROKEN )) {
146+ return -1 ;
147+ } else {
148+ throw e ;
135149 }
136- return target .write (data .getBuffer (), position );
137- } finally {
138- data .getBuffer ().limit (old );
139- decrementFrameDataRemaining ();
140150 }
141151 }
142152 return 0 ;
@@ -146,7 +156,8 @@ public long transferTo(long position, long count, FileChannel target) throws IOE
146156 }
147157
148158 private void decrementFrameDataRemaining () {
149- if (!data .getBuffer ().hasRemaining ()) {
159+ final PooledByteBuffer localData = data ;
160+ if (localData != null && !localData .getBuffer ().hasRemaining ()) {
150161 frameDataRemaining -= currentDataOriginalSize ;
151162 }
152163 }
@@ -162,36 +173,44 @@ public long transferTo(long count, ByteBuffer throughBuffer, StreamSinkChannel s
162173 return 0 ;
163174 }
164175 try {
176+ final PooledByteBuffer localData = data ;
165177 if (frameDataRemaining == 0 && anyAreSet (state , STATE_LAST_FRAME )) {
166178 synchronized (lock ) {
167179 state |= STATE_RETURNED_MINUS_ONE ;
168180 return -1 ;
169181 }
170- } else if (data != null && data .getBuffer ().hasRemaining ()) {
171- int old = data .getBuffer ().limit ();
182+ } else if (localData != null && localData .getBuffer ().hasRemaining ()) {
183+ int old = localData .getBuffer ().limit ();
172184 try {
173- if (count < data .getBuffer ().remaining ()) {
174- data .getBuffer ().limit ((int ) (data .getBuffer ().position () + count ));
185+ if (count < localData .getBuffer ().remaining ()) {
186+ localData .getBuffer ().limit ((int ) (localData .getBuffer ().position () + count ));
175187 }
176- int written = streamSinkChannel .write (data .getBuffer ());
177- if (data .getBuffer ().hasRemaining ()) {
188+ int written = streamSinkChannel .write (localData .getBuffer ());
189+ if (localData .getBuffer ().hasRemaining ()) {
178190 //we can still add more data
179191 //stick it it throughbuffer, otherwise transfer code will continue to attempt to use this method
180192 throughBuffer .clear ();
181- Buffers .copy (throughBuffer , data .getBuffer ());
193+ Buffers .copy (throughBuffer , localData .getBuffer ());
182194 throughBuffer .flip ();
183195 } else {
184196 throughBuffer .position (throughBuffer .limit ());
185197 }
186198 return written ;
187199 } finally {
188- data .getBuffer ().limit (old );
200+ localData .getBuffer ().limit (old );
189201 decrementFrameDataRemaining ();
190202 }
191203 } else {
192204 throughBuffer .position (throughBuffer .limit ());
193205 }
194206 return 0 ;
207+ } catch (IllegalStateException e ) {
208+ // NPE should be covered. ISE in case of closed buffer
209+ if (anyAreSet (state , STATE_DONE | STATE_CLOSED | STATE_STREAM_BROKEN )) {
210+ return -1 ;
211+ } else {
212+ throw e ;
213+ }
195214 } finally {
196215 exitRead ();
197216 }
@@ -589,29 +608,29 @@ private void beforeRead() throws IOException {
589608 }
590609
591610 private void exitRead () throws IOException {
592- if ( data != null && ! data . getBuffer (). hasRemaining () ) {
593- data . close ();
594- data = null ;
595- }
596- if ( frameDataRemaining == 0 ) {
597- try {
598- synchronized ( lock ) {
611+ synchronized ( lock ) {
612+ if ( data != null && ! data . getBuffer (). hasRemaining ()) {
613+ data . close () ;
614+ data = null ;
615+ }
616+ if ( frameDataRemaining == 0 ) {
617+ try {
599618 readFrameCount ++;
600619 if (pendingFrameData .isEmpty ()) {
601620 if (anyAreSet (state , STATE_RETURNED_MINUS_ONE )) {
602621 state |= STATE_DONE ;
603622 complete ();
604623 close ();
605- } else if (anyAreSet (state , STATE_LAST_FRAME )) {
624+ } else if (anyAreSet (state , STATE_LAST_FRAME )) {
606625 state |= STATE_WAITNG_MINUS_ONE ;
607626 } else {
608627 waitingForFrame = true ;
609628 }
610629 }
611- }
612- } finally {
613- if ( pendingFrameData . isEmpty ()) {
614- framedChannel . notifyFrameReadComplete ( this );
630+ } finally {
631+ if ( pendingFrameData . isEmpty ()) {
632+ framedChannel . notifyFrameReadComplete ( this );
633+ }
615634 }
616635 }
617636 }
0 commit comments