• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 Square, Inc.
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 package com.squareup.okhttp;
17 
18 import com.squareup.okhttp.internal.Util;
19 import java.io.Closeable;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.InputStreamReader;
23 import java.io.Reader;
24 import java.nio.charset.Charset;
25 import okio.Buffer;
26 import okio.BufferedSource;
27 
28 import static com.squareup.okhttp.internal.Util.UTF_8;
29 
30 public abstract class ResponseBody implements Closeable {
31   /** Multiple calls to {@link #charStream()} must return the same instance. */
32   private Reader reader;
33 
contentType()34   public abstract MediaType contentType();
35 
36   /**
37    * Returns the number of bytes in that will returned by {@link #bytes}, or
38    * {@link #byteStream}, or -1 if unknown.
39    */
contentLength()40   public abstract long contentLength() throws IOException;
41 
byteStream()42   public final InputStream byteStream() throws IOException {
43     return source().inputStream();
44   }
45 
source()46   public abstract BufferedSource source() throws IOException;
47 
bytes()48   public final byte[] bytes() throws IOException {
49     long contentLength = contentLength();
50     if (contentLength > Integer.MAX_VALUE) {
51       throw new IOException("Cannot buffer entire body for content length: " + contentLength);
52     }
53 
54     BufferedSource source = source();
55     byte[] bytes;
56     try {
57       bytes = source.readByteArray();
58     } finally {
59       Util.closeQuietly(source);
60     }
61     if (contentLength != -1 && contentLength != bytes.length) {
62       throw new IOException("Content-Length and stream length disagree");
63     }
64     return bytes;
65   }
66 
67   /**
68    * Returns the response as a character stream decoded with the charset
69    * of the Content-Type header. If that header is either absent or lacks a
70    * charset, this will attempt to decode the response body as UTF-8.
71    */
charStream()72   public final Reader charStream() throws IOException {
73     Reader r = reader;
74     return r != null ? r : (reader = new InputStreamReader(byteStream(), charset()));
75   }
76 
77   /**
78    * Returns the response as a string decoded with the charset of the
79    * Content-Type header. If that header is either absent or lacks a charset,
80    * this will attempt to decode the response body as UTF-8.
81    */
string()82   public final String string() throws IOException {
83     return new String(bytes(), charset().name());
84   }
85 
charset()86   private Charset charset() {
87     MediaType contentType = contentType();
88     return contentType != null ? contentType.charset(UTF_8) : UTF_8;
89   }
90 
close()91   @Override public void close() throws IOException {
92     source().close();
93   }
94 
95   /**
96    * Returns a new response body that transmits {@code content}. If {@code
97    * contentType} is non-null and lacks a charset, this will use UTF-8.
98    */
create(MediaType contentType, String content)99   public static ResponseBody create(MediaType contentType, String content) {
100     Charset charset = Util.UTF_8;
101     if (contentType != null) {
102       charset = contentType.charset();
103       if (charset == null) {
104         charset = Util.UTF_8;
105         contentType = MediaType.parse(contentType + "; charset=utf-8");
106       }
107     }
108     Buffer buffer = new Buffer().writeString(content, charset);
109     return create(contentType, buffer.size(), buffer);
110   }
111 
112   /** Returns a new response body that transmits {@code content}. */
create(final MediaType contentType, byte[] content)113   public static ResponseBody create(final MediaType contentType, byte[] content) {
114     Buffer buffer = new Buffer().write(content);
115     return create(contentType, content.length, buffer);
116   }
117 
118   /** Returns a new response body that transmits {@code content}. */
create( final MediaType contentType, final long contentLength, final BufferedSource content)119   public static ResponseBody create(
120       final MediaType contentType, final long contentLength, final BufferedSource content) {
121     if (content == null) throw new NullPointerException("source == null");
122     return new ResponseBody() {
123       @Override public MediaType contentType() {
124         return contentType;
125       }
126 
127       @Override public long contentLength() {
128         return contentLength;
129       }
130 
131       @Override public BufferedSource source() {
132         return content;
133       }
134     };
135   }
136 }
137