@ Override public Future < GcsFileMetadata > readObjectAsync ( final ByteBuffer dst , final GcsFilename filename , long startOffsetBytes , long timeoutMillis ) { Preconditions . checkArgument ( startOffsetBytes >= 0 , "%s: offset must be non-negative: %s" , this , startOffsetBytes ) ; final int n = dst . remaining ( ) ; Preconditions . checkArgument ( n > 0 , "%s: dst full: %s" , this , dst ) ; final int want = Math . min ( READ_LIMIT_BYTES , n ) ; final HTTPRequest req = makeRequest ( filename , null , GET , timeoutMillis ) ; req . setHeader ( new HTTPHeader ( RANGE , "bytes=" + startOffsetBytes + "-" + ( startOffsetBytes + want - 1 ) ) ) ; final HTTPRequestInfo info = new HTTPRequestInfo ( req ) ; return new FutureWrapper < HTTPResponse , GcsFileMetadata > ( urlfetch . fetchAsync ( req ) ) { @ Override protected GcsFileMetadata wrap ( HTTPResponse resp ) throws IOException { long totalLength ; switch ( resp . getResponseCode ( ) ) { case 200 : totalLength = getLengthFromHeader ( resp , X_GOOG_CONTENT_LENGTH ) ; break ; case 206 : totalLength = getLengthFromContentRange ( resp ) ; break ; case 404 : throw new FileNotFoundException ( "Could not find: " + filename ) ; case 416 : throw new BadRangeException ( "Requested Range not satisfiable; perhaps read past EOF? " + URLFetchUtils . describeRequestAndResponse ( info , resp ) ) ; default : throw HttpErrorHandler . error ( info , resp ) ; } byte [ ] content = resp . getContent ( ) ; Preconditions . checkState ( content . length <= want , "%s: got %s > wanted %s" , this , content . length , want ) ; dst . put ( content ) ; return getMetadataFromResponse ( filename , resp , totalLength ) ; } @ Override protected Throwable convertException ( Throwable e ) { return OauthRawGcsService . convertException ( info , e ) ; } } ; }
Might not fill all of dst .