1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.squareup.okhttp.internal.http; 18 19 import com.squareup.okhttp.internal.AbstractOutputStream; 20 import java.io.ByteArrayOutputStream; 21 import java.io.IOException; 22 import java.io.OutputStream; 23 import java.net.ProtocolException; 24 25 import static com.squareup.okhttp.internal.Util.checkOffsetAndCount; 26 27 /** 28 * An HTTP request body that's completely buffered in memory. This allows 29 * the post body to be transparently re-sent if the HTTP request must be 30 * sent multiple times. 31 */ 32 final class RetryableOutputStream extends AbstractOutputStream { 33 private final int limit; 34 private final ByteArrayOutputStream content; 35 36 public RetryableOutputStream(int limit) { 37 this.limit = limit; 38 this.content = new ByteArrayOutputStream(limit); 39 } 40 41 public RetryableOutputStream() { 42 this.limit = -1; 43 this.content = new ByteArrayOutputStream(); 44 } 45 46 @Override public synchronized void close() throws IOException { 47 if (closed) { 48 return; 49 } 50 closed = true; 51 if (content.size() < limit) { 52 throw new ProtocolException( 53 "content-length promised " + limit + " bytes, but received " + content.size()); 54 } 55 } 56 57 @Override public synchronized void write(byte[] buffer, int offset, int count) 58 throws IOException { 59 checkNotClosed(); 60 checkOffsetAndCount(buffer.length, offset, count); 61 if (limit != -1 && content.size() > limit - count) { 62 throw new ProtocolException("exceeded content-length limit of " + limit + " bytes"); 63 } 64 content.write(buffer, offset, count); 65 } 66 67 public synchronized int contentLength() throws IOException { 68 close(); 69 return content.size(); 70 } 71 72 public void writeToSocket(OutputStream socketOut) throws IOException { 73 content.writeTo(socketOut); 74 } 75 } 76